@jini-ai/agent-runtime 0.4.1 → 0.4.3

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.
Files changed (127) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/acp-model-probe.d.ts +6 -27
  3. package/dist/acp-model-probe.js +6 -4
  4. package/dist/agent-protocol/acp/models.d.ts +8 -0
  5. package/dist/agent-protocol/acp/models.js +38 -6
  6. package/dist/agent-protocol/acp/session.js +15 -2
  7. package/dist/agent-protocol/pi-rpc/events.js +4 -0
  8. package/dist/amr-model-cache.d.ts +2 -12
  9. package/dist/amr-profile-resolver.d.ts +3 -14
  10. package/dist/anthropic-live-models.d.ts +1 -1
  11. package/dist/anthropic-live-models.js +0 -0
  12. package/dist/artifact-taxonomy.d.ts +3 -17
  13. package/dist/auth.d.ts +0 -6
  14. package/dist/auth.js +1 -30
  15. package/dist/claude-code-models.d.ts +3 -4
  16. package/dist/claude-code-models.js +5 -7
  17. package/dist/claude-stream.d.ts +0 -4
  18. package/dist/claude-stream.js +4 -4
  19. package/dist/copilot-stream.d.ts +0 -5
  20. package/dist/copilot-stream.js +0 -5
  21. package/dist/defs/aider.d.ts +15 -0
  22. package/dist/defs/aider.js +4 -2
  23. package/dist/defs/amp.d.ts +16 -0
  24. package/dist/defs/amp.js +5 -1
  25. package/dist/defs/amr.d.ts +15 -0
  26. package/dist/defs/amr.js +6 -15
  27. package/dist/defs/antigravity.d.ts +16 -1
  28. package/dist/defs/antigravity.js +3 -2
  29. package/dist/defs/auggie.d.ts +15 -0
  30. package/dist/defs/auggie.js +3 -0
  31. package/dist/defs/claude.d.ts +15 -0
  32. package/dist/defs/claude.js +26 -36
  33. package/dist/defs/cline.d.ts +15 -0
  34. package/dist/defs/cline.js +3 -0
  35. package/dist/defs/codebuddy.d.ts +15 -0
  36. package/dist/defs/codebuddy.js +3 -1
  37. package/dist/defs/codex.d.ts +15 -0
  38. package/dist/defs/codex.js +11 -48
  39. package/dist/defs/copilot.d.ts +15 -0
  40. package/dist/defs/copilot.js +5 -14
  41. package/dist/defs/crush.d.ts +15 -0
  42. package/dist/defs/crush.js +3 -0
  43. package/dist/defs/cursor-agent.d.ts +15 -0
  44. package/dist/defs/cursor-agent.js +3 -1
  45. package/dist/defs/deepseek.d.ts +15 -0
  46. package/dist/defs/deepseek.js +3 -1
  47. package/dist/defs/devin.d.ts +15 -0
  48. package/dist/defs/devin.js +3 -1
  49. package/dist/defs/droid.d.ts +15 -0
  50. package/dist/defs/droid.js +3 -0
  51. package/dist/defs/goose.d.ts +15 -0
  52. package/dist/defs/goose.js +3 -0
  53. package/dist/defs/grok-build.d.ts +15 -0
  54. package/dist/defs/grok-build.js +5 -9
  55. package/dist/defs/hermes.d.ts +15 -0
  56. package/dist/defs/hermes.js +3 -1
  57. package/dist/defs/index.d.ts +1 -6
  58. package/dist/defs/index.js +1 -6
  59. package/dist/defs/kilo.d.ts +15 -0
  60. package/dist/defs/kilo.js +3 -1
  61. package/dist/defs/kimi.d.ts +15 -0
  62. package/dist/defs/kimi.js +3 -1
  63. package/dist/defs/kiro.d.ts +15 -0
  64. package/dist/defs/kiro.js +3 -1
  65. package/dist/defs/mimo.d.ts +15 -0
  66. package/dist/defs/mimo.js +3 -1
  67. package/dist/defs/opencode.d.ts +15 -1
  68. package/dist/defs/opencode.js +2 -1
  69. package/dist/defs/pi.d.ts +15 -0
  70. package/dist/defs/pi.js +6 -5
  71. package/dist/defs/qoder.d.ts +15 -0
  72. package/dist/defs/qoder.js +3 -1
  73. package/dist/defs/qwen.d.ts +15 -0
  74. package/dist/defs/qwen.js +3 -1
  75. package/dist/defs/reasonix.d.ts +15 -0
  76. package/dist/defs/reasonix.js +7 -23
  77. package/dist/defs/shared.d.ts +3 -8
  78. package/dist/defs/shared.js +3 -8
  79. package/dist/defs/trae-cli.d.ts +15 -0
  80. package/dist/defs/trae-cli.js +3 -1
  81. package/dist/defs/vibe.d.ts +15 -0
  82. package/dist/defs/vibe.js +3 -1
  83. package/dist/detection.d.ts +23 -4
  84. package/dist/detection.js +41 -59
  85. package/dist/diagnostics.js +1 -9
  86. package/dist/env.js +5 -31
  87. package/dist/executables.js +0 -1
  88. package/dist/index.d.ts +10 -257
  89. package/dist/index.js +20 -278
  90. package/dist/json-event-stream.js +23 -29
  91. package/dist/launch.js +1 -5
  92. package/dist/log-file.js +0 -5
  93. package/dist/metadata.js +0 -4
  94. package/dist/mmd-routes.js +2 -6
  95. package/dist/model-discovery-adapters.d.ts +22 -0
  96. package/dist/model-discovery-adapters.js +391 -0
  97. package/dist/model-discovery-config.d.ts +17 -0
  98. package/dist/model-discovery-config.js +137 -0
  99. package/dist/model-discovery-sdk.d.ts +18 -0
  100. package/dist/model-discovery-sdk.js +56 -0
  101. package/dist/model-discovery-types.d.ts +139 -0
  102. package/dist/model-discovery-types.js +2 -0
  103. package/dist/model-discovery.d.ts +46 -0
  104. package/dist/model-discovery.js +258 -0
  105. package/dist/model-registry.d.ts +5 -36
  106. package/dist/models.d.ts +1 -4
  107. package/dist/models.js +3 -1
  108. package/dist/opencode-log.js +1 -3
  109. package/dist/paths.js +1 -4
  110. package/dist/pi-models.d.ts +1 -7
  111. package/dist/pi-models.js +1 -3
  112. package/dist/prompt-augmenter.d.ts +3 -17
  113. package/dist/prompt-augmenter.js +3 -17
  114. package/dist/providers/model-catalog.d.ts +2 -0
  115. package/dist/providers/model-catalog.js +76 -55
  116. package/dist/providers/sse-decode.d.ts +4 -48
  117. package/dist/providers/sse-decode.js +3 -108
  118. package/dist/qoder-stream.d.ts +0 -3
  119. package/dist/qoder-stream.js +0 -3
  120. package/dist/registry.d.ts +1 -1
  121. package/dist/registry.js +3 -3
  122. package/dist/resolution.js +1 -4
  123. package/dist/role-marker-guard.d.ts +0 -5
  124. package/dist/role-marker-guard.js +0 -5
  125. package/dist/telemetry-sink.d.ts +3 -14
  126. package/dist/types.d.ts +9 -2
  127. package/package.json +27 -6
