@jini-ai/agent-runtime 0.4.5 → 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/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.js +1 -1
- package/dist/defs/claude.js +1 -1
- package/dist/defs/cline.js +1 -1
- package/dist/defs/codebuddy.js +1 -1
- 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 +1 -1
- 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 +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.js +1 -1
- package/dist/defs/trae-cli.js +1 -1
- package/dist/defs/vibe.js +1 -1
- package/dist/detection.js +1 -1
- package/dist/env.js +1 -1
- package/dist/executables.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/invocation.js +1 -1
- package/dist/model-discovery-adapters.d.ts +1 -2
- package/dist/model-discovery-adapters.js +2 -2
- 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/package.json +29 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
## 0.4.6 — 2026-10-13
|
|
2
|
+
|
|
3
|
+
- New `./model-discovery` subpath: the discovery policy with injected `deps` and `probes` (`createAgentModelDiscovery({ agentId, configuration, deps, probes })`, `modelDiscoveryForDef({ def, deps })`, `resolveModelForLaunch({ def, context, deps })`). It loads no child_process/fs or native adapters. The root keeps the published scalar signatures, wired to the native probes.
|
|
4
|
+
- Platform helpers come from the narrow platform subpaths; peer `@jini-ai/platform` floor is now `^0.5.5`.
|
|
5
|
+
|
|
1
6
|
## 0.4.3 — 2026-10-08
|
|
2
7
|
|
|
3
8
|
- Desktop 0.1.13 release fixes: see commits a2659d24 (admin), 5695a7c3 (chat, agent-runtime), 8ad4ac5c (devops).
|
|
@@ -39,7 +39,7 @@ import { createHash } from 'node:crypto';
|
|
|
39
39
|
import { readFile } from 'node:fs/promises';
|
|
40
40
|
import os from 'node:os';
|
|
41
41
|
import { join } from 'node:path';
|
|
42
|
-
import { createCommandInvocation } from '@jini-ai/platform';
|
|
42
|
+
import { createCommandInvocation } from '@jini-ai/platform/command';
|
|
43
43
|
import { sanitizeCustomModel } from './models.js';
|
|
44
44
|
/** A spawn costs ~2.5s and the picker list only moves when Claude Code updates or the server's
|
|
45
45
|
* "additional" options change, so one answer is trusted for this long per process. Failures are
|
package/dist/defs/aider.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const aiderAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/amp.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
// Amp CLI (https://ampcode.com) is a full agentic coding CLI, argv-shaped
|
|
4
4
|
// much like Claude Code: it has a headless execute mode and emits a
|
package/dist/defs/amr.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { execAgentFile } from './shared.js';
|
|
3
3
|
const AMR_MODELS_TIMEOUT_MS = 10_000;
|
|
4
4
|
const AMR_MODELS_RETRY_DELAYS_MS = [250, 750];
|
package/dist/defs/antigravity.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { redactOAuthUrls } from '@jini-ai/oauth';
|
|
3
3
|
import { DEFAULT_MODEL_OPTION } from './shared.js';
|
|
4
4
|
// `agy` v1.1.24 has a real `--model <id>` flag (`agy --help`: "Model for the current CLI
|
package/dist/defs/auggie.js
CHANGED
package/dist/defs/claude.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
/**
|
|
3
3
|
* Claude Code has no dedicated image-attachment flag. imageDelivery: 'prompt-path' makes the
|
|
4
4
|
* executor append local image paths to the prompt and add their directories to extraAllowedDirs;
|
package/dist/defs/cline.js
CHANGED
package/dist/defs/codebuddy.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { agentCapabilities } from '../capabilities.js';
|
|
3
3
|
import { buildClaudeMcpConfigArgs, DEFAULT_MODEL_OPTION } from './shared.js';
|
|
4
4
|
// Codebuddy Code (https://www.codebuddy.cn) — a Claude Code–compatible CLI
|
package/dist/defs/codex.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
/** CODEX_SANDBOX_MODE and CODEX_DISABLE_PLUGINS are adapter-scoped operator overrides;
|
|
3
3
|
* no product-specific environment naming is required. */
|
|
4
4
|
import { DEFAULT_MODEL_OPTION, clampCodexReasoning } from './shared.js';
|
package/dist/defs/copilot.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const copilotAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/crush.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
import { agentCapabilities } from '../capabilities.js';
|
|
4
4
|
export function parseCursorAgentModels({ stdout }) {
|
package/dist/defs/deepseek.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const deepseekAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/devin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { detectAcpModels, DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const devinAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/droid.js
CHANGED
package/dist/defs/goose.js
CHANGED
package/dist/defs/grok-build.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
const GROK_MODEL_ID_RE = /^(?:[*•-]\s*|(?=grok-))([a-z0-9][a-z0-9./_:@\[\]-]*)(?:\s+\(default\))?\s*$/i;
|
|
4
4
|
export function parseGrokBuildModels({ stdout }) {
|
package/dist/defs/hermes.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { detectAcpModels, DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const hermesAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/kilo.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { detectAcpModels, DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const kiloAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/kimi.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { detectAcpModels, DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const kimiAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/kiro.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { detectAcpModels, DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const kiroAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/mimo.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const mimoAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/opencode.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { DEFAULT_MODEL_OPTION, parseLineSeparatedModels } from './shared.js';
|
|
3
3
|
import { agentCapabilities } from '../capabilities.js';
|
|
4
4
|
const SKIP_PERMISSIONS_FLAG = '--dangerously-skip-permissions';
|
package/dist/defs/pi.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { DEFAULT_MODEL_OPTION, execAgentFile, parsePiModels } from './shared.js';
|
|
4
4
|
export const piAgentDef = {
|
package/dist/defs/qoder.js
CHANGED
package/dist/defs/qwen.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const qwenAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/reasonix.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
/** Reasonix's declarative definition stays product-neutral (R5, checkEngineBoundaries).
|
|
3
3
|
* Per-run system overlays use REASONIX_ACP_SYSTEM_APPEND via the shared systemPromptDelivery
|
|
4
4
|
* dispatch and computeChildEnv. Static def.env is computed once and cannot carry host/per-run
|
package/dist/defs/trae-cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { detectAcpModels, DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const traeCliAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/defs/vibe.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentModelDiscovery } from '../model-discovery.js';
|
|
1
|
+
import { createAgentModelDiscovery } from '../model-discovery-native.js';
|
|
2
2
|
import { detectAcpModels, DEFAULT_MODEL_OPTION } from './shared.js';
|
|
3
3
|
export const vibeAgentDef = {
|
|
4
4
|
// UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
|
package/dist/detection.js
CHANGED
|
@@ -16,7 +16,7 @@ import { getRuntimeModelDiscoveryDeps } from './model-discovery-adapters.js';
|
|
|
16
16
|
* `archived provenance ledger`.
|
|
17
17
|
*/
|
|
18
18
|
import { execAgentFile } from './invocation.js';
|
|
19
|
-
import { offlineSnapshot, modelDiscoveryForDef } from './model-discovery.js';
|
|
19
|
+
import { offlineSnapshot, modelDiscoveryForDef } from './model-discovery-native.js';
|
|
20
20
|
import { rememberLiveModels } from './models.js';
|
|
21
21
|
import { installMetaForAgent } from './metadata.js';
|
|
22
22
|
import { AGENT_DEFS } from './registry.js';
|
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.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,7 @@ 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
53
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -70,7 +70,7 @@ 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
76
|
//# 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,5 @@
|
|
|
1
1
|
import { type AgentRuntimeState } from './runtime-state.js';
|
|
2
|
-
import {
|
|
3
|
-
import type { ModelDiscoveryContext, ModelDiscoveryDeps, ModelProbeResult } from './model-discovery-types.js';
|
|
2
|
+
import type { AgentDiscoveryConfiguration, ModelDiscoveryContext, ModelDiscoveryDeps, ModelProbeResult } from './model-discovery-types.js';
|
|
4
3
|
export declare function modelProbeTimeoutMs(agentId: string): number;
|
|
5
4
|
/** Shared CLI-subcommand adapter. Output parsers are pure def-owned functions, not vendor tools. */
|
|
6
5
|
export declare function probeCliSubcommand(context: ModelDiscoveryContext, config: AgentDiscoveryConfiguration, deps: ModelDiscoveryDeps, signal: AbortSignal): Promise<ModelProbeResult>;
|
|
@@ -4,7 +4,7 @@ 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';
|
|
7
|
+
import { createCommandInvocation } from '@jini-ai/platform/command';
|
|
8
8
|
import { detectAcpModelMetadata } from './agent-protocol/acp/models.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';
|
|
@@ -12,7 +12,7 @@ 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'],
|
|
@@ -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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/agent-runtime",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "Coding-agent runtime adapters: runtime registry, detection, launch, stream parsers, and the ACP/pi-rpc subprocess transport.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -16,7 +16,21 @@
|
|
|
16
16
|
".": "node",
|
|
17
17
|
"./providers/tool-turn": "node",
|
|
18
18
|
"./model-catalog/cache": "universal",
|
|
19
|
-
"./providers/sse-decode": "universal"
|
|
19
|
+
"./providers/sse-decode": "universal",
|
|
20
|
+
"./model-discovery": "node"
|
|
21
|
+
},
|
|
22
|
+
"isolation": {
|
|
23
|
+
"forbidden": {
|
|
24
|
+
"./model-discovery": [
|
|
25
|
+
"node:child_process",
|
|
26
|
+
"child_process",
|
|
27
|
+
"node:fs",
|
|
28
|
+
"fs",
|
|
29
|
+
"./model-discovery-adapters.js",
|
|
30
|
+
"./model-discovery-native.js",
|
|
31
|
+
"./model-discovery-sdk.js"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
20
34
|
}
|
|
21
35
|
},
|
|
22
36
|
"type": "module",
|
|
@@ -43,6 +57,11 @@
|
|
|
43
57
|
"types": "./dist/providers/sse-decode.d.ts",
|
|
44
58
|
"import": "./dist/providers/sse-decode.js",
|
|
45
59
|
"default": "./dist/providers/sse-decode.js"
|
|
60
|
+
},
|
|
61
|
+
"./model-discovery": {
|
|
62
|
+
"types": "./dist/model-discovery.d.ts",
|
|
63
|
+
"import": "./dist/model-discovery.js",
|
|
64
|
+
"default": "./dist/model-discovery.js"
|
|
46
65
|
}
|
|
47
66
|
},
|
|
48
67
|
"typesVersions": {
|
|
@@ -55,6 +74,9 @@
|
|
|
55
74
|
],
|
|
56
75
|
"providers/sse-decode": [
|
|
57
76
|
"./dist/providers/sse-decode.d.ts"
|
|
77
|
+
],
|
|
78
|
+
"model-discovery": [
|
|
79
|
+
"./dist/model-discovery.d.ts"
|
|
58
80
|
]
|
|
59
81
|
}
|
|
60
82
|
},
|
|
@@ -77,19 +99,19 @@
|
|
|
77
99
|
"devDependencies": {
|
|
78
100
|
"@vitest/coverage-v8": "^2.1.9",
|
|
79
101
|
"@jini-ai/core": "^0.4.0",
|
|
80
|
-
"@jini-ai/oauth": "^0.2.2",
|
|
81
102
|
"@jini-ai/integrations": "^0.4.2",
|
|
82
|
-
"@jini-ai/platform": "^0.5.
|
|
83
|
-
"@jini-ai/protocol": "^0.4.4"
|
|
103
|
+
"@jini-ai/platform": "^0.5.5",
|
|
104
|
+
"@jini-ai/protocol": "^0.4.4",
|
|
105
|
+
"@jini-ai/oauth": "^0.2.2"
|
|
84
106
|
},
|
|
85
107
|
"dependencies": {
|
|
86
|
-
"@jini-ai/core": "^0.4.
|
|
108
|
+
"@jini-ai/core": "^0.4.4"
|
|
87
109
|
},
|
|
88
110
|
"peerDependencies": {
|
|
89
111
|
"@jini-ai/integrations": "^0.4.2",
|
|
90
112
|
"@github/copilot-sdk": "*",
|
|
91
113
|
"@jini-ai/oauth": "^0.2.2",
|
|
92
|
-
"@jini-ai/platform": "^0.5.
|
|
114
|
+
"@jini-ai/platform": "^0.5.5",
|
|
93
115
|
"@jini-ai/protocol": "^0.4.4"
|
|
94
116
|
},
|
|
95
117
|
"peerDependenciesMeta": {
|