Fix BZZZ deployment system and deploy to ironwood
## Major Fixes: 1. **Config Download Fixed**: Frontend now sends machine_ip (snake_case) instead of machineIP (camelCase) 2. **Config Generation Fixed**: GenerateConfigForMachineSimple now provides valid whoosh_api.base_url 3. **Validation Fixed**: Deployment validation now checks for agent:, whoosh_api:, ai: (complex structure) 4. **Hardcoded Values Removed**: No more personal names/paths in deployment system ## Deployment Results: - ✅ Config validation passes: "Configuration loaded and validated successfully" - ✅ Remote deployment works: BZZZ starts in normal mode on deployed machines - ✅ ironwood (192.168.1.113) successfully deployed with systemd service - ✅ P2P networking operational with peer discovery ## Technical Details: - Updated api/setup_manager.go: Fixed config generation and validation logic - Updated main.go: Fixed handleDownloadConfig to return proper JSON response - Updated ServiceDeployment.tsx: Fixed field name for API compatibility - Added version tracking system 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -45,12 +45,11 @@ type OpenAIConfig struct {
|
||||
|
||||
// Config represents the complete configuration for a Bzzz agent
|
||||
type Config struct {
|
||||
WHOOSHAPI WHOOSHAPIConfig `yaml:"hive_api"`
|
||||
WHOOSHAPI WHOOSHAPIConfig `yaml:"whoosh_api"`
|
||||
Agent AgentConfig `yaml:"agent"`
|
||||
GitHub GitHubConfig `yaml:"github"`
|
||||
P2P P2PConfig `yaml:"p2p"`
|
||||
Logging LoggingConfig `yaml:"logging"`
|
||||
HCFS HCFSConfig `yaml:"hcfs"`
|
||||
Slurp SlurpConfig `yaml:"slurp"`
|
||||
V2 V2Config `yaml:"v2"` // BZZZ v2 protocol settings
|
||||
UCXL UCXLConfig `yaml:"ucxl"` // UCXL protocol settings
|
||||
@@ -226,31 +225,6 @@ type UCXLP2PConfig struct {
|
||||
DiscoveryTimeout time.Duration `yaml:"discovery_timeout" json:"discovery_timeout"`
|
||||
}
|
||||
|
||||
// HCFSConfig holds HCFS integration configuration
|
||||
type HCFSConfig struct {
|
||||
// API settings
|
||||
APIURL string `yaml:"api_url" json:"api_url"`
|
||||
APITimeout time.Duration `yaml:"api_timeout" json:"api_timeout"`
|
||||
|
||||
// Workspace settings
|
||||
MountPath string `yaml:"mount_path" json:"mount_path"`
|
||||
WorkspaceTimeout time.Duration `yaml:"workspace_timeout" json:"workspace_timeout"`
|
||||
|
||||
// FUSE settings
|
||||
FUSEEnabled bool `yaml:"fuse_enabled" json:"fuse_enabled"`
|
||||
FUSEMountPoint string `yaml:"fuse_mount_point" json:"fuse_mount_point"`
|
||||
|
||||
// Cleanup settings
|
||||
IdleCleanupInterval time.Duration `yaml:"idle_cleanup_interval" json:"idle_cleanup_interval"`
|
||||
MaxIdleTime time.Duration `yaml:"max_idle_time" json:"max_idle_time"`
|
||||
|
||||
// Storage settings
|
||||
StoreArtifacts bool `yaml:"store_artifacts" json:"store_artifacts"`
|
||||
CompressArtifacts bool `yaml:"compress_artifacts" json:"compress_artifacts"`
|
||||
|
||||
// Enable/disable HCFS integration
|
||||
Enabled bool `yaml:"enabled" json:"enabled"`
|
||||
}
|
||||
|
||||
// LoadConfig loads configuration from file, environment variables, and defaults
|
||||
func LoadConfig(configPath string) (*Config, error) {
|
||||
@@ -281,7 +255,7 @@ func LoadConfig(configPath string) (*Config, error) {
|
||||
func getDefaultConfig() *Config {
|
||||
return &Config{
|
||||
WHOOSHAPI: WHOOSHAPIConfig{
|
||||
BaseURL: "https://hive.home.deepblack.cloud",
|
||||
BaseURL: "https://whoosh.home.deepblack.cloud",
|
||||
Timeout: 30 * time.Second,
|
||||
RetryCount: 3,
|
||||
},
|
||||
@@ -317,19 +291,6 @@ func getDefaultConfig() *Config {
|
||||
Output: "stdout",
|
||||
Structured: false,
|
||||
},
|
||||
HCFS: HCFSConfig{
|
||||
APIURL: "http://localhost:8000",
|
||||
APITimeout: 30 * time.Second,
|
||||
MountPath: "/tmp/hcfs-workspaces",
|
||||
WorkspaceTimeout: 2 * time.Hour,
|
||||
FUSEEnabled: false,
|
||||
FUSEMountPoint: "/mnt/hcfs",
|
||||
IdleCleanupInterval: 15 * time.Minute,
|
||||
MaxIdleTime: 1 * time.Hour,
|
||||
StoreArtifacts: true,
|
||||
CompressArtifacts: false,
|
||||
Enabled: true,
|
||||
},
|
||||
Slurp: GetDefaultSlurpConfig(),
|
||||
UCXL: UCXLConfig{
|
||||
Enabled: false, // Disabled by default
|
||||
@@ -456,10 +417,10 @@ func loadFromFile(config *Config, filePath string) error {
|
||||
// loadFromEnv loads configuration from environment variables
|
||||
func loadFromEnv(config *Config) error {
|
||||
// WHOOSH API configuration
|
||||
if url := os.Getenv("BZZZ_HIVE_API_URL"); url != "" {
|
||||
if url := os.Getenv("BZZZ_WHOOSH_API_URL"); url != "" {
|
||||
config.WHOOSHAPI.BaseURL = url
|
||||
}
|
||||
if apiKey := os.Getenv("BZZZ_HIVE_API_KEY"); apiKey != "" {
|
||||
if apiKey := os.Getenv("BZZZ_WHOOSH_API_KEY"); apiKey != "" {
|
||||
config.WHOOSHAPI.APIKey = apiKey
|
||||
}
|
||||
|
||||
@@ -533,7 +494,7 @@ func loadFromEnv(config *Config) error {
|
||||
func validateConfig(config *Config) error {
|
||||
// Validate required fields
|
||||
if config.WHOOSHAPI.BaseURL == "" {
|
||||
return fmt.Errorf("hive_api.base_url is required")
|
||||
return fmt.Errorf("whoosh_api.base_url is required")
|
||||
}
|
||||
|
||||
// Note: Agent.ID can be empty - it will be auto-generated from node ID in main.go
|
||||
|
||||
1
pkg/version/VERSION
Normal file
1
pkg/version/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
1.0.8
|
||||
19
pkg/version/version.go
Normal file
19
pkg/version/version.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//go:embed VERSION
|
||||
var versionContent string
|
||||
|
||||
// Version returns the current BZZZ version
|
||||
func Version() string {
|
||||
return strings.TrimSpace(versionContent)
|
||||
}
|
||||
|
||||
// FullVersion returns a formatted version string
|
||||
func FullVersion() string {
|
||||
return "v" + Version()
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-e87e5963ec1b8011.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
||||
@@ -0,0 +1 @@
|
||||
self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{1380:function(e,t,r){Promise.resolve().then(r.bind(r,9174)),Promise.resolve().then(r.bind(r,2724)),Promise.resolve().then(r.t.bind(r,2445,23))},9174:function(e,t,r){"use strict";r.r(t),r.d(t,{default:function(){return l}});var n=r(7437),s=r(2265);let a=s.forwardRef(function({title:e,titleId:t,...r},n){return s.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor","aria-hidden":"true","data-slot":"icon",ref:n,"aria-labelledby":t},r),e?s.createElement("title",{id:t},e):null,s.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"}))}),o=s.forwardRef(function({title:e,titleId:t,...r},n){return s.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor","aria-hidden":"true","data-slot":"icon",ref:n,"aria-labelledby":t},r),e?s.createElement("title",{id:t},e):null,s.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z"}))});function l(){let[e,t]=(0,s.useState)(!0);(0,s.useEffect)(()=>{let e=localStorage.getItem("chorus-theme"),n=!e||"dark"===e;t(n),r(n)},[]);let r=e=>{let t=document.documentElement;e?(t.classList.add("dark"),t.classList.remove("light")):(t.classList.remove("dark"),t.classList.add("light"))};return(0,n.jsx)("button",{onClick:()=>{let n=!e;t(n),r(n),localStorage.setItem("chorus-theme",n?"dark":"light")},className:"btn-text flex items-center space-x-2 p-2 rounded-md transition-colors duration-200","aria-label":"Switch to ".concat(e?"light":"dark"," theme"),children:e?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a,{className:"h-4 w-4"}),(0,n.jsx)("span",{className:"text-xs",children:"Light"})]}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o,{className:"h-4 w-4"}),(0,n.jsx)("span",{className:"text-xs",children:"Dark"})]})})}},2724:function(e,t,r){"use strict";r.r(t),r.d(t,{default:function(){return a}});var n=r(7437),s=r(2265);function a(){let[e,t]=(0,s.useState)(null);return((0,s.useEffect)(()=>{(async()=>{try{let e=await fetch("/api/version");if(e.ok){let r=await e.json();t(r)}}catch(e){console.warn("Failed to fetch version:",e)}})()},[]),e)?(0,n.jsxs)("div",{className:"text-xs text-gray-500",children:["BZZZ ",e.full_version]}):(0,n.jsx)("div",{className:"text-xs text-gray-500",children:"BZZZ"})}},2445:function(){},622:function(e,t,r){"use strict";var n=r(2265),s=Symbol.for("react.element"),a=Symbol.for("react.fragment"),o=Object.prototype.hasOwnProperty,l=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,i={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,r){var n,a={},c=null,u=null;for(n in void 0!==r&&(c=""+r),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)o.call(t,n)&&!i.hasOwnProperty(n)&&(a[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===a[n]&&(a[n]=t[n]);return{$$typeof:s,type:e,key:c,ref:u,props:a,_owner:l.current}}t.Fragment=a,t.jsx=c,t.jsxs=c},7437:function(e,t,r){"use strict";e.exports=r(622)}},function(e){e.O(0,[971,938,744],function(){return e(e.s=1380)}),_N_E=e.O()}]);
|
||||
@@ -0,0 +1 @@
|
||||
!function(){"use strict";var e,t,r,n,o,u,i,c,f,a={},l={};function s(e){var t=l[e];if(void 0!==t)return t.exports;var r=l[e]={exports:{}},n=!0;try{a[e](r,r.exports,s),n=!1}finally{n&&delete l[e]}return r.exports}s.m=a,e=[],s.O=function(t,r,n,o){if(r){o=o||0;for(var u=e.length;u>0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[r,n,o];return}for(var i=1/0,u=0;u<e.length;u++){for(var r=e[u][0],n=e[u][1],o=e[u][2],c=!0,f=0;f<r.length;f++)i>=o&&Object.keys(s.O).every(function(e){return s.O[e](r[f])})?r.splice(f--,1):(c=!1,o<i&&(i=o));if(c){e.splice(u--,1);var a=n();void 0!==a&&(t=a)}}return t},r=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},s.t=function(e,n){if(1&n&&(e=this(e)),8&n||"object"==typeof e&&e&&(4&n&&e.__esModule||16&n&&"function"==typeof e.then))return e;var o=Object.create(null);s.r(o);var u={};t=t||[null,r({}),r([]),r(r)];for(var i=2&n&&e;"object"==typeof i&&!~t.indexOf(i);i=r(i))Object.getOwnPropertyNames(i).forEach(function(t){u[t]=function(){return e[t]}});return u.default=function(){return e},s.d(o,u),o},s.d=function(e,t){for(var r in t)s.o(t,r)&&!s.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},s.f={},s.e=function(e){return Promise.all(Object.keys(s.f).reduce(function(t,r){return s.f[r](e,t),t},[]))},s.u=function(e){},s.miniCssF=function(e){return"static/css/7a9299e2c7bea835.css"},s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n={},o="_N_E:",s.l=function(e,t,r,u){if(n[e]){n[e].push(t);return}if(void 0!==r)for(var i,c,f=document.getElementsByTagName("script"),a=0;a<f.length;a++){var l=f[a];if(l.getAttribute("src")==e||l.getAttribute("data-webpack")==o+r){i=l;break}}i||(c=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,s.nc&&i.setAttribute("nonce",s.nc),i.setAttribute("data-webpack",o+r),i.src=s.tu(e)),n[e]=[t];var d=function(t,r){i.onerror=i.onload=null,clearTimeout(p);var o=n[e];if(delete n[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach(function(e){return e(r)}),t)return t(r)},p=setTimeout(d.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=d.bind(null,i.onerror),i.onload=d.bind(null,i.onload),c&&document.head.appendChild(i)},s.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.tt=function(){return void 0===u&&(u={createScriptURL:function(e){return e}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(u=trustedTypes.createPolicy("nextjs#bundler",u))),u},s.tu=function(e){return s.tt().createScriptURL(e)},s.p="/setup/_next/",i={272:0},s.f.j=function(e,t){var r=s.o(i,e)?i[e]:void 0;if(0!==r){if(r)t.push(r[2]);else if(272!=e){var n=new Promise(function(t,n){r=i[e]=[t,n]});t.push(r[2]=n);var o=s.p+s.u(e),u=Error();s.l(o,function(t){if(s.o(i,e)&&(0!==(r=i[e])&&(i[e]=void 0),r)){var n=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;u.message="Loading chunk "+e+" failed.\n("+n+": "+o+")",u.name="ChunkLoadError",u.type=n,u.request=o,r[1](u)}},"chunk-"+e,e)}else i[e]=0}},s.O.j=function(e){return 0===i[e]},c=function(e,t){var r,n,o=t[0],u=t[1],c=t[2],f=0;if(o.some(function(e){return 0!==i[e]})){for(r in u)s.o(u,r)&&(s.m[r]=u[r]);if(c)var a=c(s)}for(e&&e(t);f<o.length;f++)n=o[f],s.o(i,n)&&i[n]&&i[n][0](),i[n]=0;return s.O(a)},(f=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(c.bind(null,0)),f.push=c.bind(null,f.push.bind(f))}();
|
||||
3
pkg/web/static/_next/static/css/7a9299e2c7bea835.css
Normal file
3
pkg/web/static/_next/static/css/7a9299e2c7bea835.css
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user