@jini-ai/agent-runtime 0.4.4 → 0.4.6
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 +5 -0
- package/dist/agent-protocol/acp/models.d.ts +11 -0
- package/dist/agent-protocol/acp/models.js +12 -3
- package/dist/capabilities.d.ts +1 -8
- package/dist/capabilities.js +8 -1
- package/dist/claude-code-models.d.ts +13 -1
- package/dist/claude-code-models.js +15 -17
- package/dist/claude-segment-usage.d.ts +9 -2
- package/dist/claude-segment-usage.js +20 -4
- package/dist/claude-stream.d.ts +4 -0
- package/dist/claude-stream.js +5 -1
- package/dist/defs/aider.js +1 -1
- package/dist/defs/amp.js +1 -1
- package/dist/defs/amr.js +1 -1
- package/dist/defs/antigravity.js +1 -1
- package/dist/defs/auggie.js +1 -1
- package/dist/defs/claude.d.ts +2 -0
- package/dist/defs/claude.js +11 -3
- package/dist/defs/cline.js +1 -1
- package/dist/defs/codebuddy.js +2 -2
- package/dist/defs/codex.js +1 -1
- package/dist/defs/copilot.js +1 -1
- package/dist/defs/crush.js +1 -1
- package/dist/defs/cursor-agent.js +2 -2
- package/dist/defs/deepseek.js +1 -1
- package/dist/defs/devin.js +1 -1
- package/dist/defs/droid.js +1 -1
- package/dist/defs/goose.js +1 -1
- package/dist/defs/grok-build.js +1 -1
- package/dist/defs/hermes.js +1 -1
- package/dist/defs/kilo.js +1 -1
- package/dist/defs/kimi.js +1 -1
- package/dist/defs/kiro.js +1 -1
- package/dist/defs/mimo.js +1 -1
- package/dist/defs/opencode.js +2 -2
- package/dist/defs/pi.js +1 -1
- package/dist/defs/qoder.js +1 -1
- package/dist/defs/qwen.js +1 -1
- package/dist/defs/reasonix.js +1 -1
- package/dist/defs/trae-cli.js +1 -1
- package/dist/defs/vibe.js +1 -1
- package/dist/detection.d.ts +28 -4
- package/dist/detection.js +82 -43
- package/dist/diagnostics.d.ts +6 -1
- package/dist/diagnostics.js +2 -2
- package/dist/env.js +1 -1
- package/dist/executables.d.ts +15 -9
- package/dist/executables.js +73 -65
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/invocation.d.ts +24 -2
- package/dist/invocation.js +19 -7
- package/dist/launch.d.ts +2 -1
- package/dist/launch.js +2 -2
- package/dist/model-discovery-adapters.d.ts +6 -2
- package/dist/model-discovery-adapters.js +64 -51
- package/dist/model-discovery-native.d.ts +14 -0
- package/dist/model-discovery-native.js +22 -0
- package/dist/model-discovery-sdk.js +1 -1
- package/dist/model-discovery-shared.d.ts +14 -0
- package/dist/model-discovery-shared.js +53 -0
- package/dist/model-discovery-types.d.ts +26 -0
- package/dist/model-discovery.d.ts +17 -22
- package/dist/model-discovery.js +18 -69
- package/dist/models.d.ts +9 -4
- package/dist/models.js +11 -11
- package/dist/probe-scheduler.d.ts +19 -0
- package/dist/probe-scheduler.js +30 -0
- package/dist/runtime-state.d.ts +41 -0
- package/dist/runtime-state.js +31 -0
- package/dist/types.d.ts +4 -0
- package/package.json +36 -9
package/dist/detection.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { type AgentRuntimeState } from './runtime-state.js';
|
|
1
2
|
import type { ModelDiscoveryContext, ModelDiscoveryDeps, ModelCatalogSnapshot, DefaultModelResolution } from './model-discovery-types.js';
|
|
2
3
|
import { type AmrProfileResolver } from './amr-profile-resolver.js';
|
|
3
|
-
import type { AgentDiagnostic, DetectedAgent, RuntimeAgentDef, RuntimeModelSource, RuntimeModelOption } from './types.js';
|
|
4
|
+
import type { AgentDiagnostic, DetectedAgent, RuntimeAgentDef, RuntimeCapabilityMap, RuntimeModelSource, RuntimeModelOption } from './types.js';
|
|
4
5
|
type FetchedRuntimeModels = {
|
|
5
6
|
models: RuntimeModelOption[];
|
|
6
7
|
source: RuntimeModelSource;
|
|
@@ -30,6 +31,14 @@ export declare function ensureAgentCapabilities({ def, launchPath, env }: {
|
|
|
30
31
|
def: RuntimeAgentDef;
|
|
31
32
|
launchPath: string;
|
|
32
33
|
env: NodeJS.ProcessEnv;
|
|
34
|
+
}, { state, probe }?: {
|
|
35
|
+
state?: AgentRuntimeState;
|
|
36
|
+
probe?: (required: {
|
|
37
|
+
helpArgs: readonly string[];
|
|
38
|
+
capabilityFlags: Readonly<Record<string, string>>;
|
|
39
|
+
launchPath: string;
|
|
40
|
+
env: NodeJS.ProcessEnv;
|
|
41
|
+
}, optional: Record<string, never>) => Promise<RuntimeCapabilityMap>;
|
|
33
42
|
}): Promise<void>;
|
|
34
43
|
/** Result of {@link probeAgentModels}: the models to surface and where they came from. */
|
|
35
44
|
export type ProbedAgentModels = FetchedRuntimeModels;
|
|
@@ -47,7 +56,9 @@ export type ProbedAgentModels = FetchedRuntimeModels;
|
|
|
47
56
|
*/
|
|
48
57
|
export declare function probeAgentModels({ def }: {
|
|
49
58
|
def: RuntimeAgentDef;
|
|
50
|
-
}, { configuredEnv, amrProfileResolver, context, deps, force }?: {
|
|
59
|
+
}, { configuredEnv, amrProfileResolver, context, deps, force, state, env }?: {
|
|
60
|
+
state?: AgentRuntimeState;
|
|
61
|
+
env?: NodeJS.ProcessEnv;
|
|
51
62
|
configuredEnv?: Record<string, string>;
|
|
52
63
|
amrProfileResolver?: AmrProfileResolver;
|
|
53
64
|
context?: ModelDiscoveryContext;
|
|
@@ -58,13 +69,23 @@ export interface AgentDetectionModelOptions {
|
|
|
58
69
|
context?: ModelDiscoveryContext;
|
|
59
70
|
deps?: ModelDiscoveryDeps;
|
|
60
71
|
force?: boolean;
|
|
72
|
+
state?: AgentRuntimeState;
|
|
73
|
+
env?: NodeJS.ProcessEnv;
|
|
74
|
+
probeAgent?: (input: {
|
|
75
|
+
def: RuntimeAgentDef;
|
|
76
|
+
configuredEnv: Record<string, string>;
|
|
77
|
+
amrProfileResolver: AmrProfileResolver;
|
|
78
|
+
}, options: AgentDetectionModelOptions) => Promise<DetectedAgent>;
|
|
61
79
|
}
|
|
62
|
-
export declare function detectAgents({}: {}, { configuredEnvByAgent, amrProfileResolver, modelContextByAgent, modelDiscoveryDeps, force }?: {
|
|
80
|
+
export declare function detectAgents({}: {}, { configuredEnvByAgent, amrProfileResolver, modelContextByAgent, modelDiscoveryDeps, force, state, env, probeAgent }?: {
|
|
81
|
+
state?: AgentRuntimeState;
|
|
82
|
+
env?: NodeJS.ProcessEnv;
|
|
63
83
|
configuredEnvByAgent?: Record<string, Record<string, string>>;
|
|
64
84
|
amrProfileResolver?: AmrProfileResolver;
|
|
65
85
|
modelContextByAgent?: Record<string, ModelDiscoveryContext>;
|
|
66
86
|
modelDiscoveryDeps?: ModelDiscoveryDeps;
|
|
67
87
|
force?: boolean;
|
|
88
|
+
probeAgent?: AgentDetectionModelOptions['probeAgent'];
|
|
68
89
|
}): Promise<(Omit<RuntimeAgentDef, "discoverModels" | "resolveDefaultModel" | "buildArgs" | "listModels" | "fetchModels" | "deriveReasoningOptions" | "fallbackModels" | "fallbackModelsAssertedAt" | "helpArgs" | "capabilityFlags" | "fallbackBins" | "versionProbeTimeoutMs" | "maxPromptArgBytes" | "env" | "inactivityTimeoutMs" | "authProbe" | "needsAgentLogFile" | "stdoutPolicy" | "runtimeLock"> & {
|
|
69
90
|
models: RuntimeModelOption[];
|
|
70
91
|
modelsSource: RuntimeModelSource;
|
|
@@ -77,12 +98,15 @@ export declare function detectAgents({}: {}, { configuredEnvByAgent, amrProfileR
|
|
|
77
98
|
version?: string | null;
|
|
78
99
|
diagnostics?: AgentDiagnostic[];
|
|
79
100
|
})[]>;
|
|
80
|
-
export declare function detectAgentsStream({}: {}, { configuredEnvByAgent, amrProfileResolver, modelContextByAgent, modelDiscoveryDeps, force }?: {
|
|
101
|
+
export declare function detectAgentsStream({}: {}, { configuredEnvByAgent, amrProfileResolver, modelContextByAgent, modelDiscoveryDeps, force, state, env, probeAgent }?: {
|
|
102
|
+
state?: AgentRuntimeState;
|
|
103
|
+
env?: NodeJS.ProcessEnv;
|
|
81
104
|
configuredEnvByAgent?: Record<string, Record<string, string>>;
|
|
82
105
|
amrProfileResolver?: AmrProfileResolver;
|
|
83
106
|
modelContextByAgent?: Record<string, ModelDiscoveryContext>;
|
|
84
107
|
modelDiscoveryDeps?: ModelDiscoveryDeps;
|
|
85
108
|
force?: boolean;
|
|
109
|
+
probeAgent?: AgentDetectionModelOptions['probeAgent'];
|
|
86
110
|
}): AsyncGenerator<DetectedAgent>;
|
|
87
111
|
export {};
|
|
88
112
|
//# sourceMappingURL=detection.d.ts.map
|
package/dist/detection.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { userToolchainBinDirs } from './executables.js';
|
|
3
|
+
import { defaultRuntimeState } from './runtime-state.js';
|
|
4
|
+
import { getRuntimeModelDiscoveryDeps } from './model-discovery-adapters.js';
|
|
1
5
|
/**
|
|
2
6
|
* @module detection
|
|
3
7
|
*
|
|
@@ -12,9 +16,8 @@
|
|
|
12
16
|
* `archived provenance ledger`.
|
|
13
17
|
*/
|
|
14
18
|
import { execAgentFile } from './invocation.js';
|
|
15
|
-
import { offlineSnapshot, modelDiscoveryForDef } from './model-discovery.js';
|
|
19
|
+
import { offlineSnapshot, modelDiscoveryForDef } from './model-discovery-native.js';
|
|
16
20
|
import { rememberLiveModels } from './models.js';
|
|
17
|
-
import { agentCapabilities } from './capabilities.js';
|
|
18
21
|
import { installMetaForAgent } from './metadata.js';
|
|
19
22
|
import { AGENT_DEFS } from './registry.js';
|
|
20
23
|
import { applyAgentLaunchEnv, resolveAgentLaunch } from './launch.js';
|
|
@@ -109,8 +112,8 @@ function unavailableAgent(def, diagnostics = []) {
|
|
|
109
112
|
}
|
|
110
113
|
// Probe the agent's `--help` once and record which advertised flags the
|
|
111
114
|
// installed CLI supports, so buildArgs can consult the cache. Extracted
|
|
112
|
-
// from the main probe so it can run
|
|
113
|
-
//
|
|
115
|
+
// from the main probe so it can run before model discovery. It shares the existing
|
|
116
|
+
// capability cache with real launches. Returns the capability map (or null when the
|
|
114
117
|
// agent declares no help/capability metadata or the probe failed).
|
|
115
118
|
async function probeCapabilities(def, launchPath, env) {
|
|
116
119
|
if (!def.helpArgs || !def.capabilityFlags)
|
|
@@ -133,8 +136,6 @@ async function readCapabilities(helpArgs, capabilityFlags, launchPath, env) {
|
|
|
133
136
|
}
|
|
134
137
|
return caps;
|
|
135
138
|
}
|
|
136
|
-
/** One in-flight or settled `--help` probe per def id + launch path, so a run never re-spawns it. */
|
|
137
|
-
const capabilityProbes = new Map();
|
|
138
139
|
/**
|
|
139
140
|
* Makes sure `agentCapabilities` holds this def's `--help`-probed flags before its `buildArgs` runs.
|
|
140
141
|
*
|
|
@@ -154,7 +155,9 @@ const capabilityProbes = new Map();
|
|
|
154
155
|
* @param env - The env the run will spawn with.
|
|
155
156
|
* @complexity O(1) after the first call per def + path; the first call costs one `--help` spawn (5 s cap).
|
|
156
157
|
*/
|
|
157
|
-
export function ensureAgentCapabilities({ def, launchPath, env }) {
|
|
158
|
+
export function ensureAgentCapabilities({ def, launchPath, env }, { state = defaultRuntimeState, probe = ({ helpArgs, capabilityFlags, launchPath, env }) => readCapabilities(helpArgs, capabilityFlags, launchPath, env) } = {}) {
|
|
159
|
+
const agentCapabilities = state.capabilities;
|
|
160
|
+
const capabilityProbes = state.capabilityProbes;
|
|
158
161
|
const { helpArgs, capabilityFlags } = def;
|
|
159
162
|
if (!helpArgs || !capabilityFlags || agentCapabilities.has(def.id))
|
|
160
163
|
return Promise.resolve();
|
|
@@ -162,12 +165,12 @@ export function ensureAgentCapabilities({ def, launchPath, env }) {
|
|
|
162
165
|
const existing = capabilityProbes.get(key);
|
|
163
166
|
if (existing)
|
|
164
167
|
return existing;
|
|
165
|
-
const
|
|
168
|
+
const pending = probe({ helpArgs, capabilityFlags, launchPath, env }, {}).then((caps) => {
|
|
166
169
|
if (!agentCapabilities.has(def.id))
|
|
167
170
|
agentCapabilities.set(def.id, caps);
|
|
168
171
|
}, () => undefined);
|
|
169
|
-
capabilityProbes.set(key,
|
|
170
|
-
return
|
|
172
|
+
capabilityProbes.set(key, pending);
|
|
173
|
+
return pending;
|
|
171
174
|
}
|
|
172
175
|
/**
|
|
173
176
|
* The effort-level override a live model catalog earns, if any.
|
|
@@ -186,8 +189,8 @@ function derivedReasoningOverride(def, models) {
|
|
|
186
189
|
return derived && derived.length > 0 ? { reasoningOptions: derived } : {};
|
|
187
190
|
}
|
|
188
191
|
/** The env every probe of one def spawns with — the same env a real run would see. */
|
|
189
|
-
function probeEnvForLaunch(def, configuredEnv, launch) {
|
|
190
|
-
return applyAgentLaunchEnv({ env: spawnEnvForAgent({ agentId: def.id, baseEnv: { ...process.env, ...(def.env || {}) } }, { configuredEnv: configuredEnv, hooks: {} }), launch: launch });
|
|
192
|
+
function probeEnvForLaunch(def, configuredEnv, launch, options = {}) {
|
|
193
|
+
return applyAgentLaunchEnv({ env: spawnEnvForAgent({ agentId: def.id, baseEnv: { ...(options.env ?? process.env), ...(def.env || {}) } }, { configuredEnv: configuredEnv, hooks: {} }), launch: launch }, { appendPathDirs: userToolchainBinDirs({}, options) });
|
|
191
194
|
}
|
|
192
195
|
function unavailableModels(def) {
|
|
193
196
|
const catalog = offlineSnapshot('', Date.now(), def.fallbackModels);
|
|
@@ -205,15 +208,15 @@ function unavailableModels(def) {
|
|
|
205
208
|
* `source: 'fallback'` (including when the binary is not found). Never rejects.
|
|
206
209
|
* @complexity At most one model-listing spawn, bounded by the def's own timeout.
|
|
207
210
|
*/
|
|
208
|
-
export async function probeAgentModels({ def }, { configuredEnv = {}, amrProfileResolver = noopAmrProfileResolver, context, deps, force = false } = {}) {
|
|
211
|
+
export async function probeAgentModels({ def }, { configuredEnv = {}, amrProfileResolver = noopAmrProfileResolver, context, deps, force = false, state = defaultRuntimeState, env = process.env } = {}) {
|
|
209
212
|
try {
|
|
210
|
-
const launch = resolveAgentLaunch({ def: def }, { configuredEnv: configuredEnv });
|
|
213
|
+
const launch = resolveAgentLaunch({ def: def }, { configuredEnv: configuredEnv, state, env });
|
|
211
214
|
if (!launch.launchPath)
|
|
212
215
|
return unavailableModels(def);
|
|
213
|
-
const probeEnv = probeEnvForLaunch(def, configuredEnv, launch);
|
|
214
|
-
const fetched = await fetchModels(def, launch.launchPath, probeEnv, { ...(context ? { context } : {}),
|
|
216
|
+
const probeEnv = probeEnvForLaunch(def, configuredEnv, launch, { state, env });
|
|
217
|
+
const fetched = await fetchModels(def, launch.launchPath, probeEnv, { ...(context ? { context } : {}), deps: deps ?? getRuntimeModelDiscoveryDeps({ state }), force });
|
|
215
218
|
const result = withRememberedAmrModels(def, probeEnv, fetched, amrProfileResolver);
|
|
216
|
-
rememberDetectedModelList(def, configuredEnv, result.models, amrProfileResolver);
|
|
219
|
+
rememberDetectedModelList(def, configuredEnv, result.models, amrProfileResolver, { state, env });
|
|
217
220
|
return result;
|
|
218
221
|
}
|
|
219
222
|
catch {
|
|
@@ -229,28 +232,34 @@ async function probe(def, configuredEnv = {}, amrProfileResolver, options = {})
|
|
|
229
232
|
// detection probes the shim but chat/run spawns the native binary, the
|
|
230
233
|
// UI incorrectly reports "not installed" until the user pins the bin
|
|
231
234
|
// override by hand even though the real launch path is healthy.
|
|
232
|
-
const launch = resolveAgentLaunch({ def: def }, { configuredEnv: configuredEnv });
|
|
235
|
+
const launch = resolveAgentLaunch({ def: def }, { configuredEnv: configuredEnv, ...(options.state ? { state: options.state } : {}), ...(options.env ? { env: options.env } : {}) });
|
|
233
236
|
if (!launch.selectedPath || !launch.launchPath) {
|
|
234
|
-
return unavailableAgent(def, [buildExecutableDiagnostic({ def: def }, { configuredEnv: configuredEnv })]);
|
|
237
|
+
return unavailableAgent(def, [buildExecutableDiagnostic({ def: def }, { configuredEnv: configuredEnv, ...(options.state ? { state: options.state } : {}), ...(options.env ? { env: options.env } : {}) })]);
|
|
235
238
|
}
|
|
236
|
-
const probeEnv = probeEnvForLaunch(def, configuredEnv, launch);
|
|
239
|
+
const probeEnv = probeEnvForLaunch(def, configuredEnv, launch, options);
|
|
237
240
|
const outcome = await probeVersionAtPath(def, launch.launchPath, probeEnv);
|
|
238
241
|
if (outcome.kind === 'not-invocable') {
|
|
239
242
|
return unavailableAgent(def, [buildNotInvocableDiagnostic({ def: def, launch: launch, cause: outcome.cause })]);
|
|
240
243
|
}
|
|
241
|
-
// The version probe must finish first (it gates availability)
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
244
|
+
// The version probe must finish first (it gates availability). Cheap help/auth checks
|
|
245
|
+
// precede model discovery; the shared process scheduler prevents concurrent CLI startups.
|
|
246
|
+
// Capability evidence belongs to the existing ensureAgentCapabilities cache, also used by runs.
|
|
247
|
+
const runtimeState = options.state ?? defaultRuntimeState;
|
|
248
|
+
const capabilityKey = `${def.id}\u0000${launch.launchPath}`;
|
|
249
|
+
if (options.force || !runtimeState.capabilityProbes.has(capabilityKey)) {
|
|
250
|
+
runtimeState.capabilities.delete(def.id);
|
|
251
|
+
if (options.force)
|
|
252
|
+
runtimeState.capabilityProbes.delete(capabilityKey);
|
|
253
|
+
}
|
|
254
|
+
await ensureAgentCapabilities({ def, launchPath: launch.launchPath, env: probeEnv }, { state: runtimeState,
|
|
255
|
+
probe: async () => (await probeCapabilities(def, launch.launchPath, probeEnv)) ?? {},
|
|
256
|
+
});
|
|
257
|
+
const caps = runtimeState.capabilities.get(def.id);
|
|
258
|
+
const auth = await probeAgentAuthStatus({ def, resolvedBin: launch.launchPath, env: probeEnv });
|
|
259
|
+
const modelResult = await fetchModels(def, launch.launchPath, probeEnv, { version: outcome.version, ...options, deps: options.deps ?? getRuntimeModelDiscoveryDeps({ state: runtimeState }) });
|
|
251
260
|
const surfacedModelResult = withRememberedAmrModels(def, probeEnv, modelResult, amrProfileResolver);
|
|
252
261
|
if (caps) {
|
|
253
|
-
|
|
262
|
+
(options.state ?? defaultRuntimeState).capabilities.set(def.id, caps);
|
|
254
263
|
}
|
|
255
264
|
const authDiagnostic = auth ? buildAuthDiagnostic({ def: def, auth: auth }) : null;
|
|
256
265
|
return {
|
|
@@ -290,8 +299,38 @@ function stripFns(def) {
|
|
|
290
299
|
const { discoverModels: _discoverModels, resolveDefaultModel: _resolveDefaultModel, buildArgs: _buildArgs, listModels: _listModels, fetchModels: _fetchModels, deriveReasoningOptions: _deriveReasoningOptions, fallbackModels: _fallbackModels, fallbackModelsAssertedAt: _fallbackModelsAssertedAt, helpArgs: _helpArgs, capabilityFlags: _capabilityFlags, fallbackBins: _fallbackBins, versionProbeTimeoutMs: _versionProbeTimeoutMs, maxPromptArgBytes: _maxPromptArgBytes, env: _env, inactivityTimeoutMs: _inactivityTimeoutMs, authProbe: _authProbe, needsAgentLogFile: _needsAgentLogFile, stdoutPolicy: _stdoutPolicy, runtimeLock: _runtimeLock, ...rest } = def;
|
|
291
300
|
return rest;
|
|
292
301
|
}
|
|
293
|
-
|
|
302
|
+
/** Cache complete detection per host and effective launch. No TTL re-spawns version/help/auth.
|
|
303
|
+
* Explicit force queues after the current scan, so a rescan cannot overlap its predecessor.
|
|
304
|
+
* Hash credentials rather than retaining them in keys. @complexity O(e) launch-env hashing. */
|
|
305
|
+
function safeProbe(def, configuredEnv, amrProfileResolver, options = {}) {
|
|
306
|
+
const state = options.state ?? defaultRuntimeState;
|
|
307
|
+
let key;
|
|
308
|
+
try {
|
|
309
|
+
key = detectionCacheKey({ def, configuredEnv, options, state });
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return Promise.resolve(unavailableAgent(def));
|
|
313
|
+
}
|
|
314
|
+
const previous = state.detections.get(key);
|
|
315
|
+
if (previous && !options.force)
|
|
316
|
+
return previous;
|
|
317
|
+
const pending = (previous ?? Promise.resolve()).then(() => executeSafeProbe(def, configuredEnv, amrProfileResolver, options));
|
|
318
|
+
state.detections.set(key, pending);
|
|
319
|
+
return pending;
|
|
320
|
+
}
|
|
321
|
+
/** Effective launch material is hashed, so cache keys never expose credentials.
|
|
322
|
+
* Legacy remembered-model profile resolution must not gate executable availability. */
|
|
323
|
+
function detectionCacheKey({ def, configuredEnv, options, state }, _options = {}) {
|
|
324
|
+
const launch = resolveAgentLaunch({ def }, { configuredEnv, state, ...(options.env ? { env: options.env } : {}) });
|
|
325
|
+
const env = options.env ?? process.env;
|
|
326
|
+
return createHash('sha256').update(JSON.stringify({ id: def.id, path: launch.launchPath,
|
|
327
|
+
env: Object.entries(env).sort(([a], [b]) => a.localeCompare(b)), configuredEnv,
|
|
328
|
+
context: options.context })).digest('hex');
|
|
329
|
+
}
|
|
330
|
+
async function executeSafeProbe(def, configuredEnv = {}, amrProfileResolver, options = {}) {
|
|
294
331
|
try {
|
|
332
|
+
if (options.probeAgent)
|
|
333
|
+
return await options.probeAgent({ def, configuredEnv, amrProfileResolver }, options);
|
|
295
334
|
return await probe(def, configuredEnv, amrProfileResolver, options);
|
|
296
335
|
}
|
|
297
336
|
catch {
|
|
@@ -302,19 +341,19 @@ async function safeProbe(def, configuredEnv = {}, amrProfileResolver, options =
|
|
|
302
341
|
return unavailableAgent(def);
|
|
303
342
|
}
|
|
304
343
|
}
|
|
305
|
-
function rememberDetectedLiveModels(def, configuredEnv, agent, amrProfileResolver) {
|
|
306
|
-
rememberDetectedModelList(def, configuredEnv, agent.models, amrProfileResolver);
|
|
344
|
+
function rememberDetectedLiveModels(def, configuredEnv, agent, amrProfileResolver, options = {}) {
|
|
345
|
+
rememberDetectedModelList(def, configuredEnv, agent.models, amrProfileResolver, options);
|
|
307
346
|
}
|
|
308
|
-
function rememberDetectedModelList(def, configuredEnv, models, amrProfileResolver) {
|
|
347
|
+
function rememberDetectedModelList(def, configuredEnv, models, amrProfileResolver, options = {}) {
|
|
309
348
|
if (def.id === 'amr' && models.length === 0)
|
|
310
349
|
return;
|
|
311
350
|
const scope = def.id === 'amr'
|
|
312
|
-
? amrModelScopeFromEnv({ ...process.env, ...(def.env || {}), ...configuredEnv }, amrProfileResolver)
|
|
351
|
+
? amrModelScopeFromEnv({ ...(options.env ?? process.env), ...(def.env || {}), ...configuredEnv }, amrProfileResolver)
|
|
313
352
|
: null;
|
|
314
|
-
rememberLiveModels({ agentId: def.id, models: models.filter((row) => row.identityKind !== 'routing-mode') }, { scope: scope });
|
|
353
|
+
rememberLiveModels({ agentId: def.id, models: models.filter((row) => row.identityKind !== 'routing-mode') }, { scope: scope, ...(options.state ? { state: options.state } : {}) });
|
|
315
354
|
}
|
|
316
|
-
export async function detectAgents({}, { configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver, modelContextByAgent = {}, modelDiscoveryDeps, force = false } = {}) {
|
|
317
|
-
const results = await Promise.all(AGENT_DEFS.map((def) => safeProbe(def, configuredEnvByAgent?.[def.id] ?? {}, amrProfileResolver, { ...(modelContextByAgent[def.id] ? { context: modelContextByAgent[def.id] } : {}), ...(
|
|
355
|
+
export async function detectAgents({}, { configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver, modelContextByAgent = {}, modelDiscoveryDeps, force = false, state = defaultRuntimeState, env = process.env, probeAgent } = {}) {
|
|
356
|
+
const results = await Promise.all(AGENT_DEFS.map((def) => safeProbe(def, configuredEnvByAgent?.[def.id] ?? {}, amrProfileResolver, { ...(modelContextByAgent[def.id] ? { context: modelContextByAgent[def.id] } : {}), deps: modelDiscoveryDeps ?? getRuntimeModelDiscoveryDeps({ state }), force, state, env, ...(probeAgent ? { probeAgent } : {}) })));
|
|
318
357
|
// Refresh the validation cache from whatever we just surfaced to the UI
|
|
319
358
|
// so a chat endpoint can accept any model the user could have just
|
|
320
359
|
// picked, including ones that only showed up after a CLI re-auth.
|
|
@@ -323,7 +362,7 @@ export async function detectAgents({}, { configuredEnvByAgent = {}, amrProfileRe
|
|
|
323
362
|
// is in-bounds for `AGENT_DEFS` too — the assertion just satisfies
|
|
324
363
|
// `noUncheckedIndexedAccess`.
|
|
325
364
|
const def = AGENT_DEFS[index];
|
|
326
|
-
rememberDetectedLiveModels(def, configuredEnvByAgent?.[def.id] ?? {}, agent, amrProfileResolver);
|
|
365
|
+
rememberDetectedLiveModels(def, configuredEnvByAgent?.[def.id] ?? {}, agent, amrProfileResolver, { state, env });
|
|
327
366
|
}
|
|
328
367
|
return results;
|
|
329
368
|
}
|
|
@@ -333,9 +372,9 @@ export async function detectAgents({}, { configuredEnvByAgent = {}, amrProfileRe
|
|
|
333
372
|
// validation cache is refreshed per-agent (same effect as the batch path,
|
|
334
373
|
// just incrementally). `detectAgents` keeps the array contract for callers
|
|
335
374
|
// that don't care about incremental delivery.
|
|
336
|
-
export async function* detectAgentsStream({}, { configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver, modelContextByAgent = {}, modelDiscoveryDeps, force = false } = {}) {
|
|
337
|
-
const tagged = AGENT_DEFS.map((def, index) => safeProbe(def, configuredEnvByAgent?.[def.id] ?? {}, amrProfileResolver, { ...(modelContextByAgent[def.id] ? { context: modelContextByAgent[def.id] } : {}), ...(
|
|
338
|
-
rememberDetectedLiveModels(def, configuredEnvByAgent?.[def.id] ?? {}, agent, amrProfileResolver);
|
|
375
|
+
export async function* detectAgentsStream({}, { configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver, modelContextByAgent = {}, modelDiscoveryDeps, force = false, state = defaultRuntimeState, env = process.env, probeAgent } = {}) {
|
|
376
|
+
const tagged = AGENT_DEFS.map((def, index) => safeProbe(def, configuredEnvByAgent?.[def.id] ?? {}, amrProfileResolver, { ...(modelContextByAgent[def.id] ? { context: modelContextByAgent[def.id] } : {}), deps: modelDiscoveryDeps ?? getRuntimeModelDiscoveryDeps({ state }), force, state, env, ...(probeAgent ? { probeAgent } : {}) }).then((agent) => {
|
|
377
|
+
rememberDetectedLiveModels(def, configuredEnvByAgent?.[def.id] ?? {}, agent, amrProfileResolver, { state, env });
|
|
339
378
|
return { index, agent };
|
|
340
379
|
}));
|
|
341
380
|
const pending = new Set(tagged.keys());
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module diagnostics
|
|
3
|
+
* Explain three detection failures: unresolved executable, uninvocable executable or missing authentication.
|
|
4
|
+
*/
|
|
5
|
+
import { type ExecutableResolutionOptions } from './executables.js';
|
|
1
6
|
import type { AgentLaunchResolution } from './launch.js';
|
|
2
7
|
import type { AgentAuthProbeResult } from './auth.js';
|
|
3
8
|
import type { AgentDiagnostic, RuntimeAgentDef } from './types.js';
|
|
4
9
|
export declare function buildExecutableDiagnostic({ def }: {
|
|
5
10
|
def: Pick<RuntimeAgentDef, 'id' | 'name' | 'bin'>;
|
|
6
|
-
}, { configuredEnv }?: {
|
|
11
|
+
}, { configuredEnv, ...options }?: ExecutableResolutionOptions & {
|
|
7
12
|
configuredEnv?: Record<string, string>;
|
|
8
13
|
}): AgentDiagnostic;
|
|
9
14
|
export type NotInvocableCause = 'not-executable' | 'missing-target';
|
package/dist/diagnostics.js
CHANGED
|
@@ -16,7 +16,7 @@ function setEnvIntent(agentId) {
|
|
|
16
16
|
// user-supplied `*_BIN` override points at a missing/invalid file. The two
|
|
17
17
|
// cases get different copy + fix affordances because the remedy differs
|
|
18
18
|
// (install / point us at the binary vs. fix or clear the override).
|
|
19
|
-
export function buildExecutableDiagnostic({ def }, { configuredEnv = {} } = {}) {
|
|
19
|
+
export function buildExecutableDiagnostic({ def }, { configuredEnv = {}, ...options } = {}) {
|
|
20
20
|
const envKey = agentBinEnvKey({ agentId: def.id });
|
|
21
21
|
const overrideRaw = envKey ? configuredEnv?.[envKey]?.trim() : '';
|
|
22
22
|
if (envKey && overrideRaw) {
|
|
@@ -32,7 +32,7 @@ export function buildExecutableDiagnostic({ def }, { configuredEnv = {} } = {})
|
|
|
32
32
|
reason: 'not-on-path',
|
|
33
33
|
severity: 'error',
|
|
34
34
|
message: `${def.name} (\`${def.bin}\`) was not found on your PATH.`,
|
|
35
|
-
searchedDirs: agentSearchDirs().slice(0, MAX_SEARCHED_DIRS),
|
|
35
|
+
searchedDirs: agentSearchDirs({}, options).slice(0, MAX_SEARCHED_DIRS),
|
|
36
36
|
fixActions: [{ kind: 'openInstall' }, ...setEnvIntent(def.id), { kind: 'rescan' }],
|
|
37
37
|
};
|
|
38
38
|
}
|
package/dist/env.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* sandboxOverlay. The engine must not import a product's config/sandbox subsystems or env names.
|
|
8
8
|
*/
|
|
9
9
|
import os from 'node:os';
|
|
10
|
-
import { mergeProxyAwareEnv, resolveSystemProxyEnv } from '@jini-ai/platform';
|
|
10
|
+
import { mergeProxyAwareEnv, resolveSystemProxyEnv } from '@jini-ai/platform/proxy-env';
|
|
11
11
|
import { expandConfiguredEnv } from './paths.js';
|
|
12
12
|
import { resolveAmrOpenCodeExecutable } from './executables.js';
|
|
13
13
|
function stripKeysCaseInsensitive(env, keysToStrip) {
|
package/dist/executables.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import { type AgentRuntimeState } from './runtime-state.js';
|
|
1
2
|
import type { RuntimeAgentDef } from './types.js';
|
|
3
|
+
/** Host environment and runtime state used by executable resolution. */
|
|
4
|
+
export interface ExecutableResolutionOptions {
|
|
5
|
+
env?: NodeJS.ProcessEnv;
|
|
6
|
+
state?: AgentRuntimeState;
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* Override the env var names `resolveDetectionHome` / the packaged-binary
|
|
4
10
|
* lookup read. The host application (e.g. the OD adapter) calls this once
|
|
@@ -10,27 +16,27 @@ export declare function configureExecutableResolutionEnv({ overrides }: {
|
|
|
10
16
|
agentHomeEnvVar?: string;
|
|
11
17
|
resourceRootEnvVar?: string;
|
|
12
18
|
};
|
|
19
|
+
}, { state }?: {
|
|
20
|
+
state?: AgentRuntimeState;
|
|
13
21
|
}): void;
|
|
14
|
-
export declare function userToolchainBinDirs(): string[];
|
|
15
|
-
export declare function agentSearchDirs(): string[];
|
|
22
|
+
export declare function userToolchainBinDirs(_required?: Record<string, never>, options?: ExecutableResolutionOptions): string[];
|
|
23
|
+
export declare function agentSearchDirs(_required?: Record<string, never>, options?: ExecutableResolutionOptions): string[];
|
|
16
24
|
export declare function agentBinEnvKey({ agentId }: {
|
|
17
25
|
agentId: string | undefined;
|
|
18
26
|
}): string | null;
|
|
19
27
|
export declare function resolveOnPath({ bin }: {
|
|
20
28
|
bin: string;
|
|
21
|
-
}): string | null;
|
|
22
|
-
export declare function resolveAmrOpenCodeExecutable({}: {}, { env }?:
|
|
23
|
-
|
|
24
|
-
}): string | null;
|
|
25
|
-
export declare function codexAppBundleCandidates(): string[];
|
|
29
|
+
}, options?: ExecutableResolutionOptions): string | null;
|
|
30
|
+
export declare function resolveAmrOpenCodeExecutable({}: {}, { env, state }?: ExecutableResolutionOptions): string | null;
|
|
31
|
+
export declare function codexAppBundleCandidates(_required?: Record<string, never>, options?: ExecutableResolutionOptions): string[];
|
|
26
32
|
export declare function resolveAgentExecutable({ def }: {
|
|
27
33
|
def: RuntimeAgentDef;
|
|
28
|
-
},
|
|
34
|
+
}, options?: ExecutableResolutionOptions & {
|
|
29
35
|
configuredEnv?: Record<string, string>;
|
|
30
36
|
}): string | null;
|
|
31
37
|
export declare function inspectAgentExecutableResolution({ def }: {
|
|
32
38
|
def: RuntimeAgentDef;
|
|
33
|
-
},
|
|
39
|
+
}, options?: ExecutableResolutionOptions & {
|
|
34
40
|
configuredEnv?: Record<string, string>;
|
|
35
41
|
}): {
|
|
36
42
|
configuredOverridePath: string | null;
|