subconscious-cli 4.1.1 → 4.1.3
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 +5 -2
- package/bin/model-capabilities.js +11 -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/registry.generated.json +27 -6
- package/bin/runbook/codex/run.sh +9 -3
- package/bin/runbook/copilot/install.sh +8 -3
- package/bin/runbook/cursor/install.sh +2 -1
- package/bin/runbook/deepseek-harness/run.sh +8 -1
- package/bin/runbook/model-capabilities.generated.sh +9 -0
- package/bin/runbook/opencode/install.sh +8 -2
- package/bin/runbook/opencode/run.sh +8 -2
- package/bin/runbook/pi/install.sh +8 -2
- package/bin/runbook/subconscious-code/install.sh +51 -17
- package/bin/runbook/subconscious-code/run.sh +3 -3
- package/bin/windows/launch.js +7 -2
- package/bin/windows/setup.js +6 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -204,8 +204,11 @@ Starting with CLI 4.1.1, `subc marathon` is the native agent command. On Windows
|
|
|
204
204
|
the installer writes `marathon.exe`, avoiding the system `sc.exe` command.
|
|
205
205
|
`subc sc` remains a compatibility alias but never launches Windows service
|
|
206
206
|
control. Older pinned release binaries are also installed as `marathon.exe`.
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
Starting with CLI 4.1.2 and native agent 0.1.6, macOS and Linux also install
|
|
208
|
+
and launch `marathon`. Existing `.sc` settings, sessions, and `SC_*` variables
|
|
209
|
+
are preserved on every platform. Shell behavior is unchanged. Older Unix
|
|
210
|
+
release archives are installed under the new name; existing `sc` files are
|
|
211
|
+
left untouched. `subc sc` remains a compatibility alias on every platform.
|
|
209
212
|
|
|
210
213
|
`subc codex` disables Codex apps and plugin tools for that launch by default so
|
|
211
214
|
requests remain below the gateway's 128-tool limit. Core coding tools remain
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
// The models endpoint currently supplies IDs, not modality metadata. Keep
|
|
4
|
+
// explicit capabilities in the same registry used to generate the Unix lookup.
|
|
5
|
+
const { modelCapabilities = {} } = JSON.parse(
|
|
6
|
+
readFileSync(new URL('./registry.generated.json', import.meta.url), 'utf8'),
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
export function modelSupportsVision(modelId) {
|
|
10
|
+
return Object.hasOwn(modelCapabilities, modelId) && modelCapabilities[modelId].vision === true;
|
|
11
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -6,13 +6,19 @@
|
|
|
6
6
|
"subconscious/glm-5.3-marathon",
|
|
7
7
|
"subconscious/glm-5.2",
|
|
8
8
|
"subconscious/tim-qwen3.6-27b",
|
|
9
|
-
"subconscious/deepseek-v4-flash-marathon"
|
|
9
|
+
"subconscious/deepseek-v4-flash-marathon",
|
|
10
|
+
"subconscious/deepseek-v4.1-flash-marathon"
|
|
10
11
|
],
|
|
11
12
|
"baseUrl": "https://api.subconscious.dev",
|
|
12
13
|
"baseUrlV1": "https://api.subconscious.dev/v1",
|
|
13
14
|
"keyPlaceholder": "your_key",
|
|
14
15
|
"platformUrl": "https://subconscious.dev/platform"
|
|
15
16
|
},
|
|
17
|
+
"modelCapabilities": {
|
|
18
|
+
"subconscious/deepseek-v4.1-flash-marathon": {
|
|
19
|
+
"vision": true
|
|
20
|
+
}
|
|
21
|
+
},
|
|
16
22
|
"agents": [
|
|
17
23
|
{
|
|
18
24
|
"id": "subconscious-code",
|
|
@@ -33,10 +39,7 @@
|
|
|
33
39
|
],
|
|
34
40
|
"protocol": "openai",
|
|
35
41
|
"homepage": "https://github.com/subconscious-systems/subconscious-code",
|
|
36
|
-
"bin": "
|
|
37
|
-
"binByPlatform": {
|
|
38
|
-
"win32": "marathon"
|
|
39
|
-
},
|
|
42
|
+
"bin": "marathon",
|
|
40
43
|
"install": {
|
|
41
44
|
"darwin": "subc marathon install",
|
|
42
45
|
"linux": "subc marathon install",
|
|
@@ -54,7 +57,7 @@
|
|
|
54
57
|
],
|
|
55
58
|
"setupNeedsAuth": false
|
|
56
59
|
},
|
|
57
|
-
"launch": "
|
|
60
|
+
"launch": "marathon",
|
|
58
61
|
"env": {
|
|
59
62
|
"SC_BASE_URL": "{baseUrlV1}",
|
|
60
63
|
"SC_DLR_URL": "{baseUrl}",
|
|
@@ -256,6 +259,24 @@
|
|
|
256
259
|
"context": 5000000,
|
|
257
260
|
"output": 65536
|
|
258
261
|
}
|
|
262
|
+
},
|
|
263
|
+
"subconscious/deepseek-v4.1-flash-marathon": {
|
|
264
|
+
"name": "subconscious/deepseek-v4.1-flash-marathon",
|
|
265
|
+
"tools": true,
|
|
266
|
+
"attachment": true,
|
|
267
|
+
"modalities": {
|
|
268
|
+
"input": [
|
|
269
|
+
"text",
|
|
270
|
+
"image"
|
|
271
|
+
],
|
|
272
|
+
"output": [
|
|
273
|
+
"text"
|
|
274
|
+
]
|
|
275
|
+
},
|
|
276
|
+
"limit": {
|
|
277
|
+
"context": 5000000,
|
|
278
|
+
"output": 65536
|
|
279
|
+
}
|
|
259
280
|
}
|
|
260
281
|
}
|
|
261
282
|
}
|
package/bin/runbook/codex/run.sh
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
set -euo pipefail
|
|
32
32
|
|
|
33
33
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
34
|
+
source "${SCRIPT_DIR}/../model-capabilities.generated.sh"
|
|
34
35
|
|
|
35
36
|
# Load shared env from SUBC_ENV_FILE, or a sibling .env / env.example.
|
|
36
37
|
SHARED_ENV="${SUBC_ENV_FILE:-${SCRIPT_DIR}/../.env}"
|
|
@@ -105,7 +106,8 @@ esac
|
|
|
105
106
|
DEFAULT_SUBCONSCIOUS_MODELS="subconscious/glm-5.3-marathon
|
|
106
107
|
subconscious/glm-5.2
|
|
107
108
|
subconscious/tim-qwen3.6-27b
|
|
108
|
-
subconscious/deepseek-v4-flash-marathon
|
|
109
|
+
subconscious/deepseek-v4-flash-marathon
|
|
110
|
+
subconscious/deepseek-v4.1-flash-marathon"
|
|
109
111
|
SUPPORTED_MODELS=()
|
|
110
112
|
|
|
111
113
|
add_supported_model() {
|
|
@@ -132,10 +134,14 @@ while IFS= read -r model_id; do
|
|
|
132
134
|
done <<< "${SUBCONSCIOUS_MODELS:-$DEFAULT_SUBCONSCIOUS_MODELS}"
|
|
133
135
|
|
|
134
136
|
write_model_catalog() {
|
|
135
|
-
local catalog_file="$1" model_id index=0
|
|
137
|
+
local catalog_file="$1" model_id vision_fields index=0
|
|
136
138
|
{
|
|
137
139
|
printf '{\n "models": [\n'
|
|
138
140
|
for model_id in "${SUPPORTED_MODELS[@]}"; do
|
|
141
|
+
vision_fields=""
|
|
142
|
+
if subc_model_supports_vision "$model_id"; then
|
|
143
|
+
vision_fields=', "input_modalities": ["text", "image"]'
|
|
144
|
+
fi
|
|
139
145
|
if [[ "$index" -gt 0 ]]; then
|
|
140
146
|
printf ',\n'
|
|
141
147
|
fi
|
|
@@ -169,7 +175,7 @@ write_model_catalog() {
|
|
|
169
175
|
"apply_patch_tool_type": "freeform",
|
|
170
176
|
"truncation_policy": { "mode": "tokens", "limit": 10000 },
|
|
171
177
|
"supports_parallel_tool_calls": true,
|
|
172
|
-
"experimental_supported_tools": []
|
|
178
|
+
"experimental_supported_tools": []${vision_fields}
|
|
173
179
|
}
|
|
174
180
|
EOF
|
|
175
181
|
index=$((index + 1))
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
set -euo pipefail
|
|
65
65
|
|
|
66
66
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
67
|
+
source "${SCRIPT_DIR}/../model-capabilities.generated.sh"
|
|
67
68
|
HOOK_SRC="${SCRIPT_DIR}/hook.sh"
|
|
68
69
|
HOOKS_TEMPLATE="${SCRIPT_DIR}/hooks.json"
|
|
69
70
|
|
|
@@ -177,7 +178,8 @@ done
|
|
|
177
178
|
DEFAULT_SUBCONSCIOUS_MODELS="subconscious/glm-5.3-marathon
|
|
178
179
|
subconscious/glm-5.2
|
|
179
180
|
subconscious/tim-qwen3.6-27b
|
|
180
|
-
subconscious/deepseek-v4-flash-marathon
|
|
181
|
+
subconscious/deepseek-v4-flash-marathon
|
|
182
|
+
subconscious/deepseek-v4.1-flash-marathon"
|
|
181
183
|
SUPPORTED_MODELS=()
|
|
182
184
|
|
|
183
185
|
add_supported_model() {
|
|
@@ -294,13 +296,16 @@ write_config() {
|
|
|
294
296
|
local existing
|
|
295
297
|
existing="$(strip_subconscious "$models_json")"
|
|
296
298
|
|
|
297
|
-
local provider_models='[]' model_id
|
|
299
|
+
local provider_models='[]' model_id vision
|
|
298
300
|
for model_id in "${SUPPORTED_MODELS[@]}"; do
|
|
301
|
+
vision=false
|
|
302
|
+
if subc_model_supports_vision "$model_id"; then vision=true; fi
|
|
299
303
|
provider_models=$(jq -cn \
|
|
300
304
|
--argjson models "$provider_models" \
|
|
301
305
|
--arg modelId "$model_id" \
|
|
302
306
|
--arg modelName "Subconscious ${model_id}" \
|
|
303
307
|
--arg url "$messages_url" \
|
|
308
|
+
--argjson vision "$vision" \
|
|
304
309
|
--argjson maxIn "$MAX_INPUT_TOKENS" \
|
|
305
310
|
--argjson maxOut "$MAX_OUTPUT_TOKENS" \
|
|
306
311
|
'$models + [{
|
|
@@ -308,7 +313,7 @@ write_config() {
|
|
|
308
313
|
name: $modelName,
|
|
309
314
|
url: $url,
|
|
310
315
|
toolCalling: true,
|
|
311
|
-
vision:
|
|
316
|
+
vision: $vision,
|
|
312
317
|
maxInputTokens: $maxIn,
|
|
313
318
|
maxOutputTokens: $maxOut,
|
|
314
319
|
thinking: true,
|
|
@@ -59,7 +59,8 @@ COMMAND="install"
|
|
|
59
59
|
DEFAULT_SUBCONSCIOUS_MODELS="subconscious/glm-5.3-marathon
|
|
60
60
|
subconscious/glm-5.2
|
|
61
61
|
subconscious/tim-qwen3.6-27b
|
|
62
|
-
subconscious/deepseek-v4-flash-marathon
|
|
62
|
+
subconscious/deepseek-v4-flash-marathon
|
|
63
|
+
subconscious/deepseek-v4.1-flash-marathon"
|
|
63
64
|
|
|
64
65
|
SUPPORTED_MODELS=()
|
|
65
66
|
add_supported_model() {
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
set -euo pipefail
|
|
6
6
|
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
source "${SCRIPT_DIR}/../model-capabilities.generated.sh"
|
|
9
|
+
|
|
7
10
|
GATEWAY_URL="${GATEWAY_URL:-}"
|
|
8
11
|
API_KEY="${DEEPSEEK_HARNESS_API_KEY:-${API_KEY:-}}"
|
|
9
12
|
MODEL="${MODEL:-subconscious/glm-5.3-marathon}"
|
|
@@ -13,7 +16,8 @@ MAX_TOKENS="${DEEPSEEK_HARNESS_MAX_TOKENS:-65536}"
|
|
|
13
16
|
DEFAULT_SUBCONSCIOUS_MODELS="subconscious/glm-5.3-marathon
|
|
14
17
|
subconscious/glm-5.2
|
|
15
18
|
subconscious/tim-qwen3.6-27b
|
|
16
|
-
subconscious/deepseek-v4-flash-marathon
|
|
19
|
+
subconscious/deepseek-v4-flash-marathon
|
|
20
|
+
subconscious/deepseek-v4.1-flash-marathon"
|
|
17
21
|
|
|
18
22
|
if [[ -z "$GATEWAY_URL" || -z "$API_KEY" ]]; then
|
|
19
23
|
echo "error: GATEWAY_URL and API_KEY are required to launch DeepSeek Harness" >&2
|
|
@@ -79,6 +83,9 @@ trap cleanup EXIT HUP INT TERM
|
|
|
79
83
|
for model_id in "${SUPPORTED_MODELS[@]}"; do
|
|
80
84
|
printf " - id: '%s'\n" "$model_id"
|
|
81
85
|
printf " name: '%s'\n" "$model_id"
|
|
86
|
+
if subc_model_supports_vision "$model_id"; then
|
|
87
|
+
printf '%s\n' ' input: [text, image]'
|
|
88
|
+
fi
|
|
82
89
|
printf " contextWindow: %s\n" "$CONTEXT_WINDOW"
|
|
83
90
|
printf " maxTokens: %s\n" "$MAX_TOKENS"
|
|
84
91
|
done
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Generated from agents/registry.json. Do not edit by hand.
|
|
3
|
+
# Exact IDs only: similarly named models do not inherit capabilities.
|
|
4
|
+
subc_model_supports_vision() {
|
|
5
|
+
case "${1:-}" in
|
|
6
|
+
'subconscious/deepseek-v4.1-flash-marathon') return 0 ;;
|
|
7
|
+
*) return 1 ;;
|
|
8
|
+
esac
|
|
9
|
+
}
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
set -euo pipefail
|
|
55
55
|
|
|
56
56
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
57
|
+
source "${SCRIPT_DIR}/../model-capabilities.generated.sh"
|
|
57
58
|
|
|
58
59
|
# Load shared env from SUBC_ENV_FILE, or a sibling .env / env.example.
|
|
59
60
|
SHARED_ENV="${SUBC_ENV_FILE:-${SCRIPT_DIR}/../.env}"
|
|
@@ -122,7 +123,8 @@ done
|
|
|
122
123
|
DEFAULT_SUBCONSCIOUS_MODELS="subconscious/glm-5.3-marathon
|
|
123
124
|
subconscious/glm-5.2
|
|
124
125
|
subconscious/tim-qwen3.6-27b
|
|
125
|
-
subconscious/deepseek-v4-flash-marathon
|
|
126
|
+
subconscious/deepseek-v4-flash-marathon
|
|
127
|
+
subconscious/deepseek-v4.1-flash-marathon"
|
|
126
128
|
SUPPORTED_MODELS=()
|
|
127
129
|
|
|
128
130
|
add_supported_model() {
|
|
@@ -147,7 +149,11 @@ done <<< "${SUBCONSCIOUS_MODELS:-$DEFAULT_SUBCONSCIOUS_MODELS}"
|
|
|
147
149
|
|
|
148
150
|
MODELS_JSON=""
|
|
149
151
|
for model_id in "${SUPPORTED_MODELS[@]}"; do
|
|
150
|
-
|
|
152
|
+
vision_fields=""
|
|
153
|
+
if subc_model_supports_vision "$model_id"; then
|
|
154
|
+
vision_fields=',"attachment":true,"modalities":{"input":["text","image"],"output":["text"]}'
|
|
155
|
+
fi
|
|
156
|
+
model_json="\"${model_id}\":{\"name\":\"${model_id}\",\"tools\":true,\"limit\":{\"context\":${CONTEXT_LIMIT},\"output\":${OUTPUT_LIMIT}}${vision_fields}}"
|
|
151
157
|
if [[ -n "$MODELS_JSON" ]]; then
|
|
152
158
|
MODELS_JSON="${MODELS_JSON},${model_json}"
|
|
153
159
|
else
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
set -euo pipefail
|
|
19
19
|
|
|
20
20
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
|
+
source "${SCRIPT_DIR}/../model-capabilities.generated.sh"
|
|
21
22
|
|
|
22
23
|
# Load shared env from SUBC_ENV_FILE, or a sibling .env / env.example.
|
|
23
24
|
SHARED_ENV="${SUBC_ENV_FILE:-${SCRIPT_DIR}/../.env}"
|
|
@@ -33,7 +34,8 @@ OUTPUT_LIMIT="${OPENCODE_OUTPUT_LIMIT:-65536}"
|
|
|
33
34
|
DEFAULT_SUBCONSCIOUS_MODELS="subconscious/glm-5.3-marathon
|
|
34
35
|
subconscious/glm-5.2
|
|
35
36
|
subconscious/tim-qwen3.6-27b
|
|
36
|
-
subconscious/deepseek-v4-flash-marathon
|
|
37
|
+
subconscious/deepseek-v4-flash-marathon
|
|
38
|
+
subconscious/deepseek-v4.1-flash-marathon"
|
|
37
39
|
SUPPORTED_MODELS=()
|
|
38
40
|
|
|
39
41
|
add_supported_model() {
|
|
@@ -58,7 +60,11 @@ done <<< "${SUBCONSCIOUS_MODELS:-$DEFAULT_SUBCONSCIOUS_MODELS}"
|
|
|
58
60
|
|
|
59
61
|
MODELS_JSON=""
|
|
60
62
|
for model_id in "${SUPPORTED_MODELS[@]}"; do
|
|
61
|
-
|
|
63
|
+
vision_fields=""
|
|
64
|
+
if subc_model_supports_vision "$model_id"; then
|
|
65
|
+
vision_fields=',"attachment":true,"modalities":{"input":["text","image"],"output":["text"]}'
|
|
66
|
+
fi
|
|
67
|
+
model_json="\"${model_id}\":{\"name\":\"${model_id}\",\"tools\":true,\"limit\":{\"context\":${CONTEXT_LIMIT},\"output\":${OUTPUT_LIMIT}}${vision_fields}}"
|
|
62
68
|
if [[ -n "$MODELS_JSON" ]]; then
|
|
63
69
|
MODELS_JSON="${MODELS_JSON},${model_json}"
|
|
64
70
|
else
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
set -euo pipefail
|
|
48
48
|
|
|
49
49
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
50
|
+
source "${SCRIPT_DIR}/../model-capabilities.generated.sh"
|
|
50
51
|
EXTENSION_SRC="${SCRIPT_DIR}/subconscious-compaction.ts"
|
|
51
52
|
|
|
52
53
|
# Load shared env from SUBC_ENV_FILE, or a sibling .env / env.example.
|
|
@@ -117,7 +118,8 @@ done
|
|
|
117
118
|
DEFAULT_SUBCONSCIOUS_MODELS="subconscious/glm-5.3-marathon
|
|
118
119
|
subconscious/glm-5.2
|
|
119
120
|
subconscious/tim-qwen3.6-27b
|
|
120
|
-
subconscious/deepseek-v4-flash-marathon
|
|
121
|
+
subconscious/deepseek-v4-flash-marathon
|
|
122
|
+
subconscious/deepseek-v4.1-flash-marathon"
|
|
121
123
|
SUPPORTED_MODELS=()
|
|
122
124
|
|
|
123
125
|
add_supported_model() {
|
|
@@ -142,7 +144,11 @@ done <<< "${SUBCONSCIOUS_MODELS:-$DEFAULT_SUBCONSCIOUS_MODELS}"
|
|
|
142
144
|
|
|
143
145
|
MODEL_ENTRIES_JSON=""
|
|
144
146
|
for model_id in "${SUPPORTED_MODELS[@]}"; do
|
|
145
|
-
|
|
147
|
+
vision_fields=""
|
|
148
|
+
if subc_model_supports_vision "$model_id"; then
|
|
149
|
+
vision_fields=',"input":["text","image"]'
|
|
150
|
+
fi
|
|
151
|
+
model_json="{\"id\":\"${model_id}\",\"contextWindow\":${CONTEXT_WINDOW},\"maxTokens\":${MAX_TOKENS},\"compat\":{\"sendSessionAffinityHeaders\":true,\"sessionAffinityFormat\":\"openai-nosession\"}${vision_fields}}"
|
|
146
152
|
if [[ -n "$MODEL_ENTRIES_JSON" ]]; then
|
|
147
153
|
MODEL_ENTRIES_JSON="${MODEL_ENTRIES_JSON},${model_json}"
|
|
148
154
|
else
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Install a precompiled
|
|
2
|
+
# Install a precompiled Marathon release for the current platform.
|
|
3
3
|
|
|
4
4
|
set -euo pipefail
|
|
5
5
|
|
|
@@ -9,9 +9,9 @@ INSTALL_DIR="${SC_INSTALL_DIR:-${HOME}/.local/bin}"
|
|
|
9
9
|
|
|
10
10
|
usage() {
|
|
11
11
|
cat <<'EOF'
|
|
12
|
-
Usage: subc
|
|
12
|
+
Usage: subc marathon install
|
|
13
13
|
|
|
14
|
-
Install the latest
|
|
14
|
+
Install the latest Marathon release. Linux downloads and verifies the
|
|
15
15
|
published static binary. macOS downloads and verifies the matching native binary.
|
|
16
16
|
EOF
|
|
17
17
|
}
|
|
@@ -23,7 +23,7 @@ case "${1:-install}" in
|
|
|
23
23
|
exit 0
|
|
24
24
|
;;
|
|
25
25
|
*)
|
|
26
|
-
echo "error: unsupported
|
|
26
|
+
echo "error: unsupported Marathon setup action: $1" >&2
|
|
27
27
|
usage >&2
|
|
28
28
|
exit 2
|
|
29
29
|
;;
|
|
@@ -60,8 +60,8 @@ architecture="$(uname -m)"
|
|
|
60
60
|
version="$(release_tag || true)"
|
|
61
61
|
|
|
62
62
|
if [[ -z "$version" ]]; then
|
|
63
|
-
echo "error: no published
|
|
64
|
-
echo "The release may still be building. Retry subc
|
|
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
65
|
exit 1
|
|
66
66
|
fi
|
|
67
67
|
|
|
@@ -76,27 +76,51 @@ case "${platform}:${architecture}" in
|
|
|
76
76
|
;;
|
|
77
77
|
esac
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
executable="marathon"
|
|
80
|
+
asset="${executable}-${target}.tar.gz"
|
|
80
81
|
checksum="${asset}.sha256"
|
|
81
|
-
work_dir="$(mktemp -d "${TMPDIR:-/tmp}/subc-
|
|
82
|
+
work_dir="$(mktemp -d "${TMPDIR:-/tmp}/subc-marathon-install.XXXXXX")"
|
|
83
|
+
staging=''
|
|
82
84
|
cleanup() {
|
|
83
|
-
rm -f "$work_dir/$asset" "$work_dir/$checksum" "$work_dir/sc"
|
|
85
|
+
rm -f "$work_dir/$asset" "$work_dir/$checksum" "$work_dir/sc" "$work_dir/marathon"
|
|
86
|
+
if [[ -n "$staging" ]]; then rm -f "$staging"; fi
|
|
84
87
|
rmdir "$work_dir" 2>/dev/null || true
|
|
85
88
|
}
|
|
86
89
|
trap cleanup EXIT HUP INT TERM
|
|
87
90
|
|
|
88
|
-
echo "Downloading
|
|
91
|
+
echo "Downloading Marathon v${version} for ${target}..."
|
|
89
92
|
if command -v gh >/dev/null 2>&1 \
|
|
90
|
-
&& gh release view "v${version}" --repo "$REPOSITORY" >/dev/null
|
|
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
|
|
91
105
|
gh release download "v${version}" --repo "$REPOSITORY" \
|
|
92
106
|
--pattern "$asset" --pattern "$checksum" --dir "$work_dir"
|
|
93
107
|
else
|
|
94
108
|
command -v curl >/dev/null 2>&1 || {
|
|
95
|
-
echo "error: curl is required to download
|
|
109
|
+
echo "error: curl is required to download Marathon" >&2
|
|
96
110
|
exit 1
|
|
97
111
|
}
|
|
98
112
|
release_url="${REPOSITORY_URL}/releases/download/v${version}"
|
|
99
|
-
curl -
|
|
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
|
|
100
124
|
curl -fL "${release_url}/${checksum}" -o "$work_dir/$checksum"
|
|
101
125
|
fi
|
|
102
126
|
|
|
@@ -106,7 +130,7 @@ elif command -v shasum >/dev/null 2>&1; then
|
|
|
106
130
|
expected="$(awk '{print $1}' "$work_dir/$checksum")"
|
|
107
131
|
actual="$(shasum -a 256 "$work_dir/$asset" | awk '{print $1}')"
|
|
108
132
|
[[ "$actual" == "$expected" ]] || {
|
|
109
|
-
echo "error:
|
|
133
|
+
echo "error: Marathon checksum verification failed" >&2
|
|
110
134
|
exit 1
|
|
111
135
|
}
|
|
112
136
|
else
|
|
@@ -114,7 +138,17 @@ else
|
|
|
114
138
|
exit 1
|
|
115
139
|
fi
|
|
116
140
|
|
|
117
|
-
tar -xzf "$work_dir/$asset" -C "$work_dir"
|
|
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
|
|
118
146
|
mkdir -p "$INSTALL_DIR"
|
|
119
|
-
|
|
120
|
-
echo "
|
|
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"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Launch
|
|
2
|
+
# Launch Marathon without changing ~/.sc or project settings.
|
|
3
3
|
|
|
4
4
|
set -euo pipefail
|
|
5
5
|
|
|
@@ -8,7 +8,7 @@ API_KEY="${SC_API_KEY:-${API_KEY:-}}"
|
|
|
8
8
|
MODEL="${MODEL:-subconscious/glm-5.3-marathon}"
|
|
9
9
|
|
|
10
10
|
if [[ -z "$GATEWAY_URL" || -z "$API_KEY" ]]; then
|
|
11
|
-
echo "error: GATEWAY_URL and API_KEY are required to launch
|
|
11
|
+
echo "error: GATEWAY_URL and API_KEY are required to launch Marathon" >&2
|
|
12
12
|
exit 1
|
|
13
13
|
fi
|
|
14
14
|
|
|
@@ -18,4 +18,4 @@ export SC_DLR_URL="${GATEWAY_URL%/}"
|
|
|
18
18
|
export SC_DLR_ENABLED=true
|
|
19
19
|
export SC_MODEL="$MODEL"
|
|
20
20
|
|
|
21
|
-
exec
|
|
21
|
+
exec marathon "$@"
|
package/bin/windows/launch.js
CHANGED
|
@@ -3,6 +3,7 @@ import fs from 'node:fs/promises';
|
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { claudeNativeLaunch } from './claude.js';
|
|
6
|
+
import { modelSupportsVision } from '../model-capabilities.js';
|
|
6
7
|
import { defaults, value, origin, modelIds, positiveInteger, parseOptions, writeJson } from './common.js';
|
|
7
8
|
|
|
8
9
|
function connection(env, keyName) {
|
|
@@ -25,7 +26,10 @@ export async function windowsLaunch(id, argv, env, { tempRoot = os.tmpdir() } =
|
|
|
25
26
|
if (id === 'opencode') {
|
|
26
27
|
const context = positiveInteger(value(env, 'OPENCODE_CONTEXT_LIMIT', '5000000'), 'OPENCODE_CONTEXT_LIMIT');
|
|
27
28
|
const output = positiveInteger(value(env, 'OPENCODE_OUTPUT_LIMIT', '65536'), 'OPENCODE_OUTPUT_LIMIT');
|
|
28
|
-
const models = Object.fromEntries(modelIds(env).map(id => [id, {
|
|
29
|
+
const models = Object.fromEntries(modelIds(env).map(id => [id, {
|
|
30
|
+
name: id, tools: true, limit: { context, output },
|
|
31
|
+
...(modelSupportsVision(id) ? { attachment: true, modalities: { input: ['text', 'image'], output: ['text'] } } : {}),
|
|
32
|
+
}]));
|
|
29
33
|
childEnv.OPENCODE_CONFIG_CONTENT = JSON.stringify({
|
|
30
34
|
$schema: 'https://opencode.ai/config.json', disabled_providers: ['subconscious'],
|
|
31
35
|
provider: { 'subconscious-cli': { npm: '@ai-sdk/openai-compatible', name: 'Subconscious Gateway', options: {
|
|
@@ -51,6 +55,7 @@ export async function windowsLaunch(id, argv, env, { tempRoot = os.tmpdir() } =
|
|
|
51
55
|
supports_reasoning_summaries: false, support_verbosity: false, default_verbosity: null,
|
|
52
56
|
apply_patch_tool_type: 'freeform', truncation_policy: { mode: 'tokens', limit: 10000 },
|
|
53
57
|
supports_parallel_tool_calls: true, experimental_supported_tools: [],
|
|
58
|
+
...(modelSupportsVision(id) ? { input_modalities: ['text', 'image'] } : {}),
|
|
54
59
|
})) };
|
|
55
60
|
// Validate all flags before creating a temporary directory.
|
|
56
61
|
const threads = positiveInteger(value(env, 'MAX_CONCURRENT_SUBAGENTS', '4'), 'MAX_CONCURRENT_SUBAGENTS');
|
|
@@ -81,7 +86,7 @@ export async function windowsLaunch(id, argv, env, { tempRoot = os.tmpdir() } =
|
|
|
81
86
|
const cleanup = () => fs.rm(dir, { recursive: true, force: true });
|
|
82
87
|
try {
|
|
83
88
|
const file = path.join(dir, 'subconscious.cordis.yml');
|
|
84
|
-
const text = `- id: llm-pi-ai\n config:\n providers:\n subconscious:\n apiKeyEnv: SUBCONSCIOUS_API_KEY\n displayName: Subconscious Gateway\n api: openai-completions\n baseURL: !!js process.env.SUBCONSCIOUS_DSH_BASE_URL\n headers:\n x-subconscious-client: deepseek-harness\n compat:\n supportsDeveloperRole: false\n maxTokensField: max_tokens\n defaultContextWindow: ${context}\n defaultMaxTokens: ${maxTokens}\n models:\n${models.map(id => ` - id: '${id}'\n name: '${id}'\n contextWindow: ${context}\n maxTokens: ${maxTokens}`).join('\n')}\n- id: agent-default-model\n config:\n provider: subconscious\n model: '${model}'\n`;
|
|
89
|
+
const text = `- id: llm-pi-ai\n config:\n providers:\n subconscious:\n apiKeyEnv: SUBCONSCIOUS_API_KEY\n displayName: Subconscious Gateway\n api: openai-completions\n baseURL: !!js process.env.SUBCONSCIOUS_DSH_BASE_URL\n headers:\n x-subconscious-client: deepseek-harness\n compat:\n supportsDeveloperRole: false\n maxTokensField: max_tokens\n defaultContextWindow: ${context}\n defaultMaxTokens: ${maxTokens}\n models:\n${models.map(id => ` - id: '${id}'\n name: '${id}'\n${modelSupportsVision(id) ? ' input: [text, image]\n' : ''} contextWindow: ${context}\n maxTokens: ${maxTokens}`).join('\n')}\n- id: agent-default-model\n config:\n provider: subconscious\n model: '${model}'\n`;
|
|
85
90
|
await fs.writeFile(file, text, { mode: 0o600, flag: 'wx' });
|
|
86
91
|
const mode = ['web', 'headless'].includes(argv[0]) ? argv[0] : 'web';
|
|
87
92
|
const rest = ['web', 'headless'].includes(argv[0]) ? argv.slice(1) : argv;
|
package/bin/windows/setup.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { modelSupportsVision } from '../model-capabilities.js';
|
|
4
5
|
import { defaults, origin, value, modelIds, positiveInteger, parseOptions, object, readJson, writeJson } from './common.js';
|
|
5
6
|
|
|
6
7
|
const owned = command => {
|
|
@@ -92,7 +93,7 @@ export async function windowsSetup(id, action, argv, environment, { home = os.ho
|
|
|
92
93
|
const context = positiveInteger(options['--max-input-tokens'] || value(env, 'COPILOT_MAX_INPUT_TOKENS', '5000000'), 'max-input-tokens');
|
|
93
94
|
const maxTokens = positiveInteger(options['--max-output-tokens'] || value(env, 'COPILOT_MAX_OUTPUT_TOKENS', '65536'), 'max-output-tokens');
|
|
94
95
|
providers.push({ name: providerName, vendor: 'customendpoint', apiKey: '${input:chat.lm.secret.subconscious-gateway}', apiType: 'messages', models: modelIds(env).map(id => ({
|
|
95
|
-
id, name: `Subconscious ${id}`, url: `${gatewayUrl}/v1/messages`, toolCalling: true, vision:
|
|
96
|
+
id, name: `Subconscious ${id}`, url: `${gatewayUrl}/v1/messages`, toolCalling: true, vision: modelSupportsVision(id),
|
|
96
97
|
maxInputTokens: context, maxOutputTokens: maxTokens, thinking: true, streaming: true,
|
|
97
98
|
requestHeaders: { 'x-subconscious-client': 'copilot' },
|
|
98
99
|
})) });
|
|
@@ -131,7 +132,10 @@ export async function windowsSetup(id, action, argv, environment, { home = os.ho
|
|
|
131
132
|
if (installing) {
|
|
132
133
|
const context = positiveInteger(options['--context-window'] || value(env, 'PI_CONTEXT_WINDOW', '5000000'), 'context-window');
|
|
133
134
|
const maxTokens = positiveInteger(options['--max-tokens'] || value(env, 'PI_MAX_TOKENS', '65536'), 'max-tokens');
|
|
134
|
-
providers.subconscious = { baseUrl: `${gatewayUrl}/v1`, api: 'openai-completions', apiKey, headers: { 'x-subconscious-client': 'pi' }, models: modelIds(env).map(id => ({
|
|
135
|
+
providers.subconscious = { baseUrl: `${gatewayUrl}/v1`, api: 'openai-completions', apiKey, headers: { 'x-subconscious-client': 'pi' }, models: modelIds(env).map(id => ({
|
|
136
|
+
id, contextWindow: context, maxTokens, compat: { sendSessionAffinityHeaders: true, sessionAffinityFormat: 'openai-nosession' },
|
|
137
|
+
...(modelSupportsVision(id) ? { input: ['text', 'image'] } : {}),
|
|
138
|
+
})) };
|
|
135
139
|
await fs.mkdir(path.dirname(extension), { recursive: true });
|
|
136
140
|
await fs.copyFile(new URL('./pi-compaction.ts', import.meta.url), extension);
|
|
137
141
|
await writeJson(config, { gatewayUrl, apiKey });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "subconscious-cli",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.3",
|
|
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/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/release.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/release.test.js",
|
|
13
13
|
"test:tui": "go -C tui test ./...",
|
|
14
14
|
"prepack": "npm run build:tui",
|
|
15
15
|
"prepublishOnly": "node scripts/require-publish-script.js"
|