subconscious-cli 6.0.1 → 6.1.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.
Files changed (73) hide show
  1. package/README.md +119 -0
  2. package/bin/agent-data.js +242 -0
  3. package/bin/agent-help.js +106 -0
  4. package/bin/agent-install.js +354 -0
  5. package/bin/agent-launch.js +199 -0
  6. package/bin/agent-spawn.js +137 -0
  7. package/bin/agents.js +236 -932
  8. package/bin/auth.js +9 -1
  9. package/bin/claude-picker.js +143 -0
  10. package/bin/cli.js +60 -1
  11. package/bin/clipboard-image.js +2 -0
  12. package/bin/feedback.js +14 -3
  13. package/bin/harness-manifest.js +286 -0
  14. package/bin/headless-args.js +35 -0
  15. package/bin/launch-values.js +25 -0
  16. package/bin/model-capabilities.js +10 -9
  17. package/bin/models.js +13 -13
  18. package/bin/native/subc-tui-darwin-amd64 +0 -0
  19. package/bin/native/subc-tui-darwin-arm64 +0 -0
  20. package/bin/native/subc-tui-linux-amd64 +0 -0
  21. package/bin/native/subc-tui-linux-arm64 +0 -0
  22. package/bin/native/subc-tui-windows-amd64.exe +0 -0
  23. package/bin/native/subc-tui-windows-arm64.exe +0 -0
  24. package/bin/opencode-provider.js +21 -0
  25. package/bin/profile-settings.js +129 -0
  26. package/bin/profiles.js +29 -424
  27. package/bin/runbook/README.md +66 -23
  28. package/bin/runbook/claude-code/agent.json +300 -0
  29. package/bin/runbook/claude-code/install.sh +9 -252
  30. package/bin/runbook/codex/agent.json +461 -0
  31. package/bin/runbook/codex/hooks-lib.sh +17 -4
  32. package/bin/runbook/codex/install.sh +0 -4
  33. package/bin/runbook/codex/run.sh +16 -235
  34. package/bin/runbook/copilot/agent.json +185 -0
  35. package/bin/runbook/copilot/install.sh +45 -63
  36. package/bin/runbook/cursor/agent.json +137 -0
  37. package/bin/runbook/cursor/install.sh +8 -35
  38. package/bin/runbook/deepseek-harness/agent.json +163 -0
  39. package/bin/runbook/deepseek-harness/run.sh +20 -59
  40. package/bin/runbook/image-window/index.ts +14 -0
  41. package/bin/runbook/image-window/window.d.ts +19 -0
  42. package/bin/runbook/image-window/window.js +140 -0
  43. package/bin/runbook/lib.sh +41 -0
  44. package/bin/runbook/opencode/agent.json +158 -0
  45. package/bin/runbook/opencode/install.sh +9 -183
  46. package/bin/runbook/opencode/opencode-plugin.d.ts +10 -3
  47. package/bin/runbook/opencode/subconscious-image-window.ts +24 -0
  48. package/bin/runbook/pi/agent.json +216 -0
  49. package/bin/runbook/pi/install.sh +18 -44
  50. package/bin/runbook/pi/run.sh +6 -18
  51. package/bin/runbook/pi/subconscious-compaction.ts +3 -1
  52. package/bin/runbook/shared.json +58 -0
  53. package/bin/runbook/subconscious-code/agent.json +156 -0
  54. package/bin/sessions.js +52 -22
  55. package/bin/tui.js +13 -0
  56. package/bin/update-check.js +5 -1
  57. package/bin/upgrade.js +24 -31
  58. package/bin/usage.js +21 -10
  59. package/bin/windows/agents.js +18 -17
  60. package/bin/windows/common.js +2 -28
  61. package/bin/windows/install.js +11 -17
  62. package/bin/windows/launch.js +252 -231
  63. package/bin/windows/process.js +12 -1
  64. package/bin/windows/setup.js +29 -9
  65. package/package.json +2 -3
  66. package/bin/registry.generated.json +0 -406
  67. package/bin/runbook/claude-code/run.sh +0 -254
  68. package/bin/runbook/model-capabilities.generated.sh +0 -9
  69. package/bin/runbook/opencode/provider.sh +0 -93
  70. package/bin/runbook/opencode/run.sh +0 -99
  71. package/bin/runbook/opencode/subconscious-compaction.ts +0 -100
  72. package/bin/runbook/subconscious-code/run.sh +0 -21
  73. package/bin/windows/claude.js +0 -100
