capix-code 1.3.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 ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "capix-code",
3
+ "version": "1.3.0",
4
+ "description": "Capix Code \u2014 decentralized AI coding agent with GPU marketplace",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "bin": {
8
+ "capix-code": "./bin/capix-code.cjs"
9
+ },
10
+ "files": [
11
+ "bin/",
12
+ "scripts/",
13
+ "dist/customer/config/",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "engines": {
18
+ "node": ">=20"
19
+ },
20
+ "scripts": {
21
+ "compile": "tsc --noEmit",
22
+ "lint": "eslint src/",
23
+ "format": "prettier --write .",
24
+ "format:check": "prettier --check .",
25
+ "test": "vitest run",
26
+ "test:watch": "vitest",
27
+ "test:coverage": "vitest run --coverage",
28
+ "manifest:validate": "node scripts/validate-manifest.mjs manifest/release-manifest.json",
29
+ "manifest:build": "node scripts/build-manifest.mjs",
30
+ "resolve-version": "node scripts/resolve-version.mjs",
31
+ "prepack": "node scripts/prepare-npm-meta.mjs",
32
+ "pack:npm-platform": "node scripts/prepare-npm-platform.mjs",
33
+ "postinstall": "node scripts/postinstall.js"
34
+ },
35
+ "devDependencies": {
36
+ "@ai-sdk/provider": "3.0.8",
37
+ "@eslint/js": "^9.0.0",
38
+ "@types/node": "^22.0.0",
39
+ "@vitest/coverage-v8": "^2.1.0",
40
+ "@capix/runtime-provider": "file:packages/runtime-provider",
41
+ "@opencode-ai/plugin": "1.17.18",
42
+ "@opencode-ai/sdk": "1.17.18",
43
+ "bun": "^1.3.14",
44
+ "eslint": "^9.0.0",
45
+ "husky": "^9.0.0",
46
+ "lint-staged": "^15.0.0",
47
+ "opencode-ai": "1.17.18",
48
+ "prettier": "^3.0.0",
49
+ "typescript": "^5.7.0",
50
+ "typescript-eslint": "^8.0.0",
51
+ "vitest": "^2.1.0"
52
+ },
53
+ "lint-staged": {
54
+ "*.{ts,js}": [
55
+ "prettier --write",
56
+ "eslint --fix"
57
+ ],
58
+ "*.{json,md,yml}": [
59
+ "prettier --write"
60
+ ]
61
+ },
62
+ "optionalDependencies": {
63
+ "@capix-code/darwin-arm64": "1.2.7",
64
+ "@capix-code/darwin-x64": "1.2.7",
65
+ "@capix-code/linux-arm64": "1.2.7",
66
+ "@capix-code/linux-x64": "1.2.7",
67
+ "@capix-code/windows-x64": "1.2.7"
68
+ },
69
+ "keywords": [
70
+ "ai",
71
+ "coding",
72
+ "agent",
73
+ "gpu",
74
+ "llm",
75
+ "inference",
76
+ "capix",
77
+ "solana"
78
+ ]
79
+ }
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ ROOT="${1:?artifact directory required}"
4
+ SUFFIX=""
5
+ test -f "$ROOT/bin/capix-code.exe" && SUFFIX=".exe"
6
+ required=(
7
+ "bin/capix-code$SUFFIX"
8
+ "engine/capix-engine$SUFFIX"
9
+ runtime/src/plugin.ts
10
+ runtime/src/native-bridge.ts
11
+ runtime/src/broker.ts
12
+ runtime/src/sandbox.ts
13
+ runtime/src/capix-provider.ts
14
+ runtime/src/ai-sdk-provider.ts
15
+ runtime/packages/runtime-provider/package.json
16
+ runtime/node_modules/@capix/runtime-provider/package.json
17
+ config/capix-defaults.json
18
+ config/defaults.json
19
+ )
20
+ for path in "${required[@]}"; do
21
+ test -e "$ROOT/$path" || { echo "✗ artifact missing $path"; exit 1; }
22
+ done
23
+ test -x "$ROOT/engine/capix-engine$SUFFIX" || { echo "✗ bundled engine is not executable"; exit 1; }
24
+ test -x "$ROOT/bin/capix-code$SUFFIX" || { echo "✗ native launcher is not executable"; exit 1; }
25
+ grep -q '"name": "@capix/runtime-provider"' "$ROOT/runtime/packages/runtime-provider/package.json"
26
+ grep -q '"model": "{env:CAPIX_MODEL:capix/auto}"' "$ROOT/config/defaults.json"
27
+ grep -q 'SuperGemma' "$ROOT/config/defaults.json"
28
+ grep -q '/oauth/authorize' "$ROOT/runtime/src/broker.ts"
29
+ grep -q '/oauth/token' "$ROOT/runtime/src/broker.ts"
30
+ echo "✓ artifact contains pinned engine, plugin, broker, sandbox and runtime provider"
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ ROOT="${1:?artifact directory required}"
4
+ FORBIDDEN='opencode|vast|hetzner|void|vscode'
5
+
6
+ if find "$ROOT" -path "$ROOT/runtime/node_modules" -prune -o -type f -print | sed "s|$ROOT/||" | grep -Eiq "$FORBIDDEN"; then
7
+ echo "✗ customer artifact contains a forbidden filename"
8
+ exit 1
9
+ fi
10
+
11
+ for command in "--help" "--version" "doctor"; do
12
+ output="$($ROOT/bin/capix-code $command 2>&1)"
13
+ if printf '%s' "$output" | grep -Eiq "$FORBIDDEN"; then
14
+ echo "✗ forbidden customer-visible brand in: capix-code $command"
15
+ exit 1
16
+ fi
17
+ done
18
+
19
+ # The embedded engine is not invoked directly by customers, but every help
20
+ # surface it can render through the launcher must still be Capix-only.
21
+ for args in "--help" "run --help"; do
22
+ output="$($ROOT/engine/capix-engine $args 2>&1)"
23
+ if printf '%s' "$output" | grep -Eiq "$FORBIDDEN"; then
24
+ echo "✗ forbidden predecessor brand in embedded engine output: $args"
25
+ exit 1
26
+ fi
27
+ done
28
+
29
+ # Native account commands must never fall through to the bundled engine's
30
+ # command parser. An unsigned CI artifact has no user keychain credential, so
31
+ # the expected result is a clean Capix-only sign-in instruction.
32
+ set +e
33
+ status_output="$($ROOT/bin/capix-code status 2>&1)"
34
+ status_code=$?
35
+ set -e
36
+ if [ "$status_code" -eq 0 ]; then
37
+ # A developer machine may already have a valid native keychain session.
38
+ printf '%s' "$status_output" | grep -Fq '"accountId"' || {
39
+ echo "✗ authenticated status did not return canonical Capix account data"; exit 1;
40
+ }
41
+ else
42
+ printf '%s' "$status_output" | grep -Fq 'capix-code login' || {
43
+ echo "✗ status did not return the native Capix authentication instruction"; exit 1;
44
+ }
45
+ fi
46
+ if printf '%s' "$status_output" | grep -Eiq "$FORBIDDEN"; then
47
+ echo "✗ status leaked a forbidden inherited brand"; exit 1
48
+ fi
49
+
50
+ if grep -ERiq "$FORBIDDEN" "$ROOT/config"; then
51
+ echo "✗ forbidden customer-visible brand in configuration"
52
+ exit 1
53
+ fi
54
+ echo "✓ customer-visible artifact surfaces use Capix branding only"
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ ROOT="${1:?prepared engine source required}"
4
+ # Internal import/package symbols intentionally retain their upstream ABI.
5
+ # This expression targets customer-readable identity and command prose only.
6
+ FORBIDDEN='OpenCode|OC \||run opencode|close opencode|Starting opencode|opencode -s|opencode (models|auth|does|version|server|with|to|upgrade|mcp|session)|Thank you[^\n]*opencode'
7
+ SURFACES=(
8
+ packages/tui/src/logo.ts
9
+ packages/tui/src/app.tsx
10
+ packages/tui/src/util/presentation.ts
11
+ packages/capix-code/src/cli/ui.ts
12
+ packages/capix-code/src/index.ts
13
+ packages/capix-code/src/cli/error.ts
14
+ packages/capix-code/src/cli/cmd/run.ts
15
+ packages/capix-code/src/cli/cmd/run/splash.ts
16
+ packages/capix-code/src/cli/cmd/run/footer.permission.tsx
17
+ packages/capix-code/src/cli/cmd/run/footer.prompt.tsx
18
+ packages/capix-code/src/cli/cmd/run/permission.shared.ts
19
+ packages/capix-code/src/provider/error.ts
20
+ packages/capix-code/src/cli/cmd/attach.ts
21
+ packages/capix-code/src/cli/cmd/upgrade.ts
22
+ packages/capix-code/src/cli/cmd/uninstall.ts
23
+ packages/capix-code/src/cli/cmd/serve.ts
24
+ packages/capix-code/src/cli/cmd/web.ts
25
+ packages/capix-code/src/cli/cmd/pr.ts
26
+ packages/capix-code/src/cli/cmd/tui.ts
27
+ packages/capix-code/src/cli/network.ts
28
+ )
29
+ for file in "${SURFACES[@]}"; do
30
+ test -f "$ROOT/$file" || { echo "✗ missing customer presentation source: $file"; exit 1; }
31
+ if grep -Eq "$FORBIDDEN" "$ROOT/$file"; then
32
+ echo "✗ predecessor branding remains in customer presentation source: $file"
33
+ grep -En "$FORBIDDEN" "$ROOT/$file" | head -n 10
34
+ exit 1
35
+ fi
36
+ done
37
+ grep -Fq 'CAPIX CODE' "$ROOT/packages/capix-code/src/cli/ui.ts" || {
38
+ echo "✗ Capix Code startup wordmark is missing"
39
+ exit 1
40
+ }
41
+ grep -Fq 'export const identity' "$ROOT/packages/tui/src/logo.ts" &&
42
+ grep -Fq 'CAPIX CODE' "$ROOT/packages/tui/src/logo.ts" || {
43
+ echo "✗ Capix Code TUI identity is missing"
44
+ exit 1
45
+ }
46
+ echo "✓ prepared engine customer presentation sources are Capix-only"
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bash
2
+ # bootstrap.sh — clone upstream source and prepare capix-code.
3
+ set -euo pipefail
4
+
5
+ DIR="$(cd "$(dirname "$0")/.." && pwd)"
6
+ CAPIX_CODE_DIR="${CAPIX_CODE_DIR:-$DIR/upstream}"
7
+
8
+ # TODO: Update this SHA when upgrading upstream
9
+ CAPIX_CODE_REF="${CAPIX_CODE_REF:-9976269ab1accfc9f9dc98a4a688c516934de422}"
10
+
11
+ if [ -d "$CAPIX_CODE_DIR/.git" ]; then
12
+ echo "✓ $CAPIX_CODE_DIR already cloned."
13
+ else
14
+ echo "▸ Cloning upstream source into $CAPIX_CODE_DIR (SHA: $CAPIX_CODE_REF)…"
15
+ git clone https://github.com/anomalyco/opencode.git "$CAPIX_CODE_DIR"
16
+ git -C "$CAPIX_CODE_DIR" checkout "$CAPIX_CODE_REF"
17
+ fi
18
+
19
+ ACTUAL_REF="$(git -C "$CAPIX_CODE_DIR" rev-parse HEAD)"
20
+ if [ "$ACTUAL_REF" != "$CAPIX_CODE_REF" ]; then
21
+ echo "✗ Source checkout is at $ACTUAL_REF; expected pinned ref $CAPIX_CODE_REF"
22
+ echo " Use a new CAPIX_CODE_DIR or restore the pinned checkout before continuing."
23
+ exit 1
24
+ fi
25
+
26
+ # A prepared checkout is intentionally changed by scripts/rebrand.sh. Treat the
27
+ # expected renamed package as an idempotent success, while still rejecting an
28
+ # unrelated dirty checkout before the first rebrand.
29
+ if [ -d "$CAPIX_CODE_DIR/packages/capix-code" ]; then
30
+ echo "✓ Pinned Capix Code source already prepared: $ACTUAL_REF"
31
+ exit 0
32
+ fi
33
+
34
+ git -C "$CAPIX_CODE_DIR" diff --quiet || {
35
+ echo "✗ Source tree has unstaged changes before Capix preparation"
36
+ exit 1
37
+ }
38
+ echo "✓ Pinned source ready: $ACTUAL_REF"
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Build (materialize) manifest/release-manifest.json from real per-platform
3
+ * release entries produced by write-release-entry.mjs.
4
+ *
5
+ * A publishable manifest is assembled ONLY from real artifact metadata — it
6
+ * never copies through TEMPLATE placeholders. If a required platform entry is
7
+ * missing or carries invalid metadata, the build fails closed.
8
+ *
9
+ * Usage:
10
+ * node scripts/build-manifest.mjs \
11
+ * --entries release-artifacts \
12
+ * --base-url https://github.com/CapIX-Protocol/Capix-Code/releases/download \
13
+ * --stable-version v1.2.4 \
14
+ * --source-sha <40-hex> \
15
+ * --launcher-version 1.2.4 --opencode-version 1.17.18 \
16
+ * --plugin-version 1.2.4 --provider-version 1.2.4 \
17
+ * [--out manifest/release-manifest.json] [--require-all]
18
+ *
19
+ * The stable version is the single source of truth consumed by the installer's
20
+ * `latest` resolver and by validate-manifest.
21
+ */
22
+ import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
23
+ import { basename, join, resolve } from 'node:path';
24
+ import { pathToFileURL } from 'node:url';
25
+
26
+ const REQUIRED_PLATFORMS = ['darwin-arm64', 'darwin-x64', 'linux-arm64', 'linux-x64', 'win32-x64'];
27
+ const SEMVER_TAG = /^v\d+\.\d+\.\d+$/;
28
+ const SHA1 = /^[0-9a-f]{40}$/;
29
+ const SHA256 = /^[0-9a-f]{64}$/;
30
+ const SEMVER = /^\d+\.\d+\.\d+$/;
31
+
32
+ function parseArgs(argv) {
33
+ const args = {
34
+ entries: 'release-artifacts',
35
+ out: 'manifest/release-manifest.json',
36
+ requireAll: false,
37
+ };
38
+ for (let i = 0; i < argv.length; i++) {
39
+ const a = argv[i];
40
+ switch (a) {
41
+ case '--entries':
42
+ args.entries = argv[++i];
43
+ break;
44
+ case '--base-url':
45
+ args.baseUrl = argv[++i];
46
+ break;
47
+ case '--stable-version':
48
+ args.stableVersion = argv[++i];
49
+ break;
50
+ case '--source-sha':
51
+ args.sourceSha = argv[++i];
52
+ break;
53
+ case '--launcher-version':
54
+ args.launcherVersion = argv[++i];
55
+ break;
56
+ case '--opencode-version':
57
+ args.opencodeVersion = argv[++i];
58
+ break;
59
+ case '--plugin-version':
60
+ args.pluginVersion = argv[++i];
61
+ break;
62
+ case '--provider-version':
63
+ args.providerVersion = argv[++i];
64
+ break;
65
+ case '--out':
66
+ args.out = argv[++i];
67
+ break;
68
+ case '--require-all':
69
+ args.requireAll = true;
70
+ break;
71
+ default:
72
+ throw new Error(`unknown argument: ${a}`);
73
+ }
74
+ }
75
+ return args;
76
+ }
77
+
78
+ function requireArg(args, name) {
79
+ const v = args[name];
80
+ if (!v)
81
+ throw new Error(
82
+ `${name} is required (pass --${name.replace(/([A-Z])/g, '-$1').toLowerCase()})`
83
+ );
84
+ return v;
85
+ }
86
+
87
+ /** Read every capix-code-*-{platform}-{arch}.release.json in the entries dir. */
88
+ export function readReleaseEntries(entriesDir) {
89
+ const files = readdirSync(entriesDir).filter((f) => /\.release\.json$/i.test(f));
90
+ const entries = new Map();
91
+ for (const f of files) {
92
+ let parsed;
93
+ try {
94
+ parsed = JSON.parse(readFileSync(join(entriesDir, f), 'utf8'));
95
+ } catch (err) {
96
+ throw new Error(`cannot parse ${f}: ${err.message}`);
97
+ }
98
+ if (parsed.product !== 'capix-code') throw new Error(`${f}: product is not capix-code`);
99
+ const platform = parsed.platform;
100
+ if (!platform || !REQUIRED_PLATFORMS.includes(platform)) {
101
+ throw new Error(`${f}: unrecognized platform "${platform}"`);
102
+ }
103
+ if (entries.has(platform))
104
+ throw new Error(`duplicate release entry for platform ${platform} (${f})`);
105
+ entries.set(platform, parsed);
106
+ }
107
+ return entries;
108
+ }
109
+
110
+ /**
111
+ * Build the manifest object from a map of platform -> release entry.
112
+ * Pure function — testable without touching the filesystem.
113
+ */
114
+ export function buildManifestFromEntries(entries, opts) {
115
+ const {
116
+ baseUrl,
117
+ stableVersion,
118
+ sourceSha,
119
+ launcherVersion,
120
+ opencodeVersion,
121
+ pluginVersion,
122
+ providerVersion,
123
+ } = opts;
124
+ const errors = [];
125
+ if (!SEMVER_TAG.test(stableVersion ?? ''))
126
+ errors.push('--stable-version must be vMAJOR.MINOR.PATCH');
127
+ if (!SHA1.test(sourceSha ?? ''))
128
+ errors.push('--source-sha must be a 40-character lowercase hex commit SHA');
129
+ for (const [name, v] of [
130
+ ['launcher', launcherVersion],
131
+ ['opencode', opencodeVersion],
132
+ ['plugin', pluginVersion],
133
+ ['provider', providerVersion],
134
+ ]) {
135
+ if (!SEMVER.test(v ?? '')) errors.push(`--${name}-version must be MAJOR.MINOR.PATCH`);
136
+ }
137
+ if (!baseUrl || !/^https:\/\//.test(baseUrl)) errors.push('--base-url must be an https URL');
138
+
139
+ const present = [...entries.keys()];
140
+ if (opts.requireAll) {
141
+ for (const p of REQUIRED_PLATFORMS)
142
+ if (!entries.has(p)) errors.push(`missing required platform entry: ${p}`);
143
+ }
144
+ if (errors.length) throw new Error(errors.join('; '));
145
+
146
+ const platforms = {};
147
+ for (const p of REQUIRED_PLATFORMS) {
148
+ const e = entries.get(p);
149
+ if (!e) continue; // when not --require-all, only publish what exists
150
+ if (!SHA256.test(e.sha256 ?? ''))
151
+ throw new Error(`${p}: release entry sha256 is not a valid 64-hex digest`);
152
+ if (typeof e.sizeBytes !== 'number' || e.sizeBytes <= 0)
153
+ throw new Error(`${p}: release entry sizeBytes must be positive`);
154
+ const tag = stableVersion;
155
+ platforms[p] = {
156
+ url: `${baseUrl}/${tag}/${e.artifact}`,
157
+ sha256: e.sha256,
158
+ // Unsigned artifacts ship a null signatureUrl; strict signing is a
159
+ // separate, later gate. Never TEMPLATE.
160
+ signatureUrl: e.signed ? `${baseUrl}/${tag}/${e.artifact}.sig` : null,
161
+ sizeBytes: e.sizeBytes,
162
+ };
163
+ }
164
+
165
+ const createdAt = process.env.SOURCE_DATE_EPOCH
166
+ ? new Date(Number(process.env.SOURCE_DATE_EPOCH) * 1000).toISOString()
167
+ : new Date().toISOString();
168
+
169
+ return {
170
+ id: `rel_capix_code_${stableVersion.slice(1).replace(/\./g, '_')}`,
171
+ schemaVersion: 1,
172
+ stableVersion,
173
+ createdAt,
174
+ createdBy: 'release-engineering',
175
+ immutable: true,
176
+ launcher: { sourceSha, version: launcherVersion },
177
+ opencode: { sourceSha, version: opencodeVersion },
178
+ plugin: { sourceSha, version: pluginVersion },
179
+ provider: { sourceSha, version: providerVersion },
180
+ acpVersion: '1',
181
+ ipcVersion: '1',
182
+ apiRange: { min: 'v1', max: 'v1' },
183
+ platforms,
184
+ sbomRef: `${baseUrl}/${stableVersion}/sbom.spdx.json`,
185
+ provenanceRef: `${baseUrl}/${stableVersion}/provenance.json`,
186
+ signatureRef: null,
187
+ thirdPartyNoticesRef: `${baseUrl}/${stableVersion}/NOTICE`,
188
+ rollbackConstraints: ['retain-n-1'],
189
+ publishedPlatforms: present,
190
+ };
191
+ }
192
+
193
+ function main() {
194
+ const args = parseArgs(process.argv.slice(2));
195
+ const entries = readReleaseEntries(args.entries);
196
+ const manifest = buildManifestFromEntries(entries, {
197
+ baseUrl: requireArg(args, 'baseUrl'),
198
+ stableVersion: requireArg(args, 'stableVersion'),
199
+ sourceSha: requireArg(args, 'sourceSha'),
200
+ launcherVersion: requireArg(args, 'launcherVersion'),
201
+ opencodeVersion: requireArg(args, 'opencodeVersion'),
202
+ pluginVersion: requireArg(args, 'pluginVersion'),
203
+ providerVersion: requireArg(args, 'providerVersion'),
204
+ requireAll: args.requireAll,
205
+ });
206
+ writeFileSync(args.out, `${JSON.stringify(manifest, null, 2)}\n`);
207
+ console.log(
208
+ `✓ wrote ${args.out} (stable=${manifest.stableVersion}, platforms=${Object.keys(manifest.platforms).join(',')})`
209
+ );
210
+ }
211
+
212
+ if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
213
+ try {
214
+ main();
215
+ } catch (err) {
216
+ console.error(`✗ ${err.message}`);
217
+ process.exit(1);
218
+ }
219
+ }
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env bash
2
+ # build.sh — produce packaged capix-code binaries.
3
+ set -euo pipefail
4
+
5
+ DIR="$(cd "$(dirname "$0")/.." && pwd)"
6
+ CAPIX_CODE_DIR="${CAPIX_CODE_DIR:-$DIR/upstream}"
7
+ BUN="${BUN_BIN:-$(command -v bun || true)}"
8
+ if [ -z "$BUN" ] && [ -x "$DIR/node_modules/.bin/bun" ]; then BUN="$DIR/node_modules/.bin/bun"; fi
9
+ [ -n "$BUN" ] || { echo "✗ Bun 1.3.14 is required"; exit 1; }
10
+ [ "$($BUN --version)" = "1.3.14" ] || { echo "✗ Expected Bun 1.3.14"; exit 1; }
11
+
12
+ if [ ! -d "$CAPIX_CODE_DIR" ]; then
13
+ echo "✗ No $CAPIX_CODE_DIR. Run ./scripts/bootstrap.sh first."
14
+ exit 1
15
+ fi
16
+
17
+ cd "$CAPIX_CODE_DIR"
18
+
19
+ echo "▸ Building capix-code standalone binary…"
20
+ "$BUN" install
21
+
22
+ # The embedded engine otherwise falls back to a timestamped 0.0.0 development
23
+ # identifier. Stamp it with the immutable Capix Code package version so the TUI,
24
+ # API metadata and diagnostics all report the customer release.
25
+ CAPIX_RELEASE_VERSION="${CAPIX_CODE_VERSION:-$(node -p 'require(process.argv[1]).version' "$DIR/package.json")}"
26
+ export OPENCODE_VERSION="$CAPIX_RELEASE_VERSION"
27
+
28
+ # Write default config if the init script exists.
29
+ if [ -f "packages/capix-code/scripts/init-capix-config.ts" ]; then
30
+ "$BUN" run packages/capix-code/scripts/init-capix-config.ts 2>/dev/null || true
31
+ fi
32
+
33
+ # Build using the upstream build script.
34
+ if [ -f "packages/capix-code/script/build.ts" ]; then
35
+ "$BUN" run --cwd packages/capix-code script/build.ts --single
36
+ fi
37
+
38
+ # Find the output — handle both renamed and original patterns.
39
+ EXE_SUFFIX=""
40
+ case "$(uname -s)" in MINGW*|MSYS*|CYGWIN*) EXE_SUFFIX=".exe";; esac
41
+ OUTPUT=$(find packages/capix-code/dist -name "capix-code$EXE_SUFFIX" -type f 2>/dev/null | head -1)
42
+ if [ -z "$OUTPUT" ]; then
43
+ OUTPUT=$(find packages/capix-code/dist -name "opencode$EXE_SUFFIX" -type f 2>/dev/null | head -1)
44
+ if [ -n "$OUTPUT" ]; then
45
+ NEW_OUTPUT="$(dirname "$OUTPUT")/capix-code$EXE_SUFFIX"
46
+ mv "$OUTPUT" "$NEW_OUTPUT"
47
+ OUTPUT="$NEW_OUTPUT"
48
+ fi
49
+ fi
50
+
51
+ if [ -n "$OUTPUT" ]; then
52
+ ARTIFACT="$DIR/dist/customer"
53
+ rm -rf "$ARTIFACT"
54
+ mkdir -p "$ARTIFACT/bin" "$ARTIFACT/engine" "$ARTIFACT/runtime/packages" "$ARTIFACT/config"
55
+ cp "$OUTPUT" "$ARTIFACT/engine/capix-engine$EXE_SUFFIX"
56
+ cp -R "$DIR/src" "$ARTIFACT/runtime/src"
57
+ cp -R "$DIR/packages/runtime-provider" "$ARTIFACT/runtime/packages/runtime-provider"
58
+ cp "$DIR/config/runtime-package.json" "$ARTIFACT/runtime/package.json"
59
+ cp "$DIR/config/capix-defaults.json" "$DIR/config/defaults.json" "$ARTIFACT/config/"
60
+ cp -R "$DIR/commands" "$ARTIFACT/commands"
61
+ chmod 0755 "$ARTIFACT/engine/capix-engine$EXE_SUFFIX"
62
+ # Install from the dedicated runtime manifest. The outer npm package has
63
+ # platform selectors which do not belong inside the embedded runtime.
64
+ (cd "$ARTIFACT/runtime" && npm install --omit=dev --ignore-scripts)
65
+ (cd "$DIR/launcher" && cargo build --locked --release)
66
+ cp "$DIR/launcher/target/release/capix-code$EXE_SUFFIX" "$ARTIFACT/bin/capix-code$EXE_SUFFIX"
67
+ chmod 0755 "$ARTIFACT/bin/capix-code$EXE_SUFFIX"
68
+ "$DIR/scripts/assert-artifact.sh" "$ARTIFACT"
69
+ "$DIR/scripts/assert-customer-brand.sh" "$ARTIFACT"
70
+ echo "✓ Customer artifact staged: $ARTIFACT"
71
+ else
72
+ echo "✗ No binary found in dist/ — build may have failed."
73
+ exit 1
74
+ fi
@@ -0,0 +1,8 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ DIST_DIR="${1:-dist}"
4
+ for f in "$DIST_DIR"/*.tar.gz "$DIST_DIR"/*.zip; do
5
+ [ -f "$f" ] || continue
6
+ shasum -a 256 "$f" > "$f.sha256"
7
+ echo " $(basename $f): $(cat "$f.sha256" | awk '{print $1}')"
8
+ done
@@ -0,0 +1,30 @@
1
+ #!/bin/bash
2
+ # Local development installation of Capix Code
3
+ # This is NOT a production installer — for development only
4
+ set -euo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+ SOURCE_DIR="$(dirname "$SCRIPT_DIR")"
8
+
9
+ echo "=== Capix Code Development Install ==="
10
+ echo "Path: $SOURCE_DIR"
11
+ echo ""
12
+
13
+ # Install dependencies
14
+ cd "$SOURCE_DIR"
15
+ if [ ! -d "node_modules" ]; then
16
+ echo "Installing dependencies..."
17
+ npm install
18
+ fi
19
+
20
+ # Type check
21
+ echo "Running type check..."
22
+ npx tsc --noEmit
23
+
24
+ # Run tests
25
+ echo "Running tests..."
26
+ npx vitest run
27
+
28
+ echo ""
29
+ echo "✅ Development environment ready."
30
+ echo "Run: npx tsx src/plugin.ts # to start the Capix Code agent"
package/scripts/dev.sh ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # dev.sh — launch capix-code in dev mode.
4
+ #
5
+ # Requires the repository-pinned Bun 1.3.14 runtime.
6
+ set -euo pipefail
7
+
8
+ DIR="$(cd "$(dirname "$0")/.." && pwd)"
9
+ CAPIX_CODE_DIR="${CAPIX_CODE_DIR:-$DIR/upstream}"
10
+ BUN="${BUN_BIN:-$(command -v bun || true)}"
11
+ if [ -z "$BUN" ] && [ -x "$DIR/node_modules/.bin/bun" ]; then BUN="$DIR/node_modules/.bin/bun"; fi
12
+ [ -n "$BUN" ] || { echo "✗ Bun 1.3.14 is required; install the pinned runtime first"; exit 1; }
13
+ [ "$($BUN --version)" = "1.3.14" ] || { echo "✗ Expected Bun 1.3.14"; exit 1; }
14
+
15
+ if [ ! -d "$CAPIX_CODE_DIR" ]; then
16
+ echo "✗ No $CAPIX_CODE_DIR. Run ./scripts/bootstrap.sh first."
17
+ exit 1
18
+ fi
19
+
20
+ cd "$CAPIX_CODE_DIR"
21
+
22
+ echo "▸ Installing dependencies (Bun)…"
23
+ "$BUN" install
24
+
25
+ echo "▸ Writing default Capix config (if missing)…"
26
+ "$BUN" run packages/capix-code/scripts/init-capix-config.ts 2>/dev/null || true
27
+
28
+ echo "▸ Launching capix-code (dev mode)…"
29
+ echo ""
30
+ echo " Set your Capix env vars before starting:"
31
+ echo " export CAPIX_BASE_URL=https://capix.network/api/v1"
32
+ echo " export CAPIX_API_KEY=cpk_... (or your deployed cpxllm_... key)"
33
+ echo " export CAPIX_MODEL=capix/auto (optional — defaults to auto)"
34
+ echo ""
35
+ "$BUN" run --cwd packages/capix-code --conditions=browser src/index.ts "$@"