@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
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.4.3 — 2026-10-08
2
+
3
+ - Desktop 0.1.13 release fixes: see commits a2659d24 (admin), 5695a7c3 (chat, agent-runtime), 8ad4ac5c (devops).
4
+
5
+ ## 0.4.2 — 2026-10-08
6
+
7
+ - Tovu clean-up release: code Tovu moved into Jini, plus the Jini clean-up (see the commit log).
8
+
1
9
  ## 0.4.1 — 2026-10-06
2
10
 
3
11
  - Tool turns accept message `images` (`{ mimeType, data }`) and deliver them to providers as image content.
@@ -1,30 +1,9 @@
1
1
  /**
2
2
  * @module acp-model-probe
3
- *
4
- * Port replacing OD's `detectAcpModels` import
5
- * (`apps/daemon/src/acp.js`) inside `defs/shared.ts`. Eight of this
6
- * package's def literals (devin, hermes, kilo, kimi, kiro, reasonix,
7
- * trae-cli, vibe) fetch their live model list by speaking a session/new →
8
- * session/list_models-shaped ACP JSON-RPC handshake to the spawned CLI.
9
- *
10
- * That handshake lives in OD's `acp.ts` (1744 lines) — the full ACP
11
- * subprocess transport, which r1's recon classifies as its own separate
12
- * GENERIC-ENGINE zone (`agent-protocol/`, 17 files) and a *later*
13
- * extraction task, not this one. Porting it here would blow this task's
14
- * scope far past "harvest wholesale" for what is genuinely a large,
15
- * separate subsystem.
16
- *
17
- * So `detectAcpModels` becomes an injectable port: an `AcpModelProbe` with
18
- * a single `detectModels(requiredArgs, optionalArgs)` method, matching the real call shape
19
- * every ACP-based def literal already uses. The default implementation is
20
- * a no-op that resolves to `[]`, which makes `detection.ts`'s `fetchModels`
21
- * step treat the live-fetch as "returned nothing" and fall back to the
22
- * def's static `fallbackModels` — the same behavior OD gets when the vela
23
- * probe times out or errors. A future task that ports the ACP transport
24
- * (or the OD adapter, sooner) calls `setAcpModelProbe()` once at startup to
25
- * wire in the real implementation; every def literal that calls
26
- * `detectAcpModels(...)` picks it up automatically, no per-def changes
27
- * needed.
3
+ * Replaceable live-model probe for ACP-based runtime defs. The default uses the native,
4
+ * prompt-free initialize/session-new handshake; setAcpModelProbe installs a host implementation
5
+ * and null restores native transport. noopAcpModelProbe is an explicit opt-out that returns no
6
+ * live models, allowing detection to fall back to the def's static catalog.
28
7
  */
29
8
  import type { RuntimeEnv, RuntimeModelOption } from './types.js';