@@ -7,10 +7,6 @@
7
7
  * `../pi-models.ts` for why these are ports, not direct lifts), and two
8
8
  * small generic parsers (`clampCodexReasoning`, `parseLineSeparatedModels`).
9
9
  *
10
- * Ported from OD's `apps/daemon/src/runtimes/defs/shared.ts` — the origin
11
- * imported `detectAcpModels` from `../../acp.js` and `parsePiModels` from
12
- * `../../pi-rpc.js` directly; here they come from this package's own
13
- * port/vendor modules instead. See `archived provenance ledger`.
14
10
  */
15
11
  import { detectAcpModels } from '../acp-model-probe.js';
16
12
  import { parsePiModels } from '../pi-models.js';
@@ -28,10 +24,9 @@ export { detectAcpModels, parsePiModels, execAgentFile, DEFAULT_MODEL_OPTION };
28
24
  * surface, which is why it declared the strategy at all. Both current declarers (`claude`,
29
25
  * `codebuddy`) call this; a third would too, instead of copying the branch.
30
26
  *
31
- * Why explicit rather than auto-discovery: confirmed live (2026-07-30) that auto-discovery of a
32
- * project `.mcp.json` requires an interactive trust prompt a headless daemon-spawned child has no
33
- * TTY to answer — the MCP server connection sat at `"pending"` forever and none of its tools ever
34
- * reached the model. The identical config passed via `--mcp-config` connected immediately.
27
+ * Explicit config bypasses project .mcp.json auto-discovery's interactive trust prompt: a
28
+ * headless daemon child has no TTY to answer it, leaving the MCP connection pending indefinitely.
29
+ * Passing the staged file via --mcp-config makes it available without that prompt.
35
30
  *
36
31
  * `--strict-mcp-config` is paired with it deliberately, not for symmetry: it makes the CLI load
