@jini-ai/agent-runtime 0.3.9 → 0.3.10

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.
@@ -14,6 +14,7 @@ export declare const claudeAgentDef: {
14
14
  '--add-dir': string;
15
15
  '--effort': string;
16
16
  '--append-system-prompt': string;
17
+ '--setting-sources': string;
17
18
  };
18
19
  fallbackModels: import("../types.js").RuntimeModelOption[];
19
20
  fallbackModelsAssertedAt: string;
@@ -27,6 +28,9 @@ export declare const claudeAgentDef: {
27
28
  promptInputFormat: "stream-json";
28
29
  streamFormat: string;
29
30
  externalMcpInjection: "claude-mcp-json";
31
+ env: {
32
+ ENABLE_TOOL_SEARCH: string;
33
+ };
30
34
  systemPromptDelivery: {
31
35
  strategy: "append-flag";
32
36
  flag: string;
@@ -108,6 +108,7 @@ export const claudeAgentDef = {
108
108
  '--add-dir': 'addDir',
109
109
  '--effort': 'effort',
110
110
  '--append-system-prompt': 'appendSystemPrompt',
111
+ '--setting-sources': 'settingSources',
111
112
  },
112
113
  // `claude` has no list-models subcommand, so the model list is answered from the best source
113
114
  // available, in this order:
@@ -238,6 +239,15 @@ export const claudeAgentDef = {
238
239
  if (options.allowedTools && options.allowedTools.length > 0) {
239
240
  args.push('--allowedTools', ...options.allowedTools);
240
241
  }
242
+ // See `RuntimeBuildOptions.settingSources`. Probe-gated like `--effort`: an older build
243
+ // rejects an unknown option with exit 1, which would kill the chat rather than degrade it.
244
+ if (options.settingSources !== undefined && caps.settingSources) {
245
+ args.push('--setting-sources', options.settingSources.join(','));
246
+ }
247
+ // See `RuntimeBuildOptions.settings`. Not probe-gated: `--settings` long predates `--setting-sources`.
248
+ if (options.settings) {
249
+ args.push('--settings', options.settings);
250
+ }
241
251
  return args;
242
252
  },
243
253
  promptViaStdin: true,
@@ -247,6 +257,14 @@ export const claudeAgentDef = {
247
257
  // so the daemon writes the user's external MCP servers there before
248
258
  // launching (server.ts handles the cwd guard).
249
259
  externalMcpInjection: 'claude-mcp-json',
260
+ // Load MCP tools up front instead of deferring them behind the CLI's ToolSearch tool.
261
+ // Deferral cost every run one extra model round (a `select:` ToolSearch call, ~3 s) before its
262
+ // first real tool call, while the run's MCP set is only what the daemon stages
263
+ // (`--strict-mcp-config`; 11 tools for the Tovu host), so loading it eagerly is cheap. Documented at
264
+ // code.claude.com/docs/en/mcp ("`false` — All MCP tools loaded upfront, no deferral"); verified
265
+ // in the installed 2.1.283 binary (a defined-falsy value selects the "standard" tool mode).
266
+ // A default only: a run's own env can still set ENABLE_TOOL_SEARCH (see agent-executor).
267
+ env: { ENABLE_TOOL_SEARCH: 'false' },
250
268
  // Formerly inline in `buildArgs` above (see the comment there) — moved to the declarative
251
269
  // shape every def now uses to receive `RuntimeBuildOptions.systemPromptOverlay`. Same flag,
252
270
  // same probe gate (`capabilityFlags['--append-system-prompt']` above), same "append, never
@@ -4,6 +4,26 @@ type FetchedRuntimeModels = {
4
4
  models: RuntimeModelOption[];
5
5
  source: RuntimeModelSource;
6
6
  };
7
+ /**
8
+ * Makes sure `agentCapabilities` holds this def's `--help`-probed flags before its `buildArgs` runs.
9
+ *
10
+ * Why this exists: `agentCapabilities` used to be filled ONLY by {@link detectAgents}. A host whose
11
+ * run process never calls `detectAgents` (it lists agents with its own lighter probe, or not at
12
+ * all) left the map empty for every run, so every probe-gated flag stayed off for good — for
13
+ * `claude` that meant no `--include-partial-messages` (no streamed text) and no `--effort`, even on
14
+ * a CLI that supports both. The run path calls this with the exact launch path and env it is about
15
+ * to spawn, so the gate reflects the binary that actually runs.
16
+ *
17
+ * A no-op when the def declares no probe or the map already has an entry (a `detectAgents` result
18
+ * wins). Probes once per def id + launch path for the life of the process. A failed probe records
19
+ * nothing, which keeps the safe baseline (no optional flags), and is not retried on every run.
20
+ *
21
+ * @param def - The def about to be spawned.
22
+ * @param launchPath - The resolved executable the run will spawn.
23
+ * @param env - The env the run will spawn with.
24
+ * @complexity O(1) after the first call per def + path; the first call costs one `--help` spawn (5 s cap).
25
+ */
26
+ export declare function ensureAgentCapabilities(def: RuntimeAgentDef, launchPath: string, env: NodeJS.ProcessEnv): Promise<void>;
7
27
  /** Result of {@link probeAgentModels}: the models to surface and where they came from. */
8
28
  export type ProbedAgentModels = FetchedRuntimeModels;
9
29
  /**
package/dist/detection.js CHANGED
@@ -140,12 +140,7 @@ async function probeCapabilities(def, launchPath, env) {
140
140
  if (!def.helpArgs || !def.capabilityFlags)
141
141
  return null;
142
142
  try {
143
- const { stdout } = await execAgentFile(launchPath, def.helpArgs, { env, timeout: 5000, maxBuffer: 4 * 1024 * 1024 });
144
- const caps = {};
145
- for (const [flag, key] of Object.entries(def.capabilityFlags)) {
146
- caps[key] = String(stdout).includes(flag);
147
- }
148
- return caps;
143
+ return await readCapabilities(def.helpArgs, def.capabilityFlags, launchPath, env);
149
144
  }
150
145
  catch {
151
146
  // If --help fails, leave caps empty so buildArgs falls back to the
@@ -153,6 +148,51 @@ async function probeCapabilities(def, launchPath, env) {
153
148
  return {};
154
149
  }
155
150
  }
151
+ /** Runs the def's `--help` probe and maps each advertised flag to its capability key; throws on a failed probe. */
152
+ async function readCapabilities(helpArgs, capabilityFlags, launchPath, env) {
153
+ const { stdout } = await execAgentFile(launchPath, [...helpArgs], { env, timeout: 5000, maxBuffer: 4 * 1024 * 1024 });
154
+ const caps = {};
155
+ for (const [flag, key] of Object.entries(capabilityFlags)) {
156
+ caps[key] = String(stdout).includes(flag);
157
+ }
158
+ return caps;
159
+ }
160
+ /** One in-flight or settled `--help` probe per def id + launch path, so a run never re-spawns it. */
161
+ const capabilityProbes = new Map();
162
+ /**
163
+ * Makes sure `agentCapabilities` holds this def's `--help`-probed flags before its `buildArgs` runs.
164
+ *
165
+ * Why this exists: `agentCapabilities` used to be filled ONLY by {@link detectAgents}. A host whose
166
+ * run process never calls `detectAgents` (it lists agents with its own lighter probe, or not at
167
+ * all) left the map empty for every run, so every probe-gated flag stayed off for good — for
168
+ * `claude` that meant no `--include-partial-messages` (no streamed text) and no `--effort`, even on
169
+ * a CLI that supports both. The run path calls this with the exact launch path and env it is about
170
+ * to spawn, so the gate reflects the binary that actually runs.
171
+ *
172
+ * A no-op when the def declares no probe or the map already has an entry (a `detectAgents` result
173
+ * wins). Probes once per def id + launch path for the life of the process. A failed probe records
174
+ * nothing, which keeps the safe baseline (no optional flags), and is not retried on every run.
175
+ *
176
+ * @param def - The def about to be spawned.
177
+ * @param launchPath - The resolved executable the run will spawn.
178
+ * @param env - The env the run will spawn with.
179
+ * @complexity O(1) after the first call per def + path; the first call costs one `--help` spawn (5 s cap).
180
+ */
181
+ export function ensureAgentCapabilities(def, launchPath, env) {
182
+ const { helpArgs, capabilityFlags } = def;
183
+ if (!helpArgs || !capabilityFlags || agentCapabilities.has(def.id))
184
+ return Promise.resolve();
185
+ const key = `${def.id}\u0000${launchPath}`;
186
+ const existing = capabilityProbes.get(key);
187
+ if (existing)
188
+ return existing;
189
+ const probe = readCapabilities(helpArgs, capabilityFlags, launchPath, env).then((caps) => {
190
+ if (!agentCapabilities.has(def.id))
191
+ agentCapabilities.set(def.id, caps);
192
+ }, () => undefined);
193
+ capabilityProbes.set(key, probe);
194
+ return probe;
195
+ }
156
196
  /**
157
197
  * The effort-level override a live model catalog earns, if any.
158
198
  *
package/dist/types.d.ts CHANGED
@@ -95,6 +95,21 @@ export type RuntimeBuildOptions = {
95
95
  * `undefined`/empty means no restriction, same as today.
96
96
  */
97
97
  allowedTools?: readonly string[];
98
+ /**
99
+ * Which of the CLI's own settings layers to load — today `claude`'s `--setting-sources`
100
+ * (`user`, `project`, `local`). An EMPTY list loads none: no settings-file hooks, no plugins the
101
+ * operator enabled for themselves, no personal model/effort defaults. For a host that embeds the
102
+ * CLI as a product assistant, so the operator's personal setup (e.g. SessionStart hooks that
103
+ * inject their own instructions) never reaches the product's runs. Unlike staging a separate
104
+ * `CLAUDE_CONFIG_DIR`, this keeps the CLI's Keychain login. `undefined` = the CLI's default (all).
105
+ */
106
+ settingSources?: readonly string[];
107
+ /**
108
+ * Extra settings for this run — today `claude`'s `--settings <file-or-json>`, which the CLI applies
109
+ * on top of (and independently of) {@link settingSources}. Lets a host that loads no settings layers
110
+ * still hand the run the few it wants, e.g. one PreToolUse hook. `undefined`/empty = no flag.
111
+ */
112
+ settings?: string;
98
113
  };
99
114
  export type RuntimeContext = {
100
115
  cwd?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/agent-runtime",
3
- "version": "0.3.9",
3
+ "version": "0.3.10",
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": {
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@jini-ai/platform": "0.3.0",
42
- "@jini-ai/protocol": "0.3.0"
42
+ "@jini-ai/protocol": "0.3.1"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@vitest/coverage-v8": "^2.1.9"