@jini-ai/agent-runtime 0.4.4 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/agent-protocol/acp/models.d.ts +11 -0
  3. package/dist/agent-protocol/acp/models.js +12 -3
  4. package/dist/capabilities.d.ts +1 -8
  5. package/dist/capabilities.js +8 -1
  6. package/dist/claude-code-models.d.ts +13 -1
  7. package/dist/claude-code-models.js +15 -17
  8. package/dist/claude-segment-usage.d.ts +9 -2
  9. package/dist/claude-segment-usage.js +20 -4
  10. package/dist/claude-stream.d.ts +4 -0
  11. package/dist/claude-stream.js +5 -1
  12. package/dist/defs/aider.js +1 -1
  13. package/dist/defs/amp.js +1 -1
  14. package/dist/defs/amr.js +1 -1
  15. package/dist/defs/antigravity.js +1 -1
  16. package/dist/defs/auggie.js +1 -1
  17. package/dist/defs/claude.d.ts +2 -0
  18. package/dist/defs/claude.js +11 -3
  19. package/dist/defs/cline.js +1 -1
  20. package/dist/defs/codebuddy.js +2 -2
  21. package/dist/defs/codex.js +1 -1
  22. package/dist/defs/copilot.js +1 -1
  23. package/dist/defs/crush.js +1 -1
  24. package/dist/defs/cursor-agent.js +2 -2
  25. package/dist/defs/deepseek.js +1 -1
  26. package/dist/defs/devin.js +1 -1
  27. package/dist/defs/droid.js +1 -1
  28. package/dist/defs/goose.js +1 -1
  29. package/dist/defs/grok-build.js +1 -1
  30. package/dist/defs/hermes.js +1 -1
  31. package/dist/defs/kilo.js +1 -1
  32. package/dist/defs/kimi.js +1 -1
  33. package/dist/defs/kiro.js +1 -1
  34. package/dist/defs/mimo.js +1 -1
  35. package/dist/defs/opencode.js +2 -2
  36. package/dist/defs/pi.js +1 -1
  37. package/dist/defs/qoder.js +1 -1
  38. package/dist/defs/qwen.js +1 -1
  39. package/dist/defs/reasonix.js +1 -1
  40. package/dist/defs/trae-cli.js +1 -1
  41. package/dist/defs/vibe.js +1 -1
  42. package/dist/detection.d.ts +28 -4
  43. package/dist/detection.js +82 -43
  44. package/dist/diagnostics.d.ts +6 -1
  45. package/dist/diagnostics.js +2 -2
  46. package/dist/env.js +1 -1
  47. package/dist/executables.d.ts +15 -9
  48. package/dist/executables.js +73 -65
  49. package/dist/index.d.ts +3 -2
  50. package/dist/index.js +3 -2
  51. package/dist/invocation.d.ts +24 -2
  52. package/dist/invocation.js +19 -7
  53. package/dist/launch.d.ts +2 -1
  54. package/dist/launch.js +2 -2
  55. package/dist/model-discovery-adapters.d.ts +6 -2
  56. package/dist/model-discovery-adapters.js +64 -51
  57. package/dist/model-discovery-native.d.ts +14 -0
  58. package/dist/model-discovery-native.js +22 -0
  59. package/dist/model-discovery-sdk.js +1 -1
  60. package/dist/model-discovery-shared.d.ts +14 -0
  61. package/dist/model-discovery-shared.js +53 -0
  62. package/dist/model-discovery-types.d.ts +26 -0
  63. package/dist/model-discovery.d.ts +17 -22
  64. package/dist/model-discovery.js +18 -69
  65. package/dist/models.d.ts +9 -4
  66. package/dist/models.js +11 -11
  67. package/dist/probe-scheduler.d.ts +19 -0
  68. package/dist/probe-scheduler.js +30 -0
  69. package/dist/runtime-state.d.ts +41 -0
  70. package/dist/runtime-state.js +31 -0
  71. package/dist/types.d.ts +4 -0
  72. package/package.json +36 -9
