@agentproto/driver-agent-cli 0.3.0 → 1.0.0

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.
@@ -150,6 +150,11 @@ var authSchema = z.object({
150
150
  grace_s: z.number().int().nonnegative().optional()
151
151
  }).strict().optional()
152
152
  }).strict();
153
+ var authSubscriptionSchema = z.object({
154
+ setEnv: z.string().min(1),
155
+ conflictEnv: z.array(z.string()).optional(),
156
+ unsetEnvAdd: z.array(z.string()).optional()
157
+ }).strict();
153
158
  var sessionSchema = z.object({
154
159
  mode: z.enum(["ephemeral", "persistent", "resumable"]).default("ephemeral"),
155
160
  idle_timeout_ms: z.number().int().min(1e3).default(6e5),
@@ -164,6 +169,10 @@ var sessionSchema = z.object({
164
169
  var modelsSchema = z.object({
165
170
  default: z.string().optional(),
166
171
  allowed: z.array(z.string()).optional(),
172
+ // Model-id patterns the adapter must never route to (case-insensitive,
173
+ // trailing `*` = prefix match). Enforced at compose time — see
174
+ // AgentCliModels.deny. Reserves premium providers for dedicated adapters.
175
+ deny: z.array(z.string()).optional(),
167
176
  env: z.record(z.string(), z.string()).optional(),
168
177
  // How a model is selected at session start: "config" (ACP
169
178
  // set_config_option, default) | "command" (a `/model <id>` control turn,
@@ -190,8 +199,21 @@ var capabilitiesSchema = z.object({
190
199
  var modeSchema = z.object({
191
200
  id: z.string().regex(MODE_ID_PATTERN),
192
201
  description: z.string().optional(),
202
+ bin_args_prepend: z.array(z.string()).optional(),
193
203
  bin_args_append: z.array(z.string()).optional(),
194
- env: z.record(z.string(), z.string()).optional()
204
+ env: z.record(z.string(), z.string()).optional(),
205
+ // Env keys to DELETE from the spawn env (auth hygiene for gateway
206
+ // modes — see AgentCliMode.env_unset). Applied at the runtime merge
207
+ // point, not as a static set.
208
+ env_unset: z.array(z.string()).optional(),
209
+ // Honest support status surfaced to clients. Absent ⇒ "active".
210
+ status: z.enum(["active", "noop", "planned"]).optional(),
211
+ status_note: z.string().optional(),
212
+ // How the host activates this mode: "bin_args" (default, argv/env
213
+ // composed at spawn) | "config" (no CLI surface — forwarded to the ACP
214
+ // arm's connect({mode}) and applied via session/set_config_option
215
+ // configId:"mode", e.g. opencode).
216
+ apply: z.enum(["bin_args", "config"]).optional()
195
217
  }).strict();
196
218
  var optionSchema = z.object({
197
219
  id: z.string().regex(OPTION_ID_PATTERN),
@@ -201,9 +223,14 @@ var optionSchema = z.object({
201
223
  default: z.union([z.boolean(), z.number(), z.string()]).optional(),
202
224
  min: z.number().int().optional(),
203
225
  max: z.number().int().optional(),
226
+ bin_args_prepend: z.array(z.string()).optional(),
204
227
  bin_args_template: z.array(z.string()).optional(),
205
228
  bin_args_append_when_true: z.array(z.string()).optional(),
206
- env: z.record(z.string(), z.string()).optional()
229
+ env: z.record(z.string(), z.string()).optional(),
230
+ // Env keys to DELETE from the spawn env when this option is active
231
+ // (auth hygiene for value-bearing gateway options — see
232
+ // AgentCliOption.env_unset). Symmetric with modeSchema.env_unset.
233
+ env_unset: z.array(z.string()).optional()
207
234
  }).strict().refine(
208
235
  // type === "enum" REQUIRES an `enum` array. The JSON Schema enforces
209
236
  // this via `if/then`; the zod side mirrors with a refine so both
@@ -211,6 +238,17 @@ var optionSchema = z.object({
211
238
  (o) => o.type !== "enum" || Array.isArray(o.enum) && o.enum.length > 0,
212
239
  { message: "option.type === 'enum' requires a non-empty `enum` array" }
213
240
  );
241
+ var presetSchema = z.object({
242
+ id: z.string().min(1),
243
+ label: z.string().min(1),
244
+ description: z.string().optional(),
245
+ schemaFlavor: z.enum(["anthropic", "openai"]),
246
+ baseUrl: z.string().min(1),
247
+ keyEnv: z.string().min(1),
248
+ scrubEnv: z.array(z.string()).optional(),
249
+ defaultModel: z.string().optional(),
250
+ homepage: z.string().optional()
251
+ }).strict();
214
252
  var continuationStrategyIdSchema = z.enum(CONTINUATION_STRATEGY_IDS);
215
253
  var continuationSchema = z.object({
216
254
  default: continuationStrategyIdSchema,
@@ -250,10 +288,19 @@ var agentCliFrontmatterSchema = z.object({
250
288
  version: z.string().regex(SEMVER_PATTERN),
251
289
  bin: z.string().regex(BIN_PATTERN),
252
290
  bin_args: z.array(z.string()).optional(),
291
+ // Always-on spawn env (merged before mode/option env, which can
292
+ // override). See AgentCliDefinition.env — used by generic ACP agents.
293
+ env: z.record(z.string(), z.string()).optional(),
253
294
  install: z.array(installMethodSchema).min(1),
254
295
  version_check: versionCheckSchema,
255
296
  setup: z.array(setupStepSchema).optional(),
256
297
  auth: authSchema.optional(),
298
+ // Billing-auth resolver inputs (DECISION 3). `provider` is a CatalogProvider
299
+ // id (validated against the catalog by the runtime resolver, not here, to
300
+ // keep this generic doctype decoupled from @agentproto/model-catalog).
301
+ provider: z.string().min(1).optional(),
302
+ authSubscription: authSubscriptionSchema.optional(),
303
+ authEnforce: z.enum(["always", "when-configured"]).optional(),
257
304
  sandbox: z.union([z.string(), z.record(z.string(), z.unknown())]),
258
305
  runner: z.union([z.string(), z.record(z.string(), z.unknown())]).optional(),
259
306
  protocol: z.enum(["acp", "mcp", "proprietary", "print"]),
@@ -266,6 +313,9 @@ var agentCliFrontmatterSchema = z.object({
266
313
  capabilities: capabilitiesSchema.optional(),
267
314
  modes: z.array(modeSchema).optional(),
268
315
  options: z.array(optionSchema).optional(),
316
+ // AIP-45 gateway presets this adapter can drive (merged into the
317
+ // provider-preset catalog; built-in wins on id collision).
318
+ presets: z.array(presetSchema).optional(),
269
319
  continuation: continuationSchema.optional(),
270
320
  requires: z.object({
271
321
  os: z.array(z.enum(["darwin", "linux", "windows"])).optional(),
@@ -386,11 +436,17 @@ function createAcpProtocolArm(options) {
386
436
  },
387
437
  onActivity: opts.onActivity,
388
438
  turnIdleTimeoutMs: opts.turnIdleTimeoutMs,
439
+ // Permission-hold mode: surface + park requests for the daemon inbox
440
+ // instead of auto-answering them in-arm (see AcpProtocolOptions).
441
+ ...options.permissionHold ? { permissionHold: true } : {},
389
442
  // Wire the permission handler so the agent's `session/request_permission`
390
443
  // callbacks get a real answer instead of bubbling up as
391
444
  // "AcpClient.requestPermission: no handler configured" → which
392
445
  // surfaces in the chat as an opaque "Internal error" when the
393
446
  // agent tries to Write / Bash anything gated.
447
+ // `params` is contextually typed as the SDK's `RequestPermissionRequest`
448
+ // (via `AcpClientOptions.handlers`), which is assignable to
449
+ // `AcpPermissionRequestParams` — so no cast is needed on either side.
394
450
  handlers: {
395
451
  requestPermission: async (params) => permissionHandler(params)
396
452
  }
@@ -406,7 +462,8 @@ function createAcpProtocolArm(options) {
406
462
  cwd,
407
463
  mcpServers: opts.mcpServers,
408
464
  ...opts.model ? { model: opts.model } : {},
409
- ...opts.effort ? { effort: opts.effort } : {}
465
+ ...opts.effort ? { effort: opts.effort } : {},
466
+ ...opts.mode ? { mode: opts.mode } : {}
410
467
  });
411
468
  }
412
469
  },
@@ -425,6 +482,9 @@ function createAcpProtocolArm(options) {
425
482
  if (!session) return;
426
483
  await session.cancel();
427
484
  },
485
+ respondPermission(requestId, resolution) {
486
+ return client?.respondPermission(requestId, resolution) ?? false;
487
+ },
428
488
  async close() {
429
489
  if (session) await session.close();
430
490
  if (client) await client.close();
@@ -493,22 +553,26 @@ function createPrintSession(opts) {
493
553
  try {
494
554
  if (!child.stdout)
495
555
  throw new Error("print-arm: child has no stdout pipe");
496
- const rl = createInterface({ input: child.stdout, crlfDelay: Infinity });
497
556
  let capturedSessionId = "";
498
557
  const mastraState = eventSchema === "mastra-jsonl" ? createMastraMapperState() : void 0;
499
- for await (const line of rl) {
500
- if (!line.trim()) continue;
558
+ const rl = createInterface({ input: child.stdout, crlfDelay: Infinity });
559
+ const queue = new EventQueue();
560
+ rl.on("line", (line) => {
561
+ if (!line.trim()) return;
501
562
  let evt;
502
563
  try {
503
564
  evt = JSON.parse(line);
504
565
  } catch {
505
- continue;
566
+ return;
506
567
  }
507
568
  const csid = captureSessionId(evt, eventSchema);
508
569
  if (csid) capturedSessionId = csid;
509
570
  const sid = capturedSessionId || sessionId || "";
510
571
  const mapped = mapEvent(evt, sid, stderrLines, eventSchema, mastraState);
511
- if (!mapped) continue;
572
+ if (mapped) queue.push(mapped);
573
+ });
574
+ rl.once("close", () => queue.end());
575
+ for await (const mapped of queue) {
512
576
  yield mapped;
513
577
  }
514
578
  const exitCode = await waitForExit(child);
@@ -774,6 +838,37 @@ function mapMastraEvent(evt, sessionId, stderrLines, state) {
774
838
  }
775
839
  };
776
840
  }
841
+ // ── Token usage ─────────────────────────────────────────────
842
+ // Mastra Code DOES expose usage: its `AgentController` emits a native
843
+ // `usage_update` event ({ type: "usage_update", usage: TokenUsage })
844
+ // on every model step-finish — verified against @mastra/core 1.48.0's
845
+ // AgentControllerEvent union and its emit site
846
+ // (`this.#session.emit({ type: "usage_update", usage: stepUsage })`).
847
+ // `TokenUsage` carries `{ promptTokens, completionTokens, totalTokens }`.
848
+ // Map it to this repo's `usage_update` StreamEvent (the SAME shape
849
+ // claude-code emits over ACP) so mastracode sessions — both the print
850
+ // arm and the in-process arm, which share this mapper — carry token
851
+ // telemetry in the transcript. mastracode reports these cumulatively
852
+ // (its own headless `runMC` result-usage is last-write-wins over these
853
+ // events), and last-write-wins on the descriptor matches that. It
854
+ // carries no context-window size/used or per-turn cost here, so those
855
+ // stay 0 / absent (projectEvent guards on >0, never clobbering a real
856
+ // size).
857
+ case "usage_update": {
858
+ const usage = evt.usage;
859
+ const promptTokens = typeof usage?.promptTokens === "number" ? usage.promptTokens : void 0;
860
+ const completionTokens = typeof usage?.completionTokens === "number" ? usage.completionTokens : void 0;
861
+ if (promptTokens === void 0 && completionTokens === void 0)
862
+ return null;
863
+ return {
864
+ kind: "usage_update",
865
+ sessionId,
866
+ size: 0,
867
+ used: 0,
868
+ ...promptTokens !== void 0 ? { tokensIn: promptTokens } : {},
869
+ ...completionTokens !== void 0 ? { tokensOut: completionTokens } : {}
870
+ };
871
+ }
777
872
  // ── Shell output (tool-like) ────────────────────────────────
778
873
  case "shell_output":
779
874
  return typeof evt.output === "string" ? {
@@ -794,6 +889,45 @@ function mapMastraEvent(evt, sessionId, stderrLines, state) {
794
889
  return null;
795
890
  }
796
891
  }
892
+ var QUEUE_HIGH_WATER_MARK = 1e4;
893
+ var EventQueue = class {
894
+ buffer = [];
895
+ resolveNext = null;
896
+ ended = false;
897
+ highWaterWarned = false;
898
+ push(evt) {
899
+ this.buffer.push(evt);
900
+ if (this.buffer.length > QUEUE_HIGH_WATER_MARK && !this.highWaterWarned) {
901
+ this.highWaterWarned = true;
902
+ console.warn(
903
+ `print-arm: event backlog exceeded ${QUEUE_HIGH_WATER_MARK} buffered events \u2014 downstream consumer is not keeping up. The child's stdout is still being drained (no ENOBUFS), but memory will grow until the consumer catches up.`
904
+ );
905
+ }
906
+ const resolve = this.resolveNext;
907
+ this.resolveNext = null;
908
+ resolve?.();
909
+ }
910
+ /** Signal that no further events will be pushed. */
911
+ end() {
912
+ this.ended = true;
913
+ const resolve = this.resolveNext;
914
+ this.resolveNext = null;
915
+ resolve?.();
916
+ }
917
+ async *[Symbol.asyncIterator]() {
918
+ for (; ; ) {
919
+ const evt = this.buffer.shift();
920
+ if (evt !== void 0) {
921
+ yield evt;
922
+ continue;
923
+ }
924
+ if (this.ended) return;
925
+ await new Promise((resolve) => {
926
+ this.resolveNext = resolve;
927
+ });
928
+ }
929
+ }
930
+ };
797
931
  function mapMastraFinishReason(raw) {
798
932
  switch (raw) {
799
933
  case "complete":
@@ -847,9 +981,16 @@ var RuntimeConfigError = class extends Error {
847
981
  }
848
982
  };
849
983
  function composeSpawn(handle, config) {
850
- const binArgs = [...handle.bin_args ?? []];
851
- const env = {};
852
- if (!config) return { binArgs, env };
984
+ if (!config)
985
+ return {
986
+ binArgs: [...handle.bin_args ?? []],
987
+ env: { ...handle.env ?? {} },
988
+ envUnset: []
989
+ };
990
+ const prepend = [];
991
+ const append = [];
992
+ const env = { ...handle.env ?? {} };
993
+ const envUnset = [];
853
994
  if (config.mode !== void 0) {
854
995
  const mode = (handle.modes ?? []).find((m) => m.id === config.mode);
855
996
  if (!mode) {
@@ -860,8 +1001,12 @@ function composeSpawn(handle, config) {
860
1001
  `Mode '${config.mode}' is not declared by manifest '${handle.id}'. Known modes: ${known}`
861
1002
  );
862
1003
  }
863
- if (mode.bin_args_append) binArgs.push(...mode.bin_args_append);
864
- if (mode.env) Object.assign(env, mode.env);
1004
+ if ((mode.apply ?? "bin_args") === "bin_args") {
1005
+ if (mode.bin_args_prepend) prepend.push(...mode.bin_args_prepend);
1006
+ if (mode.bin_args_append) append.push(...mode.bin_args_append);
1007
+ if (mode.env) Object.assign(env, mode.env);
1008
+ if (mode.env_unset) envUnset.push(...mode.env_unset);
1009
+ }
865
1010
  }
866
1011
  if (config.options && Object.keys(config.options).length > 0) {
867
1012
  const declared = handle.options ?? [];
@@ -881,8 +1026,23 @@ function composeSpawn(handle, config) {
881
1026
  const value = config.options[option.id];
882
1027
  validateOptionValue(option, value);
883
1028
  const patch = renderOptionPatch(option, value);
884
- binArgs.push(...patch.binArgs);
1029
+ prepend.push(...patch.prepend);
1030
+ append.push(...patch.append);
885
1031
  Object.assign(env, patch.env);
1032
+ if (patch.envUnset.length) envUnset.push(...patch.envUnset);
1033
+ }
1034
+ }
1035
+ const requestedModel = config.options?.model;
1036
+ if (typeof requestedModel === "string" && handle.models?.deny?.length) {
1037
+ const denyHit = handle.models.deny.find(
1038
+ (pattern) => matchesModelPattern(pattern, requestedModel)
1039
+ );
1040
+ if (denyHit) {
1041
+ throw new RuntimeConfigError(
1042
+ "model_denied",
1043
+ "config.options.model",
1044
+ `Model '${requestedModel}' is denied by manifest '${handle.id}' (matches deny pattern '${denyHit}'). This adapter deliberately does not route to that provider \u2014 use a permitted model or a different adapter.`
1045
+ );
886
1046
  }
887
1047
  }
888
1048
  if (config.continuation !== void 0 && handle.continuation) {
@@ -894,12 +1054,21 @@ function composeSpawn(handle, config) {
894
1054
  );
895
1055
  }
896
1056
  }
897
- return { binArgs, env };
1057
+ return {
1058
+ binArgs: [...prepend, ...handle.bin_args ?? [], ...append],
1059
+ env,
1060
+ envUnset
1061
+ };
898
1062
  }
899
1063
  function resolveContinuationStrategy(handle, config) {
900
1064
  if (config?.continuation) return config.continuation;
901
1065
  return handle.continuation?.default ?? "none";
902
1066
  }
1067
+ function matchesModelPattern(pattern, modelId) {
1068
+ const p = pattern.toLowerCase();
1069
+ const m = modelId.toLowerCase();
1070
+ return p.endsWith("*") ? m.startsWith(p.slice(0, -1)) : m === p;
1071
+ }
903
1072
  function validateOptionValue(option, value) {
904
1073
  const path = `config.options.${option.id}`;
905
1074
  switch (option.type) {
@@ -965,17 +1134,23 @@ function validateOptionValue(option, value) {
965
1134
  function renderOptionPatch(option, value) {
966
1135
  const stringValue = String(value);
967
1136
  if (option.type === "boolean") {
968
- if (value !== true) return { binArgs: [], env: {} };
1137
+ if (value !== true) return { prepend: [], append: [], env: {}, envUnset: [] };
969
1138
  return {
970
- binArgs: option.bin_args_append_when_true ? [...option.bin_args_append_when_true] : [],
971
- env: option.env ? interpolateEnv(option.env, stringValue) : {}
1139
+ prepend: [],
1140
+ append: option.bin_args_append_when_true ? [...option.bin_args_append_when_true] : [],
1141
+ env: option.env ? interpolateEnv(option.env, stringValue) : {},
1142
+ envUnset: option.env_unset ? [...option.env_unset] : []
972
1143
  };
973
1144
  }
974
1145
  return {
975
- binArgs: option.bin_args_template ? option.bin_args_template.map(
1146
+ prepend: option.bin_args_prepend ? option.bin_args_prepend.map(
1147
+ (token) => token.replace(/\{value\}/g, stringValue)
1148
+ ) : [],
1149
+ append: option.bin_args_template ? option.bin_args_template.map(
976
1150
  (token) => token.replace(/\{value\}/g, stringValue)
977
1151
  ) : [],
978
- env: option.env ? interpolateEnv(option.env, stringValue) : {}
1152
+ env: option.env ? interpolateEnv(option.env, stringValue) : {},
1153
+ envUnset: option.env_unset ? [...option.env_unset] : []
979
1154
  };
980
1155
  }
981
1156
  function interpolateEnv(env, value) {
@@ -1032,9 +1207,26 @@ function createAgentCliRuntime(definition) {
1032
1207
  const composed = composeSpawn(definition, opts?.config);
1033
1208
  const env = {
1034
1209
  ...filterStringEnv(process.env),
1035
- ...composed.env,
1036
- ...opts?.env ?? {}
1210
+ ...composed.env
1037
1211
  };
1212
+ for (const k of composed.envUnset) delete env[k];
1213
+ const authSpec = opts?.auth;
1214
+ const hasGatewayAuthToken = "ANTHROPIC_AUTH_TOKEN" in composed.env;
1215
+ const engageAuth = !!authSpec && !hasGatewayAuthToken && (authSpec.enforce === "always" || authSpec.explicit === true);
1216
+ if (authSpec && engageAuth) {
1217
+ for (const key of authSpec.unsetEnv) {
1218
+ if (!(key in composed.env)) delete env[key];
1219
+ }
1220
+ if (!authSpec.credential) {
1221
+ throw new RuntimeConfigError(
1222
+ "missing_auth_credential",
1223
+ "opts.auth.credential",
1224
+ `agent-cli '${definition.id}': auth mode "${authSpec.mode}" requires an explicit credential (resolved from a named config/store ref), but none was provided.` + (authSpec.mode === "subscription" ? ` Mint one via \`claude setup-token\` (bills the Max/Pro subscription, not API credits) and configure it \u2014 never inherited from the shell.` : ` Configure an API key (\`agentproto auth provider set \u2026\` or per-spawn) \u2014 never inherited from the shell.`)
1225
+ );
1226
+ }
1227
+ env[authSpec.setEnv] = authSpec.credential;
1228
+ }
1229
+ Object.assign(env, opts?.env ?? {});
1038
1230
  const permissionMode = resolveClaudeCodePermissionMode(
1039
1231
  definition,
1040
1232
  opts?.config?.mode
@@ -1079,7 +1271,13 @@ function createAgentCliRuntime(definition) {
1079
1271
  }
1080
1272
  });
1081
1273
  }
1082
- const arm = await buildProtocolArm(definition, child, cwd, opts?.config?.mode);
1274
+ const arm = await buildProtocolArm(
1275
+ definition,
1276
+ child,
1277
+ cwd,
1278
+ opts?.config?.mode,
1279
+ opts?.permissionHold ?? false
1280
+ );
1083
1281
  arm._stderrTail = () => stderrBuf.join("\n");
1084
1282
  const abortController = new AbortController();
1085
1283
  if (opts?.signal) {
@@ -1091,6 +1289,9 @@ function createAgentCliRuntime(definition) {
1091
1289
  const optEffort = opts?.config?.options?.effort;
1092
1290
  const modelApply = definition.models?.apply ?? "config";
1093
1291
  const configModel = optModel && modelApply === "config" ? String(optModel) : void 0;
1292
+ const requestedModeId = opts?.config?.mode;
1293
+ const requestedModeDecl = requestedModeId ? (definition.modes ?? []).find((m) => m.id === requestedModeId) : void 0;
1294
+ const configMode = requestedModeDecl?.apply === "config" ? requestedModeId : void 0;
1094
1295
  const turnIdleTimeoutMs = opts?.turnIdleTimeoutMs ?? definition.session?.turn_idle_timeout_ms;
1095
1296
  await arm.connect({
1096
1297
  cwd,
@@ -1100,8 +1301,10 @@ function createAgentCliRuntime(definition) {
1100
1301
  ...opts?.mcpServers ? { mcpServers: opts.mcpServers } : {},
1101
1302
  ...configModel ? { model: configModel } : {},
1102
1303
  ...optEffort ? { effort: String(optEffort) } : {},
1304
+ ...configMode ? { mode: configMode } : {},
1103
1305
  ...opts?.onActivity ? { onActivity: opts.onActivity } : {},
1104
- ...turnIdleTimeoutMs !== void 0 ? { turnIdleTimeoutMs } : {}
1306
+ ...turnIdleTimeoutMs !== void 0 ? { turnIdleTimeoutMs } : {},
1307
+ ...opts?.permissionHold ? { permissionHold: true } : {}
1105
1308
  });
1106
1309
  if (optModel && modelApply === "command") {
1107
1310
  await applyModelCommand(arm, String(optModel));
@@ -1117,6 +1320,11 @@ function createAgentCliRuntime(definition) {
1117
1320
  async cancel() {
1118
1321
  abortController.abort();
1119
1322
  },
1323
+ ...arm.respondPermission ? {
1324
+ respondPermission(requestId, resolution) {
1325
+ return arm.respondPermission(requestId, resolution);
1326
+ }
1327
+ } : {},
1120
1328
  async close() {
1121
1329
  await arm.close();
1122
1330
  if (child && !child.killed) child.kill("SIGTERM");
@@ -1162,7 +1370,7 @@ async function* promptTurn(arm, turnId, message) {
1162
1370
  yield evt;
1163
1371
  }
1164
1372
  }
1165
- async function buildProtocolArm(def, child, cwd, requestedMode) {
1373
+ async function buildProtocolArm(def, child, cwd, requestedMode, permissionHold) {
1166
1374
  switch (def.protocol) {
1167
1375
  case "acp":
1168
1376
  if (!child) {
@@ -1172,7 +1380,8 @@ async function buildProtocolArm(def, child, cwd, requestedMode) {
1172
1380
  child,
1173
1381
  cwd,
1174
1382
  clientInfo: { name: def.id, version: def.version },
1175
- requestedMode
1383
+ requestedMode,
1384
+ ...permissionHold ? { permissionHold: true } : {}
1176
1385
  });
1177
1386
  case "mcp":
1178
1387
  throw new Error("createAgentCliRuntime: mcp protocol arm not yet implemented");
@@ -1204,5 +1413,5 @@ function filterStringEnv(env) {
1204
1413
  }
1205
1414
 
1206
1415
  export { RuntimeConfigError, agentCliFrontmatterSchema, autoAllowPermissionHandler, composeSpawn, createAcpProtocolArm, createAgentCliRuntime, createMastraMapperState, createPrintSession, createProprietaryProtocolArm, defineAgentCli, mapMastraEvent, planModePermissionHandler, resolveContinuationStrategy, runtimeConfigSchema, toFileBasedMcpServers };
1207
- //# sourceMappingURL=chunk-KHHRPQ2Q.mjs.map
1208
- //# sourceMappingURL=chunk-KHHRPQ2Q.mjs.map
1416
+ //# sourceMappingURL=chunk-XTZNZ7MA.mjs.map
1417
+ //# sourceMappingURL=chunk-XTZNZ7MA.mjs.map