@agentproto/driver-agent-cli 1.2.0 → 2.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.
@@ -212,6 +212,14 @@ var capabilitiesSchema = z.object({
212
212
  var modeSchema = z.object({
213
213
  id: z.string().regex(MODE_ID_PATTERN),
214
214
  description: z.string().optional(),
215
+ // Which orthogonal session-config axis this mode expresses (SPEC-tracked in
216
+ // @agentproto/runtime's session-config.ts). Narrowed to only "context" (SPEC
217
+ // §3.4a): route is derived from the model catalog (@route), not a manifest
218
+ // mode, and posture comes from the harness's own ACP mode registry
219
+ // (SessionModeState.availableModes) — neither is a `modes[]` entry anymore.
220
+ // The legacy "posture"/"route" classification still exists, but only inside
221
+ // the daemon's back-compat `decomposeMode` shim, not this manifest surface.
222
+ kind: z.enum(["context"]).optional(),
215
223
  bin_args_prepend: z.array(z.string()).optional(),
216
224
  bin_args_append: z.array(z.string()).optional(),
217
225
  env: z.record(z.string(), z.string()).optional(),
@@ -438,6 +446,15 @@ function createAcpProtocolArm(options) {
438
446
  get sessionId() {
439
447
  return session?.sessionId;
440
448
  },
449
+ get availableConfigOptions() {
450
+ return session?.availableConfigOptions ?? [];
451
+ },
452
+ get availableModes() {
453
+ return session?.availableModes ?? [];
454
+ },
455
+ get currentModeId() {
456
+ return session?.currentModeId;
457
+ },
441
458
  async connect(opts) {
442
459
  const permissionHandler = options.onPermissionRequest ?? defaultPermissionHandlerForMode(options.requestedMode);
443
460
  client = await createAcpClient({
@@ -495,6 +512,14 @@ function createAcpProtocolArm(options) {
495
512
  if (!session) return;
496
513
  await session.cancel();
497
514
  },
515
+ async setConfigOption(configId, value) {
516
+ if (!session) return { applied: false, reason: "not-connected" };
517
+ return session.setConfigOption(configId, value);
518
+ },
519
+ async setSessionMode(modeId) {
520
+ if (!session) return { applied: false, reason: "not-connected" };
521
+ return session.setSessionMode(modeId);
522
+ },
498
523
  respondPermission(requestId, resolution) {
499
524
  return client?.respondPermission(requestId, resolution) ?? false;
500
525
  },
@@ -608,6 +633,33 @@ function createPrintSession(opts) {
608
633
  async cancel() {
609
634
  activeChild?.kill("SIGTERM");
610
635
  },
636
+ // The print arm spawns a fresh subprocess PER TURN from `baseArgs`,
637
+ // which already has the model baked in (composed once, before this
638
+ // session object was even constructed — see `bin_args_template`
639
+ // handling in define-agent-cli.ts/compose.ts). There is no live
640
+ // connection to apply a mid-session config change to, and rebuilding
641
+ // `baseArgs` would mean a fresh session, not a live switch — so this
642
+ // is honestly `requires-restart`, same as the `arg` model-apply
643
+ // strategy for ACP arms.
644
+ async setModel() {
645
+ return { applied: false, reason: "requires-restart" };
646
+ },
647
+ // No ACP session — no wrapper-advertised capability read-surface and
648
+ // no `session/set_mode` RPC to switch live. Mirrors the "arm has no
649
+ // mid-session config surface" case `define-agent-cli.ts` reports for
650
+ // `setModel` on other arms.
651
+ availableConfigOptions: [],
652
+ availableModes: [],
653
+ currentModeId: void 0,
654
+ async setSessionMode() {
655
+ return { applied: false, reason: "not-supported" };
656
+ },
657
+ // Same as `setSessionMode`: a print arm has no live ACP session to apply
658
+ // `set_config_option(configId:"effort")` against — effort is baked into
659
+ // the spawn argv/env, so a live change is honestly `not-supported`.
660
+ async setEffort() {
661
+ return { applied: false, reason: "not-supported" };
662
+ },
611
663
  async close() {
612
664
  activeChild?.kill("SIGTERM");
613
665
  mcpRestore?.();
@@ -767,8 +819,12 @@ function createMastraMapperState() {
767
819
  return { lastTextLength: 0 };
768
820
  }
769
821
  function extractTextFromBlocks(content) {
770
- if (!Array.isArray(content)) return "";
771
- return content.filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("");
822
+ let blocks = content;
823
+ if (blocks !== null && typeof blocks === "object" && !Array.isArray(blocks) && Array.isArray(blocks.parts)) {
824
+ blocks = blocks.parts;
825
+ }
826
+ if (!Array.isArray(blocks)) return "";
827
+ return blocks.filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("");
772
828
  }
773
829
  function mapMastraEvent(evt, sessionId, stderrLines, state) {
774
830
  switch (evt.type) {
@@ -982,6 +1038,31 @@ async function createProprietaryProtocolArm(options) {
982
1038
  return await candidate(options.definition);
983
1039
  }
984
1040
 
1041
+ // src/legacy-modes.ts
1042
+ var LEGACY_GATEWAY_MODE_IDS = /* @__PURE__ */ new Set([
1043
+ "moonshot",
1044
+ "openrouter",
1045
+ "requesty",
1046
+ "deepseek"
1047
+ ]);
1048
+ var LEGACY_POSTURE_MODE_IDS = /* @__PURE__ */ new Set([
1049
+ "default",
1050
+ "plan",
1051
+ "accept-edits",
1052
+ "bypass-permissions",
1053
+ "read-only",
1054
+ "full-access",
1055
+ "build"
1056
+ ]);
1057
+ function inferLegacyModeKind(modeId) {
1058
+ if (LEGACY_GATEWAY_MODE_IDS.has(modeId)) return "route";
1059
+ if (LEGACY_POSTURE_MODE_IDS.has(modeId)) return "posture";
1060
+ return "context";
1061
+ }
1062
+ function isLegacyExtractedModeId(modeId) {
1063
+ return LEGACY_GATEWAY_MODE_IDS.has(modeId) || LEGACY_POSTURE_MODE_IDS.has(modeId);
1064
+ }
1065
+
985
1066
  // src/manifest/compose.ts
986
1067
  var RuntimeConfigError = class extends Error {
987
1068
  code;
@@ -1007,14 +1088,15 @@ function composeSpawn(handle, config) {
1007
1088
  if (config.mode !== void 0) {
1008
1089
  const mode = (handle.modes ?? []).find((m) => m.id === config.mode);
1009
1090
  if (!mode) {
1010
- const known = (handle.modes ?? []).map((m) => m.id).join(", ") || "(none)";
1011
- throw new RuntimeConfigError(
1012
- "unknown_mode",
1013
- "config.mode",
1014
- `Mode '${config.mode}' is not declared by manifest '${handle.id}'. Known modes: ${known}`
1015
- );
1016
- }
1017
- if ((mode.apply ?? "bin_args") === "bin_args") {
1091
+ if (!isLegacyExtractedModeId(config.mode)) {
1092
+ const known = (handle.modes ?? []).map((m) => m.id).join(", ") || "(none)";
1093
+ throw new RuntimeConfigError(
1094
+ "unknown_mode",
1095
+ "config.mode",
1096
+ `Mode '${config.mode}' is not declared by manifest '${handle.id}'. Known modes: ${known}`
1097
+ );
1098
+ }
1099
+ } else if ((mode.apply ?? "bin_args") === "bin_args") {
1018
1100
  if (mode.bin_args_prepend) prepend.push(...mode.bin_args_prepend);
1019
1101
  if (mode.bin_args_append) append.push(...mode.bin_args_append);
1020
1102
  if (mode.env) Object.assign(env, mode.env);
@@ -1237,7 +1319,8 @@ function createAgentCliRuntime(definition) {
1237
1319
  for (const k of composed.envUnset) delete env[k];
1238
1320
  const authSpec = opts?.auth;
1239
1321
  const hasGatewayAuthToken = "ANTHROPIC_AUTH_TOKEN" in composed.env;
1240
- const engageAuth = !!authSpec && !hasGatewayAuthToken && (authSpec.enforce === "always" || authSpec.explicit === true);
1322
+ const hasGatewayBaseUrl = "ANTHROPIC_BASE_URL" in composed.env;
1323
+ const engageAuth = !!authSpec && !hasGatewayAuthToken && !hasGatewayBaseUrl && (authSpec.enforce === "always" || authSpec.explicit === true);
1241
1324
  if (authSpec && engageAuth) {
1242
1325
  for (const key of authSpec.unsetEnv) {
1243
1326
  if (!(key in composed.env)) delete env[key];
@@ -1341,6 +1424,15 @@ function createAgentCliRuntime(definition) {
1341
1424
  return {
1342
1425
  sessionId,
1343
1426
  pid: child?.pid,
1427
+ // Capability read-surface (SPEC §3.9/§3.4a) — snapshotted once
1428
+ // `arm.connect()` above has resolved, so an ACP arm's captured
1429
+ // `newSession`/`loadSession` response is already populated. Arms
1430
+ // that don't model this (print, proprietary) leave the getters
1431
+ // undefined, defaulted here to the same empty/absent shape their
1432
+ // `setModel`-style counterparts use for "not supported".
1433
+ availableConfigOptions: arm.availableConfigOptions ?? [],
1434
+ availableModes: arm.availableModes ?? [],
1435
+ currentModeId: arm.currentModeId,
1344
1436
  send(message) {
1345
1437
  const turnId = randomUUID();
1346
1438
  currentTurnId = turnId;
@@ -1379,6 +1471,58 @@ function createAgentCliRuntime(definition) {
1379
1471
  return arm.respondPermission(requestId, resolution);
1380
1472
  }
1381
1473
  } : {},
1474
+ /**
1475
+ * Mid-session model switch — the runtime counterpart to the
1476
+ * spawn-time `modelApply` handling above. Dispatches on the same
1477
+ * `definition.models.apply` strategy so a live switch behaves
1478
+ * exactly like the spawn-time apply would have, just against an
1479
+ * already-running session. See {@link SetModelResult} for the
1480
+ * reason vocabulary; this never throws and never tears down the
1481
+ * session on a rejected switch.
1482
+ */
1483
+ async setModel(modelId) {
1484
+ if (modelApply === "arg") {
1485
+ return { applied: false, reason: "requires-restart" };
1486
+ }
1487
+ if (modelApply === "command") {
1488
+ return applyModelCommand(arm, modelId);
1489
+ }
1490
+ if (!arm.setConfigOption) {
1491
+ return { applied: false, reason: "not-supported" };
1492
+ }
1493
+ const result = await arm.setConfigOption("model", modelId);
1494
+ return result.applied ? { applied: true, model: modelId } : { applied: false, ...result.reason ? { reason: result.reason } : {} };
1495
+ },
1496
+ /**
1497
+ * Mid-session posture switch — the native-mode counterpart to
1498
+ * `setModel`, wired directly to the arm's `setSessionMode` (only
1499
+ * the ACP arm implements it). See {@link SetSessionModeResult} for
1500
+ * the reason vocabulary; this never throws and never tears down
1501
+ * the session on a rejected switch.
1502
+ */
1503
+ async setSessionMode(modeId) {
1504
+ if (!arm.setSessionMode) {
1505
+ return { applied: false, reason: "not-supported" };
1506
+ }
1507
+ const result = await arm.setSessionMode(modeId);
1508
+ return result.applied ? { applied: true, modeId } : { applied: false, ...result.reason ? { reason: result.reason } : {} };
1509
+ },
1510
+ /**
1511
+ * Mid-session effort switch — the effort-axis counterpart to
1512
+ * `setModel`'s `"config"` strategy, wired to the same
1513
+ * `arm.setConfigOption` surface with `configId:"effort"` (only the
1514
+ * ACP arm implements it). Best-effort and non-fatal: an effort label
1515
+ * the current model rejects resolves `{applied:false, reason}` (SPEC
1516
+ * risk R7), never thrown and never tearing down the session. See
1517
+ * {@link SetEffortResult} for the reason vocabulary.
1518
+ */
1519
+ async setEffort(effort) {
1520
+ if (!arm.setConfigOption) {
1521
+ return { applied: false, reason: "not-supported" };
1522
+ }
1523
+ const result = await arm.setConfigOption("effort", effort);
1524
+ return result.applied ? { applied: true, effort } : { applied: false, ...result.reason ? { reason: result.reason } : {} };
1525
+ },
1382
1526
  async close() {
1383
1527
  await arm.close();
1384
1528
  if (child && !child.killed) child.kill("SIGTERM");
@@ -1398,17 +1542,19 @@ async function applyModelCommand(arm, modelId) {
1398
1542
  if (/switch|model\s+set|now using/i.test(JSON.stringify(evt))) acked = true;
1399
1543
  }
1400
1544
  } catch (err) {
1545
+ const reason = err instanceof Error ? err.message : String(err);
1401
1546
  console.warn(
1402
1547
  `[agent-cli] /model ${modelId} control turn failed (continuing on default):`,
1403
1548
  err instanceof Error ? err.message : err
1404
1549
  );
1405
- return;
1550
+ return { applied: false, reason };
1406
1551
  }
1407
1552
  if (!acked) {
1408
- console.warn(
1409
- `[agent-cli] /model ${modelId}: no switch acknowledgement \u2014 agent may be on its default model`
1410
- );
1553
+ const reason = "no switch acknowledgement \u2014 agent may be on its default model";
1554
+ console.warn(`[agent-cli] /model ${modelId}: ${reason}`);
1555
+ return { applied: false, reason };
1411
1556
  }
1557
+ return { applied: true, model: modelId };
1412
1558
  }
1413
1559
  async function* promptTurn(arm, turnId, message) {
1414
1560
  await arm.send(turnId, message);
@@ -1466,6 +1612,6 @@ function filterStringEnv(env) {
1466
1612
  return out;
1467
1613
  }
1468
1614
 
1469
- export { RuntimeConfigError, agentCliFrontmatterSchema, autoAllowPermissionHandler, composeSpawn, createAcpProtocolArm, createAgentCliRuntime, createMastraMapperState, createPrintSession, createProprietaryProtocolArm, defineAgentCli, mapMastraEvent, planModePermissionHandler, resolveContinuationStrategy, runtimeConfigSchema, toFileBasedMcpServers };
1470
- //# sourceMappingURL=chunk-TJHKDKCU.mjs.map
1471
- //# sourceMappingURL=chunk-TJHKDKCU.mjs.map
1615
+ export { LEGACY_GATEWAY_MODE_IDS, LEGACY_POSTURE_MODE_IDS, RuntimeConfigError, agentCliFrontmatterSchema, autoAllowPermissionHandler, composeSpawn, createAcpProtocolArm, createAgentCliRuntime, createMastraMapperState, createPrintSession, createProprietaryProtocolArm, defineAgentCli, inferLegacyModeKind, isLegacyExtractedModeId, mapMastraEvent, planModePermissionHandler, resolveContinuationStrategy, runtimeConfigSchema, toFileBasedMcpServers };
1616
+ //# sourceMappingURL=chunk-LP542BMX.mjs.map
1617
+ //# sourceMappingURL=chunk-LP542BMX.mjs.map