37
32
  * ONLY this config, closing the separate "spawned CLI inherits the interactive developer's own
@@ -7,10 +7,6 @@
7
7
  * `../pi-models.ts` for why these are ports, not direct lifts), and two
8
8
  * small generic parsers (`clampCodexReasoning`, `parseLineSeparatedModels`).
9
9
  *
10
- * Ported from OD's `apps/daemon/src/runtimes/defs/shared.ts` — the origin
11
- * imported `detectAcpModels` from `../../acp.js` and `parsePiModels` from
12
- * `../../pi-rpc.js` directly; here they come from this package's own
13
- * port/vendor modules instead. See `archived provenance ledger`.
14
10
  */
15
11
  import { detectAcpModels } from '../acp-model-probe.js';
16
12
  import { parsePiModels } from '../pi-models.js';
@@ -27,10 +23,9 @@ export { detectAcpModels, parsePiModels, execAgentFile, DEFAULT_MODEL_OPTION };
27
23
  * surface, which is why it declared the strategy at all. Both current declarers (`claude`,
28
24
  * `codebuddy`) call this; a third would too, instead of copying the branch.
29
25
  *
30
- * Why explicit rather than auto-discovery: confirmed live (2026-07-30) that auto-discovery of a
31
- * project `.mcp.json` requires an interactive trust prompt a headless daemon-spawned child has no
32
- * TTY to answer — the MCP server connection sat at `"pending"` forever and none of its tools ever
33
- * reached the model. The identical config passed via `--mcp-config` connected immediately.
26
+ * Explicit config bypasses project .mcp.json auto-discovery's interactive trust prompt: a
27
+ * headless daemon child has no TTY to answer it, leaving the MCP connection pending indefinitely.
28
+ * Passing the staged file via --mcp-config makes it available without that prompt.
34
29
  *
35
30
  * `--strict-mcp-config` is paired with it deliberately, not for symmetry: it makes the CLI load
36
31
  * ONLY this config, closing the separate "spawned CLI inherits the interactive developer's own
@@ -21,5 +21,20 @@ export declare const traeCliAgentDef: {
21
21
  mcpDiscovery: string;
22
22
  externalMcpInjection: "acp-merge";
23
23
  imageDelivery: "native";
24
+ discoverModels(requiredArgs: {
25
+ context: import("../model-discovery-types.js").ModelDiscoveryContext;
26
+ }, optionalArgs?: {
27
+ signal?: AbortSignal;
28
+ force?: boolean;
29
+ staleWhileRevalidate?: boolean;
30
+ deps?: import("../model-discovery-types.js").ModelDiscoveryDeps;
31
+ }): Promise<import("../model-discovery-types.js").ModelCatalogSnapshot>;
32
+ resolveDefaultModel(requiredArgs: {
33
+ context: import("../model-discovery-types.js").ModelDiscoveryContext;
34
+ catalog: import("../model-discovery-types.js").ModelCatalogSnapshot;
35
+ }, optionalArgs?: {
36
+ signal?: AbortSignal;
37
+ deps?: import("../model-discovery-types.js").ModelDiscoveryDeps;
38
+ }): Promise<import("../model-discovery-types.js").DefaultModelResolution>;
24
39
  };
25
40
  //# sourceMappingURL=trae-cli.d.ts.map
@@ -1,6 +1,8 @@
1
- /** Ported verbatim from OD's `apps/daemon/src/runtimes/defs/trae-cli.ts` (import path adjusted only). See `archived provenance ledger`. */
1
+ import { createAgentModelDiscovery } from '../model-discovery.js';
2
2
  import { detectAcpModels, DEFAULT_MODEL_OPTION } from './shared.js';
