@jini-ai/agent-runtime 0.3.9 → 0.4.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/CHANGELOG.md +103 -0
- package/README.md +34 -17
- package/dist/acp-model-probe.d.ts +6 -4
- package/dist/acp-model-probe.js +3 -3
- package/dist/agent-protocol/acp/account-failure.d.ts +4 -2
- package/dist/agent-protocol/acp/account-failure.js +1 -1
- package/dist/agent-protocol/acp/json.d.ts +6 -6
- package/dist/agent-protocol/acp/json.js +3 -3
- package/dist/agent-protocol/acp/models.d.ts +10 -5
- package/dist/agent-protocol/acp/models.js +32 -31
- package/dist/agent-protocol/acp/session-params.d.ts +3 -1
- package/dist/agent-protocol/acp/session-params.js +2 -1
- package/dist/agent-protocol/acp/session.d.ts +28 -22
- package/dist/agent-protocol/acp/session.js +181 -147
- package/dist/agent-protocol/acp/text-suppression.d.ts +1 -1
- package/dist/agent-protocol/acp/text-suppression.js +1 -1
- package/dist/agent-protocol/acp/types.d.ts +3 -2
- package/dist/agent-protocol/acp/updates.d.ts +11 -11
- package/dist/agent-protocol/acp/updates.js +2 -2
- package/dist/agent-protocol/core/json-line-stream.d.ts +24 -8
- package/dist/agent-protocol/core/json-line-stream.js +8 -8
- package/dist/agent-protocol/pi-rpc/events.d.ts +5 -1
- package/dist/agent-protocol/pi-rpc/events.js +36 -36
- package/dist/agent-protocol/pi-rpc/internal.d.ts +4 -1
- package/dist/agent-protocol/pi-rpc/models.d.ts +3 -1
- package/dist/agent-protocol/pi-rpc/models.js +1 -1
- package/dist/agent-protocol/pi-rpc/session.d.ts +1 -1
- package/dist/agent-protocol/pi-rpc/session.js +33 -32
- package/dist/amr-model-cache.d.ts +12 -4
- package/dist/amr-model-cache.js +17 -21
- package/dist/amr-profile-resolver.d.ts +3 -1
- package/dist/anthropic-live-models.js +0 -0
- package/dist/artifact-taxonomy.d.ts +6 -2
- package/dist/auth.d.ts +52 -15
- package/dist/auth.js +36 -36
- package/dist/claude-code-models.js +2 -2
- package/dist/claude-stream.d.ts +22 -3
- package/dist/claude-stream.js +24 -8
- package/dist/copilot-stream.d.ts +7 -3
- package/dist/copilot-stream.js +3 -3
- package/dist/defs/aider.d.ts +8 -1
- package/dist/defs/aider.js +2 -2
- package/dist/defs/amp.d.ts +8 -1
- package/dist/defs/amp.js +2 -2
- package/dist/defs/amr.d.ts +22 -6
- package/dist/defs/amr.js +23 -23
- package/dist/defs/antigravity.d.ts +15 -4
- package/dist/defs/antigravity.js +9 -8
- package/dist/defs/auggie.d.ts +4 -1
- package/dist/defs/auggie.js +1 -1
- package/dist/defs/claude.d.ts +16 -2
- package/dist/defs/claude.js +22 -4
- package/dist/defs/cline.d.ts +4 -1
- package/dist/defs/cline.js +1 -1
- package/dist/defs/codebuddy.d.ts +8 -1
- package/dist/defs/codebuddy.js +2 -2
- package/dist/defs/codex.d.ts +18 -4
- package/dist/defs/codex.js +7 -7
- package/dist/defs/copilot.d.ts +8 -1
- package/dist/defs/copilot.js +2 -2
- package/dist/defs/crush.d.ts +8 -1
- package/dist/defs/crush.js +1 -1
- package/dist/defs/cursor-agent.d.ts +14 -3
- package/dist/defs/cursor-agent.js +5 -5
- package/dist/defs/deepseek.d.ts +8 -1
- package/dist/defs/deepseek.js +2 -2
- package/dist/defs/devin.d.ts +12 -2
- package/dist/defs/devin.js +3 -3
- package/dist/defs/droid.d.ts +8 -1
- package/dist/defs/droid.js +1 -1
- package/dist/defs/gemini.d.ts +8 -1
- package/dist/defs/gemini.js +1 -1
- package/dist/defs/goose.d.ts +4 -1
- package/dist/defs/goose.js +1 -1
- package/dist/defs/grok-build.d.ts +11 -2
- package/dist/defs/grok-build.js +3 -3
- package/dist/defs/hermes.d.ts +4 -1
- package/dist/defs/hermes.js +2 -2
- package/dist/defs/kilo.d.ts +4 -1
- package/dist/defs/kilo.js +2 -2
- package/dist/defs/kimi.d.ts +4 -1
- package/dist/defs/kimi.js +2 -2
- package/dist/defs/kiro.d.ts +4 -1
- package/dist/defs/kiro.js +2 -2
- package/dist/defs/mimo.d.ts +8 -1
- package/dist/defs/mimo.js +2 -2
- package/dist/defs/opencode.d.ts +9 -2
- package/dist/defs/opencode.js +2 -2
- package/dist/defs/pi.d.ts +12 -2
- package/dist/defs/pi.js +9 -9
- package/dist/defs/qoder.d.ts +8 -1
- package/dist/defs/qoder.js +2 -2
- package/dist/defs/qwen.d.ts +8 -1
- package/dist/defs/qwen.js +2 -2
- package/dist/defs/reasonix.d.ts +4 -1
- package/dist/defs/reasonix.js +3 -3
- package/dist/defs/shared.d.ts +4 -2
- package/dist/defs/shared.js +2 -2
- package/dist/defs/trae-cli.d.ts +12 -2
- package/dist/defs/trae-cli.js +3 -3
- package/dist/defs/vibe.d.ts +4 -1
- package/dist/defs/vibe.js +2 -2
- package/dist/detection.d.ts +38 -3
- package/dist/detection.js +77 -37
- package/dist/diagnostics.d.ts +14 -3
- package/dist/diagnostics.js +5 -5
- package/dist/env.d.ts +16 -4
- package/dist/env.js +7 -7
- package/dist/executables.d.ts +24 -8
- package/dist/executables.js +13 -13
- package/dist/index.d.ts +228 -4
- package/dist/index.js +230 -6
- package/dist/invocation.d.ts +6 -1
- package/dist/invocation.js +2 -2
- package/dist/json-event-stream.d.ts +7 -2
- package/dist/json-event-stream.js +3 -3
- package/dist/launch.d.ts +12 -2
- package/dist/launch.js +3 -3
- package/dist/log-file.d.ts +4 -1
- package/dist/log-file.js +2 -2
- package/dist/mcp.d.ts +6 -3
- package/dist/mcp.js +1 -1
- package/dist/metadata.d.ts +7 -3
- package/dist/metadata.js +1 -1
- package/dist/mmd-routes.d.ts +22 -6
- package/dist/mmd-routes.js +14 -14
- package/dist/model-catalog-cache.d.ts +50 -0
- package/dist/model-catalog-cache.js +61 -0
- package/dist/model-loading-state.d.ts +10 -0
- package/dist/model-loading-state.js +23 -0
- package/dist/model-registry.d.ts +28 -7
- package/dist/model-registry.js +11 -8
- package/dist/models.d.ts +31 -6
- package/dist/models.js +6 -6
- package/dist/opencode-log.d.ts +12 -4
- package/dist/opencode-log.js +8 -8
- package/dist/paths.d.ts +6 -2
- package/dist/paths.js +3 -3
- package/dist/pi-models.d.ts +3 -1
- package/dist/pi-models.js +2 -2
- package/dist/prompt-budget.d.ts +17 -4
- package/dist/prompt-budget.js +3 -3
- package/dist/prompt-file.d.ts +5 -1
- package/dist/prompt-file.js +1 -1
- package/dist/providers/aihubmix.d.ts +34 -9
- package/dist/providers/aihubmix.js +26 -26
- package/dist/providers/anthropic-messages.d.ts +77 -20
- package/dist/providers/anthropic-messages.js +53 -50
- package/dist/providers/azure-chat.d.ts +21 -7
- package/dist/providers/azure-chat.js +18 -16
- package/dist/providers/connection-guard.d.ts +45 -31
- package/dist/providers/connection-guard.js +40 -143
- package/dist/providers/connection-test.d.ts +1 -1
- package/dist/providers/connection-test.js +13 -30
- package/dist/providers/elevenlabs.d.ts +7 -2
- package/dist/providers/elevenlabs.js +4 -4
- package/dist/providers/google-messages.d.ts +44 -10
- package/dist/providers/google-messages.js +36 -34
- package/dist/providers/google-schema.d.ts +26 -0
- package/dist/providers/google-schema.js +253 -0
- package/dist/providers/google.d.ts +21 -6
- package/dist/providers/google.js +10 -10
- package/dist/providers/index.d.ts +3 -2
- package/dist/providers/index.js +3 -2
- package/dist/providers/model-catalog.d.ts +1 -1
- package/dist/providers/model-catalog.js +14 -27
- package/dist/providers/oauth-callback-server.d.ts +1 -1
- package/dist/providers/oauth-callback-server.js +3 -2
- package/dist/providers/oauth-credentials.d.ts +7 -1
- package/dist/providers/oauth-credentials.js +5 -5
- package/dist/providers/oauth-provider.d.ts +2 -2
- package/dist/providers/oauth-provider.js +20 -25
- package/dist/providers/oauth-tokens.d.ts +26 -6
- package/dist/providers/oauth-tokens.js +9 -9
- package/dist/providers/ollama-chat.d.ts +66 -31
- package/dist/providers/ollama-chat.js +64 -61
- package/dist/providers/openai-chat.d.ts +77 -22
- package/dist/providers/openai-chat.js +71 -67
- package/dist/providers/pkce.d.ts +33 -20
- package/dist/providers/pkce.js +75 -146
- package/dist/providers/sse-decode.d.ts +3 -1
- package/dist/providers/sse-decode.js +1 -1
- package/dist/providers/token-params.d.ts +16 -5
- package/dist/providers/token-params.js +6 -6
- package/dist/providers/tool-turn-types.d.ts +89 -0
- package/dist/providers/tool-turn-types.js +2 -0
- package/dist/providers/tool-turn.d.ts +10 -0
- package/dist/providers/tool-turn.js +252 -0
- package/dist/qoder-stream.d.ts +7 -3
- package/dist/qoder-stream.js +3 -3
- package/dist/registry.d.ts +6 -2
- package/dist/registry.js +4 -4
- package/dist/resolution.d.ts +5 -1
- package/dist/resolution.js +3 -3
- package/dist/role-marker-guard.d.ts +9 -5
- package/dist/role-marker-guard.js +5 -5
- package/dist/terminal-launch.d.ts +6 -1
- package/dist/terminal-launch.js +2 -2
- package/dist/types.d.ts +37 -6
- package/package.json +43 -4
package/dist/detection.d.ts
CHANGED
|
@@ -4,6 +4,30 @@ type FetchedRuntimeModels = {
|
|
|
4
4
|
models: RuntimeModelOption[];
|
|
5
5
|
source: RuntimeModelSource;
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Makes sure `agentCapabilities` holds this def's `--help`-probed flags before its `buildArgs` runs.
|
|
9
|
+
*
|
|
10
|
+
* Why this exists: `agentCapabilities` used to be filled ONLY by {@link detectAgents}. A host whose
|
|
11
|
+
* run process never calls `detectAgents` (it lists agents with its own lighter probe, or not at
|
|
12
|
+
* all) left the map empty for every run, so every probe-gated flag stayed off for good — for
|
|
13
|
+
* `claude` that meant no `--include-partial-messages` (no streamed text) and no `--effort`, even on
|
|
14
|
+
* a CLI that supports both. The run path calls this with the exact launch path and env it is about
|
|
15
|
+
* to spawn, so the gate reflects the binary that actually runs.
|
|
16
|
+
*
|
|
17
|
+
* A no-op when the def declares no probe or the map already has an entry (a `detectAgents` result
|
|
18
|
+
* wins). Probes once per def id + launch path for the life of the process. A failed probe records
|
|
19
|
+
* nothing, which keeps the safe baseline (no optional flags), and is not retried on every run.
|
|
20
|
+
*
|
|
21
|
+
* @param def - The def about to be spawned.
|
|
22
|
+
* @param launchPath - The resolved executable the run will spawn.
|
|
23
|
+
* @param env - The env the run will spawn with.
|
|
24
|
+
* @complexity O(1) after the first call per def + path; the first call costs one `--help` spawn (5 s cap).
|
|
25
|
+
*/
|
|
26
|
+
export declare function ensureAgentCapabilities({ def, launchPath, env }: {
|
|
27
|
+
def: RuntimeAgentDef;
|
|
28
|
+
launchPath: string;
|
|
29
|
+
env: NodeJS.ProcessEnv;
|
|
30
|
+
}): Promise<void>;
|
|
7
31
|
/** Result of {@link probeAgentModels}: the models to surface and where they came from. */
|
|
8
32
|
export type ProbedAgentModels = FetchedRuntimeModels;
|
|
9
33
|
/**
|
|
@@ -18,8 +42,16 @@ export type ProbedAgentModels = FetchedRuntimeModels;
|
|
|
18
42
|
* `source: 'fallback'` (including when the binary is not found). Never rejects.
|
|
19
43
|
* @complexity At most one model-listing spawn, bounded by the def's own timeout.
|
|
20
44
|
*/
|
|
21
|
-
export declare function probeAgentModels(def
|
|
22
|
-
|
|
45
|
+
export declare function probeAgentModels({ def }: {
|
|
46
|
+
def: RuntimeAgentDef;
|
|
47
|
+
}, { configuredEnv, amrProfileResolver }?: {
|
|
48
|
+
configuredEnv?: Record<string, string>;
|
|
49
|
+
amrProfileResolver?: AmrProfileResolver;
|
|
50
|
+
}): Promise<ProbedAgentModels>;
|
|
51
|
+
export declare function detectAgents({}: {}, { configuredEnvByAgent, amrProfileResolver }?: {
|
|
52
|
+
configuredEnvByAgent?: Record<string, Record<string, string>>;
|
|
53
|
+
amrProfileResolver?: AmrProfileResolver;
|
|
54
|
+
}): Promise<(Omit<RuntimeAgentDef, "buildArgs" | "listModels" | "fetchModels" | "deriveReasoningOptions" | "fallbackModels" | "fallbackModelsAssertedAt" | "helpArgs" | "capabilityFlags" | "fallbackBins" | "versionProbeTimeoutMs" | "maxPromptArgBytes" | "env" | "inactivityTimeoutMs" | "authProbe" | "needsAgentLogFile" | "stdoutPolicy" | "runtimeLock"> & {
|
|
23
55
|
models: RuntimeModelOption[];
|
|
24
56
|
modelsSource: RuntimeModelSource;
|
|
25
57
|
available: boolean;
|
|
@@ -29,6 +61,9 @@ export declare function detectAgents(configuredEnvByAgent?: Record<string, Recor
|
|
|
29
61
|
version?: string | null;
|
|
30
62
|
diagnostics?: AgentDiagnostic[];
|
|
31
63
|
})[]>;
|
|
32
|
-
export declare function detectAgentsStream(
|
|
64
|
+
export declare function detectAgentsStream({}: {}, { configuredEnvByAgent, amrProfileResolver }?: {
|
|
65
|
+
configuredEnvByAgent?: Record<string, Record<string, string>>;
|
|
66
|
+
amrProfileResolver?: AmrProfileResolver;
|
|
67
|
+
}): AsyncGenerator<DetectedAgent>;
|
|
33
68
|
export {};
|
|
34
69
|
//# sourceMappingURL=detection.d.ts.map
|
package/dist/detection.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* `AmrProfileResolver` port (see `amr-profile-resolver.ts`), defaulting to
|
|
10
10
|
* a no-op. `detectAgents`/`detectAgentsStream` take it as an optional last
|
|
11
11
|
* parameter; every other agent's detection path is unaffected. See
|
|
12
|
-
* `
|
|
12
|
+
* `archived provenance ledger`.
|
|
13
13
|
*/
|
|
14
14
|
import { execAgentFile } from './invocation.js';
|
|
15
15
|
import { getRememberedLiveModels, rememberLiveModels } from './models.js';
|
|
@@ -22,12 +22,12 @@ import { probeAgentAuthStatus } from './auth.js';
|
|
|
22
22
|
import { noopAmrProfileResolver } from './amr-profile-resolver.js';
|
|
23
23
|
import { buildAuthDiagnostic, buildExecutableDiagnostic, buildNotInvocableDiagnostic } from './diagnostics.js';
|
|
24
24
|
function amrModelScopeFromEnv(env, amrProfileResolver) {
|
|
25
|
-
return amrProfileResolver.resolveProfile(env);
|
|
25
|
+
return amrProfileResolver.resolveProfile({ env: env });
|
|
26
26
|
}
|
|
27
27
|
function withRememberedAmrModels(def, env, modelResult, amrProfileResolver) {
|
|
28
28
|
if (def.id !== 'amr' || modelResult.models.length > 0)
|
|
29
29
|
return modelResult;
|
|
30
|
-
const rememberedModels = getRememberedLiveModels(def.id, amrModelScopeFromEnv(env, amrProfileResolver));
|
|
30
|
+
const rememberedModels = getRememberedLiveModels({ agentId: def.id }, { scope: amrModelScopeFromEnv(env, amrProfileResolver) });
|
|
31
31
|
if (rememberedModels.length === 0)
|
|
32
32
|
return modelResult;
|
|
33
33
|
return { models: rememberedModels, source: 'live' };
|
|
@@ -35,7 +35,7 @@ function withRememberedAmrModels(def, env, modelResult, amrProfileResolver) {
|
|
|
35
35
|
async function fetchModels(def, resolvedBin, env) {
|
|
36
36
|
if (typeof def.fetchModels === 'function') {
|
|
37
37
|
try {
|
|
38
|
-
const parsed = await def.fetchModels(resolvedBin, env);
|
|
38
|
+
const parsed = await def.fetchModels({ resolvedBin: resolvedBin, env: env });
|
|
39
39
|
if (!parsed || parsed.length === 0) {
|
|
40
40
|
return { models: def.fallbackModels, source: 'fallback' };
|
|
41
41
|
}
|
|
@@ -49,15 +49,15 @@ async function fetchModels(def, resolvedBin, env) {
|
|
|
49
49
|
return { models: def.fallbackModels, source: 'fallback' };
|
|
50
50
|
}
|
|
51
51
|
try {
|
|
52
|
-
const { stdout } = await execAgentFile(resolvedBin, def.listModels.args, {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const parsed = def.listModels.parse(String(stdout));
|
|
52
|
+
const { stdout } = await execAgentFile({ command: resolvedBin, args: def.listModels.args }, { options: {
|
|
53
|
+
env,
|
|
54
|
+
timeout: def.listModels.timeoutMs,
|
|
55
|
+
// Models lists from popular CLIs (e.g. opencode) easily exceed the
|
|
56
|
+
// default 1MB buffer once you include every openrouter model. Bump
|
|
57
|
+
// it so we don't truncate the listing.
|
|
58
|
+
maxBuffer: 8 * 1024 * 1024,
|
|
59
|
+
} });
|
|
60
|
+
const parsed = def.listModels.parse({ stdout: String(stdout) });
|
|
61
61
|
// Empty / null parse result means the CLI didn't actually return a
|
|
62
62
|
// usable list (e.g. cursor-agent's "No models available"); fall back
|
|
63
63
|
// to the static hint so the picker isn't stuck on Default-only.
|
|
@@ -95,10 +95,10 @@ async function fetchModels(def, resolvedBin, env) {
|
|
|
95
95
|
*/
|
|
96
96
|
async function probeVersionAtPath(def, resolved, env) {
|
|
97
97
|
try {
|
|
98
|
-
const { stdout } = await execAgentFile(resolved, def.versionArgs, {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
const { stdout } = await execAgentFile({ command: resolved, args: def.versionArgs }, { options: {
|
|
99
|
+
env,
|
|
100
|
+
timeout: def.versionProbeTimeoutMs ?? 3000,
|
|
101
|
+
} });
|
|
102
102
|
// `String.split()` on a non-empty string always returns at least one
|
|
103
103
|
// element, so `[0]` is never `undefined` here — the assertion just
|
|
104
104
|
// satisfies `noUncheckedIndexedAccess`.
|
|
@@ -128,7 +128,7 @@ function unavailableAgent(def, diagnostics = []) {
|
|
|
128
128
|
modelsSource: 'fallback',
|
|
129
129
|
available: false,
|
|
130
130
|
...(diagnostics.length > 0 ? { diagnostics } : {}),
|
|
131
|
-
...installMetaForAgent(def.id),
|
|
131
|
+
...installMetaForAgent({ agentId: def.id }),
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
134
|
// Probe the agent's `--help` once and record which advertised flags the
|
|
@@ -140,12 +140,7 @@ async function probeCapabilities(def, launchPath, env) {
|
|
|
140
140
|
if (!def.helpArgs || !def.capabilityFlags)
|
|
141
141
|
return null;
|
|
142
142
|
try {
|
|
143
|
-
|
|
144
|
-
const caps = {};
|
|
145
|
-
for (const [flag, key] of Object.entries(def.capabilityFlags)) {
|
|
146
|
-
caps[key] = String(stdout).includes(flag);
|
|
147
|
-
}
|
|
148
|
-
return caps;
|
|
143
|
+
return await readCapabilities(def.helpArgs, def.capabilityFlags, launchPath, env);
|
|
149
144
|
}
|
|
150
145
|
catch {
|
|
151
146
|
// If --help fails, leave caps empty so buildArgs falls back to the
|
|
@@ -153,6 +148,51 @@ async function probeCapabilities(def, launchPath, env) {
|
|
|
153
148
|
return {};
|
|
154
149
|
}
|
|
155
150
|
}
|
|
151
|
+
/** Runs the def's `--help` probe and maps each advertised flag to its capability key; throws on a failed probe. */
|
|
152
|
+
async function readCapabilities(helpArgs, capabilityFlags, launchPath, env) {
|
|
153
|
+
const { stdout } = await execAgentFile({ command: launchPath, args: [...helpArgs] }, { options: { env, timeout: 5000, maxBuffer: 4 * 1024 * 1024 } });
|
|
154
|
+
const caps = {};
|
|
155
|
+
for (const [flag, key] of Object.entries(capabilityFlags)) {
|
|
156
|
+
caps[key] = String(stdout).includes(flag);
|
|
157
|
+
}
|
|
158
|
+
return caps;
|
|
159
|
+
}
|
|
160
|
+
/** One in-flight or settled `--help` probe per def id + launch path, so a run never re-spawns it. */
|
|
161
|
+
const capabilityProbes = new Map();
|
|
162
|
+
/**
|
|
163
|
+
* Makes sure `agentCapabilities` holds this def's `--help`-probed flags before its `buildArgs` runs.
|
|
164
|
+
*
|
|
165
|
+
* Why this exists: `agentCapabilities` used to be filled ONLY by {@link detectAgents}. A host whose
|
|
166
|
+
* run process never calls `detectAgents` (it lists agents with its own lighter probe, or not at
|
|
167
|
+
* all) left the map empty for every run, so every probe-gated flag stayed off for good — for
|
|
168
|
+
* `claude` that meant no `--include-partial-messages` (no streamed text) and no `--effort`, even on
|
|
169
|
+
* a CLI that supports both. The run path calls this with the exact launch path and env it is about
|
|
170
|
+
* to spawn, so the gate reflects the binary that actually runs.
|
|
171
|
+
*
|
|
172
|
+
* A no-op when the def declares no probe or the map already has an entry (a `detectAgents` result
|
|
173
|
+
* wins). Probes once per def id + launch path for the life of the process. A failed probe records
|
|
174
|
+
* nothing, which keeps the safe baseline (no optional flags), and is not retried on every run.
|
|
175
|
+
*
|
|
176
|
+
* @param def - The def about to be spawned.
|
|
177
|
+
* @param launchPath - The resolved executable the run will spawn.
|
|
178
|
+
* @param env - The env the run will spawn with.
|
|
179
|
+
* @complexity O(1) after the first call per def + path; the first call costs one `--help` spawn (5 s cap).
|
|
180
|
+
*/
|
|
181
|
+
export function ensureAgentCapabilities({ def, launchPath, env }) {
|
|
182
|
+
const { helpArgs, capabilityFlags } = def;
|
|
183
|
+
if (!helpArgs || !capabilityFlags || agentCapabilities.has(def.id))
|
|
184
|
+
return Promise.resolve();
|
|
185
|
+
const key = `${def.id}\u0000${launchPath}`;
|
|
186
|
+
const existing = capabilityProbes.get(key);
|
|
187
|
+
if (existing)
|
|
188
|
+
return existing;
|
|
189
|
+
const probe = readCapabilities(helpArgs, capabilityFlags, launchPath, env).then((caps) => {
|
|
190
|
+
if (!agentCapabilities.has(def.id))
|
|
191
|
+
agentCapabilities.set(def.id, caps);
|
|
192
|
+
}, () => undefined);
|
|
193
|
+
capabilityProbes.set(key, probe);
|
|
194
|
+
return probe;
|
|
195
|
+
}
|
|
156
196
|
/**
|
|
157
197
|
* The effort-level override a live model catalog earns, if any.
|
|
158
198
|
*
|
|
@@ -166,12 +206,12 @@ async function probeCapabilities(def, launchPath, env) {
|
|
|
166
206
|
* @complexity O(1) here; the hook's own cost is documented on `deriveReasoningOptions`.
|
|
167
207
|
*/
|
|
168
208
|
function derivedReasoningOverride(def, models) {
|
|
169
|
-
const derived = def.deriveReasoningOptions?.(models);
|
|
209
|
+
const derived = def.deriveReasoningOptions?.({ models: models });
|
|
170
210
|
return derived && derived.length > 0 ? { reasoningOptions: derived } : {};
|
|
171
211
|
}
|
|
172
212
|
/** The env every probe of one def spawns with — the same env a real run would see. */
|
|
173
213
|
function probeEnvForLaunch(def, configuredEnv, launch) {
|
|
174
|
-
return applyAgentLaunchEnv(spawnEnvForAgent(def.id, { ...process.env, ...(def.env || {}) }, configuredEnv
|
|
214
|
+
return applyAgentLaunchEnv({ env: spawnEnvForAgent({ agentId: def.id, baseEnv: { ...process.env, ...(def.env || {}) } }, { configuredEnv: configuredEnv, hooks: {} }), launch: launch });
|
|
175
215
|
}
|
|
176
216
|
/**
|
|
177
217
|
* The model half of {@link detectAgents} for ONE def, without the `--version`/`--help`/auth probes:
|
|
@@ -185,9 +225,9 @@ function probeEnvForLaunch(def, configuredEnv, launch) {
|
|
|
185
225
|
* `source: 'fallback'` (including when the binary is not found). Never rejects.
|
|
186
226
|
* @complexity At most one model-listing spawn, bounded by the def's own timeout.
|
|
187
227
|
*/
|
|
188
|
-
export async function probeAgentModels(def, configuredEnv = {}, amrProfileResolver = noopAmrProfileResolver) {
|
|
228
|
+
export async function probeAgentModels({ def }, { configuredEnv = {}, amrProfileResolver = noopAmrProfileResolver } = {}) {
|
|
189
229
|
try {
|
|
190
|
-
const launch = resolveAgentLaunch(def, configuredEnv);
|
|
230
|
+
const launch = resolveAgentLaunch({ def: def }, { configuredEnv: configuredEnv });
|
|
191
231
|
if (!launch.launchPath)
|
|
192
232
|
return { models: def.fallbackModels, source: 'fallback' };
|
|
193
233
|
const probeEnv = probeEnvForLaunch(def, configuredEnv, launch);
|
|
@@ -209,14 +249,14 @@ async function probe(def, configuredEnv = {}, amrProfileResolver) {
|
|
|
209
249
|
// detection probes the shim but chat/run spawns the native binary, the
|
|
210
250
|
// UI incorrectly reports "not installed" until the user pins the bin
|
|
211
251
|
// override by hand even though the real launch path is healthy.
|
|
212
|
-
const launch = resolveAgentLaunch(def, configuredEnv);
|
|
252
|
+
const launch = resolveAgentLaunch({ def: def }, { configuredEnv: configuredEnv });
|
|
213
253
|
if (!launch.selectedPath || !launch.launchPath) {
|
|
214
|
-
return unavailableAgent(def, [buildExecutableDiagnostic(def, configuredEnv)]);
|
|
254
|
+
return unavailableAgent(def, [buildExecutableDiagnostic({ def: def }, { configuredEnv: configuredEnv })]);
|
|
215
255
|
}
|
|
216
256
|
const probeEnv = probeEnvForLaunch(def, configuredEnv, launch);
|
|
217
257
|
const outcome = await probeVersionAtPath(def, launch.launchPath, probeEnv);
|
|
218
258
|
if (outcome.kind === 'not-invocable') {
|
|
219
|
-
return unavailableAgent(def, [buildNotInvocableDiagnostic(def, launch, outcome.cause)]);
|
|
259
|
+
return unavailableAgent(def, [buildNotInvocableDiagnostic({ def: def, launch: launch, cause: outcome.cause })]);
|
|
220
260
|
}
|
|
221
261
|
// The version probe must finish first (it gates availability), but the
|
|
222
262
|
// three post-version probes are independent reads — run them
|
|
@@ -226,13 +266,13 @@ async function probe(def, configuredEnv = {}, amrProfileResolver) {
|
|
|
226
266
|
const [caps, modelResult, auth] = await Promise.all([
|
|
227
267
|
probeCapabilities(def, launch.launchPath, probeEnv),
|
|
228
268
|
fetchModels(def, launch.launchPath, probeEnv),
|
|
229
|
-
probeAgentAuthStatus(def, launch.launchPath, probeEnv),
|
|
269
|
+
probeAgentAuthStatus({ def: def, resolvedBin: launch.launchPath, env: probeEnv }),
|
|
230
270
|
]);
|
|
231
271
|
const surfacedModelResult = withRememberedAmrModels(def, probeEnv, modelResult, amrProfileResolver);
|
|
232
272
|
if (caps) {
|
|
233
273
|
agentCapabilities.set(def.id, caps);
|
|
234
274
|
}
|
|
235
|
-
const authDiagnostic = auth ? buildAuthDiagnostic(def, auth) : null;
|
|
275
|
+
const authDiagnostic = auth ? buildAuthDiagnostic({ def: def, auth: auth }) : null;
|
|
236
276
|
return {
|
|
237
277
|
...stripFns(def),
|
|
238
278
|
...derivedReasoningOverride(def, surfacedModelResult.models),
|
|
@@ -243,7 +283,7 @@ async function probe(def, configuredEnv = {}, amrProfileResolver) {
|
|
|
243
283
|
version: outcome.version,
|
|
244
284
|
...(auth ? { authStatus: auth.status, ...(auth.message ? { authMessage: auth.message } : {}) } : {}),
|
|
245
285
|
...(authDiagnostic ? { diagnostics: [authDiagnostic] } : {}),
|
|
246
|
-
...installMetaForAgent(def.id),
|
|
286
|
+
...installMetaForAgent({ agentId: def.id }),
|
|
247
287
|
};
|
|
248
288
|
}
|
|
249
289
|
function stripFns(def) {
|
|
@@ -289,9 +329,9 @@ function rememberDetectedModelList(def, configuredEnv, models, amrProfileResolve
|
|
|
289
329
|
const scope = def.id === 'amr'
|
|
290
330
|
? amrModelScopeFromEnv({ ...process.env, ...(def.env || {}), ...configuredEnv }, amrProfileResolver)
|
|
291
331
|
: null;
|
|
292
|
-
rememberLiveModels(def.id, models, scope);
|
|
332
|
+
rememberLiveModels({ agentId: def.id, models: models }, { scope: scope });
|
|
293
333
|
}
|
|
294
|
-
export async function detectAgents(configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver) {
|
|
334
|
+
export async function detectAgents({}, { configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver } = {}) {
|
|
295
335
|
const results = await Promise.all(AGENT_DEFS.map((def) => safeProbe(def, configuredEnvByAgent?.[def.id] ?? {}, amrProfileResolver)));
|
|
296
336
|
// Refresh the validation cache from whatever we just surfaced to the UI
|
|
297
337
|
// so a chat endpoint can accept any model the user could have just
|
|
@@ -311,7 +351,7 @@ export async function detectAgents(configuredEnvByAgent = {}, amrProfileResolver
|
|
|
311
351
|
// validation cache is refreshed per-agent (same effect as the batch path,
|
|
312
352
|
// just incrementally). `detectAgents` keeps the array contract for callers
|
|
313
353
|
// that don't care about incremental delivery.
|
|
314
|
-
export async function* detectAgentsStream(configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver) {
|
|
354
|
+
export async function* detectAgentsStream({}, { configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver } = {}) {
|
|
315
355
|
const tagged = AGENT_DEFS.map((def, index) => safeProbe(def, configuredEnvByAgent?.[def.id] ?? {}, amrProfileResolver).then((agent) => {
|
|
316
356
|
rememberDetectedLiveModels(def, configuredEnvByAgent?.[def.id] ?? {}, agent, amrProfileResolver);
|
|
317
357
|
return { index, agent };
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import type { AgentLaunchResolution } from './launch.js';
|
|
2
2
|
import type { AgentAuthProbeResult } from './auth.js';
|
|
3
3
|
import type { AgentDiagnostic, RuntimeAgentDef } from './types.js';
|
|
4
|
-
export declare function buildExecutableDiagnostic(def
|
|
4
|
+
export declare function buildExecutableDiagnostic({ def }: {
|
|
5
|
+
def: Pick<RuntimeAgentDef, 'id' | 'name' | 'bin'>;
|
|
6
|
+
}, { configuredEnv }?: {
|
|
7
|
+
configuredEnv?: Record<string, string>;
|
|
8
|
+
}): AgentDiagnostic;
|
|
5
9
|
export type NotInvocableCause = 'not-executable' | 'missing-target';
|
|
6
|
-
export declare function buildNotInvocableDiagnostic(def
|
|
7
|
-
|
|
10
|
+
export declare function buildNotInvocableDiagnostic({ def, launch, cause }: {
|
|
11
|
+
def: Pick<RuntimeAgentDef, 'id' | 'name'>;
|
|
12
|
+
launch: Pick<AgentLaunchResolution, 'selectedPath' | 'launchPath'>;
|
|
13
|
+
cause: NotInvocableCause;
|
|
14
|
+
}): AgentDiagnostic;
|
|
15
|
+
export declare function buildAuthDiagnostic({ def, auth }: {
|
|
16
|
+
def: Pick<RuntimeAgentDef, 'id' | 'name'>;
|
|
17
|
+
auth: AgentAuthProbeResult;
|
|
18
|
+
}): AgentDiagnostic | null;
|
|
8
19
|
//# sourceMappingURL=diagnostics.d.ts.map
|
package/dist/diagnostics.js
CHANGED
|
@@ -17,15 +17,15 @@ import { agentBinEnvKey, agentSearchDirs } from './executables.js';
|
|
|
17
17
|
// land without ballooning the response payload.
|
|
18
18
|
const MAX_SEARCHED_DIRS = 24;
|
|
19
19
|
function setEnvIntent(agentId) {
|
|
20
|
-
const envKey = agentBinEnvKey(agentId);
|
|
20
|
+
const envKey = agentBinEnvKey({ agentId: agentId });
|
|
21
21
|
return envKey ? [{ kind: 'setEnv', envKey }] : [];
|
|
22
22
|
}
|
|
23
23
|
// The agent is not resolvable at all: either nothing matched on PATH, or a
|
|
24
24
|
// user-supplied `*_BIN` override points at a missing/invalid file. The two
|
|
25
25
|
// cases get different copy + fix affordances because the remedy differs
|
|
26
26
|
// (install / point us at the binary vs. fix or clear the override).
|
|
27
|
-
export function buildExecutableDiagnostic(def, configuredEnv = {}) {
|
|
28
|
-
const envKey = agentBinEnvKey(def.id);
|
|
27
|
+
export function buildExecutableDiagnostic({ def }, { configuredEnv = {} } = {}) {
|
|
28
|
+
const envKey = agentBinEnvKey({ agentId: def.id });
|
|
29
29
|
const overrideRaw = envKey ? configuredEnv?.[envKey]?.trim() : '';
|
|
30
30
|
if (envKey && overrideRaw) {
|
|
31
31
|
return {
|
|
@@ -48,7 +48,7 @@ export function buildExecutableDiagnostic(def, configuredEnv = {}) {
|
|
|
48
48
|
// are real binaries that need their executable bit restored; missing-target
|
|
49
49
|
// failures are usually leftover npm/nvm/mise shims whose underlying target
|
|
50
50
|
// was uninstalled.
|
|
51
|
-
export function buildNotInvocableDiagnostic(def, launch, cause) {
|
|
51
|
+
export function buildNotInvocableDiagnostic({ def, launch, cause }) {
|
|
52
52
|
if (cause === 'not-executable') {
|
|
53
53
|
return {
|
|
54
54
|
reason: 'not-executable',
|
|
@@ -71,7 +71,7 @@ export function buildNotInvocableDiagnostic(def, launch, cause) {
|
|
|
71
71
|
// for adapters that declare a cheap, side-effect-free authProbe; until an
|
|
72
72
|
// adapter also declares a spawn-safe OAuth producer, diagnostics point at
|
|
73
73
|
// docs.
|
|
74
|
-
export function buildAuthDiagnostic(def, auth) {
|
|
74
|
+
export function buildAuthDiagnostic({ def, auth }) {
|
|
75
75
|
if (auth.status === 'ok')
|
|
76
76
|
return null;
|
|
77
77
|
const signInIntent = { kind: 'openDocs' };
|
package/dist/env.d.ts
CHANGED
|
@@ -3,17 +3,29 @@ export interface SpawnEnvHooks {
|
|
|
3
3
|
/**
|
|
4
4
|
* Per-agent env customization (e.g. vela/AMR profile forwarding,
|
|
5
5
|
* analytics identity, a routed model's endpoint override). Called after
|
|
6
|
-
* the proxy-aware merge
|
|
6
|
+
* the proxy-aware merge and built-in housekeeping, before `sandboxOverlay`.
|
|
7
7
|
* Return a partial env to merge in, or nothing to leave `env` as-is
|
|
8
8
|
* (mutating `env` directly is also fine — it's a live object).
|
|
9
9
|
*/
|
|
10
|
-
perAgentEnv?: (
|
|
10
|
+
perAgentEnv?: (requiredArgs: {
|
|
11
|
+
agentId: string;
|
|
12
|
+
env: NodeJS.ProcessEnv;
|
|
13
|
+
}) => NodeJS.ProcessEnv | void;
|
|
11
14
|
/**
|
|
12
15
|
* Applied last, after all other env composition. A host with a
|
|
13
16
|
* sandboxed/jailed spawn mode plugs its own env constraints in here.
|
|
14
17
|
*/
|
|
15
|
-
sandboxOverlay?: (
|
|
18
|
+
sandboxOverlay?: (requiredArgs: {
|
|
19
|
+
env: NodeJS.ProcessEnv;
|
|
20
|
+
}) => NodeJS.ProcessEnv;
|
|
16
21
|
}
|
|
17
|
-
export declare function spawnEnvForAgent(agentId
|
|
22
|
+
export declare function spawnEnvForAgent({ agentId, baseEnv }: {
|
|
23
|
+
agentId: string;
|
|
24
|
+
baseEnv: RuntimeEnvMap;
|
|
25
|
+
}, { configuredEnv, systemProxyEnv, hooks }?: {
|
|
26
|
+
configuredEnv?: unknown;
|
|
27
|
+
systemProxyEnv?: RuntimeEnvMap;
|
|
28
|
+
hooks?: SpawnEnvHooks;
|
|
29
|
+
}): NodeJS.ProcessEnv;
|
|
18
30
|
export {};
|
|
19
31
|
//# sourceMappingURL=env.d.ts.map
|
package/dist/env.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* classification anticipated — it read OD's own app-config subsystem, OD's
|
|
13
13
|
* sandbox-mode subsystem, and vela/AMR-specific env forwarding including a
|
|
14
14
|
* literal product-name identity value and two product-prefixed env var
|
|
15
|
-
* names (see `
|
|
15
|
+
* names (see `archived provenance ledger` for the exact originals). None of that is
|
|
16
16
|
* ported:
|
|
17
17
|
*
|
|
18
18
|
* - `mergeProxyAwareEnv` / `resolveSystemProxyEnv` now come from
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* was itself product-branded. A host that needs equivalent trace
|
|
31
31
|
* correlation can build it as a `perAgentEnv` hook.
|
|
32
32
|
*
|
|
33
|
-
* See `
|
|
33
|
+
* See `archived provenance ledger` for the full accounting.
|
|
34
34
|
*/
|
|
35
35
|
import os from 'node:os';
|
|
36
36
|
import { mergeProxyAwareEnv, resolveSystemProxyEnv } from '@jini-ai/platform';
|
|
@@ -43,8 +43,8 @@ function stripKeysCaseInsensitive(env, keysToStrip) {
|
|
|
43
43
|
delete env[key];
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
export function spawnEnvForAgent(agentId, baseEnv, configuredEnv = {}, systemProxyEnv = resolveSystemProxyEnv(), hooks = {}) {
|
|
47
|
-
const expandedConfiguredEnv = expandConfiguredEnv(configuredEnv);
|
|
46
|
+
export function spawnEnvForAgent({ agentId, baseEnv }, { configuredEnv = {}, systemProxyEnv = resolveSystemProxyEnv(), hooks = {} } = {}) {
|
|
47
|
+
const expandedConfiguredEnv = expandConfiguredEnv({ configuredEnv: configuredEnv });
|
|
48
48
|
const env = mergeProxyAwareEnv(process.platform, systemProxyEnv, baseEnv, expandedConfiguredEnv);
|
|
49
49
|
if (agentId === 'amr') {
|
|
50
50
|
// `execAgentFile` REPLACES the child environment (execFile with `env`
|
|
@@ -59,7 +59,7 @@ export function spawnEnvForAgent(agentId, baseEnv, configuredEnv = {}, systemPro
|
|
|
59
59
|
env.HOME = home;
|
|
60
60
|
}
|
|
61
61
|
if (!env.VELA_OPENCODE_BIN?.trim()) {
|
|
62
|
-
const opencodeBin = resolveAmrOpenCodeExecutable(env);
|
|
62
|
+
const opencodeBin = resolveAmrOpenCodeExecutable({}, { env: env });
|
|
63
63
|
if (opencodeBin)
|
|
64
64
|
env.VELA_OPENCODE_BIN = opencodeBin;
|
|
65
65
|
}
|
|
@@ -87,9 +87,9 @@ export function spawnEnvForAgent(agentId, baseEnv, configuredEnv = {}, systemPro
|
|
|
87
87
|
env.MIMOCODE_DISABLE_PROJECT_CONFIG = 'true';
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
-
const perAgentOverrides = hooks.perAgentEnv?.(agentId, env);
|
|
90
|
+
const perAgentOverrides = hooks.perAgentEnv?.({ agentId: agentId, env: env });
|
|
91
91
|
if (perAgentOverrides)
|
|
92
92
|
Object.assign(env, perAgentOverrides);
|
|
93
|
-
return hooks.sandboxOverlay ? hooks.sandboxOverlay(env) : env;
|
|
93
|
+
return hooks.sandboxOverlay ? hooks.sandboxOverlay({ env: env }) : env;
|
|
94
94
|
}
|
|
95
95
|
//# sourceMappingURL=env.js.map
|
package/dist/executables.d.ts
CHANGED
|
@@ -5,18 +5,34 @@ import type { RuntimeAgentDef } from './types.js';
|
|
|
5
5
|
* at startup if it wants its own namespaced env vars instead of the
|
|
6
6
|
* generic defaults.
|
|
7
7
|
*/
|
|
8
|
-
export declare function configureExecutableResolutionEnv(overrides: {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export declare function configureExecutableResolutionEnv({ overrides }: {
|
|
9
|
+
overrides: {
|
|
10
|
+
agentHomeEnvVar?: string;
|
|
11
|
+
resourceRootEnvVar?: string;
|
|
12
|
+
};
|
|
11
13
|
}): void;
|
|
12
14
|
export declare function userToolchainBinDirs(): string[];
|
|
13
15
|
export declare function agentSearchDirs(): string[];
|
|
14
|
-
export declare function agentBinEnvKey(agentId
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
export declare function agentBinEnvKey({ agentId }: {
|
|
17
|
+
agentId: string | undefined;
|
|
18
|
+
}): string | null;
|
|
19
|
+
export declare function resolveOnPath({ bin }: {
|
|
20
|
+
bin: string;
|
|
21
|
+
}): string | null;
|
|
22
|
+
export declare function resolveAmrOpenCodeExecutable({}: {}, { env }?: {
|
|
23
|
+
env?: Record<string, string | undefined>;
|
|
24
|
+
}): string | null;
|
|
17
25
|
export declare function codexAppBundleCandidates(): string[];
|
|
18
|
-
export declare function resolveAgentExecutable(def
|
|
19
|
-
|
|
26
|
+
export declare function resolveAgentExecutable({ def }: {
|
|
27
|
+
def: RuntimeAgentDef;
|
|
28
|
+
}, { configuredEnv }?: {
|
|
29
|
+
configuredEnv?: Record<string, string>;
|
|
30
|
+
}): string | null;
|
|
31
|
+
export declare function inspectAgentExecutableResolution({ def }: {
|
|
32
|
+
def: RuntimeAgentDef;
|
|
33
|
+
}, { configuredEnv }?: {
|
|
34
|
+
configuredEnv?: Record<string, string>;
|
|
35
|
+
}): {
|
|
20
36
|
configuredOverridePath: string | null;
|
|
21
37
|
pathResolvedPath: string | null;
|
|
22
38
|
selectedPath: string | null;
|
package/dist/executables.js
CHANGED
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
*
|
|
11
11
|
* 1. `wellKnownUserToolchainBins` now comes from `@jini-ai/platform` instead of
|
|
12
12
|
* the OD workspace package it originally shipped from (same function,
|
|
13
|
-
* already verbatim-lifted — see `@jini-ai/platform`'s own `
|
|
13
|
+
* already verbatim-lifted — see `@jini-ai/platform`'s own `archived provenance ledger`).
|
|
14
14
|
* 2. De-branded: the origin's product-prefixed agent-home / resource-root
|
|
15
15
|
* env var names and its sandbox-runtime-config integration (an
|
|
16
16
|
* OD-daemon-level subsystem out of this package's charter) are replaced
|
|
17
17
|
* by `configureExecutableResolutionEnv()` — an injectable pair of
|
|
18
18
|
* env-var names, defaulting to `AGENT_RUNTIME_HOME` /
|
|
19
19
|
* `AGENT_RUNTIME_RESOURCE_ROOT`, with no sandbox dependency. See
|
|
20
|
-
* `
|
|
20
|
+
* `archived provenance ledger` for the exact original names.
|
|
21
21
|
*/
|
|
22
22
|
import { accessSync, constants, existsSync, statSync } from 'node:fs';
|
|
23
23
|
import { delimiter } from 'node:path';
|
|
@@ -65,7 +65,7 @@ const executableResolutionEnv = {
|
|
|
65
65
|
* at startup if it wants its own namespaced env vars instead of the
|
|
66
66
|
* generic defaults.
|
|
67
67
|
*/
|
|
68
|
-
export function configureExecutableResolutionEnv(overrides) {
|
|
68
|
+
export function configureExecutableResolutionEnv({ overrides }) {
|
|
69
69
|
if (overrides.agentHomeEnvVar)
|
|
70
70
|
executableResolutionEnv.agentHomeEnvVar = overrides.agentHomeEnvVar;
|
|
71
71
|
if (overrides.resourceRootEnvVar)
|
|
@@ -144,12 +144,12 @@ export function agentSearchDirs() {
|
|
|
144
144
|
// The `*_BIN` environment variable that overrides PATH detection for a given
|
|
145
145
|
// agent id (e.g. `cursor-agent` → `CURSOR_AGENT_BIN`), or null when the agent
|
|
146
146
|
// has no override key. Drives the `setEnv` / `clearEnv` fix intents.
|
|
147
|
-
export function agentBinEnvKey(agentId) {
|
|
147
|
+
export function agentBinEnvKey({ agentId }) {
|
|
148
148
|
if (!agentId)
|
|
149
149
|
return null;
|
|
150
150
|
return AGENT_BIN_ENV_KEYS.get(agentId) ?? null;
|
|
151
151
|
}
|
|
152
|
-
export function resolveOnPath(bin) {
|
|
152
|
+
export function resolveOnPath({ bin }) {
|
|
153
153
|
const exts = process.platform === 'win32'
|
|
154
154
|
? (process.env.PATHEXT || '.EXE;.CMD;.BAT').split(';')
|
|
155
155
|
: [''];
|
|
@@ -176,7 +176,7 @@ function looksExecutableOnWindows(filePath) {
|
|
|
176
176
|
function executableFilePath(raw) {
|
|
177
177
|
if (typeof raw !== 'string' || raw.trim().length === 0)
|
|
178
178
|
return null;
|
|
179
|
-
const expanded = expandHomePath(raw.trim());
|
|
179
|
+
const expanded = expandHomePath({ value: raw.trim() });
|
|
180
180
|
if (!path.isAbsolute(expanded))
|
|
181
181
|
return null;
|
|
182
182
|
try {
|
|
@@ -205,7 +205,7 @@ function configuredExecutableOverride(def, configuredEnv = {}) {
|
|
|
205
205
|
return null;
|
|
206
206
|
return executableFilePath(configuredEnv?.[envKey]);
|
|
207
207
|
}
|
|
208
|
-
export function resolveAmrOpenCodeExecutable(env = process.env) {
|
|
208
|
+
export function resolveAmrOpenCodeExecutable({}, { env = process.env } = {}) {
|
|
209
209
|
const configured = executableFilePath(env.VELA_OPENCODE_BIN);
|
|
210
210
|
if (configured)
|
|
211
211
|
return configured;
|
|
@@ -222,7 +222,7 @@ export function resolveAmrOpenCodeExecutable(env = process.env) {
|
|
|
222
222
|
return bundled;
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
|
-
return resolveOnPath('opencode-cli') ?? resolveOnPath('opencode');
|
|
225
|
+
return resolveOnPath({ bin: 'opencode-cli' }) ?? resolveOnPath({ bin: 'opencode' });
|
|
226
226
|
}
|
|
227
227
|
// The AMR (vela) OpenCode companion ships as a
|
|
228
228
|
// `<resourceRoot>/bin/libexec/opencode/opencode` *executable file*, not just
|
|
@@ -257,7 +257,7 @@ function packagedBuiltInExecutable(def, configuredEnv = {}) {
|
|
|
257
257
|
const resourceRoot = process.env[executableResolutionEnv.resourceRootEnvVar]?.trim();
|
|
258
258
|
if (!resourceRoot)
|
|
259
259
|
return null;
|
|
260
|
-
if (!resolveAmrOpenCodeExecutable({ ...process.env, ...configuredEnv }) &&
|
|
260
|
+
if (!resolveAmrOpenCodeExecutable({}, { env: { ...process.env, ...configuredEnv } }) &&
|
|
261
261
|
!packagedVelaOpenCodeCompanionTree(resourceRoot)) {
|
|
262
262
|
return null;
|
|
263
263
|
}
|
|
@@ -320,10 +320,10 @@ export function codexAppBundleCandidates() {
|
|
|
320
320
|
}
|
|
321
321
|
return candidates;
|
|
322
322
|
}
|
|
323
|
-
export function resolveAgentExecutable(def, configuredEnv = {}) {
|
|
324
|
-
return inspectAgentExecutableResolution(def, configuredEnv).selectedPath;
|
|
323
|
+
export function resolveAgentExecutable({ def }, { configuredEnv = {} } = {}) {
|
|
324
|
+
return inspectAgentExecutableResolution({ def: def }, { configuredEnv: configuredEnv }).selectedPath;
|
|
325
325
|
}
|
|
326
|
-
export function inspectAgentExecutableResolution(def, configuredEnv = {}) {
|
|
326
|
+
export function inspectAgentExecutableResolution({ def }, { configuredEnv = {} } = {}) {
|
|
327
327
|
if (!def?.bin) {
|
|
328
328
|
return {
|
|
329
329
|
configuredOverridePath: null,
|
|
@@ -338,7 +338,7 @@ export function inspectAgentExecutableResolution(def, configuredEnv = {}) {
|
|
|
338
338
|
];
|
|
339
339
|
let pathResolvedPath = null;
|
|
340
340
|
for (const bin of candidates) {
|
|
341
|
-
const resolved = resolveOnPath(bin);
|
|
341
|
+
const resolved = resolveOnPath({ bin: bin });
|
|
342
342
|
if (resolved) {
|
|
343
343
|
pathResolvedPath = resolved;
|
|
344
344
|
break;
|