30
9
  export interface AcpModelProbeRequest {
@@ -41,10 +20,10 @@ export interface AcpModelProbe {
41
20
  detectModels(requiredArgs: Pick<AcpModelProbeRequest, 'bin' | 'args'>, optionalArgs?: Omit<AcpModelProbeRequest, 'bin' | 'args'>): Promise<RuntimeModelOption[]>;
42
21
  }
43
22
  export declare const noopAcpModelProbe: AcpModelProbe;
44
- /** Install the real ACP transport (or a test double). Pass `null` to restore the no-op default. */
23
+ /** Install a transport/test double. Pass `null` to restore the native transport. */
45
24
  export declare function setAcpModelProbe({ probe }: {
46
25
  probe: AcpModelProbe | null;
47
26
  }): void;
48
- /** Drop-in replacement for OD's `detectAcpModels` — delegates to whatever probe is currently installed. */
27
+ /** Delegate to the currently installed probe. */
49
28
  export declare function detectAcpModels(requiredArgs: Pick<AcpModelProbeRequest, "bin" | "args">, optionalArgs?: Omit<AcpModelProbeRequest, "bin" | "args">): Promise<RuntimeModelOption[]>;
50
29
  //# sourceMappingURL=acp-model-probe.d.ts.map
@@ -1,14 +1,16 @@
1
+ import { detectAcpModels as probeNativeModels } from './agent-protocol/acp/models.js';
1
2
  export const noopAcpModelProbe = {
2
3
  async detectModels() {
3
4
  return [];
4
5
  },
5
6
  };
6
- let activeAcpModelProbe = noopAcpModelProbe;
7
- /** Install the real ACP transport (or a test double). Pass `null` to restore the no-op default. */
7
+ const nativeAcpModelProbe = { detectModels: (required, optional = {}) => probeNativeModels(required, { ...optional, ...(optional.env ? { env: optional.env } : {}) }) };
8
+ let activeAcpModelProbe = nativeAcpModelProbe;
9
+ /** Install a transport/test double. Pass `null` to restore the native transport. */
8
10
  export function setAcpModelProbe({ probe }) {
9
- activeAcpModelProbe = probe ?? noopAcpModelProbe;
11
+ activeAcpModelProbe = probe ?? nativeAcpModelProbe;
10
12
  }
11
- /** Drop-in replacement for OD's `detectAcpModels` — delegates to whatever probe is currently installed. */
13
+ /** Delegate to the currently installed probe. */
12
14
  export async function detectAcpModels(requiredArgs, optionalArgs = {}) {
13
15
  return activeAcpModelProbe.detectModels(requiredArgs, optionalArgs);
14
16
  }
@@ -20,6 +20,8 @@ export interface DetectAcpModelsOptions {
20
20
  clientName?: string;
21
21
  clientVersion?: string;
22
22
  defaultModelOption?: ModelOption;
23
+ signal?: AbortSignal;
24
+ onSessionResult?: (result: UnknownRecord) => void;
23
25
  }
24
26
  /**
25
27
  * Normalises a raw config-option field value to a lowercase, whitespace- and
@@ -114,4 +116,10 @@ export declare function currentModelFromSessionResult(result: UnknownRecord): st
114
116
  * @returns A promise resolving to the available `ModelOption[]`.
115
117
  */
116
118
  export declare function detectAcpModels(requiredArgs: Pick<DetectAcpModelsOptions, "bin" | "args">, optionalArgs?: Omit<DetectAcpModelsOptions, "bin" | "args">): Promise<ModelOption[]>;
119
+ /** Retains native current selection. Session creation can write CLI state/start services;
120
+ * this metadata probe never sends session/prompt. The old array API remains compatible. */
121
+ export declare function detectAcpModelMetadata(requiredArgs: Pick<DetectAcpModelsOptions, 'bin' | 'args'>, optionalArgs?: Omit<DetectAcpModelsOptions, 'bin' | 'args'>): Promise<{
122
+ models: ModelOption[];
123
+ currentModelId: string | null;
124
+ }>;
117
125
  //# sourceMappingURL=models.d.ts.map
@@ -191,7 +191,7 @@ export function currentModelFromSessionResult(result) {
191
191
  * @returns A promise resolving to the available `ModelOption[]`.
192
192
  */
193
193
  export async function detectAcpModels(requiredArgs, optionalArgs = {}) {
194
- const { bin, args, cwd = process.cwd(), env = process.env, timeoutMs = DEFAULT_TIMEOUT_MS, clientName = 'agent-runtime-detect', clientVersion = 'runtime-adapter', defaultModelOption = { id: 'default', label: 'Default (CLI config)' }, } = { ...optionalArgs, ...requiredArgs };
194
+ const { bin, args, cwd = process.cwd(), env = process.env, timeoutMs = DEFAULT_TIMEOUT_MS, clientName = 'agent-runtime-detect', clientVersion = 'runtime-adapter', defaultModelOption = { id: 'default', label: 'Default (CLI config)' }, signal, onSessionResult, } = { ...optionalArgs, ...requiredArgs };
195
195
  const effectiveTimeoutMs = resolveAcpTimeoutMs(env, timeoutMs);
196
196
  return await new Promise((resolve, reject) => {
197
197
  const child = spawn(bin, args, {
@@ -203,6 +203,7 @@ export async function detectAcpModels(requiredArgs, optionalArgs = {}) {
203
203
  child.stderr.setEncoding('utf8');
204
204
  let settled = false;
205
205
  let stderrBuf = '';
206
+ let stdoutBytes = 0;
206
207
  let expectedId = 1;
207
208
  let nextId = 2;
208
209
  let timer = null;
@@ -212,17 +213,27 @@ export async function detectAcpModels(requiredArgs, optionalArgs = {}) {
212
213
  settled = true;
213
214
  if (timer)
214
215
  clearTimeout(timer);
216
+ signal?.removeEventListener('abort', abort);
215
217
  try {
216
218
  child.stdin.end();
217
219
  }
218
220
  catch { }
221
+ if (!child.killed)
222
+ child.kill('SIGTERM');
223
+ const killTimer = setTimeout(() => { if (child.exitCode === null)
224
+ child.kill('SIGKILL'); }, 250);
225
+ killTimer.unref();
219
226
  fn(value);
220
227
  };
221
228
  const fail = (message) => {
222
229
  finish(reject, new Error(message));
223
- if (!child.killed)
224
- child.kill('SIGTERM');
225
230
  };
231
+ const abort = () => fail('ACP model detection aborted');
232
+ signal?.addEventListener('abort', abort, { once: true });
233
+ if (signal?.aborted) {
234
+ abort();
235
+ return;
236
+ }
226
237
  const writeRpc = (id, method, params) => {
227
238
  try {
228
239
  sendRpc(child.stdin, id, method, params);
@@ -258,13 +269,19 @@ export async function detectAcpModels(requiredArgs, optionalArgs = {}) {
258
269
  return;
259
270
  }
260
271
  if (expectedId === 2) {
272
+ onSessionResult?.(result);
261
273
  const models = normalizeModels({ models: result.models, defaultModelOption: defaultModelOption }, { configOptions: result.configOptions });
262
274
  finish(resolve, models);
263
- if (!child.killed)
264
- child.kill('SIGTERM');
265
275
  }
266
276
  } });
267
- child.stdout.on('data', (chunk) => parser.feed({ chunk: chunk }));
277
+ child.stdout.on('data', (chunk) => {
278
+ stdoutBytes += Buffer.byteLength(String(chunk), 'utf8');
279
+ if (stdoutBytes > 8 * 1024 * 1024) {
280
+ fail('ACP metadata output exceeded its limit');
281
+ return;
282
+ }
283
+ parser.feed({ chunk: chunk });
284
+ });
268
285
  child.stdout.on('close', () => parser.flush());
269
286
  child.stdin.on('error', (err) => fail(`stdin error: ${err.message}`));
270
287
  child.stderr.on('data', (chunk) => {
@@ -291,4 +308,19 @@ export async function detectAcpModels(requiredArgs, optionalArgs = {}) {
291
308
  });
292
309
  });
293
310
  }
311
+ /** Retains native current selection. Session creation can write CLI state/start services;
312
+ * this metadata probe never sends session/prompt. The old array API remains compatible. */
313
+ export async function detectAcpModelMetadata(requiredArgs, optionalArgs = {}) {
314
+ let currentModelId = null;
315
+ const models = await detectAcpModels(requiredArgs, { ...optionalArgs, onSessionResult: (result) => {
316
+ currentModelId = currentModelFromSessionResult(result);
317
+ optionalArgs.onSessionResult?.(result);
318
+ } });
319
+ return { models: models.filter((model) => model.id !== 'default').map((model) => {
320
+ const label = model.label.replace(/ • current$/, '');
321
+ const suffix = ` (${model.id})`;
322
+ // Remove only our ID annotation; native display-name capability suffixes are meaningful.
323
+ return { ...model, label: label.endsWith(suffix) ? label.slice(0, -suffix.length) : label };
324
+ }), currentModelId };
325
+ }
294
326
  //# sourceMappingURL=models.js.map
@@ -72,7 +72,8 @@ function resolveModelConfigId(modelConfig) {
72
72
  export function handleRpcError({ state, effects, obj, error, rpcErr, }) {
73
73
  if (obj.id === state.setModelRequestId &&
74
74
  modelSelectionErrorIsRecoverable(error?.code) &&
75
- state.promptRequestId === null) {
75
+ state.promptRequestId === null &&
76
+ (!effects.model || effects.model === 'default')) {
76
77
  effects.recoverFromModelSelectionError();
77
78
  return;
78
79
  }
@@ -299,6 +300,13 @@ export function handleToolCallUpdate({ state, effects, update, }) {
299
300
  }
300
301
  /** Top-level `session/update` dispatcher: emits a generic status for non-streaming update kinds, then routes to the matching per-kind handler. */
301
302
  export function handleSessionUpdate({ state, effects, update, }) {
303
+ // Model/config updates are authoritative protocol metadata, not assistant self-report.
304
+ const changedModel = currentModelFromSessionResult(update)
305
+ ?? (update.sessionUpdate === 'current_model_update' && typeof update.currentModelId === 'string' ? update.currentModelId : null);
306
+ if (changedModel && changedModel !== state.activeModel) {
307
+ state.activeModel = changedModel;
308
+ effects.send({ event: 'agent', payload: { type: 'status', label: 'model', model: changedModel } });
309
+ }
302
310
  if (effects.modelUnavailableErrorCode && tryPromoteAmrRetryStatus({ effects, update }))
303
311
  return;
304
312
  if (update.sessionUpdate !== 'agent_message_chunk' && update.sessionUpdate !== 'agent_thought_chunk') {
@@ -337,6 +345,11 @@ export function handleInitializeAck({ state, effects }) {
337
345
  export function triggerSetModelIfNeeded({ state, effects, }) {
338
346
  if (!state.sessionId || !effects.model || effects.model === 'default')
339
347
  return false;
348
+ // Hosts now pin the concrete starting model on every run. When session/new already reports that
349
+ // model, a set_model round-trip is redundant, and a CLI without set_model support would turn it
350
+ // into a fatal explicit-model rejection.
351
+ if (state.activeModel === effects.model)
352
+ return false;
340
353
  state.setModelRequestId = state.nextId;
341
354
  state.expectedId = state.nextId;
342
355
  const setModelMethod = state.modelConfigId ? 'session/set_config_option' : 'session/set_model';
@@ -357,7 +370,7 @@ export function handleSessionNewAck({ state, effects, result, rawLine, }) {
357
370
  notifySessionInit(effects);
358
371
  state.modelConfigId = resolveModelConfigId(findModelConfigOption(result.configOptions));
359
372
  state.activeModel = currentModelFromSessionResult(result);
360
- if (state.sessionId && state.activeModel) {
373
+ if (state.sessionId && state.activeModel && (!effects.model || effects.model === state.activeModel)) {
361
374
  effects.send({ event: 'agent', payload: { type: 'status', label: 'model', model: state.activeModel } });
362
375
  }
363
376
  if (triggerSetModelIfNeeded({ state, effects }))
@@ -197,6 +197,10 @@ const PI_RPC_EVENT_HANDLERS = {
197
197
  * @returns `'agent_end'` on run completion, `null` otherwise.
198
198
  */
199
199
  export function mapPiRpcEvent({ raw, send, ctx }) {
200
+ const message = getRecord(raw.message);
201
+ if (message?.role === 'assistant' && typeof message.model === 'string' && typeof message.provider === 'string') {
202
+ send({ event: 'agent', payload: { type: 'status', label: 'model', model: `${message.provider}/${message.model}` } });
203
+ }
200
204
  const handler = typeof raw.type === 'string' ? PI_RPC_EVENT_HANDLERS[raw.type] : undefined;
201
205
  return handler ? handler(raw, send, ctx) : null;
202
206
  }
@@ -1,17 +1,7 @@
1
1
  /**
2
2
  * @module amr-model-cache
3
- *
4
- * A live-model-catalog cache that returns a cached remote list instantly
5
- * while refreshing in the background, falling back to a static preset
6
- * list on cold start. Ported verbatim from OD's
7
- * `apps/daemon/src/runtimes/amr/amr-model-cache.ts` with one change: the
8
- * `AmrModelsResponse` return type is now vendored locally (a small,
9
- * self-contained shape) instead of imported from OD's contracts workspace
10
- * package.
11
- *
12
- * Named for its origin use (the AMR/vela agent's live model list), but the
13
- * caching pattern itself is generic to any agent with a similarly-shaped
14
- * "cheap static preset + slower authoritative remote list" catalog.
3
+ * Return cached remote models while refreshing, with static presets on cold start. This caching
4
+ * pattern also serves other agents with cheap presets and slower authoritative remote catalogs.
15
5
  */
16
6
  import type { RuntimeModelOption } from './types.js';
17
7
  export type AmrModelsResponse = {
@@ -1,17 +1,6 @@
1
- /**
2
- * @module amr-profile-resolver
3
- *
4
- * Port replacing OD's `resolveAmrProfile` import
5
- * (`apps/daemon/src/integrations/vela.js`) inside `detection.ts`. OD uses
6
- * this to scope the remembered-live-models cache for the `amr` agent id by
7
- * "profile" — an AMR/vela-vendor concept (which OpenRouter-compatible
8
- * account/link config is active) that has no generic runtime meaning.
9
- *
10
- * `detection.ts` accepts an `AmrProfileResolver` and calls it only for the
11
- * `amr` def id; every other agent's scoping is unaffected. The default
12
- * no-op resolver returns a constant scope (equivalent to "no profile
13
- * scoping"), so a non-OD consumer's AMR-model cache degrades gracefully —
14
- * it just doesn't split by profile — until it supplies a real resolver.
1
+ /** @module amr-profile-resolver
2
+ * Profile scoping is an AMR/vela account/link concept, not a generic runtime rule. detection.ts
3
+ * consults this host port only for amr; the default constant scope leaves its cache unsplit.
15
4
  */
16
5
  export interface AmrProfileResolver {
17
6
  /** Return a scope key for the `amr` agent's remembered-live-models cache, derived from the spawn env. */
@@ -41,5 +41,5 @@ export declare function mergeLiveModels(fallback: readonly RuntimeModelOption[],
41
41
  * @complexity O(1) plus, at most, one cached outbound HTTPS call bounded by
42
42
  * {@link LIVE_MODEL_TIMEOUT_MS}.
43
43
  */
44
- export declare function loadAnthropicLiveModels(env: RuntimeEnv, fallbackModels: readonly RuntimeModelOption[], now?: () => number): Promise<RuntimeModelOption[] | null>;
44
+ export declare function loadAnthropicLiveModels(env: RuntimeEnv, _fallbackModels: readonly RuntimeModelOption[], now?: () => number): Promise<RuntimeModelOption[] | null>;
45
45
  //# sourceMappingURL=anthropic-live-models.d.ts.map
Binary file
@@ -1,20 +1,6 @@
1
- /**
2
- * @module artifact-taxonomy
3
- *
4
- * Port replacing the classification half of OD's
5
- * `runtimes/runs/run-artifacts.ts` (`isArtifactPath`, `isDesignSystemFile`,
6
- * `isPreviewModulePath`, `didRunCreateDesignSystemFile`,
7
- * `countDesignSystemPreviewModules`). That file's real behavior is entirely
8
- * OD-product classification (HTML-prototype/SVG/design-system-file
9
- * taxonomy feeding PostHog `run_finished.artifact_count` /
10
- * `design_system_created` analytics) plus OD-specific imports into OD's own
11
- * analytics-contracts and question-form-detection modules — none of it is
12
- * ported.
13
- *
14
- * Per r1b §1b, only the taxonomy/classification *interface* belongs to
15
- * this package. `ArtifactTaxonomy`'s companion `ArtifactStore` (actual
16
- * read/write persistence) is explicitly a later storage/sqlite task's
17
- * concern — not defined here.
1
+ /** @module artifact-taxonomy
2
+ * Hosts define artifact classification and opaque analytics buckets; product file-kind taxonomy
3
+ * cannot enter the runtime. Artifact persistence belongs to ArtifactStore, not this classifier.
18
4
  */
19
5
  export interface ArtifactTaxonomy {
20
6
  /** Does this file path count as a user-facing artifact? (OD: html/svg/prototype/live-artifact.) */
package/dist/auth.d.ts CHANGED
@@ -23,9 +23,6 @@ export declare function reasonixAuthGuidance({}: {}, { hostName }?: {
23
23
  export declare function claudeAuthGuidance({}: {}, { hostName }?: {
24
24
  hostName?: string;
25
25
  }): string;
26
- export declare function geminiAuthGuidance({}: {}, { hostName }?: {
27
- hostName?: string;
28
- }): string;
29
26
  export declare function isCursorAuthFailureText({ text }: {
30
27
  text: string;
31
28
  }): boolean;
@@ -41,9 +38,6 @@ export declare function isReasonixAuthFailureText({ text }: {
41
38
  export declare function isClaudeAuthFailureText({ text }: {
42
39
  text: string;
43
40
  }): boolean;
44
- export declare function isGeminiAuthFailureText({ text }: {
45
- text: string;
46
- }): boolean;
47
41
  export declare function classifyAgentAuthFailure({ agentId, text }: {
48
42
  agentId: string;
49
43
  text: string;
package/dist/auth.js CHANGED
@@ -55,17 +55,6 @@ function reasonixAuthGuidanceText(hostName) {
55
55
  function claudeAuthGuidanceText(hostName) {
56
56
  return `Claude Code is installed but is not authenticated. Run \`claude auth login\` or open \`claude\` and complete login in a terminal, then rescan. If ${hostName} was launched outside an interactive shell, your shell rc files (e.g. ~/.zshrc) may not be loaded into its environment.`;
57
57
  }
58
- // Gemini CLI has two distinct sign-in failures, and one fix covers both. With no auth method
59
- // configured, headless mode exits with "Please set an Auth method in your <settings.json> or
60
- // specify one of the following environment variables before running: GEMINI_API_KEY,
61
- // GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_GENAI_USE_GCA". With "Login with Google" on a free / Google AI
62
- // Pro / Ultra account it dies with `IneligibleTierError: This client is no longer supported for
63
- // Gemini Code Assist for individuals` (Google stopped serving those tiers on 2026-06-18; API keys,
64
- // Vertex AI and Code Assist licenses still work). Signing in again cannot fix the second one, so
65
- // the guidance points at an API key or Antigravity instead of a re-login.
66
- function geminiAuthGuidanceText(hostName) {
67
- return `Gemini CLI is installed but has no usable sign-in. Google no longer serves Gemini CLI's "Login with Google" for free, Google AI Pro or Ultra accounts. Use a Gemini API key instead: run \`gemini\` in a terminal, type /auth, choose "Use Gemini API key", and make GEMINI_API_KEY available to ${hostName}'s process environment (or configure Vertex AI). Google's replacement for individual accounts is Antigravity (\`agy\`), which you can pick here instead.`;
68
- }
69
58
  export function cursorAuthGuidance({}, { hostName = DEFAULT_HOST_NAME } = {}) {
70
59
  return cursorAuthGuidanceText(hostName);
71
60
  }
@@ -84,9 +73,6 @@ export function reasonixAuthGuidance({}, { hostName = DEFAULT_HOST_NAME } = {})
84
73
  export function claudeAuthGuidance({}, { hostName = DEFAULT_HOST_NAME } = {}) {
85
74
  return claudeAuthGuidanceText(hostName);
86
75
  }
87
- export function geminiAuthGuidance({}, { hostName = DEFAULT_HOST_NAME } = {}) {
88
- return geminiAuthGuidanceText(hostName);
89
- }
90
76
  export function isCursorAuthFailureText({ text }) {
91
77
  const value = String(text || '');
92
78
  if (!value.trim())
@@ -159,16 +145,6 @@ export function isClaudeAuthFailureText({ text }) {
159
145
  /authentication required/i.test(value) ||
160
146
  /please (?:sign|log)[ _-]?in/i.test(value));
161
147
  }
162
- export function isGeminiAuthFailureText({ text }) {
163
- const value = String(text || '');
164
- if (!value.trim())
165
- return false;
166
- return (/please set an auth method/i.test(value) ||
167
- /IneligibleTierError/.test(value) ||
168
- /no longer supported for gemini code assist/i.test(value) ||
169
- /error authenticating/i.test(value) ||
170
- /api key not valid/i.test(value));
171
- }
172
148
  export function classifyAgentAuthFailure({ agentId, text }, { hostName = DEFAULT_HOST_NAME } = {}) {
173
149
  if (agentId === 'claude') {
174
150
  if (!isClaudeAuthFailureText({ text: text }))
@@ -195,11 +171,6 @@ export function classifyAgentAuthFailure({ agentId, text }, { hostName = DEFAULT
195
171
  return null;
196
172
  return { status: 'missing', message: reasonixAuthGuidance({}, { hostName: hostName }) };
197
173
  }
198
- if (agentId === 'gemini') {
199
- if (!isGeminiAuthFailureText({ text: text }))
200
- return null;
201
- return { status: 'missing', message: geminiAuthGuidance({}, { hostName: hostName }) };
202
- }
203
174
  return null;
204
175
  }
205
176
  // A bare HTTP status number (`500`, `429`, …) is too noisy to trust on its own
@@ -279,7 +250,7 @@ function genericAuthGuidance(agentName, hostName) {
279
250
  // regex (e.g. cursor-agent's healthy `status` output mentions "login" in
280
251
  // ways the generic matcher would misread). The generic classifier is only a
281
252
  // fallback for adapters with no tailored classifier of their own.
282
- const TAILORED_AUTH_AGENTS = new Set(['claude', 'cursor-agent', 'deepseek', 'antigravity', 'reasonix', 'gemini']);
253
+ const TAILORED_AUTH_AGENTS = new Set(['claude', 'cursor-agent', 'deepseek', 'antigravity', 'reasonix']);
283
254
  function hasNonEmptyEnv(env, keys) {
284
255
  return keys.some((key) => {
285
256
  const value = env[key];
@@ -49,15 +49,14 @@ export interface ClaudeCodeModelIo {
49
49
  /** Test-only: install fake I/O (or `null` to restore the real one) and clear the process cache. */
50
50
  export declare function setClaudeCodeModelIoForTesting(io: ClaudeCodeModelIo | null): void;
51
51
  /**
52
- * Returns the `claude` model list with the CLI's own picker catalog merged in, or `null` when there
53
- * is nothing to merge. Needs no API key.
52
+ * Returns the `claude` model list from the CLI's own picker catalog, or `null` when discovery fails. Needs no API key.
54
53
  *
55
54
  * @param bin - The resolved `claude` (or fork) binary detection found.
56
55
  * @param env - The composed environment for the agent — what a spawn would actually see.
57
- * @param fallbackModels - The def's static list; always fully present, in order, in a non-null result.
56
+ * @param _fallbackModels - Compatibility argument; packaged rows are offline fallback only.
58
57
  * @param now - Injectable clock for TTL tests.
59
58
  * @complexity O(f + l) plus, at most once per {@link CLAUDE_CODE_MODEL_CACHE_TTL_MS} per cache key,
60
59
  * one CLI spawn bounded by {@link CLAUDE_CODE_INIT_TIMEOUT_MS} and one file read.
61
60
  */
62
- export declare function loadClaudeCodeModels(bin: string, env: RuntimeEnv, fallbackModels: readonly RuntimeModelOption[], now?: () => number): Promise<RuntimeModelOption[] | null>;
61
+ export declare function loadClaudeCodeModels(bin: string, env: RuntimeEnv, _fallbackModels: readonly RuntimeModelOption[], now?: () => number): Promise<RuntimeModelOption[] | null>;
63
62
  //# sourceMappingURL=claude-code-models.d.ts.map
@@ -27,7 +27,7 @@
27
27
  * older CLI without the control protocol, a fork bin (`openclaude`), a timeout.
28
28
  *
29
29
  * **Enrichment, never a gate.** Every failure resolves to `null` ("nothing to add"), and a non-null
30
- * result is always `mergeLiveModels(fallback, live)` — the static list is fully present, in order.
30
+ * result contains only discovered rows. Packaged fallback rows are kept separate by the snapshot layer.
31
31
  *
32
32
  * The cache-file parser ({@link parseClaudeCodePickerCache}) is shared with
33
33
  * `scripts/check-model-fallback-freshness.ts` so the freshness guard and the runtime can never
@@ -39,7 +39,6 @@ import { readFile } from 'node:fs/promises';
39
39
  import os from 'node:os';
40
40
  import { join } from 'node:path';
41
41
  import { createCommandInvocation } from '@jini-ai/platform';
42
- import { mergeLiveModels } from './anthropic-live-models.js';
43
42
  import { sanitizeCustomModel } from './models.js';
44
43
  /** A spawn costs ~2.5s and the picker list only moves when Claude Code updates or the server's
45
44
  * "additional" options change, so one answer is trusted for this long per process. Failures are
@@ -229,17 +228,16 @@ async function discoverClaudeCodeModels(bin, env) {
229
228
  }
230
229
  }
231
230
  /**
232
- * Returns the `claude` model list with the CLI's own picker catalog merged in, or `null` when there
233
- * is nothing to merge. Needs no API key.
231
+ * Returns the `claude` model list from the CLI's own picker catalog, or `null` when discovery fails. Needs no API key.
234
232
  *
235
233
  * @param bin - The resolved `claude` (or fork) binary detection found.
236
234
  * @param env - The composed environment for the agent — what a spawn would actually see.
237
- * @param fallbackModels - The def's static list; always fully present, in order, in a non-null result.
235
+ * @param _fallbackModels - Compatibility argument; packaged rows are offline fallback only.
238
236
  * @param now - Injectable clock for TTL tests.
239
237
  * @complexity O(f + l) plus, at most once per {@link CLAUDE_CODE_MODEL_CACHE_TTL_MS} per cache key,
240
238
  * one CLI spawn bounded by {@link CLAUDE_CODE_INIT_TIMEOUT_MS} and one file read.
241
239
  */
242
- export async function loadClaudeCodeModels(bin, env, fallbackModels, now = Date.now) {
240
+ export async function loadClaudeCodeModels(bin, env, _fallbackModels, now = Date.now) {
243
241
  const key = cacheKeyFor(bin, env);
244
242
  const cached = cache.get(key);
245
243
  const pending = cached && cached.expiresAt > now() ? cached.value : null;
@@ -247,6 +245,6 @@ export async function loadClaudeCodeModels(bin, env, fallbackModels, now = Date.
247
245
  if (!pending)
248
246
  cache.set(key, { expiresAt: now() + CLAUDE_CODE_MODEL_CACHE_TTL_MS, value });
249
247
  const live = await value;
250
- return live && live.length > 0 ? mergeLiveModels(fallbackModels, live) : null;
248
+ return live && live.length > 0 ? [...live] : null;
251
249
  }
252
250
  //# sourceMappingURL=claude-code-models.js.map
@@ -1,10 +1,6 @@
1
1
  /**
2
2
  * @module claude-stream
3
3
  *
4
- * Ported verbatim from OD's `apps/daemon/src/runtimes/claude-stream.ts`
5
- * (only the `role-marker-guard` import path changed — it now resolves
6
- * within this package instead of two directories up). See `archived provenance ledger`.
7
- *
8
4
  * Parses Claude Code's `--output-format stream-json --verbose` JSONL stream
9
5
  * (with or without `--include-partial-messages`) into a small set of
10
6
  * UI-friendly events. With partial messages on, text arrives as
@@ -1,10 +1,6 @@
1
1
  /**
2
2
  * @module claude-stream
3
3
  *
4
- * Ported verbatim from OD's `apps/daemon/src/runtimes/claude-stream.ts`
5
- * (only the `role-marker-guard` import path changed — it now resolves
6
- * within this package instead of two directories up). See `archived provenance ledger`.
7
- *
8
4
  * Parses Claude Code's `--output-format stream-json --verbose` JSONL stream
9
5
  * (with or without `--include-partial-messages`) into a small set of
10
6
  * UI-friendly events. With partial messages on, text arrives as
@@ -626,6 +622,8 @@ export function createClaudeStreamHandler({ onEvent }, options = {}) {
626
622
  const message = obj.message;
627
623
  if (!isRecord(message) || !Array.isArray(message.content))
628
624
  return;
625
+ if (typeof message.model === 'string')
626
+ onEvent({ type: 'status', label: 'model', model: message.model });
629
627
  const { textMsgId, thinkingMsgId, textAlreadyStreamed, thinkingAlreadyStreamed } = resolveAssistantMessageIds(message);
630
628
  // Per-turn `stop_reason` is emitted as `turn_end` AFTER the content
631
629
  // blocks have been processed (see below). When `--include-partial-
@@ -695,6 +693,8 @@ export function createClaudeStreamHandler({ onEvent }, options = {}) {
695
693
  }
696
694
  }
697
695
  function handleMessageStart(ev) {
696
+ if (isRecord(ev.message) && typeof ev.message.model === 'string')
697
+ onEvent({ type: 'status', label: 'model', model: ev.message.model });
698
698
  flushPendingArtifactText();
699
699
  // Clean up per-message role-marker guard from the previous message.
700
700
  if (currentMessageId)
@@ -1,11 +1,6 @@
1
1
  /**
2
2
  * @module copilot-stream
3
3
  *
4
- * Ported verbatim from OD's top-level `apps/daemon/src/copilot-stream.ts`
5
- * (relocated under `runtimes/` in Jini's daemon per r1's recon; grouped
6
- * with the other stream parsers here). Self-contained — no imports, no
7
- * product coupling. See `archived provenance ledger`.
8
- *
9
4
  * Parses GitHub Copilot CLI's `--output-format json` JSONL stream into the
10
5
  * same UI-friendly events that claude-stream.js emits, so the chat panel
11
6
  * can render Copilot's thinking / tool calls / text the same way it does
@@ -1,11 +1,6 @@
1
1
  /**
2
2
  * @module copilot-stream
3
3
  *
4
- * Ported verbatim from OD's top-level `apps/daemon/src/copilot-stream.ts`
5
- * (relocated under `runtimes/` in Jini's daemon per r1's recon; grouped
6
- * with the other stream parsers here). Self-contained — no imports, no
7
- * product coupling. See `archived provenance ledger`.
8
- *
9
4
  * Parses GitHub Copilot CLI's `--output-format json` JSONL stream into the
10
5
  * same UI-friendly events that claude-stream.js emits, so the chat panel
11
6
  * can render Copilot's thinking / tool calls / text the same way it does
@@ -17,5 +17,20 @@ export declare const aiderAgentDef: {
17
17
  streamFormat: string;
18
18
  installUrl: string;
19
19
  docsUrl: string;
20
+ discoverModels(requiredArgs: {
21
+ context: import("../model-discovery-types.js").ModelDiscoveryContext;
22
+ }, optionalArgs?: {
23
+ signal?: AbortSignal;
24
+ force?: boolean;
25
+ staleWhileRevalidate?: boolean;
26
+ deps?: import("../model-discovery-types.js").ModelDiscoveryDeps;
27
+ }): Promise<import("../model-discovery-types.js").ModelCatalogSnapshot>;
28
+ resolveDefaultModel(requiredArgs: {
29
+ context: import("../model-discovery-types.js").ModelDiscoveryContext;
30
+ catalog: import("../model-discovery-types.js").ModelCatalogSnapshot;
31
+ }, optionalArgs?: {
32
+ signal?: AbortSignal;
33
+ deps?: import("../model-discovery-types.js").ModelDiscoveryDeps;
34
+ }): Promise<import("../model-discovery-types.js").DefaultModelResolution>;
20
35
  };
21
36
  //# sourceMappingURL=aider.d.ts.map
@@ -1,6 +1,8 @@
1
- /** Ported from OD's `apps/daemon/src/runtimes/defs/aider.ts` (one de-branded comment; see `archived provenance ledger`). */
1
+ import { createAgentModelDiscovery } from '../model-discovery.js';
2
2
  import { DEFAULT_MODEL_OPTION } from './shared.js';
3
3
  export const aiderAgentDef = {
4
+ // UNVERIFIED live integration locally; source/category and limits are documented in model-discovery-adapters.ts.
5
+ ...createAgentModelDiscovery('aider', { fallbackModels: () => aiderAgentDef.fallbackModels }),
4
6
  id: 'aider',
5
7
  name: 'Aider',
6
8
  bin: 'aider',
@@ -30,7 +32,7 @@ export const aiderAgentDef = {
30
32
  // Aider's one-shot mode requires the prompt as `--message <text>` on
31
33
  // argv; neither `--message` nor `--message-file` accept `-` as a stdin
32
34
  // sentinel (it is treated as a literal filename), so we cannot pipe
33
- // the prompt in the way qwen/gemini do. Mirror the DeepSeek TUI
35
+ // the prompt in the way qwen does. Mirror the DeepSeek TUI
34
36
  // pattern: ship the prompt as argv with a conservative byte budget so
35
37
  // the /api/chat spawn path emits an actionable error before hitting
36
38
  // Windows' ~32 KB CreateProcess limit or Linux MAX_ARG_STRLEN.
@@ -5,6 +5,7 @@ export declare const ampAgentDef: {
5
5
  versionArgs: string[];
6
6
  fallbackModels: import("../types.js").RuntimeModelOption[];
7
7
  supportsCustomModel: false;
8
+ supportsConcreteModelSelection: false;
8
9
  buildArgs: ({ prompt: _prompt, imagePaths: _imagePaths }: {
9
10
  prompt: string;
10
11
  imagePaths: string[];
@@ -15,5 +16,20 @@ export declare const ampAgentDef: {
15
16
  } | undefined) => string[];
16
17
  promptViaStdin: true;
17
18
  streamFormat: string;
19
+ discoverModels(requiredArgs: {
20
+ context: import("../model-discovery-types.js").ModelDiscoveryContext;
21
+ }, optionalArgs?: {
22
+ signal?: AbortSignal;
23
+ force?: boolean;
24
+ staleWhileRevalidate?: boolean;
25
+ deps?: import("../model-discovery-types.js").ModelDiscoveryDeps;
26
+ }): Promise<import("../model-discovery-types.js").ModelCatalogSnapshot>;
27
+ resolveDefaultModel(requiredArgs: {
28
+ context: import("../model-discovery-types.js").ModelDiscoveryContext;
29
+ catalog: import("../model-discovery-types.js").ModelCatalogSnapshot;
30
+ }, optionalArgs?: {
31
+ signal?: AbortSignal;
32
+ deps?: import("../model-discovery-types.js").ModelDiscoveryDeps;
33
+ }): Promise<import("../model-discovery-types.js").DefaultModelResolution>;
18
34
  };
19
35
  //# sourceMappingURL=amp.d.ts.map