subconscious-cli 6.1.0 → 6.2.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/README.md +52 -47
- package/bin/agent-data.js +37 -1
- package/bin/agent-help.js +12 -4
- package/bin/agent-install.js +19 -135
- package/bin/agents.js +6 -5
- package/bin/cli.js +2 -1
- package/bin/models.js +12 -0
- package/bin/native/subc-tui-darwin-amd64 +0 -0
- package/bin/native/subc-tui-darwin-arm64 +0 -0
- package/bin/native/subc-tui-linux-amd64 +0 -0
- package/bin/native/subc-tui-linux-arm64 +0 -0
- package/bin/native/subc-tui-windows-amd64.exe +0 -0
- package/bin/native/subc-tui-windows-arm64.exe +0 -0
- package/bin/runbook/README.md +13 -2
- package/bin/runbook/claude-code/agent.json +6 -6
- package/bin/runbook/codex/agent.json +1 -0
- package/bin/runbook/copilot/agent.json +1 -0
- package/bin/runbook/cursor/agent.json +3 -2
- package/bin/runbook/deepseek-harness/agent.json +1 -0
- package/bin/runbook/opencode/agent.json +1 -0
- package/bin/runbook/pi/agent.json +1 -0
- package/bin/runbook/shared.json +1 -2
- package/bin/sessions.js +1 -26
- package/bin/update-check.js +30 -0
- package/bin/upgrade.js +3 -3
- package/bin/windows/agents.js +14 -47
- package/bin/windows/launch.js +1 -1
- package/package.json +2 -3
- package/bin/runbook/subconscious-code/agent.json +0 -156
- package/bin/runbook/subconscious-code/install.sh +0 -154
- package/bin/windows/install.js +0 -182
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
"command": "cursor",
|
|
4
4
|
"aliases": [],
|
|
5
5
|
"name": "Cursor",
|
|
6
|
-
"description": "Install Cursor conversation and compaction hooks, then finish model setup in Cursor Settings.",
|
|
6
|
+
"description": "Install Cursor conversation and compaction hooks in the Cursor desktop app and IDE, then finish model setup in Cursor Settings. The Cursor CLI is not supported.",
|
|
7
7
|
"protocol": "openai",
|
|
8
8
|
"homepage": "https://cursor.com",
|
|
9
9
|
"install": {
|
|
10
10
|
"commands": null,
|
|
11
|
+
"url": "https://cursor.com/download",
|
|
11
12
|
"method": "user",
|
|
12
13
|
"package": null,
|
|
13
14
|
"version": null,
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
},
|
|
23
24
|
"help": {
|
|
24
25
|
"usage": "subc [-p NAME] cursor [help|install|status|uninstall]",
|
|
25
|
-
"behavior": "Manages Cursor correlation hooks; model endpoint setup is completed in Cursor Settings.",
|
|
26
|
+
"behavior": "Manages Cursor correlation hooks in the Cursor desktop app and IDE; model endpoint setup is completed in Cursor Settings. The Cursor CLI is not supported.",
|
|
26
27
|
"options": [
|
|
27
28
|
["help", "Show this help"],
|
|
28
29
|
["install", "Install or update the Cursor hooks (default action)"],
|
package/bin/runbook/shared.json
CHANGED
package/bin/sessions.js
CHANGED
|
@@ -231,14 +231,6 @@ function piMessages(records) {
|
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
function scMessages(records) {
|
|
235
|
-
return records.flatMap((record) => {
|
|
236
|
-
if (!['user', 'assistant'].includes(record.type)) return [];
|
|
237
|
-
const text = cleanText(record.text ?? record.content);
|
|
238
|
-
return text ? [{ role: record.type, text }] : [];
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
|
|
242
234
|
async function parseFileSession(entry, harness) {
|
|
243
235
|
const records = parseLines(await readBounded(entry.file, MAX_METADATA_BYTES));
|
|
244
236
|
if (!records.length) return null;
|
|
@@ -304,19 +296,6 @@ async function parseFileSession(entry, harness) {
|
|
|
304
296
|
});
|
|
305
297
|
}
|
|
306
298
|
|
|
307
|
-
if (harness === 'sc') {
|
|
308
|
-
const meta = records[0] || {};
|
|
309
|
-
const messages = scMessages(records);
|
|
310
|
-
const id = String(meta.id || filename).replace(/^session-/, '');
|
|
311
|
-
return sessionRecord(harness, id, {
|
|
312
|
-
title: messages.find((message) => message.role === 'user')?.text,
|
|
313
|
-
cwd: meta.cwd,
|
|
314
|
-
model: meta.model,
|
|
315
|
-
updated: entry.updated,
|
|
316
|
-
sourcePath: entry.file,
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
|
|
320
299
|
return null;
|
|
321
300
|
}
|
|
322
301
|
|
|
@@ -480,7 +459,6 @@ export async function discoverSessions(options = {}) {
|
|
|
480
459
|
claude: path.join(home, '.claude', 'projects'),
|
|
481
460
|
codex: path.join(home, '.codex', 'sessions'),
|
|
482
461
|
pi: path.join(home, '.pi', 'agent', 'sessions'),
|
|
483
|
-
sc: path.join(home, '.sc', 'sessions'),
|
|
484
462
|
};
|
|
485
463
|
const indexes =
|
|
486
464
|
options.indexes ||
|
|
@@ -500,7 +478,6 @@ export async function discoverSessions(options = {}) {
|
|
|
500
478
|
codex || discoverFileSessions(roots.codex, 'codex', max),
|
|
501
479
|
Promise.resolve(discoverOpenCodeSessions(execute, max)),
|
|
502
480
|
discoverFileSessions(roots.pi, 'pi', max),
|
|
503
|
-
discoverFileSessions(roots.sc, 'sc', max),
|
|
504
481
|
]);
|
|
505
482
|
const seen = new Set();
|
|
506
483
|
return groups
|
|
@@ -555,7 +532,6 @@ export async function readSessionMessages(session, options = {}) {
|
|
|
555
532
|
if (session.harness === 'claude') return claudeMessages(records);
|
|
556
533
|
if (session.harness === 'codex') return codexMessages(records);
|
|
557
534
|
if (session.harness === 'pi') return piMessages(records);
|
|
558
|
-
if (session.harness === 'sc') return scMessages(records);
|
|
559
535
|
return [];
|
|
560
536
|
}
|
|
561
537
|
|
|
@@ -695,8 +671,7 @@ export async function sessionsCommand(argv, options = {}) {
|
|
|
695
671
|
const harnessIndex = argv.indexOf('--harness');
|
|
696
672
|
const requestedHarness =
|
|
697
673
|
harnessIndex >= 0 ? argv[harnessIndex + 1] : session.harness;
|
|
698
|
-
const targetHarness =
|
|
699
|
-
requestedHarness === 'marathon' ? 'sc' : requestedHarness;
|
|
674
|
+
const targetHarness = requestedHarness;
|
|
700
675
|
const target = SESSION_HARNESSES[targetHarness];
|
|
701
676
|
if (!target) throw new Error(`Unknown destination harness: ${targetHarness}`);
|
|
702
677
|
|
package/bin/update-check.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
2
3
|
import fs from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
3
5
|
import readline from 'node:readline';
|
|
4
6
|
import { fileURLToPath } from 'node:url';
|
|
5
7
|
import { LOGO_ART_SMALL_LINES } from './branding.js';
|
|
@@ -8,6 +10,9 @@ import { spawnWindows } from './windows/process.js';
|
|
|
8
10
|
|
|
9
11
|
export const PACKAGE_NAME = 'subconscious-cli';
|
|
10
12
|
export const UPDATE_CHECK_TIMEOUT_MS = 1500;
|
|
13
|
+
export const INSTALL_SCRIPT_URL =
|
|
14
|
+
'https://raw.githubusercontent.com/subconscious-systems/subconscious/main/scripts/install.sh';
|
|
15
|
+
|
|
11
16
|
const UPDATE_ACTIONS = ['Update now', 'Skip for now'];
|
|
12
17
|
const UPDATE_LOGO = LOGO_ART_SMALL_LINES;
|
|
13
18
|
|
|
@@ -18,10 +23,35 @@ function shellQuote(value) {
|
|
|
18
23
|
: `'${text.replaceAll("'", `'"'"'`)}'`;
|
|
19
24
|
}
|
|
20
25
|
|
|
26
|
+
/** The record scripts/install.sh leaves in the package it installed. */
|
|
27
|
+
function readCurlInstall(packageDir) {
|
|
28
|
+
try {
|
|
29
|
+
const record = JSON.parse(
|
|
30
|
+
readFileSync(path.join(packageDir, '.subc-install.json'), 'utf-8'),
|
|
31
|
+
);
|
|
32
|
+
return record?.method === 'curl' && typeof record.bin_dir === 'string'
|
|
33
|
+
? record
|
|
34
|
+
: null;
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
21
40
|
export function detectInstallTarget(
|
|
22
41
|
here = fileURLToPath(import.meta.url),
|
|
23
42
|
platform = process.platform,
|
|
24
43
|
) {
|
|
44
|
+
const packageDir = path.resolve(path.dirname(here), '..');
|
|
45
|
+
const curl = platform !== 'win32' && readCurlInstall(packageDir);
|
|
46
|
+
if (curl) {
|
|
47
|
+
// Rerun the installer into the same directories it used before.
|
|
48
|
+
const display = `curl -fsSL ${INSTALL_SCRIPT_URL} | SUBC_INSTALL_DIR=${shellQuote(packageDir)} SUBC_BIN_DIR=${shellQuote(curl.bin_dir)} bash`;
|
|
49
|
+
return {
|
|
50
|
+
command: 'bash',
|
|
51
|
+
args: ['-c', `set -o pipefail; ${display}`],
|
|
52
|
+
display,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
25
55
|
const normalized = here.replace(/\\/g, '/');
|
|
26
56
|
if (normalized.includes('/.pnpm/') || normalized.includes('/pnpm/global/')) {
|
|
27
57
|
return {
|
package/bin/upgrade.js
CHANGED
|
@@ -85,16 +85,16 @@ function askYesNo(question) {
|
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
function runInstall(
|
|
88
|
+
function runInstall() {
|
|
89
|
+
const target = detectInstallTarget();
|
|
89
90
|
if (process.platform === 'win32') {
|
|
90
|
-
const target = detectInstallTarget();
|
|
91
91
|
return runWindows(target.command, target.args).then(
|
|
92
92
|
(code) => code === 0,
|
|
93
93
|
() => false,
|
|
94
94
|
);
|
|
95
95
|
}
|
|
96
96
|
return new Promise((resolve) => {
|
|
97
|
-
const child = spawn(command, {
|
|
97
|
+
const child = spawn(target.command, target.args, { stdio: 'inherit' });
|
|
98
98
|
child.on('error', () => resolve(false));
|
|
99
99
|
child.on('exit', (code) => resolve(code === 0));
|
|
100
100
|
});
|
package/bin/windows/agents.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
agentBinary,
|
|
5
|
+
agentCommandName,
|
|
6
|
+
agentInstallDirs,
|
|
7
|
+
installAdvice,
|
|
8
|
+
} from '../agent-data.js';
|
|
5
9
|
import { separatorIndex } from '../headless-args.js';
|
|
6
10
|
import { parseOptions } from './common.js';
|
|
7
|
-
import { installWindowsAgent, windowsInstallSpec } from './install.js';
|
|
8
11
|
import { executeWindowsLaunch, windowsLaunch } from './launch.js';
|
|
9
12
|
import {
|
|
10
13
|
readWindowsVersion,
|
|
@@ -16,21 +19,6 @@ import {
|
|
|
16
19
|
} from './process.js';
|
|
17
20
|
import { windowsSetup } from './setup.js';
|
|
18
21
|
|
|
19
|
-
const askInstall = (name) =>
|
|
20
|
-
new Promise((resolve) => {
|
|
21
|
-
const rl = readline.createInterface({
|
|
22
|
-
input: process.stdin,
|
|
23
|
-
output: process.stdout,
|
|
24
|
-
});
|
|
25
|
-
rl.question(
|
|
26
|
-
` ${name} isn't installed. Install it now? [Y/n] `,
|
|
27
|
-
(answer) => {
|
|
28
|
-
rl.close();
|
|
29
|
-
resolve(['', 'y', 'yes'].includes(answer.trim().toLowerCase()));
|
|
30
|
-
},
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
22
|
export async function runWindowsAgent(agent, argv, dependencies) {
|
|
35
23
|
const {
|
|
36
24
|
profile,
|
|
@@ -54,10 +42,6 @@ export async function runWindowsAgent(agent, argv, dependencies) {
|
|
|
54
42
|
...(environment.PATH || '').split(';'),
|
|
55
43
|
...windowsBinDirs(environment),
|
|
56
44
|
]);
|
|
57
|
-
if (agent.id === 'subconscious-code' && parsed.action === 'install') {
|
|
58
|
-
if (args.length) throw new Error('Usage: subc marathon install');
|
|
59
|
-
return finish(await installWindowsAgent(agent.id, environment));
|
|
60
|
-
}
|
|
61
45
|
if (['status', 'uninstall'].includes(parsed.action)) {
|
|
62
46
|
return finish(
|
|
63
47
|
await windowsSetup(agent.id, parsed.action, args, environment),
|
|
@@ -110,31 +94,14 @@ export async function runWindowsAgent(agent, argv, dependencies) {
|
|
|
110
94
|
preferredDirs,
|
|
111
95
|
});
|
|
112
96
|
if (!executable) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)
|
|
121
|
-
console.error(
|
|
122
|
-
`${agent.name} isn't installed. ${installer ? `Install it with: ${installer.display}` : 'Install it separately, then rerun subc.'}`,
|
|
123
|
-
);
|
|
124
|
-
return finish(127);
|
|
125
|
-
}
|
|
126
|
-
const installed = await installWindowsAgent(agent.id, environment);
|
|
127
|
-
if (installed) return finish(installed);
|
|
128
|
-
executable = resolveWindowsExecutable(bin, {
|
|
129
|
-
env: environment,
|
|
130
|
-
preferredDirs,
|
|
131
|
-
});
|
|
132
|
-
if (!executable) {
|
|
133
|
-
console.error(
|
|
134
|
-
`Installed ${agent.name}, but ${bin} was not found. Add its installation directory to PATH or restart your terminal.`,
|
|
135
|
-
);
|
|
136
|
-
return finish(127);
|
|
137
|
-
}
|
|
97
|
+
// subc never installs a third-party agent; it only says how.
|
|
98
|
+
const { command, url } = installAdvice(agent, 'win32');
|
|
99
|
+
console.error(
|
|
100
|
+
`${agent.name} isn't installed. subc doesn't install it. Install it yourself, then rerun subc ${agentCommandName(agent)}.`,
|
|
101
|
+
);
|
|
102
|
+
if (command) console.error(` Install it with: ${command}`);
|
|
103
|
+
console.error(` Official install page: ${url}`);
|
|
104
|
+
return finish(127);
|
|
138
105
|
}
|
|
139
106
|
if (agent.id === 'claude-code') {
|
|
140
107
|
const version = dependencies.parseClaudeVersion(
|
package/bin/windows/launch.js
CHANGED
|
@@ -14,7 +14,7 @@ import { modelIds, positiveInteger } from '../launch-values.js';
|
|
|
14
14
|
import { modelSupportsVision } from '../model-capabilities.js';
|
|
15
15
|
import { defaults, origin, value, writeJson } from './common.js';
|
|
16
16
|
|
|
17
|
-
const PLANNED = new Set(['claude-code', '
|
|
17
|
+
const PLANNED = new Set(['claude-code', 'pi', 'opencode']);
|
|
18
18
|
|
|
19
19
|
// Windows trims a configured gateway to its origin and gives every agent but
|
|
20
20
|
// Claude the gateway and key as SUBCONSCIOUS_*. Claude has always been given
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "subconscious-cli",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "CLI for Subconscious — run Subconscious Code, Claude Code, Codex, OpenCode, DeepSeek Harness, Cursor, Copilot, and Pi",
|
|
5
5
|
"bin": {
|
|
6
6
|
"subc": "bin/cli.js"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"build:tui": "node scripts/build-tui.js",
|
|
10
10
|
"build:tui:host": "node scripts/build-tui.js --host",
|
|
11
11
|
"test": "node --test",
|
|
12
|
-
"test:windows": "node --test test/windows.test.js test/models.test.js test/model-capabilities.test.js test/auth.test.js test/tui.test.js test/update-check.test.js test/sessions.test.js test/branding.test.js test/claude-version.test.js test/usage.test.js test/feedback.test.js test/release.test.js test/github-govuln-issue.test.js test/harness-manifest.test.js test/agent-files.test.js test/agent-launch.test.js",
|
|
12
|
+
"test:windows": "node --test test/windows.test.js test/models.test.js test/model-capabilities.test.js test/auth.test.js test/tui.test.js test/update-check.test.js test/sessions.test.js test/branding.test.js test/claude-version.test.js test/usage.test.js test/feedback.test.js test/release.test.js test/github-govuln-issue.test.js test/harness-manifest.test.js test/agent-files.test.js test/agent-launch.test.js test/agent-install-policy.test.js",
|
|
13
13
|
"test:tui": "go -C tui test ./...",
|
|
14
14
|
"lint": "biome ci .",
|
|
15
15
|
"format": "biome check --write .",
|
|
@@ -37,7 +37,6 @@
|
|
|
37
37
|
"authentication",
|
|
38
38
|
"profiles",
|
|
39
39
|
"coding-agent",
|
|
40
|
-
"subconscious-code",
|
|
41
40
|
"claude-code",
|
|
42
41
|
"opencode",
|
|
43
42
|
"codex",
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "subconscious-code",
|
|
3
|
-
"command": "marathon",
|
|
4
|
-
"aliases": ["sc", "subconscious-code"],
|
|
5
|
-
"name": "Marathon",
|
|
6
|
-
"description": "Launch the native Subconscious coding agent with the active profile, gateway, and model.",
|
|
7
|
-
"protocol": "openai",
|
|
8
|
-
"homepage": "https://github.com/subconscious-systems/subconscious-code",
|
|
9
|
-
"install": {
|
|
10
|
-
"commands": {
|
|
11
|
-
"darwin": "subc marathon install",
|
|
12
|
-
"linux": "subc marathon install",
|
|
13
|
-
"win32": "subc marathon install"
|
|
14
|
-
},
|
|
15
|
-
"method": "github-release",
|
|
16
|
-
"repository": "subconscious-systems/subconscious-code",
|
|
17
|
-
"version": "latest",
|
|
18
|
-
"pin_env": "SC_CODE_VERSION",
|
|
19
|
-
"asset": "marathon-{target}.tar.gz",
|
|
20
|
-
"checksum": "marathon-{target}.tar.gz.sha256",
|
|
21
|
-
"legacy_asset": "sc-{target}.tar.gz",
|
|
22
|
-
"targets": [
|
|
23
|
-
"aarch64-apple-darwin",
|
|
24
|
-
"x86_64-apple-darwin",
|
|
25
|
-
"aarch64-unknown-linux-musl",
|
|
26
|
-
"x86_64-unknown-linux-musl"
|
|
27
|
-
],
|
|
28
|
-
"install_dir": "~/.local/bin",
|
|
29
|
-
"install_dir_env": "SC_INSTALL_DIR",
|
|
30
|
-
"minimum_version": null,
|
|
31
|
-
"verified": true,
|
|
32
|
-
"windows_targets": ["x86_64-pc-windows-msvc", "aarch64-pc-windows-msvc"],
|
|
33
|
-
"windows_assets": [
|
|
34
|
-
"marathon-{target}.zip",
|
|
35
|
-
"marathon-{target}.exe",
|
|
36
|
-
"sc-{target}.zip",
|
|
37
|
-
"sc-{target}.exe"
|
|
38
|
-
],
|
|
39
|
-
"note": "Windows installs come from the native launcher, which takes the first asset in windows_assets that the release has, plus its .sha256."
|
|
40
|
-
},
|
|
41
|
-
"runbook": {
|
|
42
|
-
"mode": "launch",
|
|
43
|
-
"setup_script": "install.sh",
|
|
44
|
-
"setup_actions": ["install"],
|
|
45
|
-
"setup_needs_auth": false,
|
|
46
|
-
"binary_install_script": "install.sh"
|
|
47
|
-
},
|
|
48
|
-
"help": {
|
|
49
|
-
"usage": "subc [-p NAME] marathon [help|install] [Marathon arguments...]",
|
|
50
|
-
"behavior": "Launches the native Subconscious coding agent with the selected profile gateway, credential, and model.",
|
|
51
|
-
"options": [
|
|
52
|
-
["help", "Show this help"],
|
|
53
|
-
[
|
|
54
|
-
"install",
|
|
55
|
-
{
|
|
56
|
-
"win32": "Install a verified Windows release, when published upstream",
|
|
57
|
-
"default": "Install the latest precompiled Linux or macOS release"
|
|
58
|
-
}
|
|
59
|
-
],
|
|
60
|
-
["--model MODEL", "Override the profile model for this launch"]
|
|
61
|
-
],
|
|
62
|
-
"args": ["ARGS...", "Pass arguments directly to Marathon"]
|
|
63
|
-
},
|
|
64
|
-
"sessions": { "key": "sc", "portable": false },
|
|
65
|
-
"prerequisites": [
|
|
66
|
-
{ "command": "gh|curl", "needed_for": "install", "required": true },
|
|
67
|
-
{
|
|
68
|
-
"command": "sha256sum|shasum",
|
|
69
|
-
"needed_for": "install",
|
|
70
|
-
"required": true
|
|
71
|
-
},
|
|
72
|
-
{ "command": "tar", "needed_for": "install", "required": true }
|
|
73
|
-
],
|
|
74
|
-
"launch": {
|
|
75
|
-
"argv": ["marathon", "{args}"],
|
|
76
|
-
"headless_argv": ["marathon", "--print={prompt}", "{args}"],
|
|
77
|
-
"headless_platforms": ["darwin", "linux"],
|
|
78
|
-
"resume": ["--resume", "{sessionFile}"],
|
|
79
|
-
"persistent_setup": false
|
|
80
|
-
},
|
|
81
|
-
"inputs": [
|
|
82
|
-
{
|
|
83
|
-
"name": "SC_API_KEY",
|
|
84
|
-
"label": "Subconscious Code API key",
|
|
85
|
-
"description": "Subconscious Code credential override; blank uses API_KEY.",
|
|
86
|
-
"type": "secret"
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
"env": [
|
|
90
|
-
{
|
|
91
|
-
"name": "SC_API_KEY",
|
|
92
|
-
"value": "{apiKey}",
|
|
93
|
-
"description": "Gateway credential."
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
"name": "SC_BASE_URL",
|
|
97
|
-
"value": "{baseUrlV1}",
|
|
98
|
-
"description": "OpenAI-compatible base URL for model requests."
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
"name": "SC_DLR_URL",
|
|
102
|
-
"value": "{baseUrl}",
|
|
103
|
-
"description": "Gateway origin for Marathon's DLR feature.",
|
|
104
|
-
"note": "What DLR does is defined in the Marathon binary, not in this repo."
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
"name": "SC_DLR_ENABLED",
|
|
108
|
-
"value": "true",
|
|
109
|
-
"description": "Turns Marathon's DLR feature on.",
|
|
110
|
-
"note": "What DLR does is defined in the Marathon binary, not in this repo."
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
"name": "SC_MODEL",
|
|
114
|
-
"value": "{model}",
|
|
115
|
-
"description": "Model for the session."
|
|
116
|
-
}
|
|
117
|
-
],
|
|
118
|
-
"config": [],
|
|
119
|
-
"capabilities": {
|
|
120
|
-
"compaction": {
|
|
121
|
-
"default": "unknown",
|
|
122
|
-
"on": {
|
|
123
|
-
"set_by_subc": false,
|
|
124
|
-
"kind": null,
|
|
125
|
-
"name": null,
|
|
126
|
-
"value": null,
|
|
127
|
-
"verified": false,
|
|
128
|
-
"note": "subc sets no compaction knob; Marathon's built-in behaviour applies."
|
|
129
|
-
},
|
|
130
|
-
"off": {
|
|
131
|
-
"set_by_subc": false,
|
|
132
|
-
"kind": null,
|
|
133
|
-
"name": null,
|
|
134
|
-
"value": null,
|
|
135
|
-
"verified": false,
|
|
136
|
-
"note": "No off knob is set or documented by subc."
|
|
137
|
-
},
|
|
138
|
-
"threshold": {
|
|
139
|
-
"set_by_subc": false,
|
|
140
|
-
"kind": null,
|
|
141
|
-
"name": null,
|
|
142
|
-
"value": null,
|
|
143
|
-
"verified": false,
|
|
144
|
-
"note": "No threshold knob is set or documented by subc."
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
"mcp": {
|
|
148
|
-
"configured_by_subc": false,
|
|
149
|
-
"transports": null,
|
|
150
|
-
"verified": false,
|
|
151
|
-
"note": "subc configures no MCP servers. Transports Marathon supports are not described in this repo."
|
|
152
|
-
},
|
|
153
|
-
"headers": [],
|
|
154
|
-
"hooks": []
|
|
155
|
-
}
|
|
156
|
-
}
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Install a precompiled Marathon release for the current platform.
|
|
3
|
-
|
|
4
|
-
set -euo pipefail
|
|
5
|
-
|
|
6
|
-
REPOSITORY="subconscious-systems/subconscious-code"
|
|
7
|
-
REPOSITORY_URL="https://github.com/${REPOSITORY}"
|
|
8
|
-
INSTALL_DIR="${SC_INSTALL_DIR:-${HOME}/.local/bin}"
|
|
9
|
-
|
|
10
|
-
usage() {
|
|
11
|
-
cat <<'EOF'
|
|
12
|
-
Usage: subc marathon install
|
|
13
|
-
|
|
14
|
-
Install the latest Marathon release. Linux downloads and verifies the
|
|
15
|
-
published static binary. macOS downloads and verifies the matching native binary.
|
|
16
|
-
EOF
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
case "${1:-install}" in
|
|
20
|
-
install) ;;
|
|
21
|
-
help|-h|--help)
|
|
22
|
-
usage
|
|
23
|
-
exit 0
|
|
24
|
-
;;
|
|
25
|
-
*)
|
|
26
|
-
echo "error: unsupported Marathon setup action: $1" >&2
|
|
27
|
-
usage >&2
|
|
28
|
-
exit 2
|
|
29
|
-
;;
|
|
30
|
-
esac
|
|
31
|
-
|
|
32
|
-
release_tag() {
|
|
33
|
-
if [[ -n "${SC_CODE_VERSION:-}" ]]; then
|
|
34
|
-
printf '%s\n' "${SC_CODE_VERSION#v}"
|
|
35
|
-
return
|
|
36
|
-
fi
|
|
37
|
-
if command -v gh >/dev/null 2>&1; then
|
|
38
|
-
local tag
|
|
39
|
-
tag="$(gh release view --repo "$REPOSITORY" --json tagName --jq '.tagName' 2>/dev/null || true)"
|
|
40
|
-
if [[ -n "$tag" ]]; then
|
|
41
|
-
printf '%s\n' "${tag#v}"
|
|
42
|
-
return
|
|
43
|
-
fi
|
|
44
|
-
fi
|
|
45
|
-
if command -v curl >/dev/null 2>&1; then
|
|
46
|
-
local tag
|
|
47
|
-
tag="$(curl -fsSL "https://api.github.com/repos/${REPOSITORY}/releases/latest" 2>/dev/null \
|
|
48
|
-
| sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
|
|
49
|
-
| head -n 1 || true)"
|
|
50
|
-
if [[ -n "$tag" ]]; then
|
|
51
|
-
printf '%s\n' "${tag#v}"
|
|
52
|
-
return
|
|
53
|
-
fi
|
|
54
|
-
fi
|
|
55
|
-
return 1
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
platform="$(uname -s)"
|
|
59
|
-
architecture="$(uname -m)"
|
|
60
|
-
version="$(release_tag || true)"
|
|
61
|
-
|
|
62
|
-
if [[ -z "$version" ]]; then
|
|
63
|
-
echo "error: no published Marathon release is available yet" >&2
|
|
64
|
-
echo "The release may still be building. Retry subc marathon install after it finishes." >&2
|
|
65
|
-
exit 1
|
|
66
|
-
fi
|
|
67
|
-
|
|
68
|
-
case "${platform}:${architecture}" in
|
|
69
|
-
Darwin:arm64) target="aarch64-apple-darwin" ;;
|
|
70
|
-
Darwin:x86_64) target="x86_64-apple-darwin" ;;
|
|
71
|
-
Linux:aarch64|Linux:arm64) target="aarch64-unknown-linux-musl" ;;
|
|
72
|
-
Linux:x86_64|Linux:amd64) target="x86_64-unknown-linux-musl" ;;
|
|
73
|
-
*)
|
|
74
|
-
echo "error: unsupported platform or architecture: ${platform} ${architecture}" >&2
|
|
75
|
-
exit 1
|
|
76
|
-
;;
|
|
77
|
-
esac
|
|
78
|
-
|
|
79
|
-
executable="marathon"
|
|
80
|
-
asset="${executable}-${target}.tar.gz"
|
|
81
|
-
checksum="${asset}.sha256"
|
|
82
|
-
work_dir="$(mktemp -d "${TMPDIR:-/tmp}/subc-marathon-install.XXXXXX")"
|
|
83
|
-
staging=''
|
|
84
|
-
cleanup() {
|
|
85
|
-
rm -f "$work_dir/$asset" "$work_dir/$checksum" "$work_dir/sc" "$work_dir/marathon"
|
|
86
|
-
if [[ -n "$staging" ]]; then rm -f "$staging"; fi
|
|
87
|
-
rmdir "$work_dir" 2>/dev/null || true
|
|
88
|
-
}
|
|
89
|
-
trap cleanup EXIT HUP INT TERM
|
|
90
|
-
|
|
91
|
-
echo "Downloading Marathon v${version} for ${target}..."
|
|
92
|
-
if command -v gh >/dev/null 2>&1 \
|
|
93
|
-
&& assets="$(gh release view "v${version}" --repo "$REPOSITORY" --json assets --jq '.assets[].name' 2>/dev/null)"; then
|
|
94
|
-
if ! printf '%s\n' "$assets" | grep -Fxq "$asset"; then
|
|
95
|
-
# Pinned legacy releases are still installed as marathon, never as sc.
|
|
96
|
-
executable="sc"
|
|
97
|
-
asset="${executable}-${target}.tar.gz"
|
|
98
|
-
checksum="${asset}.sha256"
|
|
99
|
-
fi
|
|
100
|
-
if ! printf '%s\n' "$assets" | grep -Fxq "$asset" \
|
|
101
|
-
|| ! printf '%s\n' "$assets" | grep -Fxq "$checksum"; then
|
|
102
|
-
echo "error: release is missing $asset or $checksum" >&2
|
|
103
|
-
exit 1
|
|
104
|
-
fi
|
|
105
|
-
gh release download "v${version}" --repo "$REPOSITORY" \
|
|
106
|
-
--pattern "$asset" --pattern "$checksum" --dir "$work_dir"
|
|
107
|
-
else
|
|
108
|
-
command -v curl >/dev/null 2>&1 || {
|
|
109
|
-
echo "error: curl is required to download Marathon" >&2
|
|
110
|
-
exit 1
|
|
111
|
-
}
|
|
112
|
-
release_url="${REPOSITORY_URL}/releases/download/v${version}"
|
|
113
|
-
status="$(curl -sSL -w '%{http_code}' "${release_url}/${asset}" -o "$work_dir/$asset")"
|
|
114
|
-
if [[ "$status" == 404 ]]; then
|
|
115
|
-
rm -f "$work_dir/$asset"
|
|
116
|
-
executable="sc"
|
|
117
|
-
asset="${executable}-${target}.tar.gz"
|
|
118
|
-
checksum="${asset}.sha256"
|
|
119
|
-
curl -fL "${release_url}/${asset}" -o "$work_dir/$asset"
|
|
120
|
-
elif [[ "$status" != 200 ]]; then
|
|
121
|
-
echo "error: Marathon download failed (HTTP $status)" >&2
|
|
122
|
-
exit 1
|
|
123
|
-
fi
|
|
124
|
-
curl -fL "${release_url}/${checksum}" -o "$work_dir/$checksum"
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
if command -v sha256sum >/dev/null 2>&1; then
|
|
128
|
-
(cd "$work_dir" && sha256sum --check "$checksum")
|
|
129
|
-
elif command -v shasum >/dev/null 2>&1; then
|
|
130
|
-
expected="$(awk '{print $1}' "$work_dir/$checksum")"
|
|
131
|
-
actual="$(shasum -a 256 "$work_dir/$asset" | awk '{print $1}')"
|
|
132
|
-
[[ "$actual" == "$expected" ]] || {
|
|
133
|
-
echo "error: Marathon checksum verification failed" >&2
|
|
134
|
-
exit 1
|
|
135
|
-
}
|
|
136
|
-
else
|
|
137
|
-
echo "error: sha256sum or shasum is required to verify the download" >&2
|
|
138
|
-
exit 1
|
|
139
|
-
fi
|
|
140
|
-
|
|
141
|
-
tar -xzf "$work_dir/$asset" -C "$work_dir" "$executable"
|
|
142
|
-
if [[ ! -f "$work_dir/$executable" || -L "$work_dir/$executable" ]]; then
|
|
143
|
-
echo "error: release has no regular root $executable executable" >&2
|
|
144
|
-
exit 1
|
|
145
|
-
fi
|
|
146
|
-
mkdir -p "$INSTALL_DIR"
|
|
147
|
-
if [[ -d "$INSTALL_DIR/marathon" ]]; then
|
|
148
|
-
echo "error: $INSTALL_DIR/marathon is a directory; refusing to replace it" >&2
|
|
149
|
-
exit 1
|
|
150
|
-
fi
|
|
151
|
-
staging="$(mktemp "$INSTALL_DIR/.marathon.XXXXXX")"
|
|
152
|
-
install -m 0755 "$work_dir/$executable" "$staging"
|
|
153
|
-
mv -f "$staging" "$INSTALL_DIR/marathon"
|
|
154
|
-
echo "Installed Marathon v${version} to $INSTALL_DIR/marathon"
|