3
3
  export const traeCliAgentDef = {
4
+ // UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
5
+ ...createAgentModelDiscovery('trae-cli', { fallbackModels: () => traeCliAgentDef.fallbackModels }),
4
6
  id: 'trae-cli',
5
7
  name: 'Trae CLI',
6
8
  bin: 'traecli',
@@ -12,5 +12,20 @@ export declare const vibeAgentDef: {
12
12
  streamFormat: string;
13
13
  externalMcpInjection: "acp-merge";
14
14
  imageDelivery: "native";
15
+ discoverModels(requiredArgs: {
16
+ context: import("../model-discovery-types.js").ModelDiscoveryContext;
17
+ }, optionalArgs?: {
18
+ signal?: AbortSignal;
19
+ force?: boolean;
20
+ staleWhileRevalidate?: boolean;
21
+ deps?: import("../model-discovery-types.js").ModelDiscoveryDeps;
22
+ }): Promise<import("../model-discovery-types.js").ModelCatalogSnapshot>;
23
+ resolveDefaultModel(requiredArgs: {
24
+ context: import("../model-discovery-types.js").ModelDiscoveryContext;
25
+ catalog: import("../model-discovery-types.js").ModelCatalogSnapshot;
26
+ }, optionalArgs?: {
27
+ signal?: AbortSignal;
28
+ deps?: import("../model-discovery-types.js").ModelDiscoveryDeps;
29
+ }): Promise<import("../model-discovery-types.js").DefaultModelResolution>;
15
30
  };
16
31
  //# sourceMappingURL=vibe.d.ts.map
package/dist/defs/vibe.js CHANGED
@@ -1,6 +1,8 @@
1
- /** Ported verbatim from OD's `apps/daemon/src/runtimes/defs/vibe.ts` (import path adjusted only). See `archived provenance ledger`. */
1
+ import { createAgentModelDiscovery } from '../model-discovery.js';
2
2
  import { detectAcpModels, DEFAULT_MODEL_OPTION } from './shared.js';
3
3
  export const vibeAgentDef = {
4
+ // UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
5
+ ...createAgentModelDiscovery('vibe', { fallbackModels: () => vibeAgentDef.fallbackModels }),
4
6
  id: 'vibe',
5
7
  name: 'Mistral Vibe CLI',
6
8
  bin: 'vibe-acp',
@@ -1,8 +1,11 @@
1
+ import type { ModelDiscoveryContext, ModelDiscoveryDeps, ModelCatalogSnapshot, DefaultModelResolution } from './model-discovery-types.js';
1
2
  import { type AmrProfileResolver } from './amr-profile-resolver.js';
2
3
  import type { AgentDiagnostic, DetectedAgent, RuntimeAgentDef, RuntimeModelSource, RuntimeModelOption } from './types.js';
3
4
  type FetchedRuntimeModels = {
4
5
  models: RuntimeModelOption[];
5
6
  source: RuntimeModelSource;
7
+ catalog?: ModelCatalogSnapshot;
8
+ defaultModelResolution?: DefaultModelResolution;
6
9
  };
7
10
  /**
8
11
  * Makes sure `agentCapabilities` holds this def's `--help`-probed flags before its `buildArgs` runs.
@@ -44,16 +47,29 @@ export type ProbedAgentModels = FetchedRuntimeModels;
44
47
  */
45
48
  export declare function probeAgentModels({ def }: {
46
49
  def: RuntimeAgentDef;
47
- }, { configuredEnv, amrProfileResolver }?: {
50
+ }, { configuredEnv, amrProfileResolver, context, deps, force }?: {
48
51
  configuredEnv?: Record<string, string>;
49
52
  amrProfileResolver?: AmrProfileResolver;
53
+ context?: ModelDiscoveryContext;
54
+ deps?: ModelDiscoveryDeps;
55
+ force?: boolean;
50
56
  }): Promise<ProbedAgentModels>;
51
- export declare function detectAgents({}: {}, { configuredEnvByAgent, amrProfileResolver }?: {
57
+ export interface AgentDetectionModelOptions {
58
+ context?: ModelDiscoveryContext;
59
+ deps?: ModelDiscoveryDeps;
60
+ force?: boolean;
61
+ }
62
+ export declare function detectAgents({}: {}, { configuredEnvByAgent, amrProfileResolver, modelContextByAgent, modelDiscoveryDeps, force }?: {
52
63
  configuredEnvByAgent?: Record<string, Record<string, string>>;
53
64
  amrProfileResolver?: AmrProfileResolver;
54
- }): Promise<(Omit<RuntimeAgentDef, "buildArgs" | "listModels" | "fetchModels" | "deriveReasoningOptions" | "fallbackModels" | "fallbackModelsAssertedAt" | "helpArgs" | "capabilityFlags" | "fallbackBins" | "versionProbeTimeoutMs" | "maxPromptArgBytes" | "env" | "inactivityTimeoutMs" | "authProbe" | "needsAgentLogFile" | "stdoutPolicy" | "runtimeLock"> & {
65
+ modelContextByAgent?: Record<string, ModelDiscoveryContext>;
66
+ modelDiscoveryDeps?: ModelDiscoveryDeps;
67
+ force?: boolean;
68
+ }): Promise<(Omit<RuntimeAgentDef, "discoverModels" | "resolveDefaultModel" | "buildArgs" | "listModels" | "fetchModels" | "deriveReasoningOptions" | "fallbackModels" | "fallbackModelsAssertedAt" | "helpArgs" | "capabilityFlags" | "fallbackBins" | "versionProbeTimeoutMs" | "maxPromptArgBytes" | "env" | "inactivityTimeoutMs" | "authProbe" | "needsAgentLogFile" | "stdoutPolicy" | "runtimeLock"> & {
55
69
  models: RuntimeModelOption[];
56
70
  modelsSource: RuntimeModelSource;
71
+ modelCatalog?: ModelCatalogSnapshot;
72
+ defaultModelResolution?: DefaultModelResolution;
57
73
  available: boolean;
58
74
  authStatus?: "ok" | "missing" | "unknown";
59
75
  authMessage?: string;
@@ -61,9 +77,12 @@ export declare function detectAgents({}: {}, { configuredEnvByAgent, amrProfileR
61
77
  version?: string | null;
62
78
  diagnostics?: AgentDiagnostic[];
63
79
  })[]>;
64
- export declare function detectAgentsStream({}: {}, { configuredEnvByAgent, amrProfileResolver }?: {
80
+ export declare function detectAgentsStream({}: {}, { configuredEnvByAgent, amrProfileResolver, modelContextByAgent, modelDiscoveryDeps, force }?: {
65
81
  configuredEnvByAgent?: Record<string, Record<string, string>>;
66
82
  amrProfileResolver?: AmrProfileResolver;
83
+ modelContextByAgent?: Record<string, ModelDiscoveryContext>;
84
+ modelDiscoveryDeps?: ModelDiscoveryDeps;
85
+ force?: boolean;
67
86
  }): AsyncGenerator<DetectedAgent>;
68
87
  export {};
69
88
  //# sourceMappingURL=detection.d.ts.map
package/dist/detection.js CHANGED
@@ -12,7 +12,8 @@
12
12
  * `archived provenance ledger`.
13
13
  */
14
14
  import { execAgentFile } from './invocation.js';
15
- import { getRememberedLiveModels, rememberLiveModels } from './models.js';
15
+ import { offlineSnapshot, modelDiscoveryForDef } from './model-discovery.js';
16
+ import { rememberLiveModels } from './models.js';
16
17
  import { agentCapabilities } from './capabilities.js';
17
18
  import { installMetaForAgent } from './metadata.js';
18
19
  import { AGENT_DEFS } from './registry.js';
@@ -25,50 +26,23 @@ function amrModelScopeFromEnv(env, amrProfileResolver) {
25
26
  return amrProfileResolver.resolveProfile({ env: env });
26
27
  }
27
28
  function withRememberedAmrModels(def, env, modelResult, amrProfileResolver) {
28
- if (def.id !== 'amr' || modelResult.models.length > 0)
29
- return modelResult;
30
- const rememberedModels = getRememberedLiveModels({ agentId: def.id }, { scope: amrModelScopeFromEnv(env, amrProfileResolver) });
31
- if (rememberedModels.length === 0)
32
- return modelResult;
33
- return { models: rememberedModels, source: 'live' };
29
+ // The old remembered AMR list had no age/launch fingerprint. Scoped snapshots now own
30
+ // last-good recovery; never present unscoped remembered rows as live.
31
+ void def;
32
+ void env;
33
+ void amrProfileResolver;
34
+ return modelResult;
34
35
  }
35
- async function fetchModels(def, resolvedBin, env) {
36
- if (typeof def.fetchModels === 'function') {
37
- try {
38
- const parsed = await def.fetchModels({ resolvedBin: resolvedBin, env: env });
39
- if (!parsed || parsed.length === 0) {
40
- return { models: def.fallbackModels, source: 'fallback' };
41
- }
42
- return { models: parsed, source: 'live' };
43
- }
44
- catch {
45
- return { models: def.fallbackModels, source: 'fallback' };
46
- }
47
- }
48
- if (!def.listModels) {
49
- return { models: def.fallbackModels, source: 'fallback' };
50
- }
51
- try {
52
- const { stdout } = await execAgentFile({ command: resolvedBin, args: def.listModels.args }, { options: {
53
- env,
54
- timeout: def.listModels.timeoutMs,
55
- // Models lists from popular CLIs (e.g. opencode) easily exceed the
56
- // default 1MB buffer once you include every openrouter model. Bump
57
- // it so we don't truncate the listing.
58
- maxBuffer: 8 * 1024 * 1024,
59
- } });
60
- const parsed = def.listModels.parse({ stdout: String(stdout) });
61
- // Empty / null parse result means the CLI didn't actually return a
62
- // usable list (e.g. cursor-agent's "No models available"); fall back
63
- // to the static hint so the picker isn't stuck on Default-only.
64
- if (!parsed || parsed.length === 0) {
65
- return { models: def.fallbackModels, source: 'fallback' };
66
- }
67
- return { models: parsed, source: 'live' };
68
- }
69
- catch {
70
- return { models: def.fallbackModels, source: 'fallback' };
71
- }
36
+ async function fetchModels(def, resolvedBin, env, optional = {}) {
37
+ const context = optional.context ?? { executable: resolvedBin, env, cwd: optional.cwd ?? process.cwd(), ...(optional.version !== undefined ? { version: optional.version } : {}) };
38
+ const options = { ...(optional.deps ? { deps: optional.deps } : {}), ...(optional.force ? { force: true } : {}) };
39
+ const discovery = modelDiscoveryForDef(def);
40
+ const catalog = await discovery.discoverModels({ context }, options);
41
+ const defaultModelResolution = await discovery.resolveDefaultModel({ context, catalog }, options);
42
+ // Models lists can exceed 1MB (e.g. opencode's OpenRouter catalog); the shared process port
43
+ // retains the existing 8MB bound. Empty/unusable metadata falls back with explicit provenance,
44
+ // so a failed CLI never silently empties the picker or labels packaged hints as live.
45
+ return { models: catalog.models, source: catalog.freshness === 'fresh' ? 'live' : 'fallback', catalog, defaultModelResolution };
72
46
  }
73
47
  /**
74
48
  * Run the agent's `--version` probe and classify the result. The probe
@@ -124,7 +98,9 @@ function unavailableAgent(def, diagnostics = []) {
124
98
  ...stripFns(def),
125
99
  // `fallbackModels` is a required field on `RuntimeAgentDef`, never
126
100
  // `undefined` for a well-typed def.
127
- models: def.fallbackModels,
101
+ models: offlineSnapshot('', Date.now(), def.fallbackModels).models,
102
+ modelCatalog: offlineSnapshot('', Date.now(), def.fallbackModels),
103
+ defaultModelResolution: { status: 'unresolved', reason: 'Agent executable is unavailable.' },
128
104
  modelsSource: 'fallback',
129
105
  available: false,
130
106
  ...(diagnostics.length > 0 ? { diagnostics } : {}),
@@ -213,6 +189,10 @@ function derivedReasoningOverride(def, models) {
213
189
  function probeEnvForLaunch(def, configuredEnv, launch) {
214
190
  return applyAgentLaunchEnv({ env: spawnEnvForAgent({ agentId: def.id, baseEnv: { ...process.env, ...(def.env || {}) } }, { configuredEnv: configuredEnv, hooks: {} }), launch: launch });
215
191
  }
192
+ function unavailableModels(def) {
193
+ const catalog = offlineSnapshot('', Date.now(), def.fallbackModels);
194
+ return { models: catalog.models, source: 'fallback', catalog, defaultModelResolution: { status: 'unresolved', reason: 'Agent executable is unavailable.' } };
195
+ }
216
196
  /**
217
197
  * The model half of {@link detectAgents} for ONE def, without the `--version`/`--help`/auth probes:
218
198
  * resolves the launch path, builds the same probe env, runs the def's `fetchModels`/`listModels`,
@@ -225,22 +205,22 @@ function probeEnvForLaunch(def, configuredEnv, launch) {
225
205
  * `source: 'fallback'` (including when the binary is not found). Never rejects.
226
206
  * @complexity At most one model-listing spawn, bounded by the def's own timeout.
227
207
  */
228
- export async function probeAgentModels({ def }, { configuredEnv = {}, amrProfileResolver = noopAmrProfileResolver } = {}) {
208
+ export async function probeAgentModels({ def }, { configuredEnv = {}, amrProfileResolver = noopAmrProfileResolver, context, deps, force = false } = {}) {
229
209
  try {
230
210
  const launch = resolveAgentLaunch({ def: def }, { configuredEnv: configuredEnv });
231
211
  if (!launch.launchPath)
232
- return { models: def.fallbackModels, source: 'fallback' };
212
+ return unavailableModels(def);
233
213
  const probeEnv = probeEnvForLaunch(def, configuredEnv, launch);
234
- const fetched = await fetchModels(def, launch.launchPath, probeEnv);
214
+ const fetched = await fetchModels(def, launch.launchPath, probeEnv, { ...(context ? { context } : {}), ...(deps ? { deps } : {}), force });
235
215
  const result = withRememberedAmrModels(def, probeEnv, fetched, amrProfileResolver);
236
216
  rememberDetectedModelList(def, configuredEnv, result.models, amrProfileResolver);
237
217
  return result;
238
218
  }
239
219
  catch {
240
- return { models: def.fallbackModels, source: 'fallback' };
220
+ return unavailableModels(def);
241
221
  }
242
222
  }
243
- async function probe(def, configuredEnv = {}, amrProfileResolver) {
223
+ async function probe(def, configuredEnv = {}, amrProfileResolver, options = {}) {
244
224
  // Detection must probe the exact path the runtime will spawn, not just
245
225
  // the PATH-visible shim. This is load-bearing under nvm/fnm/mise: the
246
226
  // discovered entry is often a `#!/usr/bin/env node` wrapper that is not
@@ -265,7 +245,7 @@ async function probe(def, configuredEnv = {}, amrProfileResolver) {
265
245
  // cached on `agentCapabilities` for buildArgs to consult.
266
246
  const [caps, modelResult, auth] = await Promise.all([
267
247
  probeCapabilities(def, launch.launchPath, probeEnv),
268
- fetchModels(def, launch.launchPath, probeEnv),
248
+ fetchModels(def, launch.launchPath, probeEnv, { version: outcome.version, ...options }),
269
249
  probeAgentAuthStatus({ def: def, resolvedBin: launch.launchPath, env: probeEnv }),
270
250
  ]);
271
251
  const surfacedModelResult = withRememberedAmrModels(def, probeEnv, modelResult, amrProfileResolver);
@@ -278,6 +258,8 @@ async function probe(def, configuredEnv = {}, amrProfileResolver) {
278
258
  ...derivedReasoningOverride(def, surfacedModelResult.models),
279
259
  models: surfacedModelResult.models,
280
260
  modelsSource: surfacedModelResult.source,
261
+ ...(surfacedModelResult.catalog ? { modelCatalog: surfacedModelResult.catalog } : {}),
262
+ ...(surfacedModelResult.defaultModelResolution ? { defaultModelResolution: surfacedModelResult.defaultModelResolution } : {}),
281
263
  available: true,
282
264
  path: launch.selectedPath,
283
265
  version: outcome.version,
@@ -305,12 +287,12 @@ function stripFns(def) {
305
287
  // matter extra because they carry closures — `JSON.stringify` would drop
306
288
  // the functions but keep their enclosing objects, publishing a misleading
307
289
  // `{"buffering":"until-close"}` / `{}` instead of omitting them.
308
- const { 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;
290
+ 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;
309
291
  return rest;
310
292
  }
311
- async function safeProbe(def, configuredEnv = {}, amrProfileResolver) {
293
+ async function safeProbe(def, configuredEnv = {}, amrProfileResolver, options = {}) {
312
294
  try {
313
- return await probe(def, configuredEnv, amrProfileResolver);
295
+ return await probe(def, configuredEnv, amrProfileResolver, options);
314
296
  }
315
297
  catch {
316
298
  // Fault isolation: one adapter's probe blowing up — e.g. a
@@ -329,10 +311,10 @@ function rememberDetectedModelList(def, configuredEnv, models, amrProfileResolve
329
311
  const scope = def.id === 'amr'
330
312
  ? amrModelScopeFromEnv({ ...process.env, ...(def.env || {}), ...configuredEnv }, amrProfileResolver)
331
313
  : null;
332
- rememberLiveModels({ agentId: def.id, models: models }, { scope: scope });
314
+ rememberLiveModels({ agentId: def.id, models: models.filter((row) => row.identityKind !== 'routing-mode') }, { scope: scope });
333
315
  }
334
- export async function detectAgents({}, { configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver } = {}) {
335
- const results = await Promise.all(AGENT_DEFS.map((def) => safeProbe(def, configuredEnvByAgent?.[def.id] ?? {}, amrProfileResolver)));
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] } : {}), ...(modelDiscoveryDeps ? { deps: modelDiscoveryDeps } : {}), force })));
336
318
  // Refresh the validation cache from whatever we just surfaced to the UI
337
319
  // so a chat endpoint can accept any model the user could have just
338
320
  // picked, including ones that only showed up after a CLI re-auth.
@@ -351,8 +333,8 @@ export async function detectAgents({}, { configuredEnvByAgent = {}, amrProfileRe
351
333
  // validation cache is refreshed per-agent (same effect as the batch path,
352
334
  // just incrementally). `detectAgents` keeps the array contract for callers
353
335
  // that don't care about incremental delivery.
354
- export async function* detectAgentsStream({}, { configuredEnvByAgent = {}, amrProfileResolver = noopAmrProfileResolver } = {}) {
355
- const tagged = AGENT_DEFS.map((def, index) => safeProbe(def, configuredEnvByAgent?.[def.id] ?? {}, amrProfileResolver).then((agent) => {
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] } : {}), ...(modelDiscoveryDeps ? { deps: modelDiscoveryDeps } : {}), force }).then((agent) => {
356
338
  rememberDetectedLiveModels(def, configuredEnvByAgent?.[def.id] ?? {}, agent, amrProfileResolver);
357
339
  return { index, agent };
358
340
  }));
@@ -1,14 +1,6 @@
1
1
  /**
2
2
  * @module diagnostics
3
- *
4
- * Builds the `AgentDiagnostic` explaining why a CLI isn't invocable, for
5
- * the three failure classes detection distinguishes: not resolvable at
6
- * all, resolved but not invocable, and invocable but not authenticated.
7
- *
8
- * Ported verbatim from OD's
9
- * `apps/daemon/src/runtimes/detection/diagnostics.ts`, with `AgentDiagnostic`
10
- * / `AgentFixIntent` now imported from this package's own `types.ts`
11
- * (vendored from OD's contracts workspace package, not a dependency on it).
3
+ * Explain three detection failures: unresolved executable, uninvocable executable or missing authentication.
12
4
  */
13
5
  import { agentBinEnvKey, agentSearchDirs } from './executables.js';
14
6
  // Cap on how many searched dirs we attach to a `not-on-path` diagnostic.
package/dist/env.js CHANGED
@@ -1,36 +1,10 @@
1
1
  /**
2
2
  * @module env
3
- *
4
- * Builds the environment passed to `spawn()` for a given agent adapter:
5
- * proxy-aware merge of the inherited launch env with per-agent configured
6
- * overrides, plus a couple of per-CLI housekeeping tweaks (OpenCode/MiMo
7
- * project-config-discovery, which would otherwise walk up from cwd and run
8
- * an install step that can corrupt a pnpm workspace it's spawned inside).
9
- *
10
- * Heavily de-branded from OD's `apps/daemon/src/runtimes/env.ts`. The
11
- * origin file was far more coupled than r1b's "supporting generic file"
12
- * classification anticipated — it read OD's own app-config subsystem, OD's
13
- * sandbox-mode subsystem, and vela/AMR-specific env forwarding including a
14
- * literal product-name identity value and two product-prefixed env var
15
- * names (see `archived provenance ledger` for the exact originals). None of that is
16
- * ported:
17
- *
18
- * - `mergeProxyAwareEnv` / `resolveSystemProxyEnv` now come from
19
- * `@jini-ai/platform` (the same functions, already verbatim-lifted there).
20
- * - AMR/vela-specific env injection and OD's app-config-driven analytics
21
- * identity env are replaced by an optional `perAgentEnv` hook — a plain
22
- * `(agentId, env) => NodeJS.ProcessEnv | void` the host can supply to add
23
- * its own per-agent env logic (vela profile forwarding, analytics ids,
24
- * …) without this package needing to know about vela or app-config.
25
- * - Sandbox-mode env application is replaced by an optional
26
- * `sandboxOverlay` hook with the same shape, for the same reason.
27
- * - OD's AMR trace-env helper (emitting a product-prefixed run-id/attempt/
28
- * session-id triad) is dropped entirely — it is OD/vela-adapter-owned
29
- * trace-correlation env, not a generic runtime concern, and its own name
30
- * was itself product-branded. A host that needs equivalent trace
31
- * correlation can build it as a `perAgentEnv` hook.
32
- *
33
- * See `archived provenance ledger` for the full accounting.
3
+ * Build proxy-aware spawn environment from inherited and per-agent configured values. Disable
4
+ * OpenCode/MiMo project-config discovery so an automatic install cannot corrupt the host workspace.
5
+ * The shared platform helpers own proxy merging. Host-specific profile forwarding, analytics
6
+ * identity and trace correlation enter through perAgentEnv; sandbox wiring enters through
7
+ * sandboxOverlay. The engine must not import a product's config/sandbox subsystems or env names.
34
8
  */
35
9
  import os from 'node:os';
36
10
  import { mergeProxyAwareEnv, resolveSystemProxyEnv } from '@jini-ai/platform';
@@ -39,7 +39,6 @@ const AGENT_BIN_ENV_KEYS = new Map([
39
39
  ['deepseek', 'DEEPSEEK_BIN'],
40
40
  ['devin', 'DEVIN_BIN'],
41
41
  ['droid', 'DROID_BIN'],
42
- ['gemini', 'GEMINI_BIN'],
43
42
  ['goose', 'GOOSE_BIN'],
44
43
  ['hermes', 'HERMES_BIN'],
45
44
  ['kimi', 'KIMI_BIN'],