@@ -1,93 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Shared OpenCode provider metadata for subc launch and install paths.
3
-
4
- # OpenCode groups /models entries by provider.name. Keep this stable and human
5
- # readable.
6
- SUBC_OPENCODE_PROVIDER_ID="subconscious"
7
- SUBC_OPENCODE_PROVIDER_NAME="Subconscious Gateway"
8
-
9
- subc_opencode_model_display_name() {
10
- local slug="${1:-}"
11
- slug="${slug#subconscious/}"
12
- echo "$slug" | awk -F '[-_]' '
13
- function format_token(token, lower) {
14
- lower = tolower(token)
15
- if (lower ~ /^(gpt|oss|api|gguf|ggml|nomic|vl|it|mlx)$/) return toupper(token)
16
- if (token ~ /^[0-9]+[bBkKmMgG]$/) return toupper(token)
17
- if (token ~ /^[qQ][0-9]+$/) return toupper(token)
18
- if (token ~ /^[0-9]+\.[0-9]+/) return token
19
- if (token ~ /^[A-Za-z][0-9]+[A-Za-z]$/ || token ~ /^[0-9]+[A-Za-z]$/) return toupper(token)
20
- return toupper(substr(token, 1, 1)) tolower(substr(token, 2))
21
- }
22
- {
23
- out = ""
24
- for (i = 1; i <= NF; i++) {
25
- if ($i == "") continue
26
- out = out (out == "" ? "" : " ") format_token($i)
27
- }
28
- print out
29
- }
30
- '
31
- }
32
-
33
- subc_opencode_build_whitelist_json() {
34
- local model_id
35
- WHITELIST_JSON=""
36
- for model_id in "${SUPPORTED_MODELS[@]}"; do
37
- if [[ -n "$WHITELIST_JSON" ]]; then
38
- WHITELIST_JSON="${WHITELIST_JSON},\"${model_id}\""
39
- else
40
- WHITELIST_JSON="\"${model_id}\""
41
- fi
42
- done
43
- WHITELIST_JSON="[${WHITELIST_JSON}]"
44
- }
45
-
46
- subc_opencode_build_models_json() {
47
- local model_id display_name vision_fields model_json
48
- MODELS_JSON=""
49
- for model_id in "${SUPPORTED_MODELS[@]}"; do
50
- display_name="$(subc_opencode_model_display_name "$model_id")"
51
- vision_fields=""
52
- if subc_model_supports_vision "$model_id"; then
53
- vision_fields=',"attachment":true,"modalities":{"input":["text","image"],"output":["text"]}'
54
- fi
55
- model_json="\"${model_id}\":{\"name\":\"${display_name}\",\"tools\":true,\"limit\":{\"context\":${CONTEXT_LIMIT},\"output\":${OUTPUT_LIMIT}}${vision_fields}}"
56
- if [[ -n "$MODELS_JSON" ]]; then
57
- MODELS_JSON="${MODELS_JSON},${model_json}"
58
- else
59
- MODELS_JSON="$model_json"
60
- fi
61
- done
62
- subc_opencode_build_whitelist_json
63
- }
64
-
65
- subc_opencode_build_config_json() {
66
- local base_url="${1:?base url required}"
67
- local model="${2:?model required}"
68
- cat <<EOF
69
- {"\$schema":"https://opencode.ai/config.json","disabled_providers":["subconscious-cli"],"provider":{"${SUBC_OPENCODE_PROVIDER_ID}":{"npm":"@ai-sdk/openai-compatible","name":"${SUBC_OPENCODE_PROVIDER_NAME}","whitelist":${WHITELIST_JSON},"options":{"baseURL":"${base_url}","apiKey":"{env:SUBCONSCIOUS_API_KEY}","headers":{"x-subconscious-client":"opencode"},"modelsDiscovery":{"enabled":false}},"models":{${MODELS_JSON}}}},"model":"${SUBC_OPENCODE_PROVIDER_ID}/${model}"}
70
- EOF
71
- }
72
-
73
- subc_opencode_build_provider_json() {
74
- local base_url="${1:?base url required}"
75
- cat <<EOF
76
- {
77
- "npm": "@ai-sdk/openai-compatible",
78
- "name": "${SUBC_OPENCODE_PROVIDER_NAME}",
79
- "whitelist": ${WHITELIST_JSON},
80
- "options": {
81
- "baseURL": "${base_url}",
82
- "apiKey": "{env:SUBCONSCIOUS_API_KEY}",
83
- "headers": {
84
- "x-subconscious-client": "opencode"
85
- },
86
- "modelsDiscovery": {
87
- "enabled": false
88
- }
89
- },
90
- "models": {${MODELS_JSON}}
91
- }
92
- EOF
93
- }
@@ -1,99 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Point OpenCode at the Subconscious gateway — ephemerally.
3
- #
4
- # Exports SUBCONSCIOUS_API_KEY and OPENCODE_CONFIG_CONTENT as env vars so
5
- # nothing is written to ~/.opencode/opencode.json. OpenCode reads the
6
- # config from the OPENCODE_CONFIG_CONTENT env var at startup.
7
- #
8
- # Usage:
9
- # ./run.sh # uses GATEWAY_URL/API_KEY from ../.env
10
- # ./run.sh -- auth # pass args through to opencode
11
- #
12
- # Config: copy ../env.example to ../.env and edit. .env is gitignored.
13
- # Profile env is injected by subc. A sibling .env is only used when SUBC_ENV_FILE is unset.
14
- #
15
- # Or source it to just export the env:
16
- # source run.sh
17
-
18
- set -euo pipefail
19
-
20
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
- source "${SCRIPT_DIR}/../model-capabilities.generated.sh"
22
- source "${SCRIPT_DIR}/provider.sh"
23
-
24
- # Load shared env from SUBC_ENV_FILE, or a sibling .env / env.example.
25
- SHARED_ENV="${SUBC_ENV_FILE:-${SCRIPT_DIR}/../.env}"
26
- [[ -f "$SHARED_ENV" ]] || SHARED_ENV="${SCRIPT_DIR}/../env.example"
27
- if [[ -f "$SHARED_ENV" ]]; then set -a; source "$SHARED_ENV"; set +a; fi
28
-
29
- GATEWAY_URL="${GATEWAY_URL:-}"
30
- API_KEY="${OPENCODE_API_KEY:-${API_KEY:-}}"
31
- MODEL="${MODEL:-subconscious/glm-5.3-marathon}"
32
- CONTEXT_LIMIT="${OPENCODE_CONTEXT_LIMIT:-5000000}"
33
- OUTPUT_LIMIT="${OPENCODE_OUTPUT_LIMIT:-65536}"
34
-
35
- DEFAULT_SUBCONSCIOUS_MODELS="subconscious/glm-5.3-marathon
36
- subconscious/glm-5.2
37
- subconscious/tim-qwen3.6-27b
38
- subconscious/deepseek-v4-flash-marathon
39
- subconscious/deepseek-v4.1-flash-marathon"
40
- SUPPORTED_MODELS=()
41
-
42
- add_supported_model() {
43
- local model_id="$1" existing
44
- [[ -n "$model_id" ]] || return 0
45
- if [[ ! "$model_id" =~ ^[-A-Za-z0-9._:/+]+$ ]]; then
46
- echo "error: invalid model id: $model_id" >&2
47
- exit 1
48
- fi
49
- if [[ "${#SUPPORTED_MODELS[@]}" -gt 0 ]]; then
50
- for existing in "${SUPPORTED_MODELS[@]}"; do
51
- [[ "$existing" == "$model_id" ]] && return 0
52
- done
53
- fi
54
- SUPPORTED_MODELS+=("$model_id")
55
- }
56
-
57
- add_supported_model "$MODEL"
58
- while IFS= read -r model_id; do
59
- add_supported_model "$model_id"
60
- done <<< "${SUBCONSCIOUS_MODELS:-$DEFAULT_SUBCONSCIOUS_MODELS}"
61
-
62
- subc_opencode_build_models_json
63
-
64
- if [[ -z "$GATEWAY_URL" || -z "$API_KEY" ]]; then
65
- echo "error: GATEWAY_URL and API_KEY must be set in ../.env" >&2
66
- exit 1
67
- fi
68
-
69
- # Parse args (only when executed, not sourced)
70
- PASSTHRU=()
71
- if [[ "${BASH_SOURCE[0]:-$0}" == "${0}" ]]; then
72
- while [[ $# -gt 0 ]]; do
73
- case "$1" in
74
- --)
75
- shift
76
- PASSTHRU+=("$@")
77
- break
78
- ;;
79
- *)
80
- PASSTHRU+=("$1")
81
- shift
82
- ;;
83
- esac
84
- done
85
- fi
86
-
87
- BASE_URL="${GATEWAY_URL%/}/v1"
88
-
89
- export SUBCONSCIOUS_API_KEY="$API_KEY"
90
- # Compaction reporting needs the plugin on disk; this launch path writes nothing.
91
- export SUBCONSCIOUS_GATEWAY_URL="${GATEWAY_URL%/}"
92
- export OPENCODE_CONFIG_CONTENT="$(subc_opencode_build_config_json "$BASE_URL" "$MODEL")"
93
-
94
- # If sourced, just export env and return.
95
- if [[ "${BASH_SOURCE[0]:-$0}" != "${0}" ]]; then
96
- return 0 2>/dev/null || true
97
- fi
98
-
99
- exec opencode ${PASSTHRU[@]+"${PASSTHRU[@]}"}
@@ -1,100 +0,0 @@
1
- /**
2
- * Report OpenCode compactions to the Subconscious API Gateway.
3
- *
4
- * Why this exists: OpenCode summarizes by issuing an ordinary completion through the
5
- * configured provider, which is the gateway, carrying the same session headers as every
6
- * other turn. Without a signal the gateway would count that summarization as the largest
7
- * main-thread turn of the conversation, inflating peak context and the traditional
8
- * comparison at exactly the turn where accuracy matters most.
9
- *
10
- * Two callbacks bracket it:
11
- * experimental.session.compacting -> phase "start" (awaited, so it is ordered before
12
- * the summarization request reaches the gateway)
13
- * session.compacted event -> phase "end"
14
- *
15
- * Requests between them are the compaction. `sessionID` is the same value OpenCode sends
16
- * as x-session-affinity / x-session-id, which is already the gateway's grouping key, so
17
- * no fingerprinting is involved.
18
- *
19
- * Fail open: a gateway that is down or slow must never disturb a coding session.
20
- *
21
- * Install: copy to ~/.config/opencode/plugins/ (global) or .opencode/plugins/ (project).
22
- * `opencode/install.sh` does this for you.
23
- */
24
-
25
- import type { Plugin } from '@opencode-ai/plugin';
26
-
27
- const TIMEOUT_MS = 2000;
28
-
29
- function gatewayUrl(): string | undefined {
30
- const raw = process.env.SUBCONSCIOUS_GATEWAY_URL ?? process.env.GATEWAY_URL;
31
- return raw ? raw.replace(/\/+$/, '') : undefined;
32
- }
33
-
34
- function apiKey(): string | undefined {
35
- return process.env.SUBCONSCIOUS_API_KEY ?? process.env.API_KEY;
36
- }
37
-
38
- async function report(
39
- sessionID: string,
40
- phase: 'start' | 'end',
41
- hookEventName: string,
42
- ): Promise<void> {
43
- const url = gatewayUrl();
44
- const key = apiKey();
45
- if (!url || !key || !sessionID) return;
46
-
47
- // Idempotency key for this one event. It must be unique per compaction but stable for
48
- // a redelivery of this same POST, so it is derived from the wall clock rather than any
49
- // in-process counter: a counter resets when OpenCode restarts, and a resumed session
50
- // compacting again would then reuse a key the gateway has already seen and silently
51
- // drop the signal. Computed once here, before the request, so a transport-level retry
52
- // carries the identical body.
53
- const dedupeKey = `${sessionID}:${phase}:${Date.now()}`;
54
-
55
- const controller = new AbortController();
56
- const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
57
- try {
58
- await fetch(`${url}/v1/agent-hooks`, {
59
- method: 'POST',
60
- headers: {
61
- 'content-type': 'application/json',
62
- authorization: `Bearer ${key}`,
63
- 'x-subconscious-client': 'opencode',
64
- },
65
- body: JSON.stringify({
66
- event: 'conversation_compaction',
67
- conversation_id: sessionID,
68
- phase,
69
- hook_event_name: hookEventName,
70
- dedupe_key: dedupeKey,
71
- }),
72
- signal: controller.signal,
73
- });
74
- } catch {
75
- // Fail open on timeout, offline gateway, or auth failure.
76
- } finally {
77
- clearTimeout(timer);
78
- }
79
- }
80
-
81
- export const SubconsciousCompaction: Plugin = async () => {
82
- return {
83
- 'experimental.session.compacting': async (input) => {
84
- // Deliberately does not touch `output`: mutating `context` would change the
85
- // customer's compaction prompt, and setting `prompt` would replace it entirely.
86
- await report(input.sessionID, 'start', 'session.compacting');
87
- },
88
- event: async ({ event }) => {
89
- if (event.type === 'session.compacted') {
90
- const sessionID = (event as { properties?: { sessionID?: string } })
91
- .properties?.sessionID;
92
- if (sessionID) {
93
- // No shared id with the matching `start` is needed: the gateway pairs a start
94
- // with the next end by server-stamped time, not by key.
95
- await report(sessionID, 'end', 'session.compacted');
96
- }
97
- }
98
- },
99
- };
100
- };
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Launch Marathon without changing ~/.sc or project settings.
3
-
4
- set -euo pipefail
5
-
6
- GATEWAY_URL="${GATEWAY_URL:-}"
7
- API_KEY="${SC_API_KEY:-${API_KEY:-}}"
8
- MODEL="${MODEL:-subconscious/glm-5.3-marathon}"
9
-
10
- if [[ -z "$GATEWAY_URL" || -z "$API_KEY" ]]; then
11
- echo "error: GATEWAY_URL and API_KEY are required to launch Marathon" >&2
12
- exit 1
13
- fi
14
-
15
- export SC_API_KEY="$API_KEY"
16
- export SC_BASE_URL="${GATEWAY_URL%/}/v1"
17
- export SC_DLR_URL="${GATEWAY_URL%/}"
18
- export SC_DLR_ENABLED=true
19
- export SC_MODEL="$MODEL"
20
-
21
- exec marathon "$@"
@@ -1,100 +0,0 @@
1
- // Windows-only equivalent of the existing Claude shell launch.
2
- import { readFileSync } from 'node:fs';
3
- import { resolvedModelSetting } from '../profiles.js';
4
- import { parseOptions, positiveInteger } from './common.js';
5
-
6
- const DEFAULTS = JSON.parse(
7
- readFileSync(new URL('../registry.generated.json', import.meta.url), 'utf8'),
8
- ).defaults;
9
- function claudePickerSettings(models) {
10
- return {
11
- availableModels: models,
12
- modelPicker: {
13
- replaceBuiltInOptions: true,
14
- options: models.map((model) => ({
15
- model,
16
- label: model,
17
- description: `Subconscious model ${model}`,
18
- })),
19
- },
20
- };
21
- }
22
-
23
- export function claudeNativeLaunch(argv, environment) {
24
- const { options, rest: passthrough } = parseOptions(argv, {
25
- '--gateway-url': 1,
26
- '--api-key': 1,
27
- '--model': 1,
28
- '--compact-window': 1,
29
- '--max-context-tokens': 1,
30
- });
31
- const gatewayUrl =
32
- options['--gateway-url'] || environment.GATEWAY_URL?.trim() || '';
33
- const apiKey =
34
- options['--api-key'] ||
35
- environment.CLAUDE_CODE_API_KEY?.trim() ||
36
- environment.API_KEY?.trim() ||
37
- '';
38
- const model =
39
- options['--model'] || environment.MODEL?.trim() || DEFAULTS.model;
40
- const compactWindow =
41
- options['--compact-window'] ||
42
- environment.CLAUDE_CODE_AUTO_COMPACT_WINDOW?.trim() ||
43
- environment.COMPACT_WINDOW?.trim() ||
44
- '1000000';
45
- const maxContextTokens =
46
- options['--max-context-tokens'] ||
47
- environment.CLAUDE_CODE_MAX_CONTEXT_TOKENS?.trim() ||
48
- environment.MAX_CONTEXT_TOKENS?.trim() ||
49
- '3000000';
50
-
51
- if (!gatewayUrl || !apiKey) {
52
- throw new Error(
53
- 'GATEWAY_URL and API_KEY are required to launch Claude Code',
54
- );
55
- }
56
- positiveInteger(compactWindow, 'compact-window');
57
- positiveInteger(maxContextTokens, 'max-context-tokens');
58
-
59
- const effectiveGatewayUrl =
60
- environment.CLAUDE_GATEWAY_URL?.trim() || gatewayUrl;
61
- const subagentModel =
62
- resolvedModelSetting(environment.CLAUDE_CODE_SUBAGENT_MODEL) || model;
63
- const settings =
64
- environment.SUBC_CLAUDE_SETTINGS?.trim() ||
65
- JSON.stringify(claudePickerSettings([model], model));
66
- const withoutTrailingSlash = effectiveGatewayUrl.replace(/\/+$/, '');
67
- const env = {
68
- ...environment,
69
- ANTHROPIC_BASE_URL: effectiveGatewayUrl,
70
- ANTHROPIC_AUTH_TOKEN: apiKey,
71
- ANTHROPIC_MODEL: environment.ANTHROPIC_MODEL?.trim() || model,
72
- ANTHROPIC_SMALL_FAST_MODEL:
73
- environment.ANTHROPIC_SMALL_FAST_MODEL?.trim() || model,
74
- CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY:
75
- environment.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY?.trim() || '0',
76
- CLAUDE_CODE_SUBAGENT_MODEL: subagentModel,
77
- CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS:
78
- environment.MAX_CONCURRENT_SUBAGENTS?.trim() || '4',
79
- CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH:
80
- environment.MAX_SUBAGENT_SPAWN_DEPTH?.trim() || '1',
81
- CLAUDE_CODE_AUTO_COMPACT_WINDOW: compactWindow,
82
- CLAUDE_CODE_MAX_CONTEXT_TOKENS: maxContextTokens,
83
- CLAUDE_CODE_ENABLE_TELEMETRY:
84
- environment.CLAUDE_CODE_ENABLE_TELEMETRY?.trim() || '1',
85
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:
86
- environment.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC?.trim() || '1',
87
- ENABLE_CLAUDEAI_MCP_SERVERS: 'false',
88
- OTEL_LOGS_EXPORTER: environment.OTEL_LOGS_EXPORTER?.trim() || 'otlp',
89
- OTEL_EXPORTER_OTLP_PROTOCOL:
90
- environment.OTEL_EXPORTER_OTLP_PROTOCOL?.trim() || 'http/json',
91
- OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: `${withoutTrailingSlash}/v1/logs`,
92
- OTEL_EXPORTER_OTLP_HEADERS: `x-api-key=${apiKey}`,
93
- OTEL_EXPORTER_OTLP_TIMEOUT:
94
- environment.OTEL_EXPORTER_OTLP_TIMEOUT?.trim() || '2000',
95
- OTEL_LOGS_EXPORT_INTERVAL:
96
- environment.OTEL_LOGS_EXPORT_INTERVAL?.trim() || '2000',
97
- };
98
-
99
- return { args: ['--settings', settings, ...passthrough], env };
100
- }