shennian 0.2.0 → 0.2.5
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/dist/bin/shennian.d.ts +0 -1
- package/dist/bin/shennian.js +0 -1
- package/dist/src/agents/adapter.d.ts +0 -1
- package/dist/src/agents/adapter.js +0 -1
- package/dist/src/agents/claude.d.ts +1 -1
- package/dist/src/agents/claude.js +12 -6
- package/dist/src/agents/codex.d.ts +18 -1
- package/dist/src/agents/codex.js +372 -13
- package/dist/src/agents/command-spec.d.ts +28 -3
- package/dist/src/agents/command-spec.js +251 -10
- package/dist/src/agents/cursor.d.ts +0 -1
- package/dist/src/agents/cursor.js +2 -4
- package/dist/src/agents/custom.d.ts +0 -6
- package/dist/src/agents/custom.js +4 -40
- package/dist/src/agents/detect.d.ts +0 -1
- package/dist/src/agents/detect.js +0 -1
- package/dist/src/agents/gemini.d.ts +0 -1
- package/dist/src/agents/gemini.js +7 -3
- package/dist/src/agents/model-registry/cache.d.ts +0 -1
- package/dist/src/agents/model-registry/cache.js +0 -1
- package/dist/src/agents/model-registry/discovery.d.ts +0 -1
- package/dist/src/agents/model-registry/discovery.js +90 -48
- package/dist/src/agents/model-registry/parsers.d.ts +4 -1
- package/dist/src/agents/model-registry/parsers.js +168 -1
- package/dist/src/agents/model-registry/runner.d.ts +2 -7
- package/dist/src/agents/model-registry/runner.js +3 -134
- package/dist/src/agents/model-registry/service.d.ts +0 -1
- package/dist/src/agents/model-registry/service.js +12 -10
- package/dist/src/agents/model-registry/types.d.ts +0 -1
- package/dist/src/agents/model-registry/types.js +0 -1
- package/dist/src/agents/model-registry.d.ts +3 -2
- package/dist/src/agents/model-registry.js +3 -2
- package/dist/src/agents/openclaw.d.ts +0 -1
- package/dist/src/agents/openclaw.js +13 -4
- package/dist/src/agents/pi.d.ts +0 -1
- package/dist/src/agents/pi.js +0 -1
- package/dist/src/commands/agent.d.ts +0 -1
- package/dist/src/commands/agent.js +2 -33
- package/dist/src/commands/daemon.d.ts +6 -1
- package/dist/src/commands/daemon.js +153 -18
- package/dist/src/commands/pair-qr.d.ts +0 -1
- package/dist/src/commands/pair-qr.js +0 -1
- package/dist/src/commands/pair.d.ts +0 -1
- package/dist/src/commands/pair.js +0 -1
- package/dist/src/commands/upgrade.d.ts +0 -1
- package/dist/src/commands/upgrade.js +0 -1
- package/dist/src/config/index.d.ts +0 -1
- package/dist/src/config/index.js +0 -1
- package/dist/src/fs/handler.d.ts +0 -1
- package/dist/src/fs/handler.js +18 -1
- package/dist/src/fs/security.d.ts +0 -1
- package/dist/src/fs/security.js +5 -1
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.js +36 -8
- package/dist/src/log-reporter.d.ts +0 -1
- package/dist/src/log-reporter.js +2 -20
- package/dist/src/native-fusion/parsers.d.ts +0 -1
- package/dist/src/native-fusion/parsers.js +407 -44
- package/dist/src/native-fusion/service.d.ts +0 -1
- package/dist/src/native-fusion/service.js +16 -10
- package/dist/src/native-fusion/state.d.ts +0 -1
- package/dist/src/native-fusion/state.js +0 -1
- package/dist/src/native-fusion/types.d.ts +0 -1
- package/dist/src/native-fusion/types.js +0 -1
- package/dist/src/region.d.ts +0 -1
- package/dist/src/region.js +0 -1
- package/dist/src/relay/client.d.ts +11 -2
- package/dist/src/relay/client.js +22 -4
- package/dist/src/session/handlers/agents.d.ts +0 -1
- package/dist/src/session/handlers/agents.js +0 -1
- package/dist/src/session/handlers/chat.d.ts +0 -1
- package/dist/src/session/handlers/chat.js +49 -8
- package/dist/src/session/handlers/control.d.ts +0 -1
- package/dist/src/session/handlers/control.js +0 -1
- package/dist/src/session/handlers/fs.d.ts +0 -1
- package/dist/src/session/handlers/fs.js +37 -3
- package/dist/src/session/manager.d.ts +1 -1
- package/dist/src/session/manager.js +23 -4
- package/dist/src/session/store.d.ts +0 -1
- package/dist/src/session/store.js +0 -1
- package/dist/src/session/types.d.ts +6 -1
- package/dist/src/session/types.js +0 -1
- package/dist/src/upgrade/engine.d.ts +0 -1
- package/dist/src/upgrade/engine.js +0 -1
- package/package.json +3 -2
- package/dist/bin/shennian.d.ts.map +0 -1
- package/dist/bin/shennian.js.map +0 -1
- package/dist/src/__experiments__/probe-debug.d.ts +0 -2
- package/dist/src/__experiments__/probe-debug.d.ts.map +0 -1
- package/dist/src/__experiments__/probe-debug.js +0 -66
- package/dist/src/__experiments__/probe-debug.js.map +0 -1
- package/dist/src/__experiments__/probe-final-benchmark.d.ts +0 -3
- package/dist/src/__experiments__/probe-final-benchmark.d.ts.map +0 -1
- package/dist/src/__experiments__/probe-final-benchmark.js +0 -234
- package/dist/src/__experiments__/probe-final-benchmark.js.map +0 -1
- package/dist/src/__experiments__/probe-models-final.d.ts +0 -19
- package/dist/src/__experiments__/probe-models-final.d.ts.map +0 -1
- package/dist/src/__experiments__/probe-models-final.js +0 -250
- package/dist/src/__experiments__/probe-models-final.js.map +0 -1
- package/dist/src/__experiments__/probe-models.d.ts +0 -7
- package/dist/src/__experiments__/probe-models.d.ts.map +0 -1
- package/dist/src/__experiments__/probe-models.js +0 -251
- package/dist/src/__experiments__/probe-models.js.map +0 -1
- package/dist/src/__tests__/agents-e2e.d.ts +0 -21
- package/dist/src/__tests__/agents-e2e.d.ts.map +0 -1
- package/dist/src/__tests__/agents-e2e.js +0 -146
- package/dist/src/__tests__/agents-e2e.js.map +0 -1
- package/dist/src/__tests__/claude-adapter.test.d.ts +0 -2
- package/dist/src/__tests__/claude-adapter.test.d.ts.map +0 -1
- package/dist/src/__tests__/claude-adapter.test.js +0 -75
- package/dist/src/__tests__/claude-adapter.test.js.map +0 -1
- package/dist/src/__tests__/codex-adapter.test.d.ts +0 -2
- package/dist/src/__tests__/codex-adapter.test.d.ts.map +0 -1
- package/dist/src/__tests__/codex-adapter.test.js +0 -224
- package/dist/src/__tests__/codex-adapter.test.js.map +0 -1
- package/dist/src/__tests__/config.test.d.ts +0 -2
- package/dist/src/__tests__/config.test.d.ts.map +0 -1
- package/dist/src/__tests__/config.test.js +0 -60
- package/dist/src/__tests__/config.test.js.map +0 -1
- package/dist/src/__tests__/cursor-adapter.test.d.ts +0 -2
- package/dist/src/__tests__/cursor-adapter.test.d.ts.map +0 -1
- package/dist/src/__tests__/cursor-adapter.test.js +0 -69
- package/dist/src/__tests__/cursor-adapter.test.js.map +0 -1
- package/dist/src/__tests__/custom-agent-flow.test.d.ts +0 -2
- package/dist/src/__tests__/custom-agent-flow.test.d.ts.map +0 -1
- package/dist/src/__tests__/custom-agent-flow.test.js +0 -244
- package/dist/src/__tests__/custom-agent-flow.test.js.map +0 -1
- package/dist/src/__tests__/daemon-autostart.test.d.ts +0 -2
- package/dist/src/__tests__/daemon-autostart.test.d.ts.map +0 -1
- package/dist/src/__tests__/daemon-autostart.test.js +0 -60
- package/dist/src/__tests__/daemon-autostart.test.js.map +0 -1
- package/dist/src/__tests__/e2e-relay.d.ts +0 -19
- package/dist/src/__tests__/e2e-relay.d.ts.map +0 -1
- package/dist/src/__tests__/e2e-relay.js +0 -256
- package/dist/src/__tests__/e2e-relay.js.map +0 -1
- package/dist/src/__tests__/model-discovery.test.d.ts +0 -2
- package/dist/src/__tests__/model-discovery.test.d.ts.map +0 -1
- package/dist/src/__tests__/model-discovery.test.js +0 -47
- package/dist/src/__tests__/model-discovery.test.js.map +0 -1
- package/dist/src/__tests__/model-switching.test.d.ts +0 -2
- package/dist/src/__tests__/model-switching.test.d.ts.map +0 -1
- package/dist/src/__tests__/model-switching.test.js +0 -253
- package/dist/src/__tests__/model-switching.test.js.map +0 -1
- package/dist/src/__tests__/native-fusion-parsers.test.d.ts +0 -2
- package/dist/src/__tests__/native-fusion-parsers.test.d.ts.map +0 -1
- package/dist/src/__tests__/native-fusion-parsers.test.js +0 -216
- package/dist/src/__tests__/native-fusion-parsers.test.js.map +0 -1
- package/dist/src/__tests__/native-fusion-service.test.d.ts +0 -2
- package/dist/src/__tests__/native-fusion-service.test.d.ts.map +0 -1
- package/dist/src/__tests__/native-fusion-service.test.js +0 -157
- package/dist/src/__tests__/native-fusion-service.test.js.map +0 -1
- package/dist/src/__tests__/native-session-sync.test.d.ts +0 -2
- package/dist/src/__tests__/native-session-sync.test.d.ts.map +0 -1
- package/dist/src/__tests__/native-session-sync.test.js +0 -198
- package/dist/src/__tests__/native-session-sync.test.js.map +0 -1
- package/dist/src/__tests__/pair-qr.test.d.ts +0 -2
- package/dist/src/__tests__/pair-qr.test.d.ts.map +0 -1
- package/dist/src/__tests__/pair-qr.test.js +0 -13
- package/dist/src/__tests__/pair-qr.test.js.map +0 -1
- package/dist/src/__tests__/pi-context.test.d.ts +0 -2
- package/dist/src/__tests__/pi-context.test.d.ts.map +0 -1
- package/dist/src/__tests__/pi-context.test.js +0 -261
- package/dist/src/__tests__/pi-context.test.js.map +0 -1
- package/dist/src/__tests__/session-manager.test.d.ts +0 -2
- package/dist/src/__tests__/session-manager.test.d.ts.map +0 -1
- package/dist/src/__tests__/session-manager.test.js +0 -592
- package/dist/src/__tests__/session-manager.test.js.map +0 -1
- package/dist/src/__tests__/session-store.test.d.ts +0 -2
- package/dist/src/__tests__/session-store.test.d.ts.map +0 -1
- package/dist/src/__tests__/session-store.test.js +0 -106
- package/dist/src/__tests__/session-store.test.js.map +0 -1
- package/dist/src/agents/adapter.d.ts.map +0 -1
- package/dist/src/agents/adapter.js.map +0 -1
- package/dist/src/agents/claude.d.ts.map +0 -1
- package/dist/src/agents/claude.js.map +0 -1
- package/dist/src/agents/codex.d.ts.map +0 -1
- package/dist/src/agents/codex.js.map +0 -1
- package/dist/src/agents/command-spec.d.ts.map +0 -1
- package/dist/src/agents/command-spec.js.map +0 -1
- package/dist/src/agents/cursor.d.ts.map +0 -1
- package/dist/src/agents/cursor.js.map +0 -1
- package/dist/src/agents/custom.d.ts.map +0 -1
- package/dist/src/agents/custom.js.map +0 -1
- package/dist/src/agents/detect.d.ts.map +0 -1
- package/dist/src/agents/detect.js.map +0 -1
- package/dist/src/agents/gemini.d.ts.map +0 -1
- package/dist/src/agents/gemini.js.map +0 -1
- package/dist/src/agents/model-registry/cache.d.ts.map +0 -1
- package/dist/src/agents/model-registry/cache.js.map +0 -1
- package/dist/src/agents/model-registry/discovery.d.ts.map +0 -1
- package/dist/src/agents/model-registry/discovery.js.map +0 -1
- package/dist/src/agents/model-registry/parsers.d.ts.map +0 -1
- package/dist/src/agents/model-registry/parsers.js.map +0 -1
- package/dist/src/agents/model-registry/runner.d.ts.map +0 -1
- package/dist/src/agents/model-registry/runner.js.map +0 -1
- package/dist/src/agents/model-registry/service.d.ts.map +0 -1
- package/dist/src/agents/model-registry/service.js.map +0 -1
- package/dist/src/agents/model-registry/types.d.ts.map +0 -1
- package/dist/src/agents/model-registry/types.js.map +0 -1
- package/dist/src/agents/model-registry.d.ts.map +0 -1
- package/dist/src/agents/model-registry.js.map +0 -1
- package/dist/src/agents/openclaw.d.ts.map +0 -1
- package/dist/src/agents/openclaw.js.map +0 -1
- package/dist/src/agents/pi.d.ts.map +0 -1
- package/dist/src/agents/pi.js.map +0 -1
- package/dist/src/commands/agent.d.ts.map +0 -1
- package/dist/src/commands/agent.js.map +0 -1
- package/dist/src/commands/daemon.d.ts.map +0 -1
- package/dist/src/commands/daemon.js.map +0 -1
- package/dist/src/commands/pair-qr.d.ts.map +0 -1
- package/dist/src/commands/pair-qr.js.map +0 -1
- package/dist/src/commands/pair.d.ts.map +0 -1
- package/dist/src/commands/pair.js.map +0 -1
- package/dist/src/commands/upgrade.d.ts.map +0 -1
- package/dist/src/commands/upgrade.js.map +0 -1
- package/dist/src/config/index.d.ts.map +0 -1
- package/dist/src/config/index.js.map +0 -1
- package/dist/src/fs/handler.d.ts.map +0 -1
- package/dist/src/fs/handler.js.map +0 -1
- package/dist/src/fs/multimodal.d.ts +0 -5
- package/dist/src/fs/multimodal.d.ts.map +0 -1
- package/dist/src/fs/multimodal.js +0 -39
- package/dist/src/fs/multimodal.js.map +0 -1
- package/dist/src/fs/security.d.ts.map +0 -1
- package/dist/src/fs/security.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/log-reporter.d.ts.map +0 -1
- package/dist/src/log-reporter.js.map +0 -1
- package/dist/src/native-fusion/parsers.d.ts.map +0 -1
- package/dist/src/native-fusion/parsers.js.map +0 -1
- package/dist/src/native-fusion/service.d.ts.map +0 -1
- package/dist/src/native-fusion/service.js.map +0 -1
- package/dist/src/native-fusion/state.d.ts.map +0 -1
- package/dist/src/native-fusion/state.js.map +0 -1
- package/dist/src/native-fusion/types.d.ts.map +0 -1
- package/dist/src/native-fusion/types.js.map +0 -1
- package/dist/src/native-sync/discover.d.ts +0 -6
- package/dist/src/native-sync/discover.d.ts.map +0 -1
- package/dist/src/native-sync/discover.js +0 -69
- package/dist/src/native-sync/discover.js.map +0 -1
- package/dist/src/native-sync/parsers.d.ts +0 -3
- package/dist/src/native-sync/parsers.d.ts.map +0 -1
- package/dist/src/native-sync/parsers.js +0 -373
- package/dist/src/native-sync/parsers.js.map +0 -1
- package/dist/src/native-sync/service.d.ts +0 -16
- package/dist/src/native-sync/service.d.ts.map +0 -1
- package/dist/src/native-sync/service.js +0 -95
- package/dist/src/native-sync/service.js.map +0 -1
- package/dist/src/native-sync/state.d.ts +0 -6
- package/dist/src/native-sync/state.d.ts.map +0 -1
- package/dist/src/native-sync/state.js +0 -34
- package/dist/src/native-sync/state.js.map +0 -1
- package/dist/src/native-sync/types.d.ts +0 -23
- package/dist/src/native-sync/types.d.ts.map +0 -1
- package/dist/src/native-sync/types.js +0 -4
- package/dist/src/native-sync/types.js.map +0 -1
- package/dist/src/region.d.ts.map +0 -1
- package/dist/src/region.js.map +0 -1
- package/dist/src/relay/client.d.ts.map +0 -1
- package/dist/src/relay/client.js.map +0 -1
- package/dist/src/session/handlers/agents.d.ts.map +0 -1
- package/dist/src/session/handlers/agents.js.map +0 -1
- package/dist/src/session/handlers/chat.d.ts.map +0 -1
- package/dist/src/session/handlers/chat.js.map +0 -1
- package/dist/src/session/handlers/control.d.ts.map +0 -1
- package/dist/src/session/handlers/control.js.map +0 -1
- package/dist/src/session/handlers/fs.d.ts.map +0 -1
- package/dist/src/session/handlers/fs.js.map +0 -1
- package/dist/src/session/handlers/queue.d.ts +0 -4
- package/dist/src/session/handlers/queue.d.ts.map +0 -1
- package/dist/src/session/handlers/queue.js +0 -66
- package/dist/src/session/handlers/queue.js.map +0 -1
- package/dist/src/session/manager.d.ts.map +0 -1
- package/dist/src/session/manager.js.map +0 -1
- package/dist/src/session/store.d.ts.map +0 -1
- package/dist/src/session/store.js.map +0 -1
- package/dist/src/session/types.d.ts.map +0 -1
- package/dist/src/session/types.js.map +0 -1
- package/dist/src/upgrade/engine.d.ts.map +0 -1
- package/dist/src/upgrade/engine.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
// @arch docs/architecture/cli/windows-agent-launch.md
|
|
2
|
+
// @test src/__tests__/command-spec.test.ts
|
|
3
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
4
|
+
import path from 'node:path';
|
|
2
5
|
const BUILTIN_COMMANDS = {
|
|
3
6
|
claude: [
|
|
4
7
|
{ command: 'claude', args: [], display: 'claude' },
|
|
@@ -22,33 +25,272 @@ const BUILTIN_COMMANDS = {
|
|
|
22
25
|
};
|
|
23
26
|
const availabilityCache = new Map();
|
|
24
27
|
const resolvedCache = new Map();
|
|
28
|
+
const pathLookupCache = new Map();
|
|
29
|
+
const wslAvailabilityCache = new Map();
|
|
25
30
|
export function resetCommandSpecCache() {
|
|
26
31
|
availabilityCache.clear();
|
|
27
32
|
resolvedCache.clear();
|
|
33
|
+
pathLookupCache.clear();
|
|
34
|
+
wslAvailabilityCache.clear();
|
|
28
35
|
}
|
|
29
|
-
export function
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
export function getProcessPlatform() {
|
|
37
|
+
return process.platform;
|
|
38
|
+
}
|
|
39
|
+
function splitLines(text) {
|
|
40
|
+
return text
|
|
41
|
+
.split(/\r?\n/)
|
|
42
|
+
.map((line) => line.trim())
|
|
43
|
+
.filter(Boolean);
|
|
44
|
+
}
|
|
45
|
+
function lookupCommandPaths(command) {
|
|
46
|
+
if (pathLookupCache.has(command)) {
|
|
47
|
+
return pathLookupCache.get(command) ?? [];
|
|
32
48
|
}
|
|
33
|
-
const lookup =
|
|
49
|
+
const lookup = getProcessPlatform() === 'win32' ? 'where' : 'which';
|
|
34
50
|
const result = spawnSync(lookup, [command], {
|
|
35
|
-
|
|
51
|
+
encoding: 'utf-8',
|
|
52
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
36
53
|
timeout: 3000,
|
|
37
54
|
});
|
|
38
|
-
const
|
|
55
|
+
const paths = result.status === 0 ? splitLines(result.stdout ?? '') : [];
|
|
56
|
+
pathLookupCache.set(command, paths);
|
|
57
|
+
return paths;
|
|
58
|
+
}
|
|
59
|
+
function getWindowsShellPath() {
|
|
60
|
+
return process.env.ComSpec || 'cmd.exe';
|
|
61
|
+
}
|
|
62
|
+
function isWindowsNativeBinary(filePath) {
|
|
63
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
64
|
+
return ext === '.exe' || ext === '.com';
|
|
65
|
+
}
|
|
66
|
+
function isWindowsCmdShim(filePath) {
|
|
67
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
68
|
+
return ext === '.cmd' || ext === '.bat';
|
|
69
|
+
}
|
|
70
|
+
function quoteCmdArg(text) {
|
|
71
|
+
return `"${text.replace(/"/g, '""')}"`;
|
|
72
|
+
}
|
|
73
|
+
function quotePosixArg(text) {
|
|
74
|
+
return `'${text.replace(/'/g, `'\\''`)}'`;
|
|
75
|
+
}
|
|
76
|
+
export function windowsPathToWsl(input) {
|
|
77
|
+
if (!input)
|
|
78
|
+
return undefined;
|
|
79
|
+
const normalized = input.replace(/\//g, '\\');
|
|
80
|
+
const driveMatch = normalized.match(/^([A-Za-z]):\\(.*)$/);
|
|
81
|
+
if (driveMatch) {
|
|
82
|
+
const [, drive, rest] = driveMatch;
|
|
83
|
+
const suffix = rest.replace(/\\/g, '/');
|
|
84
|
+
return `/mnt/${drive.toLowerCase()}/${suffix}`;
|
|
85
|
+
}
|
|
86
|
+
if (normalized.startsWith('\\\\wsl$\\')) {
|
|
87
|
+
const remainder = normalized.replace(/^\\\\wsl\$\\[^\\]+\\?/, '');
|
|
88
|
+
return `/${remainder.replace(/\\/g, '/')}`;
|
|
89
|
+
}
|
|
90
|
+
if (input.startsWith('/'))
|
|
91
|
+
return input;
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
function resolveArbitraryWindowsCommand(command) {
|
|
95
|
+
const normalized = command.trim();
|
|
96
|
+
if (!normalized) {
|
|
97
|
+
throw new Error('Command string is empty');
|
|
98
|
+
}
|
|
99
|
+
const hasExplicitPath = /[\\/]/.test(normalized) || /^[A-Za-z]:/.test(normalized);
|
|
100
|
+
if (hasExplicitPath) {
|
|
101
|
+
if (isWindowsCmdShim(normalized))
|
|
102
|
+
return { kind: 'cmd-shim', path: normalized };
|
|
103
|
+
return { kind: 'direct', path: normalized };
|
|
104
|
+
}
|
|
105
|
+
const paths = lookupCommandPaths(normalized);
|
|
106
|
+
const native = paths.find(isWindowsNativeBinary);
|
|
107
|
+
if (native)
|
|
108
|
+
return { kind: 'direct', path: native };
|
|
109
|
+
const shim = paths.find(isWindowsCmdShim);
|
|
110
|
+
if (shim)
|
|
111
|
+
return { kind: 'cmd-shim', path: shim };
|
|
112
|
+
return { kind: 'direct', path: normalized };
|
|
113
|
+
}
|
|
114
|
+
function canUseWslBridge(command) {
|
|
115
|
+
if (wslAvailabilityCache.has(command)) {
|
|
116
|
+
return wslAvailabilityCache.get(command) ?? false;
|
|
117
|
+
}
|
|
118
|
+
const wslPath = lookupCommandPaths('wsl.exe')[0] ?? lookupCommandPaths('wsl')[0];
|
|
119
|
+
if (!wslPath) {
|
|
120
|
+
wslAvailabilityCache.set(command, false);
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
const result = spawnSync(wslPath, ['-e', 'sh', '-lc', `command -v ${quotePosixArg(command)} >/dev/null 2>&1`], {
|
|
124
|
+
stdio: 'ignore',
|
|
125
|
+
timeout: 5000,
|
|
126
|
+
});
|
|
127
|
+
const ok = result.status === 0;
|
|
128
|
+
wslAvailabilityCache.set(command, ok);
|
|
129
|
+
return ok;
|
|
130
|
+
}
|
|
131
|
+
export function commandExists(command) {
|
|
132
|
+
if (availabilityCache.has(command)) {
|
|
133
|
+
return availabilityCache.get(command) ?? false;
|
|
134
|
+
}
|
|
135
|
+
const exists = lookupCommandPaths(command).length > 0 || (getProcessPlatform() === 'win32' && canUseWslBridge(command));
|
|
39
136
|
availabilityCache.set(command, exists);
|
|
40
137
|
return exists;
|
|
41
138
|
}
|
|
139
|
+
function resolveWindowsBuiltinCommand(candidate) {
|
|
140
|
+
const paths = lookupCommandPaths(candidate.command);
|
|
141
|
+
const native = paths.find(isWindowsNativeBinary);
|
|
142
|
+
if (native) {
|
|
143
|
+
return { ...candidate, kind: 'native', path: native };
|
|
144
|
+
}
|
|
145
|
+
const shim = paths.find(isWindowsCmdShim);
|
|
146
|
+
if (shim) {
|
|
147
|
+
return { ...candidate, kind: 'cmd-shim', path: shim };
|
|
148
|
+
}
|
|
149
|
+
if (canUseWslBridge(candidate.command)) {
|
|
150
|
+
const wslPath = lookupCommandPaths('wsl.exe')[0] ?? lookupCommandPaths('wsl')[0];
|
|
151
|
+
if (wslPath) {
|
|
152
|
+
return { ...candidate, kind: 'wsl-bridge', path: wslPath };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
42
157
|
export function resolveBuiltinCommand(type) {
|
|
43
158
|
if (resolvedCache.has(type)) {
|
|
44
159
|
return resolvedCache.get(type) ?? null;
|
|
45
160
|
}
|
|
46
|
-
const resolved = BUILTIN_COMMANDS[type]
|
|
161
|
+
const resolved = BUILTIN_COMMANDS[type]
|
|
162
|
+
.map((candidate) => {
|
|
163
|
+
if (getProcessPlatform() === 'win32') {
|
|
164
|
+
return resolveWindowsBuiltinCommand(candidate);
|
|
165
|
+
}
|
|
166
|
+
const commandPath = lookupCommandPaths(candidate.command)[0];
|
|
167
|
+
return commandPath ? { ...candidate, kind: 'native', path: commandPath } : null;
|
|
168
|
+
})
|
|
169
|
+
.find(Boolean) ?? null;
|
|
47
170
|
resolvedCache.set(type, resolved);
|
|
48
171
|
return resolved;
|
|
49
172
|
}
|
|
173
|
+
export function buildLaunchSpec(spec, runtimeArgs, cwd) {
|
|
174
|
+
if (spec.kind === 'native') {
|
|
175
|
+
return {
|
|
176
|
+
command: spec.path,
|
|
177
|
+
args: [...spec.args, ...runtimeArgs],
|
|
178
|
+
cwd,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
if (spec.kind === 'cmd-shim') {
|
|
182
|
+
const commandLine = [spec.path, ...spec.args, ...runtimeArgs].map(quoteCmdArg).join(' ');
|
|
183
|
+
return {
|
|
184
|
+
command: getWindowsShellPath(),
|
|
185
|
+
args: ['/d', '/s', '/c', `"${commandLine}"`],
|
|
186
|
+
cwd,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
const wslCwd = cwd ? windowsPathToWsl(cwd) : undefined;
|
|
190
|
+
if (cwd && !wslCwd) {
|
|
191
|
+
throw new Error(`Cannot map Windows path to WSL workDir: ${cwd}`);
|
|
192
|
+
}
|
|
193
|
+
const shellCommand = [
|
|
194
|
+
wslCwd ? `cd ${quotePosixArg(wslCwd)}` : '',
|
|
195
|
+
`exec ${[spec.command, ...spec.args, ...runtimeArgs].map(quotePosixArg).join(' ')}`,
|
|
196
|
+
].filter(Boolean).join(' && ');
|
|
197
|
+
return {
|
|
198
|
+
command: spec.path,
|
|
199
|
+
args: ['-e', 'sh', '-lc', shellCommand],
|
|
200
|
+
cwd: undefined,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
export function spawnResolvedCommand(spec, runtimeArgs, options = {}) {
|
|
204
|
+
const launch = buildLaunchSpec(spec, runtimeArgs, options.cwd);
|
|
205
|
+
return spawn(launch.command, launch.args, {
|
|
206
|
+
...options,
|
|
207
|
+
cwd: launch.cwd,
|
|
208
|
+
...(getProcessPlatform() === 'win32' && spec.kind === 'cmd-shim'
|
|
209
|
+
? { windowsVerbatimArguments: true }
|
|
210
|
+
: {}),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
export function spawnResolvedCommandSync(spec, runtimeArgs, options = {}) {
|
|
214
|
+
const launch = buildLaunchSpec(spec, runtimeArgs, options.cwd);
|
|
215
|
+
return spawnSync(launch.command, launch.args, {
|
|
216
|
+
...options,
|
|
217
|
+
cwd: launch.cwd,
|
|
218
|
+
...(getProcessPlatform() === 'win32' && spec.kind === 'cmd-shim'
|
|
219
|
+
? { windowsVerbatimArguments: true }
|
|
220
|
+
: {}),
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
export function parseCommandString(command) {
|
|
224
|
+
const args = [];
|
|
225
|
+
let current = '';
|
|
226
|
+
let inSingle = false;
|
|
227
|
+
let inDouble = false;
|
|
228
|
+
for (const ch of command) {
|
|
229
|
+
if (ch === "'" && !inDouble) {
|
|
230
|
+
inSingle = !inSingle;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (ch === '"' && !inSingle) {
|
|
234
|
+
inDouble = !inDouble;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (ch === ' ' && !inSingle && !inDouble) {
|
|
238
|
+
if (current) {
|
|
239
|
+
args.push(current);
|
|
240
|
+
current = '';
|
|
241
|
+
}
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
current += ch;
|
|
245
|
+
}
|
|
246
|
+
if (current)
|
|
247
|
+
args.push(current);
|
|
248
|
+
return args;
|
|
249
|
+
}
|
|
250
|
+
export function buildCommandStringLaunchSpec(commandString, runtimeArgs, cwd) {
|
|
251
|
+
const parts = parseCommandString(commandString);
|
|
252
|
+
const bin = parts[0];
|
|
253
|
+
if (!bin) {
|
|
254
|
+
throw new Error('Command string is empty');
|
|
255
|
+
}
|
|
256
|
+
const baseArgs = parts.slice(1);
|
|
257
|
+
if (getProcessPlatform() !== 'win32') {
|
|
258
|
+
return {
|
|
259
|
+
command: bin,
|
|
260
|
+
args: [...baseArgs, ...runtimeArgs],
|
|
261
|
+
cwd,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const invocation = resolveArbitraryWindowsCommand(bin);
|
|
265
|
+
if (invocation.kind === 'cmd-shim') {
|
|
266
|
+
return {
|
|
267
|
+
command: getWindowsShellPath(),
|
|
268
|
+
args: ['/d', '/s', '/c', `"${[invocation.path, ...baseArgs, ...runtimeArgs].map(quoteCmdArg).join(' ')}"`],
|
|
269
|
+
cwd,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
command: invocation.path,
|
|
274
|
+
args: [...baseArgs, ...runtimeArgs],
|
|
275
|
+
cwd,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
export function spawnCommandString(commandString, runtimeArgs, options = {}) {
|
|
279
|
+
const launch = buildCommandStringLaunchSpec(commandString, runtimeArgs, options.cwd);
|
|
280
|
+
const parts = parseCommandString(commandString);
|
|
281
|
+
const invocation = getProcessPlatform() === 'win32' && parts[0]
|
|
282
|
+
? resolveArbitraryWindowsCommand(parts[0])
|
|
283
|
+
: null;
|
|
284
|
+
return spawn(launch.command, launch.args, {
|
|
285
|
+
...options,
|
|
286
|
+
cwd: launch.cwd,
|
|
287
|
+
...(getProcessPlatform() === 'win32' && invocation?.kind === 'cmd-shim'
|
|
288
|
+
? { windowsVerbatimArguments: true }
|
|
289
|
+
: {}),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
50
292
|
export function getCommandVersion(spec, flag = '--version') {
|
|
51
|
-
const result =
|
|
293
|
+
const result = spawnResolvedCommandSync(spec, [flag], {
|
|
52
294
|
encoding: 'utf-8',
|
|
53
295
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
54
296
|
timeout: 5000,
|
|
@@ -59,4 +301,3 @@ export function getCommandVersion(spec, flag = '--version') {
|
|
|
59
301
|
const match = text.match(/\d+\.\d+[\w.-]*/);
|
|
60
302
|
return match?.[0];
|
|
61
303
|
}
|
|
62
|
-
//# sourceMappingURL=command-spec.js.map
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// @arch docs/architecture/cli/agent-adapters.md
|
|
2
2
|
// @test src/__tests__/cursor-adapter.test.ts
|
|
3
|
-
import { spawn } from 'node:child_process';
|
|
4
3
|
import { createInterface } from 'node:readline';
|
|
5
4
|
import { randomUUID } from 'node:crypto';
|
|
6
5
|
import { AgentAdapter, registerAgent } from './adapter.js';
|
|
7
|
-
import { resolveBuiltinCommand } from './command-spec.js';
|
|
6
|
+
import { resolveBuiltinCommand, spawnResolvedCommand } from './command-spec.js';
|
|
8
7
|
export class CursorAdapter extends AgentAdapter {
|
|
9
8
|
type = 'cursor';
|
|
10
9
|
process = null;
|
|
@@ -58,7 +57,7 @@ export class CursorAdapter extends AgentAdapter {
|
|
|
58
57
|
this.emit('error', new Error('Cursor Agent CLI not found. Expected "agent" or "cursor agent".'));
|
|
59
58
|
return;
|
|
60
59
|
}
|
|
61
|
-
const proc =
|
|
60
|
+
const proc = spawnResolvedCommand(spec, args, {
|
|
62
61
|
cwd: this.workDir ?? undefined,
|
|
63
62
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
64
63
|
env: { ...process.env },
|
|
@@ -247,4 +246,3 @@ export class CursorAdapter extends AgentAdapter {
|
|
|
247
246
|
}
|
|
248
247
|
}
|
|
249
248
|
registerAgent('cursor', () => new CursorAdapter());
|
|
250
|
-
//# sourceMappingURL=cursor.js.map
|
|
@@ -26,11 +26,5 @@ export declare class CustomAgentAdapter extends AgentAdapter {
|
|
|
26
26
|
private attachOutputHandlers;
|
|
27
27
|
private handleProtocolEvent;
|
|
28
28
|
private emitEvent;
|
|
29
|
-
/**
|
|
30
|
-
* Splits `this.command` into argv, supporting quoted strings.
|
|
31
|
-
* e.g. `python /path/to/agent.py` → ['python', '/path/to/agent.py']
|
|
32
|
-
*/
|
|
33
|
-
private buildCommandArgs;
|
|
34
29
|
}
|
|
35
30
|
export declare function registerCustomAgent(name: string, entry: CustomAgentEntry): void;
|
|
36
|
-
//# sourceMappingURL=custom.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @arch docs/architecture/cli/agent-adapters.md#custom-agents
|
|
2
|
-
import { spawn } from 'node:child_process';
|
|
3
2
|
import { createInterface } from 'node:readline';
|
|
4
3
|
import { randomUUID } from 'node:crypto';
|
|
5
4
|
import { AgentAdapter, registerAgent } from './adapter.js';
|
|
5
|
+
import { spawnCommandString } from './command-spec.js';
|
|
6
6
|
export class CustomAgentAdapter extends AgentAdapter {
|
|
7
7
|
type;
|
|
8
8
|
command;
|
|
@@ -65,15 +65,14 @@ export class CustomAgentAdapter extends AgentAdapter {
|
|
|
65
65
|
// ─── Spawn mode ───────────────────────────────────────────────────────────
|
|
66
66
|
async runSpawn(text, modelId) {
|
|
67
67
|
await this.killSpawnProcess();
|
|
68
|
-
const args = this.
|
|
69
|
-
args.push('/run', '--workdir', this.workDir ?? process.cwd());
|
|
68
|
+
const args = ['/run', '--workdir', this.workDir ?? process.cwd()];
|
|
70
69
|
if (this.sessionId)
|
|
71
70
|
args.push('--session', this.sessionId);
|
|
72
71
|
if (this.agentSessionId)
|
|
73
72
|
args.push('--resume', this.agentSessionId);
|
|
74
73
|
if (modelId)
|
|
75
74
|
args.push('--model', modelId);
|
|
76
|
-
const proc =
|
|
75
|
+
const proc = spawnCommandString(this.command, args, {
|
|
77
76
|
cwd: this.workDir ?? undefined,
|
|
78
77
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
79
78
|
env: { ...process.env },
|
|
@@ -99,9 +98,7 @@ export class CustomAgentAdapter extends AgentAdapter {
|
|
|
99
98
|
}
|
|
100
99
|
// ─── Stdio mode ───────────────────────────────────────────────────────────
|
|
101
100
|
async startStdioProcess() {
|
|
102
|
-
const
|
|
103
|
-
args.push('/start', '--workdir', this.workDir ?? process.cwd());
|
|
104
|
-
const proc = spawn(args[0], args.slice(1), {
|
|
101
|
+
const proc = spawnCommandString(this.command, ['/start', '--workdir', this.workDir ?? process.cwd()], {
|
|
105
102
|
cwd: this.workDir ?? undefined,
|
|
106
103
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
107
104
|
env: { ...process.env },
|
|
@@ -206,41 +203,8 @@ export class CustomAgentAdapter extends AgentAdapter {
|
|
|
206
203
|
const event = { ...partial, runId: this.runId, seq: this.seq++ };
|
|
207
204
|
this.emit('agentEvent', event);
|
|
208
205
|
}
|
|
209
|
-
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
210
|
-
/**
|
|
211
|
-
* Splits `this.command` into argv, supporting quoted strings.
|
|
212
|
-
* e.g. `python /path/to/agent.py` → ['python', '/path/to/agent.py']
|
|
213
|
-
*/
|
|
214
|
-
buildCommandArgs() {
|
|
215
|
-
const args = [];
|
|
216
|
-
let current = '';
|
|
217
|
-
let inSingle = false;
|
|
218
|
-
let inDouble = false;
|
|
219
|
-
for (const ch of this.command) {
|
|
220
|
-
if (ch === "'" && !inDouble) {
|
|
221
|
-
inSingle = !inSingle;
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
if (ch === '"' && !inSingle) {
|
|
225
|
-
inDouble = !inDouble;
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
if (ch === ' ' && !inSingle && !inDouble) {
|
|
229
|
-
if (current) {
|
|
230
|
-
args.push(current);
|
|
231
|
-
current = '';
|
|
232
|
-
}
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
current += ch;
|
|
236
|
-
}
|
|
237
|
-
if (current)
|
|
238
|
-
args.push(current);
|
|
239
|
-
return args;
|
|
240
|
-
}
|
|
241
206
|
}
|
|
242
207
|
export function registerCustomAgent(name, entry) {
|
|
243
208
|
const agentType = `custom:${name}`;
|
|
244
209
|
registerAgent(agentType, () => new CustomAgentAdapter(name, entry));
|
|
245
210
|
}
|
|
246
|
-
//# sourceMappingURL=custom.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { spawn } from 'node:child_process';
|
|
2
1
|
import { createInterface } from 'node:readline';
|
|
3
2
|
import { randomUUID } from 'node:crypto';
|
|
4
3
|
import { AgentAdapter, registerAgent } from './adapter.js';
|
|
4
|
+
import { resolveBuiltinCommand, spawnResolvedCommand } from './command-spec.js';
|
|
5
5
|
function num(v) {
|
|
6
6
|
return typeof v === 'number' && Number.isFinite(v) ? v : undefined;
|
|
7
7
|
}
|
|
@@ -64,7 +64,12 @@ export class GeminiAdapter extends AgentAdapter {
|
|
|
64
64
|
await this.killProcess();
|
|
65
65
|
}
|
|
66
66
|
spawnAndParse(args) {
|
|
67
|
-
const
|
|
67
|
+
const spec = resolveBuiltinCommand('gemini');
|
|
68
|
+
if (!spec) {
|
|
69
|
+
this.emit('error', new Error('Command "gemini" not found. Is Gemini CLI installed?'));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const proc = spawnResolvedCommand(spec, args, {
|
|
68
73
|
cwd: this.workDir ?? undefined,
|
|
69
74
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
70
75
|
env: { ...process.env },
|
|
@@ -165,4 +170,3 @@ export class GeminiAdapter extends AgentAdapter {
|
|
|
165
170
|
}
|
|
166
171
|
}
|
|
167
172
|
registerAgent('gemini', () => new GeminiAdapter());
|
|
168
|
-
//# sourceMappingURL=gemini.js.map
|
|
@@ -2,4 +2,3 @@ import { type CacheEntry, type CacheFile } from './types.js';
|
|
|
2
2
|
export declare function readCache(): CacheFile;
|
|
3
3
|
export declare function writeCache(cache: CacheFile): void;
|
|
4
4
|
export declare function isCacheFresh(entry: CacheEntry | undefined, version?: string): boolean;
|
|
5
|
-
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -2,4 +2,3 @@ import type { ModelInfo } from '@shennian/wire';
|
|
|
2
2
|
import type { DetectedAgent } from '../detect.js';
|
|
3
3
|
import { type DiscoveryContext } from './types.js';
|
|
4
4
|
export declare function discoverModelsForAgent(agent: DetectedAgent, context: DiscoveryContext): Promise<ModelInfo[]>;
|
|
5
|
-
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -1,75 +1,118 @@
|
|
|
1
1
|
// @arch docs/architecture/cli/model-discovery.md
|
|
2
2
|
// @test src/__tests__/model-switching.test.ts
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { createInterface } from 'node:readline';
|
|
4
|
+
import { resolveBuiltinCommand, spawnResolvedCommand } from '../command-spec.js';
|
|
5
|
+
import { fallbackClaudeAliasModels, fallbackGeminiModels, parseCodexAppServerModels, parseCursorModels, parseOpenClawModels, } from './parsers.js';
|
|
6
|
+
import { runResolvedCommand } from './runner.js';
|
|
6
7
|
import { DISCOVERY_WORKDIR } from './types.js';
|
|
8
|
+
function sendAppServerRpc(proc, pending, id, method, params, timeoutMs) {
|
|
9
|
+
if (!proc.stdin)
|
|
10
|
+
return Promise.reject(new Error('codex app-server stdin unavailable'));
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const timer = setTimeout(() => {
|
|
13
|
+
pending.delete(id);
|
|
14
|
+
reject(new Error(`codex app-server request timed out: ${method}`));
|
|
15
|
+
}, timeoutMs);
|
|
16
|
+
pending.set(id, { resolve, reject, timer });
|
|
17
|
+
proc.stdin.write(`${JSON.stringify({ id, method, params })}\n`, (error) => {
|
|
18
|
+
if (!error)
|
|
19
|
+
return;
|
|
20
|
+
clearTimeout(timer);
|
|
21
|
+
pending.delete(id);
|
|
22
|
+
reject(error);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async function discoverCodexModelsViaAppServer(spec) {
|
|
27
|
+
const proc = spawnResolvedCommand(spec, ['app-server', '--listen', 'stdio://'], {
|
|
28
|
+
cwd: DISCOVERY_WORKDIR,
|
|
29
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
30
|
+
env: { ...process.env, NO_COLOR: '1' },
|
|
31
|
+
});
|
|
32
|
+
const pending = new Map();
|
|
33
|
+
let seq = 1;
|
|
34
|
+
const rl = createInterface({ input: proc.stdout });
|
|
35
|
+
rl.on('line', (line) => {
|
|
36
|
+
if (!line.trim())
|
|
37
|
+
return;
|
|
38
|
+
let msg;
|
|
39
|
+
try {
|
|
40
|
+
msg = JSON.parse(line);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (msg.id == null)
|
|
46
|
+
return;
|
|
47
|
+
const request = pending.get(msg.id);
|
|
48
|
+
if (!request)
|
|
49
|
+
return;
|
|
50
|
+
clearTimeout(request.timer);
|
|
51
|
+
pending.delete(msg.id);
|
|
52
|
+
if (msg.error) {
|
|
53
|
+
request.reject(new Error(msg.error.message || `codex app-server error ${msg.error.code ?? ''}`.trim()));
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
request.resolve(msg.result);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
try {
|
|
60
|
+
await sendAppServerRpc(proc, pending, seq++, 'initialize', {
|
|
61
|
+
clientInfo: { name: 'shennian', title: 'Shennian', version: '0.0.0' },
|
|
62
|
+
capabilities: { experimentalApi: true },
|
|
63
|
+
}, 10_000);
|
|
64
|
+
const [modelList, configRead] = await Promise.all([
|
|
65
|
+
sendAppServerRpc(proc, pending, seq++, 'model/list', {}, 15_000),
|
|
66
|
+
sendAppServerRpc(proc, pending, seq++, 'config/read', {}, 15_000).catch(() => null),
|
|
67
|
+
]);
|
|
68
|
+
const config = typeof configRead === 'object' && configRead !== null && 'config' in configRead
|
|
69
|
+
? configRead.config
|
|
70
|
+
: undefined;
|
|
71
|
+
return parseCodexAppServerModels({
|
|
72
|
+
...(typeof modelList === 'object' && modelList !== null ? modelList : {}),
|
|
73
|
+
config,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
for (const [id, request] of pending) {
|
|
78
|
+
clearTimeout(request.timer);
|
|
79
|
+
request.reject(new Error('codex app-server stopped'));
|
|
80
|
+
pending.delete(id);
|
|
81
|
+
}
|
|
82
|
+
proc.kill('SIGTERM');
|
|
83
|
+
setTimeout(() => proc.kill('SIGKILL'), 1000).unref();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
7
86
|
async function discoverCursorModels() {
|
|
8
87
|
const spec = resolveBuiltinCommand('cursor');
|
|
9
88
|
if (!spec)
|
|
10
89
|
return [];
|
|
11
|
-
const result = await
|
|
90
|
+
const result = await runResolvedCommand(spec, ['--list-models']);
|
|
12
91
|
return parseCursorModels(result.stdout);
|
|
13
92
|
}
|
|
14
93
|
async function discoverOpenClawModels() {
|
|
15
94
|
const spec = resolveBuiltinCommand('openclaw');
|
|
16
95
|
if (!spec)
|
|
17
96
|
return [];
|
|
18
|
-
const result = await
|
|
97
|
+
const result = await runResolvedCommand(spec, ['models', 'list', '--json']);
|
|
19
98
|
return parseOpenClawModels(result.stdout);
|
|
20
99
|
}
|
|
21
100
|
async function discoverClaudeModels() {
|
|
22
|
-
|
|
23
|
-
if (!spec)
|
|
101
|
+
if (!resolveBuiltinCommand('claude'))
|
|
24
102
|
return [];
|
|
25
|
-
|
|
26
|
-
startupArgs,
|
|
27
|
-
readyPatterns: [/[>❯]/, /claude/i],
|
|
28
|
-
closePatterns: [/esc/i, /confirm/i, /default/i],
|
|
29
|
-
timeoutMs: 12_000,
|
|
30
|
-
});
|
|
31
|
-
const primaryRaw = await runDiscovery(['--bare', '--dangerously-skip-permissions']);
|
|
32
|
-
const primaryModels = parseClaudeModels(primaryRaw);
|
|
33
|
-
if (primaryModels.length > 0)
|
|
34
|
-
return primaryModels;
|
|
35
|
-
const clean = primaryRaw.toLowerCase();
|
|
36
|
-
const bareUnsupported = clean.includes('--bare') &&
|
|
37
|
-
(clean.includes('unknown option') ||
|
|
38
|
-
clean.includes('unknown argument') ||
|
|
39
|
-
clean.includes('unexpected argument') ||
|
|
40
|
-
clean.includes('unrecognized option'));
|
|
41
|
-
if (!bareUnsupported)
|
|
42
|
-
return primaryModels;
|
|
43
|
-
const fallbackRaw = await runDiscovery(['--dangerously-skip-permissions']);
|
|
44
|
-
return parseClaudeModels(fallbackRaw);
|
|
103
|
+
return fallbackClaudeAliasModels();
|
|
45
104
|
}
|
|
46
105
|
async function discoverCodexModels() {
|
|
47
106
|
const spec = resolveBuiltinCommand('codex');
|
|
48
107
|
if (!spec)
|
|
49
108
|
return [];
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
preOpenPromptPatterns: [/update available!/i, /skip until next version/i, /release notes:/i],
|
|
53
|
-
preOpenPromptInput: '\u001b[B\r',
|
|
54
|
-
readyPatterns: [/(?:^|\s)\/model\b/i, /codex/i],
|
|
55
|
-
closePatterns: [/enter to select/i, /dismiss/i, /select model/i],
|
|
56
|
-
timeoutMs: 45_000,
|
|
57
|
-
scrollAfterOpenMs: 2500,
|
|
58
|
-
scrollCount: 15,
|
|
59
|
-
scrollIntervalMs: 500,
|
|
60
|
-
});
|
|
61
|
-
return parseCodexModels(raw);
|
|
109
|
+
const appServerModels = await discoverCodexModelsViaAppServer(spec).catch(() => []);
|
|
110
|
+
return appServerModels;
|
|
62
111
|
}
|
|
63
112
|
async function discoverGeminiModels() {
|
|
64
|
-
|
|
65
|
-
if (!spec)
|
|
113
|
+
if (!resolveBuiltinCommand('gemini'))
|
|
66
114
|
return [];
|
|
67
|
-
|
|
68
|
-
readyPatterns: [/[>❯]/, /gemini/i],
|
|
69
|
-
closePatterns: [/enter to select/i, /select model/i, /\besc\b/i],
|
|
70
|
-
timeoutMs: 16_000,
|
|
71
|
-
});
|
|
72
|
-
return parseGeminiModels(raw);
|
|
115
|
+
return fallbackGeminiModels();
|
|
73
116
|
}
|
|
74
117
|
async function discoverPiModels(context) {
|
|
75
118
|
if (!context.serverUrl || !context.authToken)
|
|
@@ -116,4 +159,3 @@ export async function discoverModelsForAgent(agent, context) {
|
|
|
116
159
|
}
|
|
117
160
|
return discoverBuiltinModels(agent.type, context);
|
|
118
161
|
}
|
|
119
|
-
//# sourceMappingURL=discovery.js.map
|
|
@@ -3,6 +3,9 @@ export declare function stripAnsi(text: string): string;
|
|
|
3
3
|
export declare function parseCursorModels(raw: string): ModelInfo[];
|
|
4
4
|
export declare function parseOpenClawModels(raw: string): ModelInfo[];
|
|
5
5
|
export declare function parseClaudeModels(raw: string): ModelInfo[];
|
|
6
|
+
export declare function parseClaudeBinaryModels(raw: string): ModelInfo[];
|
|
7
|
+
export declare function fallbackClaudeAliasModels(): ModelInfo[];
|
|
6
8
|
export declare function parseCodexModels(raw: string): ModelInfo[];
|
|
9
|
+
export declare function parseCodexAppServerModels(raw: unknown): ModelInfo[];
|
|
7
10
|
export declare function parseGeminiModels(raw: string): ModelInfo[];
|
|
8
|
-
|
|
11
|
+
export declare function fallbackGeminiModels(): ModelInfo[];
|