subconscious-cli 6.0.0 → 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.
- package/README.md +135 -2
- package/bin/agent-data.js +242 -0
- package/bin/agent-help.js +106 -0
- package/bin/agent-install.js +354 -0
- package/bin/agent-launch.js +199 -0
- package/bin/agent-spawn.js +137 -0
- package/bin/agents.js +284 -840
- package/bin/auth.js +89 -33
- package/bin/branding.js +3 -1
- package/bin/claude-picker.js +143 -0
- package/bin/cli.js +87 -20
- package/bin/clipboard-image.js +24 -5
- package/bin/colors.js +1 -1
- package/bin/feedback.js +71 -21
- package/bin/harness-manifest.js +286 -0
- package/bin/headless-args.js +35 -0
- package/bin/launch-values.js +25 -0
- package/bin/model-capabilities.js +12 -8
- package/bin/models.js +35 -19
- 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/opencode-provider.js +48 -5
- package/bin/profile-settings.js +129 -0
- package/bin/profiles.js +136 -449
- package/bin/runbook/README.md +66 -23
- package/bin/runbook/claude-code/agent.json +300 -0
- package/bin/runbook/claude-code/install.sh +9 -252
- package/bin/runbook/codex/agent.json +461 -0
- package/bin/runbook/codex/hooks-lib.sh +17 -4
- package/bin/runbook/codex/install.sh +0 -4
- package/bin/runbook/codex/run.sh +16 -235
- package/bin/runbook/copilot/agent.json +185 -0
- package/bin/runbook/copilot/install.sh +45 -63
- package/bin/runbook/cursor/agent.json +137 -0
- package/bin/runbook/cursor/install.sh +8 -35
- package/bin/runbook/deepseek-harness/agent.json +163 -0
- package/bin/runbook/deepseek-harness/run.sh +20 -59
- package/bin/runbook/image-window/index.ts +14 -0
- package/bin/runbook/image-window/window.d.ts +19 -0
- package/bin/runbook/image-window/window.js +140 -0
- package/bin/runbook/lib.sh +41 -0
- package/bin/runbook/opencode/agent.json +158 -0
- package/bin/runbook/opencode/install.sh +9 -183
- package/bin/runbook/opencode/opencode-plugin.d.ts +16 -0
- package/bin/runbook/opencode/subconscious-image-window.ts +24 -0
- package/bin/runbook/pi/agent.json +216 -0
- package/bin/runbook/pi/install.sh +18 -44
- package/bin/runbook/pi/run.sh +6 -18
- package/bin/runbook/pi/subconscious-compaction.ts +71 -49
- package/bin/runbook/shared.json +58 -0
- package/bin/runbook/subconscious-code/agent.json +156 -0
- package/bin/sessions.js +173 -58
- package/bin/tui.js +104 -32
- package/bin/update-check.js +54 -21
- package/bin/upgrade.js +67 -43
- package/bin/usage.js +47 -24
- package/bin/windows/agents.js +141 -37
- package/bin/windows/common.js +36 -25
- package/bin/windows/install.js +116 -34
- package/bin/windows/launch.js +260 -77
- package/bin/windows/pi-compaction.ts +68 -13
- package/bin/windows/process.js +210 -57
- package/bin/windows/setup.js +251 -56
- package/package.json +9 -4
- package/bin/registry.generated.json +0 -406
- package/bin/runbook/claude-code/run.sh +0 -254
- package/bin/runbook/model-capabilities.generated.sh +0 -9
- package/bin/runbook/opencode/provider.sh +0 -93
- package/bin/runbook/opencode/run.sh +0 -99
- package/bin/runbook/opencode/subconscious-compaction.ts +0 -100
- package/bin/runbook/subconscious-code/run.sh +0 -21
- package/bin/windows/claude.js +0 -71
package/bin/windows/setup.js
CHANGED
|
@@ -1,22 +1,53 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { agentById } from '../agent-data.js';
|
|
5
|
+
import { resolveInputs } from '../agent-launch.js';
|
|
4
6
|
import { modelSupportsVision } from '../model-capabilities.js';
|
|
5
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
defaults,
|
|
9
|
+
modelIds,
|
|
10
|
+
object,
|
|
11
|
+
origin,
|
|
12
|
+
parseOptions,
|
|
13
|
+
positiveInteger,
|
|
14
|
+
readJson,
|
|
15
|
+
value,
|
|
16
|
+
writeJson,
|
|
17
|
+
} from './common.js';
|
|
6
18
|
|
|
7
|
-
const owned = command => {
|
|
19
|
+
const owned = (command) => {
|
|
8
20
|
if (typeof command !== 'string') return false;
|
|
9
21
|
if (/subconscious-hook\.(?:sh|cjs)/.test(command)) return true;
|
|
10
22
|
const encoded = /-EncodedCommand ([A-Za-z0-9+/=]+)$/i.exec(command)?.[1];
|
|
11
|
-
return Boolean(
|
|
23
|
+
return Boolean(
|
|
24
|
+
encoded &&
|
|
25
|
+
Buffer.from(encoded, 'base64')
|
|
26
|
+
.toString('utf16le')
|
|
27
|
+
.startsWith('# SUBC_WINDOWS_HOOK\n'),
|
|
28
|
+
);
|
|
12
29
|
};
|
|
13
30
|
const providerName = 'Subconscious Gateway';
|
|
14
|
-
const exists = async
|
|
31
|
+
const exists = async (file) => {
|
|
32
|
+
try {
|
|
33
|
+
await fs.access(file);
|
|
34
|
+
return true;
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
15
39
|
|
|
16
40
|
// Hook hosts expect command strings. Keep paths and credentials out of shell
|
|
17
41
|
// syntax: PowerShell decodes data, then invokes Node with an argv array.
|
|
18
|
-
export function windowsHookCommand(
|
|
19
|
-
|
|
42
|
+
export function windowsHookCommand(
|
|
43
|
+
client,
|
|
44
|
+
script,
|
|
45
|
+
config,
|
|
46
|
+
node = process.execPath,
|
|
47
|
+
) {
|
|
48
|
+
const data = Buffer.from(
|
|
49
|
+
JSON.stringify({ client, script, config, node }),
|
|
50
|
+
).toString('base64');
|
|
20
51
|
const source = `# SUBC_WINDOWS_HOOK\n$d = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${data}')) | ConvertFrom-Json\n& $d.node $d.script $d.client $d.config\nexit 0`;
|
|
21
52
|
return `powershell.exe -NoLogo -NoProfile -NonInteractive -EncodedCommand ${Buffer.from(source, 'utf16le').toString('base64')}`;
|
|
22
53
|
}
|
|
@@ -25,26 +56,45 @@ export function mergeHooks(document, client, command) {
|
|
|
25
56
|
const result = structuredClone(object(document, 'hooks configuration'));
|
|
26
57
|
const hooks = object(result.hooks ?? {}, 'hooks');
|
|
27
58
|
for (const [event, entries] of Object.entries(hooks)) {
|
|
28
|
-
if (!Array.isArray(entries))
|
|
59
|
+
if (!Array.isArray(entries))
|
|
60
|
+
throw new Error(`hooks.${event} must be an array; leaving it unchanged`);
|
|
29
61
|
const kept = [];
|
|
30
62
|
for (const entry of entries) {
|
|
31
63
|
object(entry, `hooks.${event} entry`);
|
|
32
64
|
if (Array.isArray(entry.hooks)) {
|
|
33
65
|
for (const hook of entry.hooks) object(hook, `hooks.${event} command`);
|
|
34
|
-
const filtered = entry.hooks.filter(hook => !owned(hook.command));
|
|
35
|
-
if (filtered.length || entry.hooks.length === 0)
|
|
66
|
+
const filtered = entry.hooks.filter((hook) => !owned(hook.command));
|
|
67
|
+
if (filtered.length || entry.hooks.length === 0)
|
|
68
|
+
kept.push({ ...entry, hooks: filtered });
|
|
36
69
|
} else if (entry.hooks !== undefined) {
|
|
37
|
-
throw new Error(
|
|
70
|
+
throw new Error(
|
|
71
|
+
`hooks.${event}.hooks must be an array; leaving it unchanged`,
|
|
72
|
+
);
|
|
38
73
|
} else if (!owned(entry.command)) kept.push(entry);
|
|
39
74
|
}
|
|
40
75
|
if (kept.length) hooks[event] = kept;
|
|
41
76
|
else delete hooks[event];
|
|
42
77
|
}
|
|
43
78
|
if (command) {
|
|
44
|
-
const events = {
|
|
79
|
+
const events = {
|
|
80
|
+
codex: ['PreCompact', 'PostCompact'],
|
|
81
|
+
cursor: ['beforeSubmitPrompt', 'preCompact'],
|
|
82
|
+
copilot: ['UserPromptSubmit', 'PreCompact'],
|
|
83
|
+
}[client];
|
|
45
84
|
for (const event of events) {
|
|
46
|
-
const hook = {
|
|
47
|
-
|
|
85
|
+
const hook = {
|
|
86
|
+
type: 'command',
|
|
87
|
+
command,
|
|
88
|
+
timeout: client === 'copilot' ? 5 : 3,
|
|
89
|
+
};
|
|
90
|
+
const entry =
|
|
91
|
+
client === 'codex'
|
|
92
|
+
? {
|
|
93
|
+
hooks: [
|
|
94
|
+
{ ...hook, statusMessage: 'Reporting Subconscious compaction' },
|
|
95
|
+
],
|
|
96
|
+
}
|
|
97
|
+
: hook;
|
|
48
98
|
hooks[event] = [...(hooks[event] || []), entry];
|
|
49
99
|
}
|
|
50
100
|
}
|
|
@@ -53,55 +103,130 @@ export function mergeHooks(document, client, command) {
|
|
|
53
103
|
return result;
|
|
54
104
|
}
|
|
55
105
|
|
|
56
|
-
export async function windowsSetup(
|
|
106
|
+
export async function windowsSetup(
|
|
107
|
+
id,
|
|
108
|
+
action,
|
|
109
|
+
argv,
|
|
110
|
+
environment,
|
|
111
|
+
{ home = os.homedir(), log = console.log } = {},
|
|
112
|
+
) {
|
|
57
113
|
const schema = { '--gateway-url': 1, '--api-key': 1, '--model': 1 };
|
|
58
|
-
if (id === 'copilot')
|
|
59
|
-
|
|
114
|
+
if (id === 'copilot')
|
|
115
|
+
Object.assign(schema, {
|
|
116
|
+
'--vscode-app': 1,
|
|
117
|
+
'--max-input-tokens': 1,
|
|
118
|
+
'--max-output-tokens': 1,
|
|
119
|
+
});
|
|
120
|
+
if (id === 'pi')
|
|
121
|
+
Object.assign(schema, { '--context-window': 1, '--max-tokens': 1 });
|
|
60
122
|
const { options } = parseOptions(argv, schema, { strict: true });
|
|
61
|
-
const
|
|
62
|
-
const
|
|
123
|
+
const agent = agentById(id);
|
|
124
|
+
const env = resolveInputs(
|
|
125
|
+
agent,
|
|
126
|
+
{
|
|
127
|
+
...environment,
|
|
128
|
+
...(options['--model'] ? { MODEL: options['--model'] } : {}),
|
|
129
|
+
},
|
|
130
|
+
{},
|
|
131
|
+
{ strict: false },
|
|
132
|
+
);
|
|
133
|
+
const gatewayUrl = origin(
|
|
134
|
+
options['--gateway-url'] || value(env, 'GATEWAY_URL', defaults.baseUrl),
|
|
135
|
+
);
|
|
63
136
|
const apiKey = options['--api-key'] || value(env, 'API_KEY');
|
|
64
137
|
const installing = action === 'install';
|
|
65
138
|
const removing = action === 'uninstall';
|
|
66
139
|
const needsKey = ['codex', 'cursor', 'copilot', 'pi'].includes(id);
|
|
67
|
-
if (installing && needsKey && !apiKey)
|
|
140
|
+
if (installing && needsKey && !apiKey)
|
|
141
|
+
throw new Error('An API key is required for setup. Run subc login first.');
|
|
68
142
|
|
|
69
143
|
if (['codex', 'cursor', 'copilot'].includes(id)) {
|
|
70
|
-
const dir =
|
|
71
|
-
|
|
144
|
+
const dir =
|
|
145
|
+
id === 'codex'
|
|
146
|
+
? env.CODEX_DIR || env.CODEX_HOME || path.join(home, '.codex')
|
|
147
|
+
: path.join(home, `.${id}`);
|
|
148
|
+
const hooksFile =
|
|
149
|
+
id === 'copilot'
|
|
150
|
+
? path.join(dir, 'hooks', 'subconscious-hooks.json')
|
|
151
|
+
: path.join(dir, 'hooks.json');
|
|
72
152
|
const script = path.join(dir, 'hooks', 'subconscious-hook.cjs');
|
|
73
153
|
const config = path.join(dir, 'subconscious-windows.json');
|
|
74
154
|
const document = await readJson(hooksFile, {});
|
|
75
155
|
// Validate all existing user configuration before writing any files.
|
|
76
|
-
const merged = mergeHooks(
|
|
156
|
+
const merged = mergeHooks(
|
|
157
|
+
document,
|
|
158
|
+
id,
|
|
159
|
+
installing ? windowsHookCommand(id, script, config) : null,
|
|
160
|
+
);
|
|
77
161
|
let providerFile, providers;
|
|
78
162
|
if (id === 'copilot') {
|
|
79
163
|
const apps = ['Code', 'Code - Insiders', 'VSCodium'];
|
|
80
164
|
const appData = env.APPDATA || path.join(home, 'AppData', 'Roaming');
|
|
81
165
|
let app = options['--vscode-app'] || env.VSCODE_APP;
|
|
82
|
-
if (app && !apps.includes(app))
|
|
166
|
+
if (app && !apps.includes(app))
|
|
167
|
+
throw new Error(
|
|
168
|
+
'--vscode-app must be Code, Code - Insiders, or VSCodium',
|
|
169
|
+
);
|
|
83
170
|
if (!app) {
|
|
84
|
-
for (const candidate of apps)
|
|
171
|
+
for (const candidate of apps)
|
|
172
|
+
if (await exists(path.join(appData, candidate, 'User'))) {
|
|
173
|
+
app = candidate;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
85
176
|
app ||= 'Code';
|
|
86
177
|
}
|
|
87
178
|
providerFile = path.join(appData, app, 'User', 'chatLanguageModels.json');
|
|
88
179
|
const current = await readJson(providerFile, []);
|
|
89
|
-
if (!Array.isArray(current))
|
|
90
|
-
|
|
91
|
-
|
|
180
|
+
if (!Array.isArray(current))
|
|
181
|
+
throw new Error(
|
|
182
|
+
`${providerFile} must be a JSON array; leaving it unchanged`,
|
|
183
|
+
);
|
|
184
|
+
for (const provider of current)
|
|
185
|
+
object(provider, 'language model provider');
|
|
186
|
+
providers = current.filter((provider) => provider.name !== providerName);
|
|
92
187
|
if (installing) {
|
|
93
|
-
const context = positiveInteger(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
188
|
+
const context = positiveInteger(
|
|
189
|
+
options['--max-input-tokens'] ||
|
|
190
|
+
value(env, 'COPILOT_MAX_INPUT_TOKENS'),
|
|
191
|
+
'max-input-tokens',
|
|
192
|
+
);
|
|
193
|
+
const maxTokens = positiveInteger(
|
|
194
|
+
options['--max-output-tokens'] ||
|
|
195
|
+
value(env, 'COPILOT_MAX_OUTPUT_TOKENS'),
|
|
196
|
+
'max-output-tokens',
|
|
197
|
+
);
|
|
198
|
+
providers.push({
|
|
199
|
+
name: providerName,
|
|
200
|
+
vendor: 'customendpoint',
|
|
201
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: VS Code secret input, not a JS template
|
|
202
|
+
apiKey: '${input:chat.lm.secret.subconscious-gateway}',
|
|
203
|
+
apiType: 'messages',
|
|
204
|
+
models: modelIds(env).map((id) => ({
|
|
205
|
+
id,
|
|
206
|
+
name: `Subconscious ${id}`,
|
|
207
|
+
url: `${gatewayUrl}/v1/messages`,
|
|
208
|
+
toolCalling: true,
|
|
209
|
+
vision: modelSupportsVision(id),
|
|
210
|
+
maxInputTokens: context,
|
|
211
|
+
maxOutputTokens: maxTokens,
|
|
212
|
+
thinking: true,
|
|
213
|
+
streaming: true,
|
|
214
|
+
requestHeaders: { 'x-subconscious-client': 'copilot' },
|
|
215
|
+
})),
|
|
216
|
+
});
|
|
100
217
|
}
|
|
101
218
|
}
|
|
102
219
|
if (action === 'status') {
|
|
103
|
-
const hasHook = Object.values(document.hooks || {}).some(entries
|
|
104
|
-
|
|
220
|
+
const hasHook = Object.values(document.hooks || {}).some((entries) =>
|
|
221
|
+
entries.some(
|
|
222
|
+
(entry) =>
|
|
223
|
+
owned(entry.command) ||
|
|
224
|
+
entry.hooks?.some((hook) => owned(hook.command)),
|
|
225
|
+
),
|
|
226
|
+
);
|
|
227
|
+
log(
|
|
228
|
+
`${id}: ${hasHook ? 'Subconscious hooks installed' : 'no Subconscious hooks'} (${hooksFile})`,
|
|
229
|
+
);
|
|
105
230
|
if (providerFile) log(`Model configuration: ${providerFile}`);
|
|
106
231
|
return 0;
|
|
107
232
|
}
|
|
@@ -110,14 +235,22 @@ export async function windowsSetup(id, action, argv, environment, { home = os.ho
|
|
|
110
235
|
await fs.copyFile(new URL('./hook.cjs', import.meta.url), script);
|
|
111
236
|
await writeJson(config, { gatewayUrl, apiKey });
|
|
112
237
|
}
|
|
113
|
-
if (installing || await exists(hooksFile))
|
|
114
|
-
|
|
238
|
+
if (installing || (await exists(hooksFile)))
|
|
239
|
+
await writeJson(hooksFile, merged);
|
|
240
|
+
if (providerFile && (installing || (await exists(providerFile))))
|
|
241
|
+
await writeJson(providerFile, providers);
|
|
115
242
|
if (removing) {
|
|
116
243
|
await fs.rm(script, { force: true });
|
|
117
244
|
await fs.rm(config, { force: true });
|
|
118
245
|
}
|
|
119
|
-
if (installing && id === 'cursor')
|
|
120
|
-
|
|
246
|
+
if (installing && id === 'cursor')
|
|
247
|
+
log(
|
|
248
|
+
`In Cursor Settings, use ${gatewayUrl}/v1, your API key, and model ${value(env, 'MODEL', defaults.model)}. Restart Cursor to load hooks.`,
|
|
249
|
+
);
|
|
250
|
+
if (installing && id === 'copilot')
|
|
251
|
+
log(
|
|
252
|
+
'Restart VS Code, select a Subconscious model, and enter your API key when prompted.',
|
|
253
|
+
);
|
|
121
254
|
log(`${id}: Windows integration ${installing ? 'installed' : 'removed'}.`);
|
|
122
255
|
return 0;
|
|
123
256
|
}
|
|
@@ -126,46 +259,108 @@ export async function windowsSetup(id, action, argv, environment, { home = os.ho
|
|
|
126
259
|
const modelsFile = path.join(dir, 'models.json');
|
|
127
260
|
const document = object(await readJson(modelsFile, {}), 'Pi models');
|
|
128
261
|
const providers = object(document.providers ?? {}, 'Pi providers');
|
|
129
|
-
if (action === 'status') {
|
|
130
|
-
|
|
262
|
+
if (action === 'status') {
|
|
263
|
+
log(
|
|
264
|
+
`Pi: ${providers.subconscious ? 'Subconscious provider installed' : 'not installed'} (${modelsFile})`,
|
|
265
|
+
);
|
|
266
|
+
return 0;
|
|
267
|
+
}
|
|
268
|
+
const extension = path.join(
|
|
269
|
+
dir,
|
|
270
|
+
'extensions',
|
|
271
|
+
'subconscious-compaction.ts',
|
|
272
|
+
);
|
|
273
|
+
// Keeps requests at the newest 30 images; same files as the shell runbook.
|
|
274
|
+
const imageWindow = path.join(
|
|
275
|
+
dir,
|
|
276
|
+
'extensions',
|
|
277
|
+
'subconscious-image-window',
|
|
278
|
+
);
|
|
131
279
|
const config = path.join(dir, 'subconscious-windows.json');
|
|
132
280
|
if (installing) {
|
|
133
|
-
const context = positiveInteger(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
281
|
+
const context = positiveInteger(
|
|
282
|
+
options['--context-window'] || value(env, 'PI_CONTEXT_WINDOW'),
|
|
283
|
+
'context-window',
|
|
284
|
+
);
|
|
285
|
+
const maxTokens = positiveInteger(
|
|
286
|
+
options['--max-tokens'] || value(env, 'PI_MAX_TOKENS'),
|
|
287
|
+
'max-tokens',
|
|
288
|
+
);
|
|
289
|
+
providers.subconscious = {
|
|
290
|
+
baseUrl: `${gatewayUrl}/v1`,
|
|
291
|
+
api: 'openai-completions',
|
|
292
|
+
apiKey,
|
|
293
|
+
headers: { 'x-subconscious-client': 'pi' },
|
|
294
|
+
models: modelIds(env).map((id) => ({
|
|
295
|
+
id,
|
|
296
|
+
contextWindow: context,
|
|
297
|
+
maxTokens,
|
|
298
|
+
compat: {
|
|
299
|
+
sendSessionAffinityHeaders: true,
|
|
300
|
+
sessionAffinityFormat: 'openai-nosession',
|
|
301
|
+
},
|
|
302
|
+
...(modelSupportsVision(id) ? { input: ['text', 'image'] } : {}),
|
|
303
|
+
})),
|
|
304
|
+
};
|
|
139
305
|
await fs.mkdir(path.dirname(extension), { recursive: true });
|
|
140
|
-
await fs.copyFile(
|
|
306
|
+
await fs.copyFile(
|
|
307
|
+
new URL('./pi-compaction.ts', import.meta.url),
|
|
308
|
+
extension,
|
|
309
|
+
);
|
|
310
|
+
await fs.rm(imageWindow, { recursive: true, force: true });
|
|
311
|
+
await fs.cp(
|
|
312
|
+
new URL('../runbook/image-window', import.meta.url),
|
|
313
|
+
imageWindow,
|
|
314
|
+
{ recursive: true },
|
|
315
|
+
);
|
|
141
316
|
await writeJson(config, { gatewayUrl, apiKey });
|
|
142
317
|
} else {
|
|
143
318
|
delete providers.subconscious;
|
|
144
319
|
await fs.rm(extension, { force: true });
|
|
320
|
+
await fs.rm(imageWindow, { recursive: true, force: true });
|
|
145
321
|
await fs.rm(config, { force: true });
|
|
146
322
|
}
|
|
147
|
-
if (installing || await exists(modelsFile))
|
|
323
|
+
if (installing || (await exists(modelsFile)))
|
|
324
|
+
await writeJson(modelsFile, { ...document, providers });
|
|
148
325
|
log(`Pi: Windows integration ${installing ? 'installed' : 'removed'}.`);
|
|
149
326
|
return 0;
|
|
150
327
|
}
|
|
151
328
|
if (id === 'claude-code' || id === 'opencode') {
|
|
152
329
|
const dir = path.join(home, id === 'claude-code' ? '.claude' : '.opencode');
|
|
153
|
-
const legacy = path.join(
|
|
330
|
+
const legacy = path.join(
|
|
331
|
+
dir,
|
|
332
|
+
id === 'claude-code' ? 'subconscious-gateway.env' : 'subconscious.env',
|
|
333
|
+
);
|
|
154
334
|
let present = await exists(legacy);
|
|
155
335
|
if (id === 'opencode') {
|
|
156
336
|
const file = path.join(dir, 'opencode.json');
|
|
157
|
-
const document = object(
|
|
158
|
-
|
|
337
|
+
const document = object(
|
|
338
|
+
await readJson(file, {}),
|
|
339
|
+
'OpenCode configuration',
|
|
340
|
+
);
|
|
341
|
+
if (document.provider !== undefined)
|
|
342
|
+
object(document.provider, 'OpenCode providers');
|
|
159
343
|
present ||= Boolean(document.provider?.subconscious);
|
|
160
|
-
if (removing && await exists(file)) {
|
|
344
|
+
if (removing && (await exists(file))) {
|
|
161
345
|
if (document.provider) delete document.provider.subconscious;
|
|
162
346
|
if (document.model?.startsWith('subconscious/')) delete document.model;
|
|
163
347
|
await writeJson(file, document);
|
|
164
348
|
}
|
|
165
|
-
if (removing)
|
|
349
|
+
if (removing)
|
|
350
|
+
await fs.rm(
|
|
351
|
+
path.join(
|
|
352
|
+
env.XDG_CONFIG_HOME || path.join(home, '.config'),
|
|
353
|
+
'opencode',
|
|
354
|
+
'plugins',
|
|
355
|
+
'subconscious-compaction.ts',
|
|
356
|
+
),
|
|
357
|
+
{ force: true },
|
|
358
|
+
);
|
|
166
359
|
}
|
|
167
360
|
if (removing) await fs.rm(legacy, { force: true });
|
|
168
|
-
log(
|
|
361
|
+
log(
|
|
362
|
+
`${id}: ${removing ? 'legacy integration removed' : present ? 'legacy integration exists' : 'launch-only; no legacy integration'}.`,
|
|
363
|
+
);
|
|
169
364
|
return 0;
|
|
170
365
|
}
|
|
171
366
|
throw new Error(`No native Windows setup is available for ${id}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "subconscious-cli",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.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,9 +9,11 @@
|
|
|
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",
|
|
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",
|
|
13
13
|
"test:tui": "go -C tui test ./...",
|
|
14
|
-
"
|
|
14
|
+
"lint": "biome ci .",
|
|
15
|
+
"format": "biome check --write .",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
15
17
|
"prepare": "node scripts/install-git-hooks.js",
|
|
16
18
|
"prepack": "npm run build:tui",
|
|
17
19
|
"prepublishOnly": "node scripts/require-publish-script.js"
|
|
@@ -51,8 +53,11 @@
|
|
|
51
53
|
"commit-msg": "npx --no-install commitlint --edit $1"
|
|
52
54
|
},
|
|
53
55
|
"devDependencies": {
|
|
56
|
+
"@biomejs/biome": "^2.5.14",
|
|
54
57
|
"@commitlint/cli": "^21.2.3",
|
|
55
58
|
"@commitlint/config-conventional": "^21.2.3",
|
|
56
|
-
"
|
|
59
|
+
"@types/node": "^26.6.2",
|
|
60
|
+
"simple-git-hooks": "^2.14.0",
|
|
61
|
+
"typescript": "^7.0.2"
|
|
57
62
|
}
|
|
58
63
|
}
|