capix-code 1.6.10 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capix-code",
3
- "version": "1.6.10",
3
+ "version": "2.0.0",
4
4
  "description": "Capix Code — decentralized AI coding agent with GPU marketplace",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
package/scripts/build.sh CHANGED
@@ -145,6 +145,33 @@ MCPWRAPPER
145
145
  cp "$DIR/launcher/target/release/capix-code$EXE_SUFFIX" "$ARTIFACT/bin/capix-code$EXE_SUFFIX"
146
146
  chmod 0755 "$ARTIFACT/bin/capix-code$EXE_SUFFIX"
147
147
 
148
+ # Write a startup config to the path the engine binary actually reads.
149
+ # The engine's core package uses ~/.config/opencode/ (not capix-code)
150
+ # because the core was not rebranded. The launcher overwrites this at
151
+ # runtime from the defaults.json, but having it pre-populated helps
152
+ # when running the engine directly for testing.
153
+ mkdir -p "$ARTIFACT/config/opencode"
154
+ cat > "$ARTIFACT/config/opencode/capix-code.json" << 'OCJSON'
155
+ {
156
+ "model": "capix/auto",
157
+ "enabled_providers": ["capix"],
158
+ "plugin": ["__RUNTIME_DIR__/src/native-bridge.ts", "__RUNTIME_DIR__/src/plugin.ts"],
159
+ "provider": {
160
+ "capix": {
161
+ "npm": "__PROVIDER_URL__",
162
+ "name": "Capix",
163
+ "models": {
164
+ "auto": {
165
+ "name": "Capix Auto (smart route)",
166
+ "limit": {"context": 128000, "output": 64000},
167
+ "api": {"url": "https://www.capix.network/api/v1", "npm": "__PROVIDER_URL__"}
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }
173
+ OCJSON
174
+
148
175
  "$DIR/scripts/assert-artifact.sh" "$ARTIFACT"
149
176
  "$DIR/scripts/assert-customer-brand.sh" "$ARTIFACT"
150
177
  echo "✓ Customer artifact staged: $ARTIFACT"
@@ -3,119 +3,140 @@ const { execSync } = require('child_process');
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const os = require('os');
6
+ const crypto = require('crypto');
6
7
 
7
- if (process.env.CI || process.env.GITHUB_ACTIONS) {
8
- console.log('Skipping binary download in CI environment.');
9
- process.exit(0);
10
- }
8
+ if (process.env.CI || process.env.GITHUB_ACTIONS) { process.exit(0); }
9
+
10
+ // Derive version from our own package metadata — never hardcode
11
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
12
+ const VERSION = pkg.version;
13
+ if (!VERSION) { console.error('Cannot determine version from package.json'); process.exit(1); }
11
14
 
12
- const VERSION = '1.6.3';
13
- const PLATFORM_MAP = { darwin: 'darwin', linux: 'linux', win32: 'win32' };
14
- const ARCH_MAP = { arm64: 'arm64', x64: 'x64' };
15
- const platform = PLATFORM_MAP[process.platform] || 'linux';
16
- const arch = ARCH_MAP[process.arch] || 'x64';
15
+ const plat = process.platform === 'win32' ? 'win32' : process.platform;
16
+ const arch = process.arch === 'arm64' ? 'arm64' : 'x64';
17
17
  const ext = process.platform === 'win32' ? 'zip' : 'tar.gz';
18
- const NAME = `capix-code-${VERSION}-${platform}-${arch}-unsigned`;
19
- const RELEASE = `https://github.com/CapIX-Protocol/Capix-Code/releases/download/v${VERSION}/${NAME}.${ext}`;
18
+ const NAME = `capix-code-${VERSION}-${plat}-${arch}-unsigned`;
19
+ const URL = `https://github.com/CapIX-Protocol/Capix-Code/releases/download/v${VERSION}/${NAME}.${ext}`;
20
+ const CHECKSUM_URL = `${URL}.sha256`;
21
+
22
+ const ROOT = path.join(os.homedir(), '.capix-code');
23
+ const TMP = path.join(os.tmpdir(), `capix-code-install-${VERSION}`);
24
+ const archivePath = path.join(TMP, `${NAME}.${ext}`);
20
25
 
21
- const installDir = path.join(os.homedir(), '.capix-code');
22
- const tmpDir = path.join(os.tmpdir(), 'capix-code-install');
26
+ fs.mkdirSync(ROOT, { recursive: true });
27
+ fs.mkdirSync(TMP, { recursive: true });
23
28
 
24
- fs.mkdirSync(installDir, { recursive: true });
25
- fs.mkdirSync(tmpDir, { recursive: true });
29
+ async function main() {
30
+ console.log(`Capix Code v${VERSION} (${plat}-${arch})`);
26
31
 
27
- try {
28
- console.log(`Downloading capix-code v${VERSION} (${platform}-${arch})...`);
29
- const archivePath = path.join(tmpDir, `${NAME}.${ext}`);
30
- execSync(`curl -fsSL -o "${archivePath}" "${RELEASE}"`, { stdio: 'inherit' });
32
+ // Download artifact
33
+ console.log('Downloading...');
34
+ execSync(`curl -fsSL -o "${archivePath}" "${URL}"`, { stdio: 'inherit' });
35
+
36
+ // Download and verify checksum
37
+ console.log('Verifying checksum...');
38
+ const checksumPath = path.join(TMP, `${NAME}.${ext}.sha256`);
39
+ execSync(`curl -fsSL -o "${checksumPath}" "${CHECKSUM_URL}"`, { stdio: 'inherit' });
40
+
41
+ const expected = fs.readFileSync(checksumPath, 'utf8').trim().split(/\s+/)[0];
42
+ const actual = crypto.createHash('sha256').update(fs.readFileSync(archivePath)).digest('hex');
43
+
44
+ if (expected !== actual) {
45
+ console.error(`Checksum mismatch: expected ${expected}, got ${actual}`);
46
+ process.exit(1);
47
+ }
48
+ console.log('Checksum OK');
31
49
 
50
+ // Extract
51
+ console.log('Extracting...');
32
52
  if (process.platform === 'win32') {
33
- execSync(`tar -xf "${archivePath}" -C "${tmpDir}"`, { stdio: 'inherit' });
53
+ execSync(`tar -xf "${archivePath}" -C "${TMP}"`, { stdio: 'inherit' });
34
54
  } else {
35
- execSync(`tar -xzf "${archivePath}" -C "${tmpDir}"`, { stdio: 'inherit' });
55
+ execSync(`tar -xzf "${archivePath}" -C "${TMP}"`, { stdio: 'inherit' });
36
56
  }
37
57
 
38
- const customerSrc = path.join(tmpDir, 'customer');
39
- if (fs.existsSync(customerSrc)) {
40
- for (const dir of ['bin', 'engine', 'runtime', 'config', 'mcp']) {
41
- const src = path.join(customerSrc, dir);
42
- const dst = path.join(installDir, dir);
43
- if (fs.existsSync(src)) {
44
- execSync(`rm -rf "${dst}" && cp -a "${src}" "${dst}"`, { stdio: 'inherit' });
45
- }
46
- }
47
- const binPath = path.join(installDir, 'bin', 'capix-code');
48
- if (fs.existsSync(binPath)) {
49
- fs.chmodSync(binPath, 0o755);
50
- }
51
- }
58
+ const src = path.join(TMP, 'customer');
59
+ if (!fs.existsSync(src)) { console.error('Artifact missing customer/'); process.exit(1); }
52
60
 
53
- // Install runtime dependencies (typescript is required by plugin.ts)
54
- const runtimeDir = path.join(installDir, 'runtime');
55
- if (fs.existsSync(path.join(runtimeDir, 'package.json'))) {
56
- console.log('Installing runtime dependencies...');
57
- execSync(`npm install --omit=dev --ignore-scripts`, { cwd: runtimeDir, stdio: 'inherit' });
61
+ // Atomic replace
62
+ const backup = ROOT + '.bak';
63
+ if (fs.existsSync(backup)) fs.rmSync(backup, { recursive: true });
64
+ if (fs.existsSync(ROOT)) fs.renameSync(ROOT, backup);
65
+ fs.mkdirSync(ROOT, { recursive: true });
66
+
67
+ for (const dir of ['bin', 'engine', 'runtime', 'config', 'mcp']) {
68
+ const s = path.join(src, dir);
69
+ const d = path.join(ROOT, dir);
70
+ if (fs.existsSync(s)) execSync(`cp -a "${s}" "${d}"`, { stdio: 'inherit' });
58
71
  }
72
+ fs.chmodSync(path.join(ROOT, 'bin', 'capix-code'), 0o755);
73
+
74
+ // Install runtime deps (typescript required by plugin.ts)
75
+ console.log('Installing runtime dependencies...');
76
+ execSync('npm install --omit=dev --ignore-scripts', {
77
+ cwd: path.join(ROOT, 'runtime'), stdio: 'inherit'
78
+ });
59
79
 
60
- // Install MCP dependencies if not already bundled
61
- const mcpDir = path.join(installDir, 'mcp');
62
- const mcpEntry = path.join(mcpDir, 'capix-mcp.js');
63
- if (!fs.existsSync(path.join(mcpDir, 'node_modules', '@modelcontextprotocol', 'sdk'))) {
80
+ // Install MCP deps
81
+ const mcpDir = path.join(ROOT, 'mcp');
82
+ if (!fs.existsSync(path.join(mcpDir, 'node_modules', '@modelcontextprotocol'))) {
64
83
  console.log('Installing MCP dependencies...');
65
- execSync(`npm install capix-mcp@2.1.0`, { cwd: mcpDir, stdio: 'inherit' });
66
- // Create wrapper that shares credentials
67
- const mcpPkgPath = path.join(mcpDir, 'node_modules', 'capix-mcp', 'dist', 'index.js');
68
- if (!fs.existsSync(mcpEntry)) {
69
- fs.writeFileSync(mcpEntry,
70
- '#!/usr/bin/env node\n' +
71
- 'const { readFileSync, writeFileSync, chmodSync, existsSync } = require("node:fs");\n' +
72
- 'const { join } = require("node:path");\n' +
73
- 'const { homedir } = require("node:os");\n' +
74
- 'const credPath = join(homedir(), ".capix-code", "credentials.json");\n' +
75
- 'async function loadMcp() {\n' +
76
- ' require(join(homedir(), ".capix-code", "mcp", "node_modules", "capix-mcp", "dist", "index.js"));\n' +
77
- '}\n' +
78
- '(async () => {\n' +
79
- ' try {\n' +
80
- ' if (existsSync(credPath)) {\n' +
81
- ' const creds = JSON.parse(readFileSync(credPath, "utf8"));\n' +
82
- ' const rt = creds["capix-code:oauth-refresh-token"];\n' +
83
- ' if (rt) {\n' +
84
- ' const res = await fetch("https://www.capix.network/oauth/token", {\n' +
85
- ' method: "POST",\n' +
86
- ' headers: { "Content-Type": "application/x-www-form-urlencoded" },\n' +
87
- ' body: new URLSearchParams({ grant_type: "refresh_token", refresh_token: rt, client_id: "capix-code" }).toString(),\n' +
88
- ' });\n' +
89
- ' const body = await res.json();\n' +
90
- ' if (body.access_token) {\n' +
91
- ' process.env.CAPIX_API_KEY = body.access_token;\n' +
92
- ' creds["capix-code:oauth-refresh-token"] = body.refresh_token;\n' +
93
- ' writeFileSync(credPath, JSON.stringify(creds, null, 2), { mode: 0o600 });\n' +
94
- ' chmodSync(credPath, 0o600);\n' +
95
- ' }\n' +
96
- ' }\n' +
97
- ' }\n' +
98
- ' } catch {}\n' +
99
- ' loadMcp();\n' +
100
- '})();\n'
101
- );
102
- fs.chmodSync(mcpEntry, 0o755);
103
- }
84
+ execSync('npm install capix-mcp@2.1.0', { cwd: mcpDir, stdio: 'inherit' });
85
+ fs.writeFileSync(path.join(mcpDir, 'capix-mcp.js'),
86
+ '#!/usr/bin/env node\n' +
87
+ 'const { join } = require("node:path");\n' +
88
+ 'const { homedir } = require("node:os");\n' +
89
+ 'require(join(homedir(), ".capix-code", "mcp", "node_modules", "capix-mcp", "dist", "index.js"));\n'
90
+ );
91
+ fs.chmodSync(path.join(mcpDir, 'capix-mcp.js'), 0o755);
104
92
  }
105
93
 
106
- // Sign binaries on macOS to prevent Gatekeeper kills
94
+ // Write config to ~/.config/opencode/ (engine binary reads this path)
95
+ const cfgDir = path.join(os.homedir(), '.config', 'opencode');
96
+ fs.mkdirSync(cfgDir, { recursive: true });
97
+ const rtDir = path.join(ROOT, 'runtime');
98
+ const providerUrl = `file://${rtDir}/packages/runtime-provider/src/index.ts`;
99
+ const apiBase = 'https://www.capix.network/api/v1';
100
+ const config = {
101
+ model: 'capix/auto',
102
+ enabled_providers: ['capix'],
103
+ plugin: [
104
+ path.join(rtDir, 'src', 'native-bridge.ts'),
105
+ path.join(rtDir, 'src', 'plugin.ts')
106
+ ],
107
+ provider: {
108
+ capix: {
109
+ npm: providerUrl,
110
+ name: 'Capix',
111
+ models: {
112
+ auto: {
113
+ name: 'Capix Auto (smart route)',
114
+ limit: { context: 128000, output: 64000 },
115
+ api: { url: apiBase, npm: providerUrl }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ };
121
+ fs.writeFileSync(path.join(cfgDir, 'capix-code.json'), JSON.stringify(config, null, 2));
122
+
123
+ // Sign on macOS
107
124
  if (process.platform === 'darwin') {
108
125
  try {
109
- execSync(`codesign --force --sign - "${path.join(installDir, 'bin', 'capix-code')}"`, { stdio: 'ignore' });
110
- execSync(`codesign --force --sign - "${path.join(installDir, 'engine', 'capix-engine')}"`, { stdio: 'ignore' });
126
+ execSync(`codesign --force --sign - "${path.join(ROOT, 'bin', 'capix-code')}"`, { stdio: 'ignore' });
127
+ execSync(`codesign --force --sign - "${path.join(ROOT, 'engine', 'capix-engine')}"`, { stdio: 'ignore' });
111
128
  } catch {}
112
129
  }
113
130
 
114
- fs.rmSync(tmpDir, { recursive: true, force: true });
115
- console.log(`✓ Capix Code v${VERSION} installed to ${installDir}`);
131
+ // Cleanup
132
+ fs.rmSync(TMP, { recursive: true, force: true });
133
+ if (fs.existsSync(backup)) fs.rmSync(backup, { recursive: true });
134
+
135
+ console.log(`✓ Capix Code v${VERSION} installed`);
116
136
  console.log('Run: capix-code login && capix-code');
117
- } catch (err) {
118
- console.warn('⚠ Binary download failed. Download manually from:');
119
- console.warn(' https://github.com/CapIX-Protocol/Capix-Code/releases');
120
- process.exit(0);
121
137
  }
138
+
139
+ main().catch(err => {
140
+ console.error('Installation failed:', err.message);
141
+ process.exit(1);
142
+ });
@@ -215,6 +215,34 @@ for relative in "${PRESENTATION_FILES[@]}"; do
215
215
  rm -f "$file.bak"
216
216
  done
217
217
  echo " ✓ terminal title, splash, logo and customer command copy replaced"
218
+ # 6c. Fix split-span rendering: <b>Open</b>\n<b>Code</b> → Capix Code
219
+ echo "▸ Fixing split-span branding in sidebar/footer…"
220
+ SIDEBAR_FILES=(
221
+ "$CAPIX_CODE_DIR/packages/tui/src/routes/session/sidebar.tsx"
222
+ "$CAPIX_CODE_DIR/packages/tui/src/feature-plugins/sidebar/footer.tsx"
223
+ )
224
+ for file in "${SIDEBAR_FILES[@]}"; do
225
+ if [ -f "$file" ]; then
226
+ perl -0pi.bak -e 's|<b>Open</b>\s*\n\s*\s*<b>Code</b>|<b>Capix Code</b>|gs' "$file"
227
+ perl -0pi.bak -e 's|<b>Open</b>\s*\n\s*<b>Code</b>|<b>Capix Code</b>|gs' "$file"
228
+ perl -0pi.bak -e 's|<b>Open</b>|<b>Capix Code</b>|g' "$file"
229
+ perl -0pi.bak -e 's|<b>Code</b>||g' "$file"
230
+ rm -f "$file.bak"
231
+ echo " ✓ Fixed split-span in $(basename $file)"
232
+ fi
233
+ done
234
+
235
+ # 6d. Fix home/footer.tsx and tips-view.tsx
236
+ for fixfile in \
237
+ "$CAPIX_CODE_DIR/packages/tui/src/feature-plugins/home/footer.tsx" \
238
+ "$CAPIX_CODE_DIR/packages/tui/src/feature-plugins/home/tips-view.tsx"
239
+ do
240
+ if [ -f "$fixfile" ]; then
241
+ sed -i.bak 's/OpenCode/Capix Code/g' "$fixfile"
242
+ rm -f "$fixfile.bak"
243
+ echo " ✓ Fixed $(basename $fixfile)"
244
+ fi
245
+ done
218
246
 
219
247
  # 7. Install script references.
220
248
  INSTALL="$CAPIX_CODE_DIR/install"