@jini-ai/agent-runtime 0.4.5 → 0.4.7
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 +11 -0
- package/dist/acp-model-probe.d.ts +14 -3
- package/dist/acp-model-probe.js +11 -5
- package/dist/agent-protocol/pi-rpc/session.d.ts +2 -0
- package/dist/agent-protocol/pi-rpc/session.js +4 -5
- package/dist/claude-code-models.js +1 -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.d.ts +3 -1
- package/dist/defs/auggie.js +3 -2
- package/dist/defs/claude.js +1 -1
- package/dist/defs/cline.d.ts +3 -1
- package/dist/defs/cline.js +3 -2
- package/dist/defs/codebuddy.js +1 -1
- package/dist/defs/codex.js +4 -4
- package/dist/defs/copilot.js +1 -1
- package/dist/defs/crush.js +1 -1
- package/dist/defs/cursor-agent.js +1 -1
- package/dist/defs/deepseek.js +1 -1
- package/dist/defs/devin.d.ts +3 -1
- package/dist/defs/devin.js +3 -2
- package/dist/defs/droid.js +1 -1
- package/dist/defs/goose.d.ts +3 -1
- package/dist/defs/goose.js +3 -2
- package/dist/defs/grok-build.js +1 -1
- package/dist/defs/hermes.d.ts +3 -1
- package/dist/defs/hermes.js +3 -2
- package/dist/defs/kilo.d.ts +3 -1
- package/dist/defs/kilo.js +3 -2
- package/dist/defs/kimi.d.ts +3 -1
- package/dist/defs/kimi.js +3 -2
- package/dist/defs/kiro.d.ts +3 -1
- package/dist/defs/kiro.js +3 -2
- package/dist/defs/mimo.js +1 -1
- package/dist/defs/opencode.js +1 -1
- 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.d.ts +3 -1
- package/dist/defs/reasonix.js +3 -2
- package/dist/defs/trae-cli.d.ts +3 -1
- package/dist/defs/trae-cli.js +3 -2
- package/dist/defs/vibe.d.ts +3 -1
- package/dist/defs/vibe.js +3 -2
- package/dist/detection.js +1 -1
- package/dist/env.js +1 -1
- package/dist/executables.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/invocation.js +1 -1
- package/dist/model-discovery-adapters.d.ts +11 -2
- package/dist/model-discovery-adapters.js +26 -9
- 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 +16 -67
- package/dist/native-runtime.d.ts +35 -0
- package/dist/native-runtime.js +53 -0
- package/dist/runtime-state.d.ts +7 -2
- package/dist/runtime-state.js +10 -4
- package/dist/types.d.ts +5 -0
- package/package.json +29 -7
package/dist/executables.js
CHANGED
|
@@ -24,7 +24,7 @@ import { accessSync, constants, existsSync, statSync } from 'node:fs';
|
|
|
24
24
|
import { delimiter } from 'node:path';
|
|
25
25
|
import path from 'node:path';
|
|
26
26
|
import { homedir } from 'node:os';
|
|
27
|
-
import { wellKnownUserToolchainBins } from '@jini-ai/platform';
|
|
27
|
+
import { wellKnownUserToolchainBins } from '@jini-ai/platform/toolchain';
|
|
28
28
|
import { expandHomePath } from './paths.js';
|
|
29
29
|
const AGENT_BIN_ENV_KEYS = new Map([
|
|
30
30
|
['amr', 'VELA_BIN'],
|
package/dist/index.d.ts
CHANGED
|
@@ -47,7 +47,8 @@ export * from './telemetry-sink.js';
|
|
|
47
47
|
export * from './providers/index.js';
|
|
48
48
|
/** ACP + pi-rpc protocol adapters over the shared JSON-line-stream core. See aliases above. */
|
|
49
49
|
export { createJsonLineStream, type AcpMcpServerInput, type AcpPermissionDecision, type AcpPermissionHandler, type AcpPermissionOption, type AcpPermissionRequest, type AcpSessionController, type ModelOption, type AttachAcpSessionOptions, type AccountFailure, type AccountFailureClassifier, buildAcpSessionNewParams, normalizeModels, detectAcpModels, attachAcpSession, noopAccountFailureClassifier, mapPiRpcEvent, attachPiRpcSession, parsePiModels as parsePiRpcModels, type PiRpcSession, type PiRpcSessionOptions, } from './agent-protocol/index.js';
|
|
50
|
-
export * from './model-discovery.js';
|
|
50
|
+
export * from './model-discovery-native.js';
|
|
51
51
|
export { getRuntimeModelDiscoveryDeps, defaultModelDiscoveryDeps, parseClaudeInitializeMetadata, parsePiRpcMetadata } from './model-discovery-adapters.js';
|
|
52
52
|
export * from './runtime-state.js';
|
|
53
|
+
export * from './native-runtime.js';
|
|
53
54
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -70,7 +70,8 @@ export * from './telemetry-sink.js';
|
|
|
70
70
|
export * from './providers/index.js';
|
|
71
71
|
/** ACP + pi-rpc protocol adapters over the shared JSON-line-stream core. See aliases above. */
|
|
72
72
|
export { createJsonLineStream, buildAcpSessionNewParams, normalizeModels, detectAcpModels, attachAcpSession, noopAccountFailureClassifier, mapPiRpcEvent, attachPiRpcSession, parsePiModels as parsePiRpcModels, } from './agent-protocol/index.js';
|
|
73
|
-
export * from './model-discovery.js';
|
|
73
|
+
export * from './model-discovery-native.js';
|
|
74
74
|
export { getRuntimeModelDiscoveryDeps, defaultModelDiscoveryDeps, parseClaudeInitializeMetadata, parsePiRpcMetadata } from './model-discovery-adapters.js';
|
|
75
75
|
export * from './runtime-state.js';
|
|
76
|
+
export * from './native-runtime.js';
|
|
76
77
|
//# sourceMappingURL=index.js.map
|
package/dist/invocation.js
CHANGED
|
@@ -13,7 +13,7 @@ import { execFile } from 'node:child_process';
|
|
|
13
13
|
import { scheduleProbeProcess } from './probe-scheduler.js';
|
|
14
14
|
import os from 'node:os';
|
|
15
15
|
import { promisify } from 'node:util';
|
|
16
|
-
import { createCommandInvocation } from '@jini-ai/platform';
|
|
16
|
+
import { createCommandInvocation } from '@jini-ai/platform/command';
|
|
17
17
|
const execFileP = promisify(execFile);
|
|
18
18
|
// Agent probes (model-list / version / help / auth-status) are short
|
|
19
19
|
// read-only metadata calls that never need the caller's project files.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AgentRuntimeState } from './runtime-state.js';
|
|
2
|
-
import { type
|
|
3
|
-
import type { ModelDiscoveryContext, ModelDiscoveryDeps, ModelProbeResult } from './model-discovery-types.js';
|
|
2
|
+
import { type AcpModelProbe } from './acp-model-probe.js';
|
|
3
|
+
import type { AgentDiscoveryConfiguration, ModelDiscoveryContext, ModelDiscoveryDeps, ModelProbeResult } from './model-discovery-types.js';
|
|
4
4
|
export declare function modelProbeTimeoutMs(agentId: string): number;
|
|
5
5
|
/** Shared CLI-subcommand adapter. Output parsers are pure def-owned functions, not vendor tools. */
|
|
6
6
|
export declare function probeCliSubcommand(context: ModelDiscoveryContext, config: AgentDiscoveryConfiguration, deps: ModelDiscoveryDeps, signal: AbortSignal): Promise<ModelProbeResult>;
|
|
@@ -24,4 +24,13 @@ export declare function parsePiRpcMetadata(stdout: string): ModelProbeResult;
|
|
|
24
24
|
export declare function getRuntimeModelDiscoveryDeps({ state }: {
|
|
25
25
|
state: AgentRuntimeState;
|
|
26
26
|
}, _optional?: Record<string, never>): ModelDiscoveryDeps;
|
|
27
|
+
/** Adapt the existing ACP port to catalog metadata; array-only transports cannot claim a default.
|
|
28
|
+
* Keeps invocation normalization, cancellation and the shared process budget in the native adapter.
|
|
29
|
+
* @param required - The host's existing ACP probe, optionally capable of reporting current selection.
|
|
30
|
+
* @returns A catalog adapter using that probe without changing security or concurrency guarantees.
|
|
31
|
+
* @example const acp = createAcpDiscoveryAdapter({ probe: hostProbe });
|
|
32
|
+
*/
|
|
33
|
+
export declare function createAcpDiscoveryAdapter({ probe }: {
|
|
34
|
+
probe: AcpModelProbe;
|
|
35
|
+
}, _optional?: Record<string, never>): ModelDiscoveryDeps['acp'];
|
|
27
36
|
//# sourceMappingURL=model-discovery-adapters.d.ts.map
|
|
@@ -4,15 +4,15 @@ import { execFile } from 'node:child_process';
|
|
|
4
4
|
import { readFile, stat } from 'node:fs/promises';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { join, dirname } from 'node:path';
|
|
7
|
-
import { createCommandInvocation } from '@jini-ai/platform';
|
|
8
|
-
import {
|
|
7
|
+
import { createCommandInvocation } from '@jini-ai/platform/command';
|
|
8
|
+
import { nativeAcpModelProbe } from './acp-model-probe.js';
|
|
9
9
|
import { CLAUDE_CODE_INITIALIZE_ARGS, CLAUDE_CODE_INITIALIZE_REQUEST } from './claude-code-models.js';
|
|
10
10
|
import { listProviderModels } from './providers/model-catalog.js';
|
|
11
11
|
import { execAgentFile } from './invocation.js';
|
|
12
12
|
import { scheduleProbeProcess } from './probe-scheduler.js';
|
|
13
13
|
import { probeCopilotSdk, probeDroidSdk } from './model-discovery-sdk.js';
|
|
14
14
|
import { parseSettingsJson, readModelConfiguration } from './model-discovery-config.js';
|
|
15
|
-
import { ModelProbeError, modelIdentityKind, withModelProbeTimeout } from './model-discovery.js';
|
|
15
|
+
import { ModelProbeError, modelIdentityKind, withModelProbeTimeout } from './model-discovery-shared.js';
|
|
16
16
|
const ACP_ARGS = {
|
|
17
17
|
amr: ['agent', 'run', '--runtime', 'opencode'],
|
|
18
18
|
auggie: ['--acp'], cline: ['--acp'], devin: ['--permission-mode', 'dangerous', '--respect-workspace-trust', 'false', 'acp'],
|
|
@@ -340,11 +340,7 @@ export const defaultModelDiscoveryDeps = {
|
|
|
340
340
|
return { protocol: 'openai', baseUrl: env.OPENAI_BASE_URL || env.OPENAI_API_BASE || VENDOR_API_BASE_URLS.openai, apiKey: env.OPENAI_API_KEY };
|
|
341
341
|
return null;
|
|
342
342
|
} },
|
|
343
|
-
acp: {
|
|
344
|
-
const invocation = createCommandInvocation({ command: context.executable, args: [...args], env: context.env });
|
|
345
|
-
const result = await scheduleProbeProcess({ work: () => detectAcpModelMetadata({ bin: invocation.command, args: invocation.args }, { cwd: context.cwd, env: context.env, timeoutMs: 15_000, signal }) }, { signal });
|
|
346
|
-
return { models: result.models, source: 'rpc', coverage: 'account', ...(result.currentModelId ? { defaultSelectionId: result.currentModelId } : {}) };
|
|
347
|
-
} },
|
|
343
|
+
acp: createAcpDiscoveryAdapter({ probe: nativeAcpModelProbe }),
|
|
348
344
|
rpc: { async probe({ agentId, context, signal }) {
|
|
349
345
|
// UNVERIFIED locally: use official prompt-free SDK interfaces, not invented CLI flags.
|
|
350
346
|
if (agentId === 'copilot')
|
|
@@ -399,6 +395,27 @@ export function parsePiRpcMetadata(stdout) {
|
|
|
399
395
|
export function getRuntimeModelDiscoveryDeps({ state }, _optional = {}) {
|
|
400
396
|
if (state === defaultRuntimeState)
|
|
401
397
|
return defaultModelDiscoveryDeps;
|
|
402
|
-
return state.discoveryDeps ??= { ...defaultModelDiscoveryDeps, cache: state.modelCatalog
|
|
398
|
+
return state.discoveryDeps ??= { ...defaultModelDiscoveryDeps, cache: state.modelCatalog,
|
|
399
|
+
acp: createAcpDiscoveryAdapter({ probe: state.acpModelProbe ?? nativeAcpModelProbe }),
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/** Adapt the existing ACP port to catalog metadata; array-only transports cannot claim a default.
|
|
403
|
+
* Keeps invocation normalization, cancellation and the shared process budget in the native adapter.
|
|
404
|
+
* @param required - The host's existing ACP probe, optionally capable of reporting current selection.
|
|
405
|
+
* @returns A catalog adapter using that probe without changing security or concurrency guarantees.
|
|
406
|
+
* @example const acp = createAcpDiscoveryAdapter({ probe: hostProbe });
|
|
407
|
+
*/
|
|
408
|
+
export function createAcpDiscoveryAdapter({ probe }, _optional = {}) {
|
|
409
|
+
return { async probe({ context, args, signal }) {
|
|
410
|
+
const invocation = createCommandInvocation({ command: context.executable, args: [...args], env: context.env });
|
|
411
|
+
const required = { bin: invocation.command, args: invocation.args };
|
|
412
|
+
const optional = { cwd: context.cwd, env: context.env, timeoutMs: 15_000, signal };
|
|
413
|
+
const result = await scheduleProbeProcess({ work: async () => {
|
|
414
|
+
if (probe.detectMetadata)
|
|
415
|
+
return probe.detectMetadata(required, optional);
|
|
416
|
+
return { models: await probe.detectModels(required, optional), currentModelId: null };
|
|
417
|
+
} }, { signal });
|
|
418
|
+
return { models: result.models, source: 'rpc', coverage: 'account', ...(result.currentModelId ? { defaultSelectionId: result.currentModelId } : {}) };
|
|
419
|
+
} };
|
|
403
420
|
}
|
|
404
421
|
//# sourceMappingURL=model-discovery-adapters.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Native composition and legacy public signatures. Injected hosts import model-discovery instead. */
|
|
2
|
+
import { resolveModelForLaunch as resolvePolicyModelForLaunch, type ModelDiscoveryDefinition } from './model-discovery.js';
|
|
3
|
+
import type { AgentDiscoveryConfiguration, AgentModelDiscoveryPort, ModelDiscoveryContext, ModelDiscoveryDeps } from './model-discovery-types.js';
|
|
4
|
+
export * from './model-discovery.js';
|
|
5
|
+
export declare function createAgentModelDiscovery(agentId: string, configuration: AgentDiscoveryConfiguration): AgentModelDiscoveryPort;
|
|
6
|
+
export declare function modelDiscoveryForDef(def: ModelDiscoveryDefinition): AgentModelDiscoveryPort;
|
|
7
|
+
export declare function resolveModelForLaunch(required: {
|
|
8
|
+
def: ModelDiscoveryDefinition;
|
|
9
|
+
context: ModelDiscoveryContext;
|
|
10
|
+
}, { deps, ...optional }?: {
|
|
11
|
+
deps?: ModelDiscoveryDeps;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
}): ReturnType<typeof resolvePolicyModelForLaunch>;
|
|
14
|
+
//# sourceMappingURL=model-discovery-native.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Native composition and legacy public signatures. Injected hosts import model-discovery instead. */
|
|
2
|
+
import { createAgentModelDiscovery as createPolicyDiscovery, modelDiscoveryForDef as policyDiscoveryForDef, resolveModelForLaunch as resolvePolicyModelForLaunch, } from './model-discovery.js';
|
|
3
|
+
import { defaultModelDiscoveryDeps, modelProbeTimeoutMs, probeAgentCatalog, probeCliCache } from './model-discovery-adapters.js';
|
|
4
|
+
export * from './model-discovery.js';
|
|
5
|
+
/** Reuse the existing probe owners, including their credential, cancellation and cache guards. */
|
|
6
|
+
const nativeModelDiscoveryProbes = {
|
|
7
|
+
catalog: ({ agentId, context, configuration, deps, signal }, _optional = {}) => probeAgentCatalog(agentId, context, configuration, deps, signal),
|
|
8
|
+
cliCache: ({ agentId, context, deps, signal }, _optional = {}) => probeCliCache(agentId, context, deps, signal),
|
|
9
|
+
timeoutMs: ({ agentId }, _optional = {}) => modelProbeTimeoutMs(agentId),
|
|
10
|
+
};
|
|
11
|
+
// These forwarding signatures deliberately retain the published API. New policy APIs use
|
|
12
|
+
// required/optional objects; changing these compatibility wrappers would break existing hosts.
|
|
13
|
+
export function createAgentModelDiscovery(agentId, configuration) {
|
|
14
|
+
return createPolicyDiscovery({ agentId, configuration, deps: defaultModelDiscoveryDeps, probes: nativeModelDiscoveryProbes });
|
|
15
|
+
}
|
|
16
|
+
export function modelDiscoveryForDef(def) {
|
|
17
|
+
return policyDiscoveryForDef({ def, deps: defaultModelDiscoveryDeps });
|
|
18
|
+
}
|
|
19
|
+
export function resolveModelForLaunch(required, { deps = defaultModelDiscoveryDeps, ...optional } = {}) {
|
|
20
|
+
return resolvePolicyModelForLaunch({ ...required, deps }, optional);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=model-discovery-native.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelProbeError, modelIdentityKind } from './model-discovery.js';
|
|
1
|
+
import { ModelProbeError, modelIdentityKind } from './model-discovery-shared.js';
|
|
2
2
|
export async function probeCopilotSdk(context, signal, optional = {}) {
|
|
3
3
|
const client = await (optional.createClient ?? createCopilotMetadataClient)(context);
|
|
4
4
|
if (signal.aborted) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Shared discovery normalization and timeout/error contracts; no native adapters. */
|
|
2
|
+
import type { RuntimeModelOption } from './types.js';
|
|
3
|
+
import type { DiscoveredModel, ModelCatalogSnapshot } from './model-discovery-types.js';
|
|
4
|
+
export declare function modelIdentityKind(id: string): DiscoveredModel['identityKind'];
|
|
5
|
+
export declare function normalizeDiscoveredModels(models: readonly RuntimeModelOption[]): DiscoveredModel[];
|
|
6
|
+
export declare class ProbeTimeout extends Error {
|
|
7
|
+
}
|
|
8
|
+
/** Cancellation always reaches the effect port. A broken port cannot hold callers indefinitely. */
|
|
9
|
+
export declare function withModelProbeTimeout<T>(work: (signal: AbortSignal) => Promise<T>, timeoutMs: number, parent?: AbortSignal): Promise<T>;
|
|
10
|
+
export declare class ModelProbeError extends Error {
|
|
11
|
+
readonly code: ModelCatalogSnapshot['diagnostics'][number]['code'];
|
|
12
|
+
constructor(code: ModelCatalogSnapshot['diagnostics'][number]['code']);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=model-discovery-shared.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export function modelIdentityKind(id) {
|
|
2
|
+
const token = id.slice(id.lastIndexOf('/') + 1);
|
|
3
|
+
if (/^(default|auto|adaptive|smart|deep|rush|ultimate|premium|balanced|fast|vercel-ai-gateway|grok-build)$/i.test(token) || /(?:^|[-/])gateway$/i.test(id))
|
|
4
|
+
return 'routing-mode';
|
|
5
|
+
if (/^(opus|sonnet|haiku|fable|best|latest|claude|gemini|gpt|codex|swe)(?:\[.*\])?$/i.test(token) || /(?:^|[-/])latest$/i.test(id))
|
|
6
|
+
return 'alias';
|
|
7
|
+
return 'concrete';
|
|
8
|
+
}
|
|
9
|
+
export function normalizeDiscoveredModels(models) {
|
|
10
|
+
const seen = new Set();
|
|
11
|
+
return models.flatMap((row) => {
|
|
12
|
+
if (!row.id || row.id === 'default' || seen.has(row.id))
|
|
13
|
+
return [];
|
|
14
|
+
seen.add(row.id);
|
|
15
|
+
const model = row;
|
|
16
|
+
return [{ ...row, identityKind: model.identityKind ?? modelIdentityKind(row.id), ...(model.resolvedId ? { resolvedId: model.resolvedId } : {}) }];
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export class ProbeTimeout extends Error {
|
|
20
|
+
}
|
|
21
|
+
/** Cancellation always reaches the effect port. A broken port cannot hold callers indefinitely. */
|
|
22
|
+
export async function withModelProbeTimeout(work, timeoutMs, parent) {
|
|
23
|
+
if (parent?.aborted)
|
|
24
|
+
throw new ProbeTimeout('Probe cancelled');
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
let timer;
|
|
27
|
+
let abortListener;
|
|
28
|
+
const stopped = new Promise((_resolve, reject) => {
|
|
29
|
+
abortListener = () => { controller.abort(); reject(new ProbeTimeout('Probe cancelled')); };
|
|
30
|
+
if (parent?.aborted)
|
|
31
|
+
abortListener();
|
|
32
|
+
else
|
|
33
|
+
parent?.addEventListener('abort', abortListener, { once: true });
|
|
34
|
+
timer = setTimeout(() => { controller.abort(); reject(new ProbeTimeout('Probe timed out')); }, timeoutMs);
|
|
35
|
+
});
|
|
36
|
+
try {
|
|
37
|
+
return await Promise.race([work(controller.signal), stopped]);
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
if (timer)
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
if (abortListener)
|
|
43
|
+
parent?.removeEventListener('abort', abortListener);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export class ModelProbeError extends Error {
|
|
47
|
+
code;
|
|
48
|
+
constructor(code) {
|
|
49
|
+
super(code);
|
|
50
|
+
this.code = code;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=model-discovery-shared.js.map
|
|
@@ -136,4 +136,30 @@ export interface ModelDiscoveryDeps {
|
|
|
136
136
|
};
|
|
137
137
|
cache: Map<string, ModelCacheEntry>;
|
|
138
138
|
}
|
|
139
|
+
export interface AgentDiscoveryConfiguration {
|
|
140
|
+
fallbackModels: () => readonly RuntimeModelOption[];
|
|
141
|
+
parse?: (input: {
|
|
142
|
+
stdout: string;
|
|
143
|
+
}) => RuntimeModelOption[] | null;
|
|
144
|
+
args?: readonly string[];
|
|
145
|
+
}
|
|
146
|
+
/** Host composition selects native probes or substitutes another discovery mechanism. */
|
|
147
|
+
export interface ModelDiscoveryProbes {
|
|
148
|
+
catalog(required: {
|
|
149
|
+
agentId: string;
|
|
150
|
+
context: ModelDiscoveryContext;
|
|
151
|
+
configuration: AgentDiscoveryConfiguration;
|
|
152
|
+
deps: ModelDiscoveryDeps;
|
|
153
|
+
signal: AbortSignal;
|
|
154
|
+
}, optional?: Record<string, never>): Promise<ModelProbeResult>;
|
|
155
|
+
cliCache(required: {
|
|
156
|
+
agentId: string;
|
|
157
|
+
context: ModelDiscoveryContext;
|
|
158
|
+
deps: ModelDiscoveryDeps;
|
|
159
|
+
signal: AbortSignal;
|
|
160
|
+
}, optional?: Record<string, never>): Promise<ModelProbeResult>;
|
|
161
|
+
timeoutMs(required: {
|
|
162
|
+
agentId: string;
|
|
163
|
+
}, optional?: Record<string, never>): number;
|
|
164
|
+
}
|
|
139
165
|
//# sourceMappingURL=model-discovery-types.d.ts.map
|
|
@@ -1,42 +1,37 @@
|
|
|
1
1
|
import type { RuntimeModelOption } from './types.js';
|
|
2
|
-
import type { AgentModelDiscoveryPort,
|
|
3
|
-
export
|
|
2
|
+
import type { AgentModelDiscoveryPort, AgentDiscoveryConfiguration, DefaultModelResolution, ModelCatalogSnapshot, ModelDiscoveryContext, ModelDiscoveryDeps, ModelDiscoveryProbes } from './model-discovery-types.js';
|
|
3
|
+
export { ModelProbeError, modelIdentityKind, normalizeDiscoveredModels, withModelProbeTimeout } from './model-discovery-shared.js';
|
|
4
|
+
export type * from './model-discovery-types.js';
|
|
4
5
|
export declare const MODEL_CATALOG_TTL_MS: number;
|
|
5
6
|
export declare const MODEL_NEGATIVE_TTL_MS = 30000;
|
|
6
|
-
export declare function modelIdentityKind(id: string): DiscoveredModel['identityKind'];
|
|
7
|
-
export declare function normalizeDiscoveredModels(models: readonly RuntimeModelOption[]): DiscoveredModel[];
|
|
8
7
|
/** Hash all launch-affecting state, including env credentials; none of the raw material escapes. */
|
|
9
8
|
export declare function modelLaunchFingerprint(context: ModelDiscoveryContext, configMaterial?: string): string;
|
|
10
|
-
/**
|
|
11
|
-
export declare function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
fallbackModels: () => readonly RuntimeModelOption[];
|
|
18
|
-
parse?: (input: {
|
|
19
|
-
stdout: string;
|
|
20
|
-
}) => RuntimeModelOption[] | null;
|
|
21
|
-
args?: readonly string[];
|
|
22
|
-
}
|
|
23
|
-
export declare function createAgentModelDiscovery(agentId: string, configuration: AgentDiscoveryConfiguration): AgentModelDiscoveryPort;
|
|
9
|
+
/** Bind supplied effect ports and probes without loading their native implementations. */
|
|
10
|
+
export declare function createAgentModelDiscovery({ agentId, configuration, deps: suppliedDeps, probes }: {
|
|
11
|
+
agentId: string;
|
|
12
|
+
configuration: AgentDiscoveryConfiguration;
|
|
13
|
+
deps: ModelDiscoveryDeps;
|
|
14
|
+
probes: ModelDiscoveryProbes;
|
|
15
|
+
}, _optional?: Record<string, never>): AgentModelDiscoveryPort;
|
|
24
16
|
export declare function offlineSnapshot(fingerprint: string, now: number, fallback: readonly RuntimeModelOption[], issue?: ModelCatalogSnapshot['diagnostics'][number]): ModelCatalogSnapshot;
|
|
25
17
|
/** Hosts may supply either discovery port independently; static definitions need no probes. */
|
|
26
|
-
type ModelDiscoveryDefinition = Partial<AgentModelDiscoveryPort> & {
|
|
18
|
+
export type ModelDiscoveryDefinition = Partial<AgentModelDiscoveryPort> & {
|
|
27
19
|
id?: string;
|
|
28
20
|
fallbackModels?: readonly RuntimeModelOption[];
|
|
29
21
|
defaultModelEnvVar?: string;
|
|
30
22
|
supportsCustomModel?: boolean;
|
|
31
23
|
supportsConcreteModelSelection?: boolean;
|
|
32
24
|
};
|
|
33
|
-
export declare function modelDiscoveryForDef(def:
|
|
25
|
+
export declare function modelDiscoveryForDef({ def, deps: suppliedDeps }: {
|
|
26
|
+
def: ModelDiscoveryDefinition;
|
|
27
|
+
deps: ModelDiscoveryDeps;
|
|
28
|
+
}, _optional?: Record<string, never>): AgentModelDiscoveryPort;
|
|
34
29
|
/** Resolve against the actual launch scope, pinning the same ID shown by the picker. */
|
|
35
|
-
export declare function resolveModelForLaunch({ def, context }: {
|
|
30
|
+
export declare function resolveModelForLaunch({ def, context, deps }: {
|
|
36
31
|
def: ModelDiscoveryDefinition;
|
|
37
32
|
context: ModelDiscoveryContext;
|
|
33
|
+
deps: ModelDiscoveryDeps;
|
|
38
34
|
}, optional?: {
|
|
39
|
-
deps?: ModelDiscoveryDeps;
|
|
40
35
|
signal?: AbortSignal;
|
|
41
36
|
}): Promise<{
|
|
42
37
|
model: string;
|
package/dist/model-discovery.js
CHANGED
|
@@ -1,34 +1,14 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { readModelConfiguration } from './model-discovery-config.js';
|
|
3
|
-
import {
|
|
4
|
-
export
|
|
3
|
+
import { ModelProbeError, ProbeTimeout, modelIdentityKind, normalizeDiscoveredModels, withModelProbeTimeout } from './model-discovery-shared.js';
|
|
4
|
+
export { ModelProbeError, modelIdentityKind, normalizeDiscoveredModels, withModelProbeTimeout } from './model-discovery-shared.js';
|
|
5
5
|
export const MODEL_CATALOG_TTL_MS = 15 * 60_000;
|
|
6
6
|
export const MODEL_NEGATIVE_TTL_MS = 30_000;
|
|
7
7
|
const MAX_CATALOG_SCOPES = 128;
|
|
8
|
-
export function modelIdentityKind(id) {
|
|
9
|
-
const token = id.slice(id.lastIndexOf('/') + 1);
|
|
10
|
-
if (/^(default|auto|adaptive|smart|deep|rush|ultimate|premium|balanced|fast|vercel-ai-gateway|grok-build)$/i.test(token) || /(?:^|[-/])gateway$/i.test(id))
|
|
11
|
-
return 'routing-mode';
|
|
12
|
-
if (/^(opus|sonnet|haiku|fable|best|latest|claude|gemini|gpt|codex|swe)(?:\[.*\])?$/i.test(token) || /(?:^|[-/])latest$/i.test(id))
|
|
13
|
-
return 'alias';
|
|
14
|
-
return 'concrete';
|
|
15
|
-
}
|
|
16
|
-
export function normalizeDiscoveredModels(models) {
|
|
17
|
-
const seen = new Set();
|
|
18
|
-
return models.flatMap((row) => {
|
|
19
|
-
if (!row.id || row.id === 'default' || seen.has(row.id))
|
|
20
|
-
return [];
|
|
21
|
-
seen.add(row.id);
|
|
22
|
-
const model = row;
|
|
23
|
-
return [{ ...row, identityKind: model.identityKind ?? modelIdentityKind(row.id), ...(model.resolvedId ? { resolvedId: model.resolvedId } : {}) }];
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
8
|
/** Hash all launch-affecting state, including env credentials; none of the raw material escapes. */
|
|
27
9
|
export function modelLaunchFingerprint(context, configMaterial = '') {
|
|
28
10
|
return createHash('sha256').update(JSON.stringify({ ...context, env: Object.entries(context.env).sort(([a], [b]) => a.localeCompare(b)), configMaterial })).digest('hex');
|
|
29
11
|
}
|
|
30
|
-
class ProbeTimeout extends Error {
|
|
31
|
-
}
|
|
32
12
|
const probePools = new WeakMap();
|
|
33
13
|
/** One cold catalog probe per host; queued callers keep cancellation responsive. */
|
|
34
14
|
async function boundedProbe(deps, work, signal) {
|
|
@@ -61,50 +41,19 @@ async function boundedProbe(deps, work, signal) {
|
|
|
61
41
|
pool.active -= 1;
|
|
62
42
|
}
|
|
63
43
|
}
|
|
64
|
-
/** Cancellation always reaches the effect port. A broken port cannot hold callers indefinitely. */
|
|
65
|
-
export async function withModelProbeTimeout(work, timeoutMs, parent) {
|
|
66
|
-
if (parent?.aborted)
|
|
67
|
-
throw new ProbeTimeout('Probe cancelled');
|
|
68
|
-
const controller = new AbortController();
|
|
69
|
-
let timer;
|
|
70
|
-
let abortListener;
|
|
71
|
-
const stopped = new Promise((_resolve, reject) => {
|
|
72
|
-
abortListener = () => { controller.abort(); reject(new ProbeTimeout('Probe cancelled')); };
|
|
73
|
-
if (parent?.aborted)
|
|
74
|
-
abortListener();
|
|
75
|
-
else
|
|
76
|
-
parent?.addEventListener('abort', abortListener, { once: true });
|
|
77
|
-
timer = setTimeout(() => { controller.abort(); reject(new ProbeTimeout('Probe timed out')); }, timeoutMs);
|
|
78
|
-
});
|
|
79
|
-
try {
|
|
80
|
-
return await Promise.race([work(controller.signal), stopped]);
|
|
81
|
-
}
|
|
82
|
-
finally {
|
|
83
|
-
if (timer)
|
|
84
|
-
clearTimeout(timer);
|
|
85
|
-
if (abortListener)
|
|
86
|
-
parent?.removeEventListener('abort', abortListener);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
44
|
function diagnostic(error) {
|
|
90
45
|
// Never stringify vendor errors: stderr/HTTP bodies may include credentials or OAuth URLs.
|
|
91
46
|
const code = error instanceof ProbeTimeout ? 'timeout' : error instanceof ModelProbeError ? error.code : 'offline';
|
|
92
47
|
return { code, message: ({ timeout: 'Model discovery timed out or was cancelled.', 'auth-missing': 'CLI credentials are unavailable.', 'unsupported-version': 'Native metadata discovery is unavailable for this version.', 'malformed-response': 'Native metadata contained no usable catalog.', offline: 'Model discovery could not reach its source.' })[code] };
|
|
93
48
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
constructor(code) {
|
|
97
|
-
super(code);
|
|
98
|
-
this.code = code;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
export function createAgentModelDiscovery(agentId, configuration) {
|
|
49
|
+
/** Bind supplied effect ports and probes without loading their native implementations. */
|
|
50
|
+
export function createAgentModelDiscovery({ agentId, configuration, deps: suppliedDeps, probes }, _optional = {}) {
|
|
102
51
|
async function scoped(context, deps, signal) {
|
|
103
52
|
const config = await withModelProbeTimeout((active) => readModelConfiguration(agentId, context, deps, active), 1000, signal);
|
|
104
53
|
return { config, key: `${agentId}:${modelLaunchFingerprint(context, config.fingerprintMaterial)}` };
|
|
105
54
|
}
|
|
106
55
|
const port = {
|
|
107
|
-
async discoverModels({ context }, { signal, force = false, staleWhileRevalidate = false, deps =
|
|
56
|
+
async discoverModels({ context }, { signal, force = false, staleWhileRevalidate = false, deps = suppliedDeps } = {}) {
|
|
108
57
|
let state;
|
|
109
58
|
try {
|
|
110
59
|
state = await scoped(context, deps, signal);
|
|
@@ -129,7 +78,7 @@ export function createAgentModelDiscovery(agentId, configuration) {
|
|
|
129
78
|
// immediately; keep stale provenance and refresh without holding the first user prompt.
|
|
130
79
|
if (staleWhileRevalidate && !cached.good && ['codex', 'opencode', 'claude', 'codebuddy'].includes(agentId)) {
|
|
131
80
|
try {
|
|
132
|
-
const disk = await withModelProbeTimeout(active =>
|
|
81
|
+
const disk = await withModelProbeTimeout(active => probes.cliCache({ agentId, context, deps, signal: active }), 1000, signal);
|
|
133
82
|
const models = normalizeDiscoveredModels(disk.models);
|
|
134
83
|
if (models.length)
|
|
135
84
|
cached.good = { models, source: 'cli-cache', coverage: disk.coverage,
|
|
@@ -145,7 +94,7 @@ export function createAgentModelDiscovery(agentId, configuration) {
|
|
|
145
94
|
}
|
|
146
95
|
const pending = (async () => {
|
|
147
96
|
try {
|
|
148
|
-
const result = await boundedProbe(deps, () => withModelProbeTimeout((active) =>
|
|
97
|
+
const result = await boundedProbe(deps, () => withModelProbeTimeout((active) => probes.catalog({ agentId, context, configuration, deps, signal: active }), probes.timeoutMs({ agentId }), signal), signal);
|
|
149
98
|
const models = normalizeDiscoveredModels(result.models);
|
|
150
99
|
if (models.length === 0)
|
|
151
100
|
throw new ModelProbeError('malformed-response');
|
|
@@ -184,7 +133,7 @@ export function createAgentModelDiscovery(agentId, configuration) {
|
|
|
184
133
|
// catalog while this coalesced, timeout-bounded refresh updates the cache in the background.
|
|
185
134
|
return staleWhileRevalidate && lastGood() || pending;
|
|
186
135
|
},
|
|
187
|
-
async resolveDefaultModel({ context, catalog }, { signal, deps =
|
|
136
|
+
async resolveDefaultModel({ context, catalog }, { signal, deps = suppliedDeps } = {}) {
|
|
188
137
|
let state;
|
|
189
138
|
try {
|
|
190
139
|
state = await scoped(context, deps, signal);
|
|
@@ -214,9 +163,9 @@ export function createAgentModelDiscovery(agentId, configuration) {
|
|
|
214
163
|
export function offlineSnapshot(fingerprint, now, fallback, issue) {
|
|
215
164
|
return { models: normalizeDiscoveredModels(fallback), source: 'offline-fallback', freshness: 'offline-fallback', fetchedAt: new Date(now).toISOString(), expiresAt: new Date(now + MODEL_NEGATIVE_TTL_MS).toISOString(), coverage: 'configured', launchFingerprint: fingerprint, diagnostics: issue ? [issue] : [] };
|
|
216
165
|
}
|
|
217
|
-
export function modelDiscoveryForDef(def) {
|
|
166
|
+
export function modelDiscoveryForDef({ def, deps: suppliedDeps }, _optional = {}) {
|
|
218
167
|
return {
|
|
219
|
-
discoverModels: def.discoverModels?.bind(def) || (async ({ context }, { deps =
|
|
168
|
+
discoverModels: def.discoverModels?.bind(def) || (async ({ context }, { deps = suppliedDeps } = {}) => {
|
|
220
169
|
const catalog = offlineSnapshot(modelLaunchFingerprint(context), deps.clock.now(), def.fallbackModels || []);
|
|
221
170
|
const configured = def.defaultModelEnvVar && context.env[def.defaultModelEnvVar]?.trim();
|
|
222
171
|
// Static hosts used their first concrete fallback before discovery existed. Preserve
|
|
@@ -224,7 +173,7 @@ export function modelDiscoveryForDef(def) {
|
|
|
224
173
|
const selection = context.model || context.resumedModelId || configured || catalog.models.find(row => row.identityKind === 'concrete')?.id;
|
|
225
174
|
return { ...catalog, ...(selection ? { defaultSelectionId: selection } : {}) };
|
|
226
175
|
}),
|
|
227
|
-
resolveDefaultModel: def.resolveDefaultModel?.bind(def) || (async ({ context, catalog }, { deps =
|
|
176
|
+
resolveDefaultModel: def.resolveDefaultModel?.bind(def) || (async ({ context, catalog }, { deps = suppliedDeps } = {}) => {
|
|
228
177
|
if (context.resumeSessionId && !context.resumedModelId && !context.model)
|
|
229
178
|
return { status: 'unresolved', reason: 'Resumed session model metadata is required.' };
|
|
230
179
|
const configured = def.defaultModelEnvVar && context.env[def.defaultModelEnvVar]?.trim();
|
|
@@ -241,16 +190,16 @@ export function modelDiscoveryForDef(def) {
|
|
|
241
190
|
};
|
|
242
191
|
}
|
|
243
192
|
/** Resolve against the actual launch scope, pinning the same ID shown by the picker. */
|
|
244
|
-
export async function resolveModelForLaunch({ def, context }, optional = {}) {
|
|
193
|
+
export async function resolveModelForLaunch({ def, context, deps }, optional = {}) {
|
|
245
194
|
if (def.supportsConcreteModelSelection === false)
|
|
246
195
|
throw new Error('This CLI cannot pin a concrete starting model.');
|
|
247
|
-
const discovery = modelDiscoveryForDef(def);
|
|
248
|
-
const catalog = await discovery.discoverModels({ context }, { ...optional, staleWhileRevalidate: true });
|
|
196
|
+
const discovery = modelDiscoveryForDef({ def, deps });
|
|
197
|
+
const catalog = await discovery.discoverModels({ context }, { ...optional, deps, staleWhileRevalidate: true });
|
|
249
198
|
// Custom input is allowed unless the definition explicitly disables it: an unlisted user ID is already
|
|
250
199
|
// the intended launch value. Never substitute a catalog default or reinterpret its spelling.
|
|
251
200
|
const resolution = context.model && def.supportsCustomModel !== false && !catalog.models.some(row => row.id === context.model)
|
|
252
|
-
? { status: 'resolved', id: context.model, selectionId: context.model, source: 'config-file', resolvedAt: new Date(
|
|
253
|
-
: await discovery.resolveDefaultModel({ context, catalog }, optional);
|
|
201
|
+
? { status: 'resolved', id: context.model, selectionId: context.model, source: 'config-file', resolvedAt: new Date(deps.clock.now()).toISOString(), launchFingerprint: catalog.launchFingerprint }
|
|
202
|
+
: await discovery.resolveDefaultModel({ context, catalog }, { ...optional, deps });
|
|
254
203
|
if (resolution.status !== 'resolved')
|
|
255
204
|
throw new Error(resolution.reason);
|
|
256
205
|
return { model: resolution.id, catalog, resolution };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Native host composition: one state and transport, with environment policies resolved once. */
|
|
2
|
+
import { type AcpModelProbe } from './acp-model-probe.js';
|
|
3
|
+
import { detectAgents, probeAgentModels } from './detection.js';
|
|
4
|
+
import { resolveAgentLaunch } from './launch.js';
|
|
5
|
+
import { getAgentDef } from './registry.js';
|
|
6
|
+
import { type AgentRuntimeState } from './runtime-state.js';
|
|
7
|
+
import type { RuntimeEnv } from './types.js';
|
|
8
|
+
export interface NativeAgentRuntime {
|
|
9
|
+
readonly state: AgentRuntimeState;
|
|
10
|
+
readonly hostEnv: RuntimeEnv;
|
|
11
|
+
readonly codexDisablePlugins: boolean;
|
|
12
|
+
readonly piGracefulShutdownMs: number;
|
|
13
|
+
readonly detectAgents: typeof detectAgents;
|
|
14
|
+
readonly probeAgentModels: typeof probeAgentModels;
|
|
15
|
+
readonly resolveAgentLaunch: typeof resolveAgentLaunch;
|
|
16
|
+
readonly getAgentDef: (required: Parameters<typeof getAgentDef>[0], optional?: Record<string, never>) => ReturnType<typeof getAgentDef>;
|
|
17
|
+
/** Drain owned discovery before clearing caches, so late probes cannot repopulate them. */
|
|
18
|
+
dispose(required: Record<string, never>, optional?: Record<string, never>): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/** Bind existing runtime owners to a host; copies env without performing I/O.
|
|
21
|
+
* @param required - The host's selected environment, used instead of ambient process configuration.
|
|
22
|
+
* @param optional - An existing state, ACP transport, or explicit policies overriding env defaults.
|
|
23
|
+
* @returns Bound runtime operations and an idempotent cache disposer. Stop runs before disposing.
|
|
24
|
+
* Discovery after disposal rejects with `InvalidStateError`; native probe failures retain their existing outcomes.
|
|
25
|
+
* @example const runtime = createNativeAgentRuntime({ env: process.env });
|
|
26
|
+
*/
|
|
27
|
+
export declare function createNativeAgentRuntime({ env }: {
|
|
28
|
+
env: RuntimeEnv;
|
|
29
|
+
}, { state, acpModelProbe, codexDisablePlugins, piGracefulShutdownMs, }?: {
|
|
30
|
+
state?: AgentRuntimeState;
|
|
31
|
+
acpModelProbe?: AcpModelProbe;
|
|
32
|
+
codexDisablePlugins?: boolean;
|
|
33
|
+
piGracefulShutdownMs?: number;
|
|
34
|
+
}): NativeAgentRuntime;
|
|
35
|
+
//# sourceMappingURL=native-runtime.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** Native host composition: one state and transport, with environment policies resolved once. */
|
|
2
|
+
import { nativeAcpModelProbe } from './acp-model-probe.js';
|
|
3
|
+
import { detectAgents, probeAgentModels } from './detection.js';
|
|
4
|
+
import { resolveAgentLaunch } from './launch.js';
|
|
5
|
+
import { getAgentDef } from './registry.js';
|
|
6
|
+
import { createAcpDiscoveryAdapter } from './model-discovery-adapters.js';
|
|
7
|
+
import { bindRuntimeAgentDef, createAgentRuntimeState } from './runtime-state.js';
|
|
8
|
+
/** Bind existing runtime owners to a host; copies env without performing I/O.
|
|
9
|
+
* @param required - The host's selected environment, used instead of ambient process configuration.
|
|
10
|
+
* @param optional - An existing state, ACP transport, or explicit policies overriding env defaults.
|
|
11
|
+
* @returns Bound runtime operations and an idempotent cache disposer. Stop runs before disposing.
|
|
12
|
+
* Discovery after disposal rejects with `InvalidStateError`; native probe failures retain their existing outcomes.
|
|
13
|
+
* @example const runtime = createNativeAgentRuntime({ env: process.env });
|
|
14
|
+
*/
|
|
15
|
+
export function createNativeAgentRuntime({ env }, { state = createAgentRuntimeState({}), acpModelProbe = state.acpModelProbe ?? nativeAcpModelProbe, codexDisablePlugins = env.CODEX_DISABLE_PLUGINS === '1', piGracefulShutdownMs = Number(env.PI_GRACEFUL_SHUTDOWN_MS) || 5000, } = {}) {
|
|
16
|
+
const hostEnv = { ...env };
|
|
17
|
+
if (state.discoveryDeps && state.acpModelProbe !== acpModelProbe) {
|
|
18
|
+
state.discoveryDeps = { ...state.discoveryDeps, acp: createAcpDiscoveryAdapter({ probe: acpModelProbe }) };
|
|
19
|
+
}
|
|
20
|
+
state.acpModelProbe = acpModelProbe;
|
|
21
|
+
const pending = new Set();
|
|
22
|
+
let disposal;
|
|
23
|
+
/** Retain operations until disposal can wait for their final cache writes. */
|
|
24
|
+
function track(work) {
|
|
25
|
+
if (disposal)
|
|
26
|
+
return Promise.reject(new DOMException('Agent runtime is disposed', 'InvalidStateError'));
|
|
27
|
+
const result = work();
|
|
28
|
+
pending.add(result);
|
|
29
|
+
void result.then(() => pending.delete(result), () => pending.delete(result));
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
state, hostEnv, codexDisablePlugins, piGracefulShutdownMs,
|
|
34
|
+
detectAgents: (required, optional = {}) => track(() => detectAgents(required, { ...optional, state, env: hostEnv })),
|
|
35
|
+
probeAgentModels: (required, optional = {}) => track(() => probeAgentModels(required, { ...optional, state, env: hostEnv })),
|
|
36
|
+
resolveAgentLaunch: (required, optional = {}) => resolveAgentLaunch(required, { ...optional, state, env: hostEnv }),
|
|
37
|
+
getAgentDef: (required, _optional = {}) => {
|
|
38
|
+
const def = getAgentDef(required);
|
|
39
|
+
return def ? bindRuntimeAgentDef({ def, state }, { codexDisablePlugins }) : def;
|
|
40
|
+
},
|
|
41
|
+
dispose(_required, _optional = {}) {
|
|
42
|
+
disposal ??= (async () => {
|
|
43
|
+
await Promise.allSettled([...pending, ...state.detections.values(), ...state.capabilityProbes.values(),
|
|
44
|
+
...[...state.modelCatalog.values()].flatMap(entry => entry.pending ? [entry.pending] : []),
|
|
45
|
+
...[...state.claudeModels.values()].map(entry => entry.value),
|
|
46
|
+
]);
|
|
47
|
+
state.clear({}, {});
|
|
48
|
+
})();
|
|
49
|
+
return disposal;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=native-runtime.js.map
|
package/dist/runtime-state.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** Mutable runtime data belongs to one host. Compatibility functions use defaultRuntimeState. */
|
|
2
|
+
import type { AcpModelProbe } from './acp-model-probe.js';
|
|
2
3
|
import type { RuntimeAgentDef, RuntimeCapabilityMap, RuntimeModelOption, DetectedAgent } from './types.js';
|
|
3
4
|
import type { ModelCacheEntry, ModelDiscoveryDeps } from './model-discovery-types.js';
|
|
4
5
|
export interface AgentRuntimeState {
|
|
@@ -13,6 +14,8 @@ export interface AgentRuntimeState {
|
|
|
13
14
|
expiresAt: number;
|
|
14
15
|
value: Promise<readonly RuntimeModelOption[] | null>;
|
|
15
16
|
}>;
|
|
17
|
+
/** Host-owned transport. Absent only for legacy definitions using the compatibility wrapper. */
|
|
18
|
+
acpModelProbe?: AcpModelProbe;
|
|
16
19
|
discoveryDeps?: ModelDiscoveryDeps;
|
|
17
20
|
readonly modelCatalog: Map<string, ModelCacheEntry>;
|
|
18
21
|
readonly executable: {
|
|
@@ -32,10 +35,12 @@ export interface AgentRuntimeState {
|
|
|
32
35
|
* Returns empty owned maps; no I/O. @complexity O(1) initialization; retained data grows with probes. */
|
|
33
36
|
export declare function createAgentRuntimeState(_required: Record<string, never>, _optional?: Record<string, never>): AgentRuntimeState;
|
|
34
37
|
export declare const defaultRuntimeState: AgentRuntimeState;
|
|
35
|
-
/** Bind the
|
|
38
|
+
/** Bind model probes and the argument builder to the host transport, capability state and plugin policy.
|
|
36
39
|
* Returns a definition copy without mutating the registry. @complexity O(1). */
|
|
37
40
|
export declare function bindRuntimeAgentDef({ def, state }: {
|
|
38
41
|
def: RuntimeAgentDef;
|
|
39
42
|
state: AgentRuntimeState;
|
|
40
|
-
},
|
|
43
|
+
}, { codexDisablePlugins }?: {
|
|
44
|
+
codexDisablePlugins?: boolean;
|
|
45
|
+
}): RuntimeAgentDef;
|
|
41
46
|
//# sourceMappingURL=runtime-state.d.ts.map
|