package/dist/models.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { defaultRuntimeState } from './runtime-state.js';
1
2
  export const DEFAULT_MODEL_OPTION = {
2
3
  id: 'default',
3
4
  label: 'Default (CLI config)',
@@ -7,33 +8,32 @@ export const DEFAULT_MODEL_OPTION = {
7
8
  // recent live list (refreshed every detectAgents() call) and additionally
8
9
  // trust any value present in the static fallback. A model that's neither
9
10
  // gets rejected so a stale or hostile value can't smuggle arbitrary flags.
10
- const liveModelCache = new Map();
11
- const liveModelOrder = new Map();
11
+ // Host state carries these maps; legacy callers use defaultRuntimeState.
12
12
  function liveModelCacheKey(agentId, scope) {
13
13
  const trimmedScope = typeof scope === 'string' ? scope.trim() : '';
14
14
  return trimmedScope ? `${agentId}\0${trimmedScope}` : agentId;
15
15
  }
16
- export function rememberLiveModels({ agentId, models }, { scope } = {}) {
16
+ export function rememberLiveModels({ agentId, models }, { scope, state = defaultRuntimeState } = {}) {
17
17
  if (!Array.isArray(models))
18
18
  return;
19
19
  const ids = models
20
20
  .map((m) => m && m.id)
21
21
  .filter((id) => typeof id === 'string');
22
22
  const key = liveModelCacheKey(agentId, scope);
23
- liveModelCache.set(key, new Set(ids));
24
- liveModelOrder.set(key, ids);
23
+ state.liveModelCache.set(key, new Set(ids));
24
+ state.liveModelOrder.set(key, ids);
25
25
  }
26
- export function getRememberedLiveModels({ agentId }, { scope } = {}) {
27
- const ids = liveModelOrder.get(liveModelCacheKey(agentId, scope)) ?? [];
26
+ export function getRememberedLiveModels({ agentId }, { scope, state = defaultRuntimeState } = {}) {
27
+ const ids = state.liveModelOrder.get(liveModelCacheKey(agentId, scope)) ?? [];
28
28
  return ids.map((id) => ({ id, label: id }));
29
29
  }
30
30
  export function preferFreshLiveModels({ freshModels, rememberedModels }) {
31
31
  return freshModels.length > 0 ? freshModels : rememberedModels;
32
32
  }
33
- export function isKnownModel({ def, modelId }, { scope } = {}) {
33
+ export function isKnownModel({ def, modelId }, { scope, state = defaultRuntimeState } = {}) {
34
34
  if (!modelId)
35
35
  return false;
36
- const live = liveModelCache.get(liveModelCacheKey(def.id, scope));
36
+ const live = state.liveModelCache.get(liveModelCacheKey(def.id, scope));
37
37
  if (live && live.has(modelId))
38
38
  return true;
39
39
  if (Array.isArray(def.fallbackModels)) {
@@ -49,7 +49,7 @@ export function isKnownModel({ def, modelId }, { scope } = {}) {
49
49
  // surfaced to the UI, then fall back to the def's first concrete fallback
50
50
  // id so the spawn layer always has a real model to forward. Defs that DO
51
51
  // list 'default' (the common case) are left untouched.
52
- export function resolveModelForAgent({ def, resolved }, { env = process.env, liveModelScope } = {}) {
52
+ export function resolveModelForAgent({ def, resolved }, { env = process.env, liveModelScope, state = defaultRuntimeState } = {}) {
53
53
  if (resolved && resolved !== 'default')
54
54
  return resolved;
55
55
  // Host-process env override. Lets an operator pin a different fallback
@@ -66,7 +66,7 @@ export function resolveModelForAgent({ def, resolved }, { env = process.env, liv
66
66
  const fallbacks = def.fallbackModels;
67
67
  if (fallbacks.some((m) => m.id === 'default'))
68
68
  return resolved;
69
- const liveModels = liveModelOrder.get(liveModelCacheKey(def.id, liveModelScope)) ?? [];
69
+ const liveModels = state.liveModelOrder.get(liveModelCacheKey(def.id, liveModelScope)) ?? [];
70
70
  const firstLive = liveModels[0];
71
71
  if (firstLive)
72
72
  return firstLive;
@@ -0,0 +1,19 @@
1
+ type Priority = 'version' | 'metadata';
2
+ /** All metadata process adapters share one process-wide slot. Version checks precede queued
3
+ * metadata, so expensive discovery cannot delay cheap availability checks. Actual chat runs
4
+ * never use this queue. A slot is held until the child adapter settles, including cancellation.
5
+ * @complexity O(q) queued selection, bounded by the runtime registry's probe count. */
6
+ export declare function createProbeScheduler(_input: Record<string, never>, _options?: Record<string, never>): <T>({ work }: {
7
+ work: () => Promise<T>;
8
+ }, { priority, signal }?: {
9
+ priority?: Priority;
10
+ signal?: AbortSignal | undefined;
11
+ }) => Promise<T>;
12
+ export declare const scheduleProbeProcess: <T>({ work }: {
13
+ work: () => Promise<T>;
14
+ }, { priority, signal }?: {
15
+ priority?: Priority;
16
+ signal?: AbortSignal | undefined;
17
+ }) => Promise<T>;
18
+ export {};
19
+ //# sourceMappingURL=probe-scheduler.d.ts.map
@@ -0,0 +1,30 @@
1
+ /** All metadata process adapters share one process-wide slot. Version checks precede queued
2
+ * metadata, so expensive discovery cannot delay cheap availability checks. Actual chat runs
3
+ * never use this queue. A slot is held until the child adapter settles, including cancellation.
4
+ * @complexity O(q) queued selection, bounded by the runtime registry's probe count. */
5
+ export function createProbeScheduler(_input, _options = {}) {
6
+ const queue = [];
7
+ let running = false;
8
+ function drain() {
9
+ if (running || !queue.length)
10
+ return;
11
+ const version = queue.findIndex(entry => entry.priority === 'version');
12
+ const entry = queue.splice(version < 0 ? 0 : version, 1)[0];
13
+ running = true;
14
+ entry.start();
15
+ }
16
+ return function schedule({ work }, { priority = 'metadata', signal } = {}) {
17
+ return new Promise((resolve, reject) => {
18
+ queue.push({ priority, start: () => {
19
+ Promise.resolve().then(() => {
20
+ if (signal?.aborted)
21
+ throw new Error('Probe cancelled');
22
+ return work();
23
+ }).then(resolve, reject).finally(() => { running = false; drain(); });
24
+ } });
25
+ drain();
26
+ });
27
+ };
28
+ }
29
+ export const scheduleProbeProcess = createProbeScheduler({});
30
+ //# sourceMappingURL=probe-scheduler.js.map
@@ -0,0 +1,41 @@
1
+ /** Mutable runtime data belongs to one host. Compatibility functions use defaultRuntimeState. */
2
+ import type { RuntimeAgentDef, RuntimeCapabilityMap, RuntimeModelOption, DetectedAgent } from './types.js';
3
+ import type { ModelCacheEntry, ModelDiscoveryDeps } from './model-discovery-types.js';
4
+ export interface AgentRuntimeState {
5
+ /** One in-flight or settled complete detection per launch scope until explicit Rescan. */
6
+ readonly detections: Map<string, Promise<DetectedAgent>>;
7
+ readonly capabilities: Map<string, RuntimeCapabilityMap>;
8
+ /** One in-flight or settled `--help` probe per def id + launch path, so a run never re-spawns it. */
9
+ readonly capabilityProbes: Map<string, Promise<void>>;
10
+ readonly liveModelCache: Map<string, Set<string>>;
11
+ readonly liveModelOrder: Map<string, string[]>;
12
+ readonly claudeModels: Map<string, {
13
+ expiresAt: number;
14
+ value: Promise<readonly RuntimeModelOption[] | null>;
15
+ }>;
16
+ discoveryDeps?: ModelDiscoveryDeps;
17
+ readonly modelCatalog: Map<string, ModelCacheEntry>;
18
+ readonly executable: {
19
+ /** Env var names consulted by detection-home/resource-root resolution. Overridable via `configureExecutableResolutionEnv`. */
20
+ envNames: {
21
+ agentHomeEnvVar: string;
22
+ resourceRootEnvVar: string;
23
+ };
24
+ toolchainKey: string | null;
25
+ toolchainDirs: string[] | null;
26
+ toolchainDirsAt: number;
27
+ };
28
+ /** Clear settled caches after host operations finish; retain its configured env names. */
29
+ clear(required: Record<string, never>, optional: Record<string, never>): void;
30
+ }
31
+ /** Independent state, including in-flight probes, for each embedding host.
32
+ * Returns empty owned maps; no I/O. @complexity O(1) initialization; retained data grows with probes. */
33
+ export declare function createAgentRuntimeState(_required: Record<string, never>, _optional?: Record<string, never>): AgentRuntimeState;
34
+ export declare const defaultRuntimeState: AgentRuntimeState;
35
+ /** Bind the agent argument builder to the same capability state detection and launch use.
36
+ * Returns a definition copy without mutating the registry. @complexity O(1). */
37
+ export declare function bindRuntimeAgentDef({ def, state }: {
38
+ def: RuntimeAgentDef;
39
+ state: AgentRuntimeState;
40
+ }, _optional?: Record<string, never>): RuntimeAgentDef;
41
+ //# sourceMappingURL=runtime-state.d.ts.map
@@ -0,0 +1,31 @@
1
+ /** Independent state, including in-flight probes, for each embedding host.
2
+ * Returns empty owned maps; no I/O. @complexity O(1) initialization; retained data grows with probes. */
3
+ export function createAgentRuntimeState(_required, _optional = {}) {
4
+ const state = {
5
+ detections: new Map(), capabilities: new Map(), capabilityProbes: new Map(), liveModelCache: new Map(), liveModelOrder: new Map(),
6
+ claudeModels: new Map(), modelCatalog: new Map(),
7
+ executable: { envNames: { agentHomeEnvVar: 'AGENT_RUNTIME_HOME', resourceRootEnvVar: 'AGENT_RUNTIME_RESOURCE_ROOT' }, toolchainKey: null, toolchainDirs: null, toolchainDirsAt: 0 },
8
+ clear() {
9
+ state.detections.clear();
10
+ state.capabilities.clear();
11
+ state.capabilityProbes.clear();
12
+ state.liveModelCache.clear();
13
+ state.liveModelOrder.clear();
14
+ state.claudeModels.clear();
15
+ state.modelCatalog.clear();
16
+ state.executable.toolchainKey = null;
17
+ state.executable.toolchainDirs = null;
18
+ state.executable.toolchainDirsAt = 0;
19
+ },
20
+ };
21
+ return state;
22
+ }
23
+ export const defaultRuntimeState = createAgentRuntimeState({});
24
+ /** Bind the agent argument builder to the same capability state detection and launch use.
25
+ * Returns a definition copy without mutating the registry. @complexity O(1). */
26
+ export function bindRuntimeAgentDef({ def, state }, _optional = {}) {
27
+ return { ...def, buildArgs: (required, optional = {}) => def.buildArgs(required, {
28
+ ...optional, options: { ...optional.options, capabilities: state.capabilities.get(def.id) ?? {} },
29
+ }) };
30
+ }
31
+ //# sourceMappingURL=runtime-state.js.map
package/dist/types.d.ts CHANGED
@@ -75,6 +75,8 @@ export type RuntimeReasoningInModelId = {
75
75
  levels: readonly RuntimeReasoningOption[];
76
76
  };
77
77
  export type RuntimeBuildOptions = {
78
+ /** Host-scoped capability flags; absent retains the published compatibility cache. */
79
+ capabilities?: RuntimeCapabilityMap;
78
80
  model?: string | null;
79
81
  reasoning?: string | null;
80
82
  permissionMode?: 'bypass' | 'restricted';
@@ -291,6 +293,8 @@ export type RuntimeAgentDef = Partial<AgentModelDiscoveryPort> & {
291
293
  runtimeContext?: RuntimeContext;
292
294
  }) => string[];
293
295
  streamFormat: string;
296
+ /** Reported money spans a session or one run; absent preserves per-run adapter behavior. */
297
+ usageCostBasis?: 'session' | 'run';
294
298
  fallbackBins?: string[];
295
299
  versionProbeTimeoutMs?: number;
296
300
  helpArgs?: string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/agent-runtime",
3
- "version": "0.4.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,20 +99,25 @@
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.1",
81
- "@jini-ai/platform": "^0.5.2",
82
- "@jini-ai/protocol": "^0.4.3"
102
+ "@jini-ai/integrations": "^0.4.2",
103
+ "@jini-ai/platform": "^0.5.5",
104
+ "@jini-ai/protocol": "^0.4.4",
105
+ "@jini-ai/oauth": "^0.2.2"
83
106
  },
84
107
  "dependencies": {
85
- "@jini-ai/core": "^0.4.2"
108
+ "@jini-ai/core": "^0.4.4"
86
109
  },
87
110
  "peerDependencies": {
111
+ "@jini-ai/integrations": "^0.4.2",
88
112
  "@github/copilot-sdk": "*",
89
- "@jini-ai/oauth": "^0.2.0",
90
- "@jini-ai/platform": "^0.5.1",
91
- "@jini-ai/protocol": "^0.4.1"
113
+ "@jini-ai/oauth": "^0.2.2",
114
+ "@jini-ai/platform": "^0.5.5",
115
+ "@jini-ai/protocol": "^0.4.4"
92
116
  },
93
117
  "peerDependenciesMeta": {
118
+ "@jini-ai/integrations": {
119
+ "optional": true
120
+ },
94
121
  "@github/copilot-sdk": {
95
122
  "optional": true
96
123
  },