@kyo-so/cli 0.15.1 → 0.16.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.
package/dist/index.js CHANGED
@@ -184081,6 +184081,7 @@ function agentConfigLeafPaths(agent) {
184081
184081
  `agents.${agent}.effort`,
184082
184082
  `agents.${agent}.role`,
184083
184083
  `agents.${agent}.timeoutMs`,
184084
+ `agents.${agent}.timeoutS`,
184084
184085
  `agents.${agent}.env`,
184085
184086
  `agents.${agent}.auth.mode`,
184086
184087
  `agents.${agent}.auth.preferExistingLogin`,
@@ -184089,7 +184090,7 @@ function agentConfigLeafPaths(agent) {
184089
184090
  `agents.${agent}.auth.envWhitelist`
184090
184091
  ];
184091
184092
  if (agent === "codex") {
184092
- paths.push("agents.codex.provider", "agents.codex.allowProjectProvider", "agents.codex.openRouter.streamIdleTimeoutMs", "agents.codex.openRouter.streamMaxRetries", "agents.codex.openRouter.requestMaxRetries");
184093
+ paths.push("agents.codex.provider", "agents.codex.allowProjectProvider", "agents.codex.openRouter.streamIdleTimeoutMs", "agents.codex.openRouter.streamIdleTimeoutS", "agents.codex.openRouter.streamMaxRetries", "agents.codex.openRouter.requestMaxRetries");
184093
184094
  }
184094
184095
  return paths;
184095
184096
  }
@@ -184126,12 +184127,15 @@ var kyosoConfigKnownLeafPaths = [
184126
184127
  "judge.mode",
184127
184128
  "judge.provider",
184128
184129
  "judge.timeoutMs",
184130
+ "judge.timeoutS",
184129
184131
  "verification.enabled",
184130
184132
  "verification.maxFindings",
184131
184133
  "verification.timeoutMs",
184134
+ "verification.timeoutS",
184132
184135
  "verification.allowDemotion",
184133
184136
  "reviewBudget.maxModelCalls",
184134
184137
  "reviewBudget.maxTotalWallTimeMs",
184138
+ "reviewBudget.maxTotalWallTimeS",
184135
184139
  "reviewBudget.warnAgentOutputBytes",
184136
184140
  "reviewBudget.maxAgentOutputBytes",
184137
184141
  "reviewBudget.maxFindingsPerAgent",
@@ -184178,7 +184182,7 @@ var defaultConfig = {
184178
184182
  enabled: true,
184179
184183
  type: "acp",
184180
184184
  command: "npx",
184181
- args: ["-y", "@agentclientprotocol/codex-acp@1.1.5"],
184185
+ args: ["-y", "@agentclientprotocol/codex-acp@1.1.7"],
184182
184186
  role: "implementation_reviewer",
184183
184187
  timeoutMs: DEFAULT_AGENT_TIMEOUT_MS,
184184
184188
  allowProjectProvider: [],
@@ -184203,7 +184207,7 @@ var defaultConfig = {
184203
184207
  enabled: true,
184204
184208
  type: "acp",
184205
184209
  command: "npx",
184206
- args: ["-y", "@agentclientprotocol/claude-agent-acp@0.60.0"],
184210
+ args: ["-y", "@agentclientprotocol/claude-agent-acp@0.61.0"],
184207
184211
  role: "architecture_security_reviewer",
184208
184212
  timeoutMs: DEFAULT_AGENT_TIMEOUT_MS,
184209
184213
  env: {
@@ -184321,22 +184325,27 @@ var kyosoConfigOverridePaths = [
184321
184325
  "agents.codex.model",
184322
184326
  "agents.codex.provider",
184323
184327
  "agents.codex.openRouter.streamIdleTimeoutMs",
184328
+ "agents.codex.openRouter.streamIdleTimeoutS",
184324
184329
  "agents.codex.openRouter.streamMaxRetries",
184325
184330
  "agents.codex.openRouter.requestMaxRetries",
184326
184331
  "agents.codex.effort",
184327
184332
  "agents.codex.role",
184328
184333
  "agents.codex.timeoutMs",
184334
+ "agents.codex.timeoutS",
184329
184335
  "agents.claude.enabled",
184330
184336
  "agents.claude.model",
184331
184337
  "agents.claude.effort",
184332
184338
  "agents.claude.role",
184333
184339
  "agents.claude.timeoutMs",
184340
+ "agents.claude.timeoutS",
184334
184341
  "verification.enabled",
184335
184342
  "verification.maxFindings",
184336
184343
  "verification.timeoutMs",
184344
+ "verification.timeoutS",
184337
184345
  "judge.mode",
184338
184346
  "judge.provider",
184339
- "judge.timeoutMs"
184347
+ "judge.timeoutMs",
184348
+ "judge.timeoutS"
184340
184349
  ];
184341
184350
  var CONFIG_OVERRIDE_PATHS = new Set(kyosoConfigOverridePaths);
184342
184351
  function isAllowedConfigOverridePath(path) {
@@ -185573,6 +185582,146 @@ function isMissingPathError(error51) {
185573
185582
  return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
185574
185583
  }
185575
185584
 
185585
+ // src/utils/timeUnits.ts
185586
+ class TimeUnitValidationError extends Error {
185587
+ field;
185588
+ constructor(field, message) {
185589
+ super(`${field} ${message}`);
185590
+ this.name = "TimeUnitValidationError";
185591
+ this.field = field;
185592
+ }
185593
+ }
185594
+ function validateMilliseconds(value, field, constraints = {}) {
185595
+ assertFiniteNumber(value, field);
185596
+ if (!Number.isSafeInteger(value)) {
185597
+ throw new TimeUnitValidationError(field, "must be a safe integer number of milliseconds.");
185598
+ }
185599
+ assertMinimumMilliseconds(value, field, constraints);
185600
+ return value;
185601
+ }
185602
+ function secondsToMilliseconds(value, field, constraints = {}) {
185603
+ assertFiniteNumber(value, field);
185604
+ const milliseconds = value * 1000;
185605
+ if (!Number.isSafeInteger(milliseconds)) {
185606
+ throw new TimeUnitValidationError(field, "must convert to a safe integer number of milliseconds.");
185607
+ }
185608
+ assertMinimumMilliseconds(milliseconds, field, constraints);
185609
+ return milliseconds;
185610
+ }
185611
+ function resolveTimeUnitPair(input, fields, constraints = {}) {
185612
+ const hasMilliseconds = input.milliseconds !== undefined;
185613
+ const hasSeconds = input.seconds !== undefined;
185614
+ if (!hasMilliseconds && !hasSeconds)
185615
+ return;
185616
+ const milliseconds = hasMilliseconds ? validateMilliseconds(input.milliseconds, fields.milliseconds, constraints) : undefined;
185617
+ const secondsMilliseconds = hasSeconds ? secondsToMilliseconds(input.seconds, fields.seconds, constraints) : undefined;
185618
+ if (secondsMilliseconds !== undefined) {
185619
+ return {
185620
+ milliseconds: secondsMilliseconds,
185621
+ source: "seconds",
185622
+ sourceField: fields.seconds
185623
+ };
185624
+ }
185625
+ return {
185626
+ milliseconds,
185627
+ source: "milliseconds",
185628
+ sourceField: fields.milliseconds
185629
+ };
185630
+ }
185631
+ function assertFiniteNumber(value, field) {
185632
+ if (typeof value !== "number" || !Number.isFinite(value)) {
185633
+ throw new TimeUnitValidationError(field, "must be a finite number.");
185634
+ }
185635
+ }
185636
+ function assertMinimumMilliseconds(value, field, constraints) {
185637
+ if (constraints.allowZero && value === 0)
185638
+ return;
185639
+ const minimumMilliseconds = constraints.minimumMilliseconds ?? 1;
185640
+ if (value < minimumMilliseconds) {
185641
+ throw new TimeUnitValidationError(field, `must be at least ${minimumMilliseconds} milliseconds.`);
185642
+ }
185643
+ }
185644
+
185645
+ // src/config/timeUnits.ts
185646
+ var configTimeUnitPairs = [
185647
+ {
185648
+ parentPath: ["agents", "codex"],
185649
+ millisecondsKey: "timeoutMs",
185650
+ secondsKey: "timeoutS"
185651
+ },
185652
+ {
185653
+ parentPath: ["agents", "claude"],
185654
+ millisecondsKey: "timeoutMs",
185655
+ secondsKey: "timeoutS"
185656
+ },
185657
+ {
185658
+ parentPath: ["agents", "codex", "openRouter"],
185659
+ millisecondsKey: "streamIdleTimeoutMs",
185660
+ secondsKey: "streamIdleTimeoutS",
185661
+ constraints: { minimumMilliseconds: 1000 }
185662
+ },
185663
+ {
185664
+ parentPath: ["judge"],
185665
+ millisecondsKey: "timeoutMs",
185666
+ secondsKey: "timeoutS"
185667
+ },
185668
+ {
185669
+ parentPath: ["verification"],
185670
+ millisecondsKey: "timeoutMs",
185671
+ secondsKey: "timeoutS"
185672
+ },
185673
+ {
185674
+ parentPath: ["reviewBudget"],
185675
+ millisecondsKey: "maxTotalWallTimeMs",
185676
+ secondsKey: "maxTotalWallTimeS"
185677
+ }
185678
+ ];
185679
+ function normalizeConfigTimeUnits(input) {
185680
+ let normalized = input;
185681
+ for (const pair of configTimeUnitPairs) {
185682
+ normalized = updateRecordAtPath(normalized, pair.parentPath, (parent) => normalizePair(parent, pair));
185683
+ }
185684
+ return normalized;
185685
+ }
185686
+ function normalizePair(parent, pair) {
185687
+ const hasSecondsProperty = Object.hasOwn(parent, pair.secondsKey);
185688
+ if (!hasSecondsProperty)
185689
+ return parent;
185690
+ const normalized = { ...parent };
185691
+ if (parent[pair.secondsKey] === undefined) {
185692
+ delete normalized[pair.secondsKey];
185693
+ return normalized;
185694
+ }
185695
+ const parentPath = pair.parentPath.join(".");
185696
+ const resolved = resolveTimeUnitPair({
185697
+ milliseconds: parent[pair.millisecondsKey],
185698
+ seconds: parent[pair.secondsKey]
185699
+ }, {
185700
+ milliseconds: `${parentPath}.${pair.millisecondsKey}`,
185701
+ seconds: `${parentPath}.${pair.secondsKey}`
185702
+ }, pair.constraints);
185703
+ if (resolved)
185704
+ normalized[pair.millisecondsKey] = resolved.milliseconds;
185705
+ delete normalized[pair.secondsKey];
185706
+ return normalized;
185707
+ }
185708
+ function updateRecordAtPath(input, path, update) {
185709
+ if (path.length === 0) {
185710
+ return isRecord3(input) ? update(input) : input;
185711
+ }
185712
+ if (!isRecord3(input))
185713
+ return input;
185714
+ const [key, ...rest] = path;
185715
+ if (key === undefined)
185716
+ return input;
185717
+ const current = input[key];
185718
+ const updated = updateRecordAtPath(current, rest, update);
185719
+ return updated === current ? input : { ...input, [key]: updated };
185720
+ }
185721
+ function isRecord3(value) {
185722
+ return typeof value === "object" && value !== null && !Array.isArray(value);
185723
+ }
185724
+
185576
185725
  // src/config/loadConfig.ts
185577
185726
  var configValidationContexts = new WeakMap;
185578
185727
  class ProjectOpenRouterAuthorizationError extends Error {
@@ -185608,7 +185757,7 @@ async function loadConfig(options = {}) {
185608
185757
  let configTrustStatus = options.ignoreConfig ? "ignored" : "not_found";
185609
185758
  if (!options.ignoreConfig) {
185610
185759
  if (await exists(globalConfigPath)) {
185611
- const globalConfig2 = await loadTomlConfigFile(globalConfigPath);
185760
+ const globalConfig2 = normalizeConfigTimeUnits(await loadTomlConfigFile(globalConfigPath));
185612
185761
  validateExplicitReviewBudgetThresholds(globalConfig2, defaultConfig);
185613
185762
  const globalConfigWarnings = collectGlobalConfigWarnings(globalConfigPath, globalConfig2);
185614
185763
  const securitySensitiveWarnings = globalConfigWarnings.filter((warning) => warning.startsWith("security-sensitive unknown settings "));
@@ -185735,7 +185884,7 @@ async function loadProjectConfig(input) {
185735
185884
  const { canonicalDirectory, canonicalPath, requestedPath } = input.projectConfig;
185736
185885
  const extension = extname2(requestedPath);
185737
185886
  if (extension === ".toml") {
185738
- const projectTomlConfig = await loadTomlConfigFile(canonicalPath);
185887
+ const projectTomlConfig = normalizeConfigTimeUnits(await loadTomlConfigFile(canonicalPath));
185739
185888
  const projectChangesOpenRouterPolicy = projectConfigChangesOpenRouterPolicy(projectTomlConfig, input.baseConfig);
185740
185889
  await assertProjectOpenRouterAuthorization({
185741
185890
  projectConfig: projectTomlConfig,
@@ -185781,7 +185930,7 @@ function configSelectsOpenRouter(config2) {
185781
185930
  return flattenLeaves(config2).some((leaf) => leaf.path.join(".") === "agents.codex.provider" && leaf.value === CODEX_OPENROUTER_PROVIDER);
185782
185931
  }
185783
185932
  function applyProjectCodexProviderReset(baseConfig, projectConfig, mergedConfig) {
185784
- if (!projectConfigSelectsDefaultProvider(projectConfig) || !configSelectsOpenRouter(baseConfig) || !isRecord3(mergedConfig) || !isRecord3(mergedConfig.agents) || !isRecord3(mergedConfig.agents.codex)) {
185933
+ if (!projectConfigSelectsDefaultProvider(projectConfig) || !configSelectsOpenRouter(baseConfig) || !isRecord4(mergedConfig) || !isRecord4(mergedConfig.agents) || !isRecord4(mergedConfig.agents.codex)) {
185785
185934
  return mergedConfig;
185786
185935
  }
185787
185936
  const shouldClearInheritedModel = !projectConfigSuppliesCodexModel(projectConfig);
@@ -185813,13 +185962,13 @@ async function assertProjectOpenRouterAuthorization(input) {
185813
185962
  });
185814
185963
  }
185815
185964
  async function projectProviderIsAuthorized(config2, projectDirectory) {
185816
- if (!isRecord3(config2))
185965
+ if (!isRecord4(config2))
185817
185966
  return false;
185818
185967
  const agents = config2.agents;
185819
- if (!isRecord3(agents))
185968
+ if (!isRecord4(agents))
185820
185969
  return false;
185821
185970
  const codex = agents.codex;
185822
- if (!isRecord3(codex) || !Array.isArray(codex.allowProjectProvider)) {
185971
+ if (!isRecord4(codex) || !Array.isArray(codex.allowProjectProvider)) {
185823
185972
  return false;
185824
185973
  }
185825
185974
  for (const directory of codex.allowProjectProvider) {
@@ -185862,7 +186011,7 @@ async function loadProjectTsConfig(input) {
185862
186011
  options: input.options
185863
186012
  });
185864
186013
  if (trustDecision.execute) {
185865
- const userConfig = await loadUserConfig(canonicalPath, source);
186014
+ const userConfig = normalizeConfigTimeUnits(await loadUserConfig(canonicalPath, source));
185866
186015
  validateExplicitReviewBudgetThresholds(userConfig, input.baseConfig);
185867
186016
  const projectChangesOpenRouterPolicy = projectConfigChangesOpenRouterPolicy(userConfig, input.baseConfig);
185868
186017
  await assertProjectOpenRouterAuthorization({
@@ -185949,7 +186098,7 @@ async function promptForConfigTrust(configPath, configHash) {
185949
186098
  }
185950
186099
  }
185951
186100
  function deepMerge2(base, override) {
185952
- if (!isRecord3(base) || !isRecord3(override))
186101
+ if (!isRecord4(base) || !isRecord4(override))
185953
186102
  return override ?? base;
185954
186103
  const result = { ...base };
185955
186104
  for (const [key, value] of Object.entries(override)) {
@@ -185969,12 +186118,12 @@ function validateExplicitReviewBudgetThresholds(config2, baseConfig) {
185969
186118
  }
185970
186119
  }
185971
186120
  function readRecord(value, key) {
185972
- if (!isRecord3(value))
186121
+ if (!isRecord4(value))
185973
186122
  return;
185974
186123
  const nested = value[key];
185975
- return isRecord3(nested) ? nested : undefined;
186124
+ return isRecord4(nested) ? nested : undefined;
185976
186125
  }
185977
- function isRecord3(value) {
186126
+ function isRecord4(value) {
185978
186127
  return typeof value === "object" && value !== null && !Array.isArray(value);
185979
186128
  }
185980
186129
  async function exists(path) {
@@ -185989,9 +186138,14 @@ async function exists(path) {
185989
186138
  // src/config/configOverrides.ts
185990
186139
  var NUMBER_VALUE = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i;
185991
186140
  var UNSET_NUMBER_OVERRIDE_PATHS = new Set([
186141
+ "agents.codex.timeoutS",
186142
+ "agents.claude.timeoutS",
185992
186143
  "agents.codex.openRouter.streamIdleTimeoutMs",
186144
+ "agents.codex.openRouter.streamIdleTimeoutS",
185993
186145
  "agents.codex.openRouter.streamMaxRetries",
185994
- "agents.codex.openRouter.requestMaxRetries"
186146
+ "agents.codex.openRouter.requestMaxRetries",
186147
+ "judge.timeoutS",
186148
+ "verification.timeoutS"
185995
186149
  ]);
185996
186150
  function applyConfigOverrides(config2, assignments) {
185997
186151
  if (assignments.length === 0)
@@ -186002,9 +186156,21 @@ function applyConfigOverrides(config2, assignments) {
186002
186156
  for (const override of overrides) {
186003
186157
  writePath2(overridden, override.path, parseConfigOverrideValue(override.value, readPath2(baseConfig, override.path), override.path));
186004
186158
  }
186005
- clearInheritedOpenRouterConfigForProviderReset(baseConfig, overridden, overrides);
186006
- assertOpenRouterProviderOverrideIncludesModel(baseConfig, overridden, overrides);
186007
- const parsed = kyosoConfigSchema.safeParse(overridden);
186159
+ let normalized;
186160
+ try {
186161
+ normalized = normalizeConfigTimeUnits(overridden);
186162
+ } catch (error51) {
186163
+ if (!(error51 instanceof TimeUnitValidationError))
186164
+ throw error51;
186165
+ const assignment2 = findAssignmentForPath(overrides, error51.field);
186166
+ if (!assignment2) {
186167
+ throw new Error(`Invalid config time value: ${error51.message}`);
186168
+ }
186169
+ throw new Error(`Invalid --set value ${JSON.stringify(assignment2)}: ${error51.message}`);
186170
+ }
186171
+ clearInheritedOpenRouterConfigForProviderReset(baseConfig, normalized, overrides);
186172
+ assertOpenRouterProviderOverrideIncludesModel(baseConfig, normalized, overrides);
186173
+ const parsed = kyosoConfigSchema.safeParse(normalized);
186008
186174
  if (parsed.success)
186009
186175
  return parsed.data;
186010
186176
  const issue2 = parsed.error.issues[0];
@@ -186034,7 +186200,7 @@ function clearInheritedOpenRouterConfigForProviderReset(baseConfig, overridden,
186034
186200
  return;
186035
186201
  }
186036
186202
  const codex = readPath2(overridden, ["agents", "codex"]);
186037
- if (!isRecord4(codex))
186203
+ if (!isRecord5(codex))
186038
186204
  return;
186039
186205
  if (!suppliesModel)
186040
186206
  delete codex.model;
@@ -186083,7 +186249,7 @@ function parseConfigOverrideValue(value, currentValue, path) {
186083
186249
  function readPath2(target, path) {
186084
186250
  let current = target;
186085
186251
  for (const key of path) {
186086
- if (!isRecord4(current))
186252
+ if (!isRecord5(current))
186087
186253
  return;
186088
186254
  current = current[key];
186089
186255
  }
@@ -186093,7 +186259,7 @@ function writePath2(target, path, value) {
186093
186259
  let current = target;
186094
186260
  for (const key of path.slice(0, -1)) {
186095
186261
  const child = current[key];
186096
- if (!isRecord4(child)) {
186262
+ if (!isRecord5(child)) {
186097
186263
  throw new Error(`Cannot apply --set key ${JSON.stringify(path.join("."))}.`);
186098
186264
  }
186099
186265
  current = child;
@@ -186102,7 +186268,7 @@ function writePath2(target, path, value) {
186102
186268
  if (leaf)
186103
186269
  current[leaf] = value;
186104
186270
  }
186105
- function isRecord4(value) {
186271
+ function isRecord5(value) {
186106
186272
  return typeof value === "object" && value !== null && !Array.isArray(value);
186107
186273
  }
186108
186274
 
@@ -186448,6 +186614,9 @@ var zToolCallUpdate = object({
186448
186614
  title: defaultOnError(string2().nullish(), () => {
186449
186615
  return;
186450
186616
  }),
186617
+ name: defaultOnError(string2().nullish(), () => {
186618
+ return;
186619
+ }),
186451
186620
  content: defaultOnError(vecSkipError(zToolCallContent).nullish(), () => {
186452
186621
  return;
186453
186622
  }),
@@ -187559,6 +187728,9 @@ var zContentChunk = object({
187559
187728
  var zToolCall = object({
187560
187729
  toolCallId: zToolCallId,
187561
187730
  title: string2(),
187731
+ name: defaultOnError(string2().nullish(), () => {
187732
+ return;
187733
+ }),
187562
187734
  kind: defaultOnError(zToolKind.optional(), () => {
187563
187735
  return;
187564
187736
  }),
@@ -188482,37 +188654,71 @@ var zCancelRequestNotification = object({
188482
188654
  })
188483
188655
  });
188484
188656
 
188485
- // node_modules/@agentclientprotocol/sdk/dist/schema/guards.gen.js
188486
- var zGuardCreateElicitationRequestForm = zElicitationFormMode.and(object({ mode: literal("form") })).and(object({ message: string2() }));
188487
- var zGuardCreateElicitationRequestUrl = zElicitationUrlMode.and(object({ mode: literal("url") })).and(object({ message: string2() }));
188488
- var zGuardCreateElicitationRequestCustom = union([zElicitationSessionScope, zElicitationRequestScope]).and(object({ message: string2() }));
188489
- var zGuardElicitationPropertySchemaString = zStringPropertySchema.and(object({ type: literal("string") }));
188490
- var zGuardElicitationPropertySchemaNumber = zNumberPropertySchema.and(object({ type: literal("number") }));
188491
- var zGuardElicitationPropertySchemaInteger = zIntegerPropertySchema.and(object({ type: literal("integer") }));
188492
- var zGuardElicitationPropertySchemaBoolean = zBooleanPropertySchema.and(object({ type: literal("boolean") }));
188493
- var zGuardElicitationPropertySchemaArray = zMultiSelectPropertySchema.and(object({ type: literal("array") }));
188494
- var zGuardMultiSelectItemsString = zStringMultiSelectItems.and(object({ type: literal("string") }));
188495
- var zGuardCreateElicitationResponseAccept = zElicitationAcceptAction.and(object({ action: literal("accept") }));
188496
- var zGuardCreateElicitationResponseDecline = object({
188497
- action: literal("decline")
188498
- });
188499
- var zGuardCreateElicitationResponseCancel = object({
188500
- action: literal("cancel")
188501
- });
188502
188657
  // node_modules/@agentclientprotocol/sdk/dist/jsonrpc.js
188503
188658
  var CANCEL_REQUEST_METHOD = "$/cancel_request";
188504
- function isRecord5(value) {
188659
+ function isRequestMessage(value) {
188660
+ return isJsonRpcEnvelope(value) && "id" in value && typeof value["method"] === "string" && isJsonRpcId(value["id"]);
188661
+ }
188662
+ function isResponseMessage(value) {
188663
+ if (!isJsonRpcEnvelope(value) || "method" in value) {
188664
+ return false;
188665
+ }
188666
+ if (!("id" in value) || !isJsonRpcId(value["id"])) {
188667
+ return false;
188668
+ }
188669
+ const hasResult = Object.hasOwn(value, "result");
188670
+ const hasError = Object.hasOwn(value, "error");
188671
+ if (hasResult === hasError) {
188672
+ return false;
188673
+ }
188674
+ return !hasError || isErrorResponse(value["error"]);
188675
+ }
188676
+ function isNotificationMessage(value) {
188677
+ return isJsonRpcEnvelope(value) && !("id" in value) && typeof value["method"] === "string";
188678
+ }
188679
+ function isRecord6(value) {
188505
188680
  return typeof value === "object" && value !== null;
188506
188681
  }
188682
+ function isJsonRpcEnvelope(value) {
188683
+ return isRecord6(value) && value["jsonrpc"] === "2.0";
188684
+ }
188507
188685
  function isJsonRpcId(value) {
188508
188686
  return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
188509
188687
  }
188688
+ function isResponseShapedMessage(value) {
188689
+ return isRecord6(value) && !("method" in value) && (("id" in value) || ("result" in value) || ("error" in value));
188690
+ }
188691
+ function isResponseBatch(batch) {
188692
+ let hasValidCall = false;
188693
+ let hasValidResponse = false;
188694
+ let hasCallShape = false;
188695
+ let hasResponseShape = false;
188696
+ for (const entry of batch) {
188697
+ hasValidCall ||= isRequestMessage(entry) || isNotificationMessage(entry);
188698
+ hasValidResponse ||= isResponseMessage(entry);
188699
+ if (!isRecord6(entry)) {
188700
+ continue;
188701
+ }
188702
+ hasCallShape ||= "method" in entry;
188703
+ hasResponseShape ||= "result" in entry || "error" in entry;
188704
+ }
188705
+ if (hasValidCall) {
188706
+ return false;
188707
+ }
188708
+ if (hasValidResponse) {
188709
+ return true;
188710
+ }
188711
+ return hasResponseShape && !hasCallShape;
188712
+ }
188510
188713
  function cancelRequestId(params) {
188511
- if (!isRecord5(params) || !isJsonRpcId(params["requestId"])) {
188714
+ if (!isRecord6(params) || !isJsonRpcId(params["requestId"])) {
188512
188715
  return;
188513
188716
  }
188514
188717
  return params["requestId"];
188515
188718
  }
188719
+ function isErrorResponse(value) {
188720
+ return isRecord6(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
188721
+ }
188516
188722
  var Handled = {
188517
188723
  yes() {
188518
188724
  return { handled: true };
@@ -188641,6 +188847,9 @@ class ConnectionContext {
188641
188847
  sendNotification(method, params) {
188642
188848
  return this.connection.sendNotification(method, params);
188643
188849
  }
188850
+ sendBatch(entries) {
188851
+ return this.connection.sendBatch(entries);
188852
+ }
188644
188853
  sendCancelRequest(requestId) {
188645
188854
  return this.connection.sendCancelRequest(requestId);
188646
188855
  }
@@ -188668,6 +188877,7 @@ class Connection {
188668
188877
  retryQueue = [];
188669
188878
  context = new ConnectionContext(this);
188670
188879
  receiveReader;
188880
+ allowBatches = true;
188671
188881
  constructor(requestHandlerOrStream, notificationHandlerOrHandlers, streamOrOptions, options) {
188672
188882
  if (typeof requestHandlerOrStream === "function") {
188673
188883
  const requestHandler = requestHandlerOrStream;
@@ -188676,16 +188886,13 @@ class Connection {
188676
188886
  this.initialize(stream2, [
188677
188887
  ...options?.handlers ?? [],
188678
188888
  this.legacyHandler(requestHandler, notificationHandler)
188679
- ]);
188889
+ ], options);
188680
188890
  return;
188681
188891
  }
188682
188892
  const stream = requestHandlerOrStream;
188683
188893
  const handlers = notificationHandlerOrHandlers;
188684
188894
  const connectionOptions = streamOrOptions;
188685
- this.initialize(stream, [
188686
- ...connectionOptions?.handlers ?? [],
188687
- ...handlers
188688
- ]);
188895
+ this.initialize(stream, [...connectionOptions?.handlers ?? [], ...handlers], connectionOptions);
188689
188896
  }
188690
188897
  static builder() {
188691
188898
  return new ConnectionBuilder;
@@ -188730,14 +188937,73 @@ class Connection {
188730
188937
  if (this.abortController.signal.aborted) {
188731
188938
  return rejectedPromise(this.closedReason());
188732
188939
  }
188940
+ const request = this.prepareRequest(method, params, mapResponse, options);
188941
+ const requestSent = this.sendWireMessage(request.message);
188942
+ requestSent.catch(() => {});
188943
+ if (options.cancellationSignal?.aborted) {
188944
+ request.cancel();
188945
+ }
188946
+ return request.response;
188947
+ }
188948
+ sendBatch(entries) {
188949
+ if (this.abortController.signal.aborted) {
188950
+ return rejectedPromise(this.closedReason());
188951
+ }
188952
+ if (!this.allowBatches) {
188953
+ return rejectedPromise(new TypeError("JSON-RPC batches are not supported on this connection"));
188954
+ }
188955
+ if (entries.length === 0) {
188956
+ return rejectedPromise(new TypeError("JSON-RPC batch must contain at least one entry"));
188957
+ }
188958
+ const messages = [];
188959
+ const cancellations = [];
188960
+ const outputs = [];
188961
+ for (const entry of entries) {
188962
+ if (entry.kind === "notification") {
188963
+ messages.push({
188964
+ jsonrpc: "2.0",
188965
+ method: entry.method,
188966
+ params: entry.params
188967
+ });
188968
+ outputs.push(Promise.resolve(undefined));
188969
+ continue;
188970
+ }
188971
+ const request = this.prepareRequest(entry.method, entry.params, entry.mapResponse, entry.options);
188972
+ messages.push(request.message);
188973
+ outputs.push(request.response);
188974
+ cancellations.push({
188975
+ signal: entry.options?.cancellationSignal,
188976
+ cancel: request.cancel
188977
+ });
188978
+ }
188979
+ const batch = messages;
188980
+ const batchSent = this.sendWireMessage(batch);
188981
+ for (const cancellation of cancellations) {
188982
+ if (cancellation.signal?.aborted) {
188983
+ cancellation.cancel();
188984
+ }
188985
+ }
188986
+ const response = Promise.all([batchSent, ...outputs]).then(([, ...resolved]) => resolved);
188987
+ response.catch(() => {});
188988
+ return response;
188989
+ }
188990
+ sendCancelRequest(requestId) {
188991
+ return this.sendNotification(CANCEL_REQUEST_METHOD, { requestId });
188992
+ }
188993
+ sendNotification(method, params) {
188994
+ if (this.abortController.signal.aborted) {
188995
+ return rejectedPromise(this.closedReason());
188996
+ }
188997
+ return this.sendWireMessage({ jsonrpc: "2.0", method, params });
188998
+ }
188999
+ prepareRequest(method, params, mapResponse, options = {}) {
188733
189000
  const id = this.nextRequestId++;
188734
189001
  let cancel = () => {};
188735
- const responsePromise = new Promise((resolve3, reject) => {
189002
+ const response = new Promise((resolve3, reject) => {
188736
189003
  const pendingResponse = {
188737
- resolve: (response) => {
189004
+ resolve: (value) => {
188738
189005
  try {
188739
- const value = mapResponse ? mapResponse(response) : response;
188740
- resolve3(value);
189006
+ resolve3(mapResponse ? mapResponse(value) : value);
188741
189007
  } catch (error51) {
188742
189008
  reject(error51);
188743
189009
  }
@@ -188760,27 +189026,12 @@ class Connection {
188760
189026
  };
188761
189027
  this.pendingResponses.set(id, pendingResponse);
188762
189028
  });
188763
- responsePromise.catch(() => {});
188764
- const requestSent = this.sendMessage({
188765
- jsonrpc: "2.0",
188766
- id,
188767
- method,
188768
- params
188769
- });
188770
- requestSent.catch(() => {});
188771
- if (options.cancellationSignal?.aborted) {
188772
- cancel();
188773
- }
188774
- return responsePromise;
188775
- }
188776
- sendCancelRequest(requestId) {
188777
- return this.sendNotification(CANCEL_REQUEST_METHOD, { requestId });
188778
- }
188779
- sendNotification(method, params) {
188780
- if (this.abortController.signal.aborted) {
188781
- return rejectedPromise(this.closedReason());
188782
- }
188783
- return this.sendMessage({ jsonrpc: "2.0", method, params });
189029
+ response.catch(() => {});
189030
+ return {
189031
+ message: { jsonrpc: "2.0", id, method, params },
189032
+ response,
189033
+ cancel: () => cancel()
189034
+ };
188784
189035
  }
188785
189036
  close(error51) {
188786
189037
  if (this.abortController.signal.aborted) {
@@ -188799,9 +189050,10 @@ class Connection {
188799
189050
  this.incomingRequests.clear();
188800
189051
  this.receiveReader?.cancel(closeError).catch(() => {});
188801
189052
  }
188802
- initialize(stream, handlers) {
189053
+ initialize(stream, handlers, options) {
188803
189054
  this.stream = stream;
188804
189055
  this.staticHandlers = handlers;
189056
+ this.allowBatches = options?.allowBatches ?? true;
188805
189057
  this.closedPromise = new Promise((resolve3) => {
188806
189058
  this.abortController.signal.addEventListener("abort", () => resolve3());
188807
189059
  });
@@ -188837,7 +189089,7 @@ class Connection {
188837
189089
  if (!message) {
188838
189090
  continue;
188839
189091
  }
188840
- this.receiveMessage(message);
189092
+ this.receiveWireMessage(message);
188841
189093
  }
188842
189094
  } finally {
188843
189095
  if (this.receiveReader === reader) {
@@ -188851,24 +189103,91 @@ class Connection {
188851
189103
  this.close(closeError);
188852
189104
  }
188853
189105
  }
188854
- receiveMessage(message) {
188855
- if (this.abortController.signal.aborted) {
189106
+ receiveWireMessage(message) {
189107
+ if (Array.isArray(message)) {
189108
+ if (!this.allowBatches) {
189109
+ this.close(new TypeError("JSON-RPC batches are not supported on this connection"));
189110
+ return;
189111
+ }
189112
+ this.receiveBatch(message);
188856
189113
  return;
188857
189114
  }
188858
- if (!isRecord5(message)) {
189115
+ if (!isRecord6(message)) {
188859
189116
  console.error("Invalid message", { message });
188860
189117
  return;
188861
189118
  }
189119
+ this.receiveMessage(message);
189120
+ }
189121
+ receiveBatch(batch) {
189122
+ if (batch.length === 0) {
189123
+ this.sendWireMessage({
189124
+ jsonrpc: "2.0",
189125
+ id: null,
189126
+ error: RequestError.invalidRequest(batch).toErrorResponse()
189127
+ }).catch(() => {});
189128
+ return;
189129
+ }
189130
+ const responseBatch = isResponseBatch(batch);
189131
+ const responseCount = responseBatch ? 0 : batch.reduce((count, message) => count + (isNotificationMessage(message) ? 0 : 1), 0);
189132
+ let remaining = responseCount;
189133
+ let remainingNotifications = batch.reduce((count, message) => count + (isNotificationMessage(message) ? 1 : 0), 0);
189134
+ let responseSent = false;
189135
+ const responses = [];
189136
+ const sendResponsesIfReady = async () => {
189137
+ if (responseSent || remaining !== 0 || remainingNotifications !== 0 || responses.length === 0) {
189138
+ return;
189139
+ }
189140
+ responseSent = true;
189141
+ await this.sendWireMessage(responses);
189142
+ };
189143
+ const collectResponse = async (response) => {
189144
+ responses.push(response);
189145
+ remaining -= 1;
189146
+ await sendResponsesIfReady();
189147
+ };
189148
+ for (const message of batch) {
189149
+ if (responseBatch) {
189150
+ if (isResponseShapedMessage(message)) {
189151
+ this.receiveMessage(message);
189152
+ }
189153
+ continue;
189154
+ }
189155
+ if (!isRequestMessage(message) && !isNotificationMessage(message)) {
189156
+ collectResponse({
189157
+ jsonrpc: "2.0",
189158
+ id: null,
189159
+ error: RequestError.invalidRequest(message).toErrorResponse()
189160
+ }).catch(() => {});
189161
+ continue;
189162
+ }
189163
+ const processing = this.receiveMessage(message, isRequestMessage(message) ? collectResponse : undefined);
189164
+ if (isNotificationMessage(message)) {
189165
+ processing.finally(() => {
189166
+ remainingNotifications -= 1;
189167
+ sendResponsesIfReady().catch((error51) => this.close(error51));
189168
+ });
189169
+ }
189170
+ }
189171
+ }
189172
+ receiveMessage(message, sendResponse) {
189173
+ if (this.abortController.signal.aborted) {
189174
+ return Promise.resolve();
189175
+ }
189176
+ if (!isRecord6(message)) {
189177
+ console.error("Invalid message", { message });
189178
+ return Promise.resolve();
189179
+ }
188862
189180
  if ("method" in message) {
188863
189181
  if (!("id" in message)) {
188864
189182
  this.handleProtocolNotification(message);
188865
189183
  }
188866
- this.processIncomingMessage(this.toIncomingMessage(message)).catch((error51) => this.close(error51));
189184
+ return this.processIncomingMessage(this.toIncomingMessage(message, sendResponse)).catch((error51) => this.close(error51));
188867
189185
  } else if ("id" in message) {
188868
189186
  this.handleResponse(message);
188869
189187
  } else {
188870
189188
  console.error("Invalid message", { message });
188871
189189
  }
189190
+ return Promise.resolve();
188872
189191
  }
188873
189192
  async processIncomingMessage(message) {
188874
189193
  if (this.abortController.signal.aborted) {
@@ -188912,7 +189231,7 @@ class Connection {
188912
189231
  }
188913
189232
  }
188914
189233
  }
188915
- toIncomingMessage(message) {
189234
+ toIncomingMessage(message, sendResponse) {
188916
189235
  if ("id" in message) {
188917
189236
  const abortController = new AbortController;
188918
189237
  this.incomingRequests.set(message.id, abortController);
@@ -188927,11 +189246,14 @@ class Connection {
188927
189246
  params: message.params,
188928
189247
  raw: message,
188929
189248
  signal: abortController.signal,
188930
- responder: new RequestResponder(message.id, (result) => this.sendMessage({
188931
- jsonrpc: "2.0",
188932
- id: message.id,
188933
- ...result
188934
- }), abortController.signal, finishRequest)
189249
+ responder: new RequestResponder(message.id, (result) => {
189250
+ const response = {
189251
+ jsonrpc: "2.0",
189252
+ id: message.id,
189253
+ ...result
189254
+ };
189255
+ return sendResponse ? sendResponse(response) : this.sendWireMessage(response);
189256
+ }, abortController.signal, finishRequest)
188935
189257
  };
188936
189258
  }
188937
189259
  return {
@@ -188946,13 +189268,13 @@ class Connection {
188946
189268
  if (pendingResponse) {
188947
189269
  this.pendingResponses.delete(response.id);
188948
189270
  pendingResponse.cleanup?.();
188949
- if ("result" in response) {
189271
+ if (!isResponseMessage(response)) {
189272
+ pendingResponse.reject(RequestError.invalidRequest(response));
189273
+ } else if ("result" in response) {
188950
189274
  pendingResponse.resolve(response.result);
188951
- } else if ("error" in response && isRecord5(response.error)) {
189275
+ } else {
188952
189276
  const { code, message, data } = response.error;
188953
189277
  pendingResponse.reject(new RequestError(code, message, data));
188954
- } else {
188955
- pendingResponse.reject(RequestError.invalidRequest(response));
188956
189278
  }
188957
189279
  } else {
188958
189280
  console.error("Got response to unknown request", response.id);
@@ -188975,7 +189297,7 @@ class Connection {
188975
189297
  closedReason() {
188976
189298
  return this.abortController.signal.reason ?? new Error("ACP connection closed");
188977
189299
  }
188978
- async sendMessage(message) {
189300
+ async sendWireMessage(message) {
188979
189301
  if (this.abortController.signal.aborted) {
188980
189302
  return rejectedPromise(this.closedReason());
188981
189303
  }
@@ -189158,7 +189480,7 @@ function ndJsonStream(output, input) {
189158
189480
  if (trimmedLine) {
189159
189481
  try {
189160
189482
  const message = JSON.parse(trimmedLine);
189161
- if (isRecord5(message)) {
189483
+ if (isRecord6(message) || Array.isArray(message)) {
189162
189484
  controller.enqueue(message);
189163
189485
  } else {
189164
189486
  console.warn("Skipping JSON line that is not an object:", trimmedLine);
@@ -189232,7 +189554,28 @@ function ndJsonStream(output, input) {
189232
189554
  });
189233
189555
  return { readable, writable };
189234
189556
  }
189557
+
189558
+ // node_modules/@agentclientprotocol/sdk/dist/schema/guards.gen.js
189559
+ var zGuardCreateElicitationRequestForm = zElicitationFormMode.and(object({ mode: literal("form") })).and(object({ message: string2() }));
189560
+ var zGuardCreateElicitationRequestUrl = zElicitationUrlMode.and(object({ mode: literal("url") })).and(object({ message: string2() }));
189561
+ var zGuardCreateElicitationRequestCustom = union([zElicitationSessionScope, zElicitationRequestScope]).and(object({ message: string2() }));
189562
+ var zGuardElicitationPropertySchemaString = zStringPropertySchema.and(object({ type: literal("string") }));
189563
+ var zGuardElicitationPropertySchemaNumber = zNumberPropertySchema.and(object({ type: literal("number") }));
189564
+ var zGuardElicitationPropertySchemaInteger = zIntegerPropertySchema.and(object({ type: literal("integer") }));
189565
+ var zGuardElicitationPropertySchemaBoolean = zBooleanPropertySchema.and(object({ type: literal("boolean") }));
189566
+ var zGuardElicitationPropertySchemaArray = zMultiSelectPropertySchema.and(object({ type: literal("array") }));
189567
+ var zGuardMultiSelectItemsString = zStringMultiSelectItems.and(object({ type: literal("string") }));
189568
+ var zGuardCreateElicitationResponseAccept = zElicitationAcceptAction.and(object({ action: literal("accept") }));
189569
+ var zGuardCreateElicitationResponseDecline = object({
189570
+ action: literal("decline")
189571
+ });
189572
+ var zGuardCreateElicitationResponseCancel = object({
189573
+ action: literal("cancel")
189574
+ });
189235
189575
  // node_modules/@agentclientprotocol/sdk/dist/acp.js
189576
+ function ndJsonStream2(output, input) {
189577
+ return ndJsonStream(output, input);
189578
+ }
189236
189579
  function emptyObjectResponse(response) {
189237
189580
  return response ?? {};
189238
189581
  }
@@ -189817,6 +190160,7 @@ function runConnectHandlers(connection, handlers) {
189817
190160
  var appBuilder = Symbol("appBuilder");
189818
190161
  var runAgentConnectHandlers = Symbol("runAgentConnectHandlers");
189819
190162
  var runClientConnectHandlers = Symbol("runClientConnectHandlers");
190163
+ var stableConnectionOptions = { allowBatches: false };
189820
190164
  class AgentApp {
189821
190165
  builder = Connection.builder();
189822
190166
  connectHandlers = [];
@@ -189879,7 +190223,7 @@ class AgentApp {
189879
190223
  return state2;
189880
190224
  }
189881
190225
  const [thisStream, peerStream] = memoryStreamPair();
189882
- const peerRawConnection = target[appBuilder]().connect(peerStream);
190226
+ const peerRawConnection = target[appBuilder]().connect(peerStream, stableConnectionOptions);
189883
190227
  const peerConnection = clientConnection(peerRawConnection);
189884
190228
  const state = this.openStreamConnection(thisStream);
189885
190229
  state.rawConnection.closed.then(() => peerConnection.close());
@@ -189894,8 +190238,8 @@ class AgentApp {
189894
190238
  }
189895
190239
  return state;
189896
190240
  }
189897
- openStreamConnection(stream2) {
189898
- const rawConnection = this.builder.connect(stream2);
190241
+ openStreamConnection(stream) {
190242
+ const rawConnection = this.builder.connect(stream, stableConnectionOptions);
189899
190243
  return {
189900
190244
  rawConnection,
189901
190245
  connection: agentConnection(rawConnection, this.connectHandlers)
@@ -189970,7 +190314,7 @@ class ClientApp {
189970
190314
  return state2;
189971
190315
  }
189972
190316
  const [thisStream, peerStream] = memoryStreamPair();
189973
- const peerRawConnection = target[appBuilder]().connect(peerStream);
190317
+ const peerRawConnection = target[appBuilder]().connect(peerStream, stableConnectionOptions);
189974
190318
  const peerConnection = agentConnection(peerRawConnection);
189975
190319
  const state = this.openStreamConnection(thisStream);
189976
190320
  state.rawConnection.closed.then(() => peerConnection.close());
@@ -189985,8 +190329,8 @@ class ClientApp {
189985
190329
  }
189986
190330
  return state;
189987
190331
  }
189988
- openStreamConnection(stream2) {
189989
- const rawConnection = this.builder.connect(stream2);
190332
+ openStreamConnection(stream) {
190333
+ const rawConnection = this.builder.connect(stream, stableConnectionOptions);
189990
190334
  return {
189991
190335
  rawConnection,
189992
190336
  connection: clientConnection(rawConnection, this.connectHandlers)
@@ -190086,7 +190430,7 @@ function createModelExecutionIdentity(input) {
190086
190430
  };
190087
190431
  }
190088
190432
  function normalizeModelExecutionIdentity(value) {
190089
- if (!isRecord6(value) || !isModelProviderRoute(value.providerRoute)) {
190433
+ if (!isRecord7(value) || !isModelProviderRoute(value.providerRoute)) {
190090
190434
  return;
190091
190435
  }
190092
190436
  return createModelExecutionIdentity({
@@ -190108,7 +190452,7 @@ function sanitizeIdentityValue(value) {
190108
190452
  function isModelProviderRoute(value) {
190109
190453
  return typeof value === "string" && MODEL_PROVIDER_ROUTES.has(value);
190110
190454
  }
190111
- function isRecord6(value) {
190455
+ function isRecord7(value) {
190112
190456
  return value !== null && typeof value === "object" && !Array.isArray(value);
190113
190457
  }
190114
190458
 
@@ -190122,7 +190466,7 @@ var TOKEN_USAGE_KEYS = [
190122
190466
  "cachedWriteTokens"
190123
190467
  ];
190124
190468
  function normalizeModelTokenUsage(usage) {
190125
- if (!isRecord7(usage))
190469
+ if (!isRecord8(usage))
190126
190470
  return;
190127
190471
  const normalized = {};
190128
190472
  for (const key of TOKEN_USAGE_KEYS) {
@@ -190135,7 +190479,7 @@ function normalizeModelTokenUsage(usage) {
190135
190479
  function isTokenCount(value) {
190136
190480
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
190137
190481
  }
190138
- function isRecord7(value) {
190482
+ function isRecord8(value) {
190139
190483
  return typeof value === "object" && value !== null && !Array.isArray(value);
190140
190484
  }
190141
190485
 
@@ -190526,12 +190870,12 @@ class AgentOutputAccumulator {
190526
190870
  var RETRY_ATTEMPT_PATTERN = /Reconnecting\.\.\.\s*(\d+)\/(\d+)/;
190527
190871
  var DISPLAY_MESSAGE_FIELDS = ["title", "text", "message", "description"];
190528
190872
  function parseCodexRetryUpdate(update) {
190529
- if (!isRecord8(update) || update.sessionUpdate !== "session_info_update") {
190873
+ if (!isRecord9(update) || update.sessionUpdate !== "session_info_update") {
190530
190874
  return;
190531
190875
  }
190532
- const meta3 = isRecord8(update._meta) ? update._meta : undefined;
190533
- const codex = meta3 && isRecord8(meta3.codex) ? meta3.codex : undefined;
190534
- const error51 = codex && isRecord8(codex.error) ? codex.error : undefined;
190876
+ const meta3 = isRecord9(update._meta) ? update._meta : undefined;
190877
+ const codex = meta3 && isRecord9(meta3.codex) ? meta3.codex : undefined;
190878
+ const error51 = codex && isRecord9(codex.error) ? codex.error : undefined;
190535
190879
  if (error51?.willRetry !== true)
190536
190880
  return;
190537
190881
  const rawMessage = typeof error51.message === "string" ? error51.message : findDisplayMessage(update) ?? "model stream retry";
@@ -190551,7 +190895,7 @@ function findDisplayMessage(update) {
190551
190895
  }
190552
190896
  return;
190553
190897
  }
190554
- function isRecord8(value) {
190898
+ function isRecord9(value) {
190555
190899
  return value !== null && typeof value === "object" && !Array.isArray(value);
190556
190900
  }
190557
190901
 
@@ -191036,7 +191380,7 @@ function isSeverity(value) {
191036
191380
  return typeof value === "string" && severities.includes(value);
191037
191381
  }
191038
191382
  function normalizeCisaSecureByDesign(value) {
191039
- if (!isRecord9(value))
191383
+ if (!isRecord10(value))
191040
191384
  return;
191041
191385
  const normalized = {};
191042
191386
  const customerSecurityOutcomes = normalizeGateStatus(value.customerSecurityOutcomes);
@@ -191077,7 +191421,7 @@ function isEvidenceQuality(value) {
191077
191421
  return typeof value === "string" && evidenceQualities.includes(value);
191078
191422
  }
191079
191423
  function isStrictAgentOpinion(value) {
191080
- if (!isRecord9(value) || !hasOnlyKeys(value, STRICT_ROOT_KEYS))
191424
+ if (!isRecord10(value) || !hasOnlyKeys(value, STRICT_ROOT_KEYS))
191081
191425
  return false;
191082
191426
  if (typeof value.summary !== "string")
191083
191427
  return false;
@@ -191087,7 +191431,7 @@ function isStrictAgentOpinion(value) {
191087
191431
  return value.cisaSecureByDesign === undefined || isStrictCisaSecureByDesign(value.cisaSecureByDesign);
191088
191432
  }
191089
191433
  function isStrictFinding(value) {
191090
- if (!isRecord9(value) || !hasOnlyKeys(value, STRICT_FINDING_KEYS)) {
191434
+ if (!isRecord10(value) || !hasOnlyKeys(value, STRICT_FINDING_KEYS)) {
191091
191435
  return false;
191092
191436
  }
191093
191437
  if (!isSeverity(value.severity) || !isCategory(value.category) || !isNonEmptyString(value.title) || !isNonEmptyString(value.evidence) || !isNonEmptyString(value.recommendation) || !isConfidence(value.confidence)) {
@@ -191099,11 +191443,11 @@ function isStrictFinding(value) {
191099
191443
  return true;
191100
191444
  }
191101
191445
  function isStrictFindingFiles(value) {
191102
- return Array.isArray(value) && value.every((item) => isRecord9(item) && hasOnlyKeys(item, STRICT_FILE_KEYS) && isNonEmptyString(item.path) && isOptionalLineNumber(item.lineStart) && isOptionalLineNumber(item.lineEnd));
191446
+ return Array.isArray(value) && value.every((item) => isRecord10(item) && hasOnlyKeys(item, STRICT_FILE_KEYS) && isNonEmptyString(item.path) && isOptionalLineNumber(item.lineStart) && isOptionalLineNumber(item.lineEnd));
191103
191447
  }
191104
191448
  function isStrictEvidenceRefs(value) {
191105
191449
  return Array.isArray(value) && value.length <= MAX_EVIDENCE_REFS2 && value.every((item) => {
191106
- if (!isRecord9(item) || !hasOnlyKeys(item, STRICT_EVIDENCE_REF_KEYS)) {
191450
+ if (!isRecord10(item) || !hasOnlyKeys(item, STRICT_EVIDENCE_REF_KEYS)) {
191107
191451
  return false;
191108
191452
  }
191109
191453
  if (item.kind !== "file" && item.kind !== "diff_hunk" && item.kind !== "plan_clause") {
@@ -191119,7 +191463,7 @@ function isStrictEvidenceRefs(value) {
191119
191463
  });
191120
191464
  }
191121
191465
  function isStrictCisaSecureByDesign(value) {
191122
- if (!isRecord9(value) || !hasOnlyKeys(value, STRICT_CISA_KEYS))
191466
+ if (!isRecord10(value) || !hasOnlyKeys(value, STRICT_CISA_KEYS))
191123
191467
  return false;
191124
191468
  for (const key of [
191125
191469
  "customerSecurityOutcomes",
@@ -191158,7 +191502,7 @@ function normalizeFindingFiles(value) {
191158
191502
  if (!Array.isArray(value))
191159
191503
  return;
191160
191504
  const files = value.flatMap((item) => {
191161
- if (!isRecord9(item) || typeof item.path !== "string" || item.path.trim().length === 0) {
191505
+ if (!isRecord10(item) || typeof item.path !== "string" || item.path.trim().length === 0) {
191162
191506
  return [];
191163
191507
  }
191164
191508
  const file2 = {
@@ -191178,7 +191522,7 @@ function normalizeEvidenceRefs2(value) {
191178
191522
  if (!Array.isArray(value))
191179
191523
  return;
191180
191524
  const references = value.slice(0, MAX_EVIDENCE_REFS2).flatMap((item) => {
191181
- if (!isRecord9(item) || item.kind !== "file" && item.kind !== "diff_hunk" && item.kind !== "plan_clause") {
191525
+ if (!isRecord10(item) || item.kind !== "file" && item.kind !== "diff_hunk" && item.kind !== "plan_clause") {
191182
191526
  return [];
191183
191527
  }
191184
191528
  const reference = { kind: item.kind };
@@ -191201,7 +191545,7 @@ function normalizeEvidenceRefs2(value) {
191201
191545
  function normalizeLineNumber(value) {
191202
191546
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 && value <= MAX_EVIDENCE_LINE2 ? value : undefined;
191203
191547
  }
191204
- function isRecord9(value) {
191548
+ function isRecord10(value) {
191205
191549
  return typeof value === "object" && value !== null && !Array.isArray(value);
191206
191550
  }
191207
191551
 
@@ -191541,7 +191885,7 @@ async function runAcpClientWorkflow(child, input, abortController, configOption,
191541
191885
  }
191542
191886
  const output = Writable.toWeb(child.stdin);
191543
191887
  const inputStream = Readable.toWeb(child.stdout);
191544
- const stream2 = ndJsonStream(output, limitAcpNdJsonLineBytes(inputStream));
191888
+ const stream = ndJsonStream2(output, limitAcpNdJsonLineBytes(inputStream));
191545
191889
  const app = client({ name: "kyoso" }).onRequest(methods.client.session.requestPermission, () => ({
191546
191890
  outcome: { outcome: "cancelled" }
191547
191891
  })).onRequest(methods.client.fs.readTextFile, async (ctx) => ({
@@ -191563,7 +191907,7 @@ async function runAcpClientWorkflow(child, input, abortController, configOption,
191563
191907
  policy: "Kyoso does not create terminals."
191564
191908
  });
191565
191909
  }).onRequest(methods.client.terminal.kill, () => ({}));
191566
- return app.connectWith(stream2, async (ctx) => {
191910
+ return app.connectWith(stream, async (ctx) => {
191567
191911
  await ctx.request(methods.agent.initialize, {
191568
191912
  protocolVersion: PROTOCOL_VERSION,
191569
191913
  clientCapabilities: {
@@ -191826,7 +192170,7 @@ function normalizeUsage(usage) {
191826
192170
  return normalizeModelTokenUsage(usage);
191827
192171
  }
191828
192172
  function withReportedExecutionIdentity(identity, metadata) {
191829
- const record2 = isRecord10(metadata) ? metadata : {};
192173
+ const record2 = isRecord11(metadata) ? metadata : {};
191830
192174
  return createModelExecutionIdentity({
191831
192175
  providerRoute: identity.providerRoute,
191832
192176
  requestedModel: identity.requestedModel,
@@ -191835,9 +192179,9 @@ function withReportedExecutionIdentity(identity, metadata) {
191835
192179
  });
191836
192180
  }
191837
192181
  function readChunkMeta(update) {
191838
- const record2 = isRecord10(update) ? update : {};
191839
- const metadata = isRecord10(record2._meta) ? record2._meta : {};
191840
- const codex = isRecord10(metadata.codex) ? metadata.codex : {};
192182
+ const record2 = isRecord11(update) ? update : {};
192183
+ const metadata = isRecord11(record2._meta) ? record2._meta : {};
192184
+ const codex = isRecord11(metadata.codex) ? metadata.codex : {};
191841
192185
  const phase = codex.phase === "commentary" || codex.phase === "final_answer" ? codex.phase : "unknown";
191842
192186
  return {
191843
192187
  ...typeof record2.messageId === "string" ? { messageId: record2.messageId } : {},
@@ -191845,15 +192189,15 @@ function readChunkMeta(update) {
191845
192189
  };
191846
192190
  }
191847
192191
  function readCodexThreadStatus(update) {
191848
- const record2 = isRecord10(update) ? update : {};
192192
+ const record2 = isRecord11(update) ? update : {};
191849
192193
  if (record2.sessionUpdate !== "session_info_update")
191850
192194
  return;
191851
- const metadata = isRecord10(record2._meta) ? record2._meta : {};
191852
- const codex = isRecord10(metadata.codex) ? metadata.codex : {};
191853
- const threadStatus = isRecord10(codex.threadStatus) ? codex.threadStatus : {};
192195
+ const metadata = isRecord11(record2._meta) ? record2._meta : {};
192196
+ const codex = isRecord11(metadata.codex) ? metadata.codex : {};
192197
+ const threadStatus = isRecord11(codex.threadStatus) ? codex.threadStatus : {};
191854
192198
  return typeof threadStatus.type === "string" ? threadStatus.type : undefined;
191855
192199
  }
191856
- function isRecord10(value) {
192200
+ function isRecord11(value) {
191857
192201
  return value !== null && typeof value === "object" && !Array.isArray(value);
191858
192202
  }
191859
192203
  function resolveEffortConfigOption(agent, effort) {
@@ -193558,7 +193902,7 @@ function validateReviewContract(request) {
193558
193902
  const contract = request.reviewContract;
193559
193903
  if (contract === undefined)
193560
193904
  return;
193561
- if (!isRecord11(contract)) {
193905
+ if (!isRecord12(contract)) {
193562
193906
  throw new KyosoRequestError("reviewContract must be an object", "VALIDATION_ERROR");
193563
193907
  }
193564
193908
  const allowedKeys = new Set(["focus", "nonGoals", "acceptedRisks"]);
@@ -193575,7 +193919,7 @@ function validateReviewContract(request) {
193575
193919
  throw new KyosoRequestError("reviewContract.nonGoals must contain at most 20 non-empty strings of 500 characters or fewer", "VALIDATION_ERROR");
193576
193920
  }
193577
193921
  const acceptedRisks = contract.acceptedRisks;
193578
- if (acceptedRisks !== undefined && (!Array.isArray(acceptedRisks) || acceptedRisks.length > 20 || acceptedRisks.some((risk) => !isRecord11(risk) || typeof risk.findingFingerprint !== "string" || !/^sha256:[0-9a-f]{64}$/.test(risk.findingFingerprint) || typeof risk.rationale !== "string" || risk.rationale.trim().length === 0 || risk.rationale.length > 500))) {
193922
+ if (acceptedRisks !== undefined && (!Array.isArray(acceptedRisks) || acceptedRisks.length > 20 || acceptedRisks.some((risk) => !isRecord12(risk) || typeof risk.findingFingerprint !== "string" || !/^sha256:[0-9a-f]{64}$/.test(risk.findingFingerprint) || typeof risk.rationale !== "string" || risk.rationale.trim().length === 0 || risk.rationale.length > 500))) {
193579
193923
  throw new KyosoRequestError("reviewContract.acceptedRisks must contain valid finding fingerprints and bounded rationales", "VALIDATION_ERROR");
193580
193924
  }
193581
193925
  }
@@ -193587,13 +193931,13 @@ function validateSelectedFiles(request) {
193587
193931
  throw new KyosoRequestError("selectedFiles must be an array", "VALIDATION_ERROR");
193588
193932
  }
193589
193933
  for (const file2 of selectedFiles) {
193590
- if (!isRecord11(file2) || typeof file2.path !== "string" || file2.path.trim().length === 0 || typeof file2.content !== "string" || file2.language !== undefined && typeof file2.language !== "string" || file2.truncated !== undefined && typeof file2.truncated !== "boolean") {
193934
+ if (!isRecord12(file2) || typeof file2.path !== "string" || file2.path.trim().length === 0 || typeof file2.content !== "string" || file2.language !== undefined && typeof file2.language !== "string" || file2.truncated !== undefined && typeof file2.truncated !== "boolean") {
193591
193935
  throw new KyosoRequestError("selectedFiles entries require string path/content and valid optional metadata", "VALIDATION_ERROR");
193592
193936
  }
193593
193937
  normalizeRelativePath(file2.path);
193594
193938
  }
193595
193939
  }
193596
- function isRecord11(value) {
193940
+ function isRecord12(value) {
193597
193941
  return typeof value === "object" && value !== null && !Array.isArray(value);
193598
193942
  }
193599
193943
 
@@ -193854,7 +194198,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
193854
194198
  const parsed = JSON.parse(json2);
193855
194199
  const summaryText = typeof parsed.summaryText === "string" && parsed.summaryText.trim().length > 0 ? sanitizeText(parsed.summaryText) : fallbackSummaryText;
193856
194200
  const disagreementComments = Array.isArray(parsed.disagreementComments) ? parsed.disagreementComments.flatMap((item) => {
193857
- if (!isRecord12(item) || typeof item.topic !== "string" || typeof item.judgeComment !== "string") {
194201
+ if (!isRecord13(item) || typeof item.topic !== "string" || typeof item.judgeComment !== "string") {
193858
194202
  return [];
193859
194203
  }
193860
194204
  return [
@@ -193870,7 +194214,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
193870
194214
  return { summaryText, disagreementComments, analysis };
193871
194215
  }
193872
194216
  function parseAnalysis(value) {
193873
- if (!isRecord12(value))
194217
+ if (!isRecord13(value))
193874
194218
  return;
193875
194219
  if (!Array.isArray(value.blindSpots) || !Array.isArray(value.contradictions) || !Array.isArray(value.partialCoverage)) {
193876
194220
  return;
@@ -193878,7 +194222,7 @@ function parseAnalysis(value) {
193878
194222
  return {
193879
194223
  blindSpots: value.blindSpots.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => typeof item === "string" ? [sanitizeAnalysisText(item)] : []),
193880
194224
  contradictions: value.contradictions.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
193881
- if (!isRecord12(item) || typeof item.topic !== "string" || typeof item.detail !== "string") {
194225
+ if (!isRecord13(item) || typeof item.topic !== "string" || typeof item.detail !== "string") {
193882
194226
  return [];
193883
194227
  }
193884
194228
  return [
@@ -193889,7 +194233,7 @@ function parseAnalysis(value) {
193889
194233
  ];
193890
194234
  }),
193891
194235
  partialCoverage: value.partialCoverage.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
193892
- if (!isRecord12(item) || typeof item.note !== "string")
194236
+ if (!isRecord13(item) || typeof item.note !== "string")
193893
194237
  return [];
193894
194238
  const findingId = typeof item.findingId === "string" ? sanitizeAnalysisText(item.findingId) : undefined;
193895
194239
  return [
@@ -193936,7 +194280,7 @@ function extractFirstJsonObject2(text) {
193936
194280
  }
193937
194281
  return;
193938
194282
  }
193939
- function isRecord12(value) {
194283
+ function isRecord13(value) {
193940
194284
  return typeof value === "object" && value !== null && !Array.isArray(value);
193941
194285
  }
193942
194286
 
@@ -194481,11 +194825,11 @@ function canonicalJson(value) {
194481
194825
  function canonicalize(value) {
194482
194826
  if (Array.isArray(value))
194483
194827
  return value.map(canonicalize);
194484
- if (!isRecord13(value))
194828
+ if (!isRecord14(value))
194485
194829
  return value;
194486
194830
  return Object.fromEntries(Object.entries(value).filter(([, child]) => child !== undefined).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([key, child]) => [key, canonicalize(child)]));
194487
194831
  }
194488
- function isRecord13(value) {
194832
+ function isRecord14(value) {
194489
194833
  return typeof value === "object" && value !== null && !Array.isArray(value);
194490
194834
  }
194491
194835
 
@@ -194493,19 +194837,24 @@ function isRecord13(value) {
194493
194837
  var REVIEW_BUDGET_KEYS = new Set([
194494
194838
  "maxModelCalls",
194495
194839
  "maxTotalWallTimeMs",
194840
+ "maxTotalWallTimeS",
194496
194841
  "maxAgentOutputBytes",
194497
194842
  "maxFindingsPerAgent",
194498
194843
  "skipOptionalPhasesWhenTokenUsageUnknown"
194499
194844
  ]);
194500
194845
  var MODEL_CALL_KINDS = ["primary", "verifier", "judge"];
194501
194846
  function resolveReviewBudget(ceiling, requested) {
194502
- if (requested !== undefined && !isRecord14(requested)) {
194847
+ if (requested !== undefined && !isRecord15(requested)) {
194503
194848
  throw new KyosoRequestError("options.reviewBudget must be an object.", "REVIEW_BUDGET_INVALID");
194504
194849
  }
194850
+ const hasWallTimeSeconds = requested?.maxTotalWallTimeS !== undefined;
194505
194851
  for (const [key, value] of Object.entries(requested ?? {})) {
194506
194852
  if (!REVIEW_BUDGET_KEYS.has(key)) {
194507
194853
  throw new KyosoRequestError(`options.reviewBudget.${key} is not supported.`, "REVIEW_BUDGET_INVALID");
194508
194854
  }
194855
+ if (key === "maxTotalWallTimeS" || key === "maxTotalWallTimeMs" && hasWallTimeSeconds) {
194856
+ continue;
194857
+ }
194509
194858
  if (key === "skipOptionalPhasesWhenTokenUsageUnknown") {
194510
194859
  if (typeof value !== "boolean") {
194511
194860
  throw new KyosoRequestError(`options.reviewBudget.${key} must be a boolean.`, "REVIEW_BUDGET_INVALID");
@@ -194516,12 +194865,26 @@ function resolveReviewBudget(ceiling, requested) {
194516
194865
  throw new KyosoRequestError(`options.reviewBudget.${key} must be a positive integer.`, "REVIEW_BUDGET_INVALID");
194517
194866
  }
194518
194867
  }
194519
- const numericKeys = [
194520
- "maxModelCalls",
194521
- "maxTotalWallTimeMs",
194522
- "maxAgentOutputBytes",
194523
- "maxFindingsPerAgent"
194524
- ];
194868
+ let requestedWallTime;
194869
+ if (hasWallTimeSeconds) {
194870
+ try {
194871
+ requestedWallTime = resolveTimeUnitPair({
194872
+ milliseconds: requested?.maxTotalWallTimeMs,
194873
+ seconds: requested?.maxTotalWallTimeS
194874
+ }, {
194875
+ milliseconds: "options.reviewBudget.maxTotalWallTimeMs",
194876
+ seconds: "options.reviewBudget.maxTotalWallTimeS"
194877
+ });
194878
+ } catch (error51) {
194879
+ if (error51 instanceof TimeUnitValidationError) {
194880
+ throw new KyosoRequestError(error51.message, "REVIEW_BUDGET_INVALID");
194881
+ }
194882
+ throw error51;
194883
+ }
194884
+ }
194885
+ const numericKeys = ["maxModelCalls", "maxAgentOutputBytes", "maxFindingsPerAgent"];
194886
+ if (!hasWallTimeSeconds)
194887
+ numericKeys.push("maxTotalWallTimeMs");
194525
194888
  for (const key of numericKeys) {
194526
194889
  const value = requested?.[key];
194527
194890
  if (value === undefined)
@@ -194530,13 +194893,19 @@ function resolveReviewBudget(ceiling, requested) {
194530
194893
  throw new KyosoRequestError(`options.reviewBudget.${key} cannot exceed the user-global ceiling.`, "REVIEW_BUDGET_EXCEEDS_CEILING");
194531
194894
  }
194532
194895
  }
194896
+ if (hasWallTimeSeconds && requested?.maxTotalWallTimeMs !== undefined && requested.maxTotalWallTimeMs > ceiling.maxTotalWallTimeMs) {
194897
+ throw new KyosoRequestError("options.reviewBudget.maxTotalWallTimeMs cannot exceed the user-global ceiling.", "REVIEW_BUDGET_EXCEEDS_CEILING");
194898
+ }
194899
+ if (requestedWallTime && requestedWallTime.milliseconds > ceiling.maxTotalWallTimeMs) {
194900
+ throw new KyosoRequestError(`${requestedWallTime.sourceField} cannot exceed the user-global ceiling.`, "REVIEW_BUDGET_EXCEEDS_CEILING");
194901
+ }
194533
194902
  if (ceiling.skipOptionalPhasesWhenTokenUsageUnknown && requested?.skipOptionalPhasesWhenTokenUsageUnknown === false) {
194534
194903
  throw new KyosoRequestError("options.reviewBudget.skipOptionalPhasesWhenTokenUsageUnknown cannot relax the user-global ceiling.", "REVIEW_BUDGET_EXCEEDS_CEILING");
194535
194904
  }
194536
194905
  const maxAgentOutputBytes = requested?.maxAgentOutputBytes ?? ceiling.maxAgentOutputBytes;
194537
194906
  return {
194538
194907
  maxModelCalls: requested?.maxModelCalls ?? ceiling.maxModelCalls,
194539
- maxTotalWallTimeMs: requested?.maxTotalWallTimeMs ?? ceiling.maxTotalWallTimeMs,
194908
+ maxTotalWallTimeMs: requestedWallTime?.milliseconds ?? requested?.maxTotalWallTimeMs ?? ceiling.maxTotalWallTimeMs,
194540
194909
  warnAgentOutputBytes: ceiling.warnAgentOutputBytes,
194541
194910
  maxAgentOutputBytes,
194542
194911
  maxFindingsPerAgent: requested?.maxFindingsPerAgent ?? ceiling.maxFindingsPerAgent,
@@ -194853,10 +195222,63 @@ function emptyReviewModelCallPlan() {
194853
195222
  ceilingEffects: []
194854
195223
  };
194855
195224
  }
194856
- function isRecord14(value) {
195225
+ function isRecord15(value) {
194857
195226
  return typeof value === "object" && value !== null && !Array.isArray(value);
194858
195227
  }
194859
195228
 
195229
+ // src/core/requestTimeUnits.ts
195230
+ function normalizeRequestTimeUnits(request) {
195231
+ if (!request.options)
195232
+ return request;
195233
+ const options = { ...request.options };
195234
+ normalizeRequestTimeUnitField(options, "maxAgentTimeoutMs", "maxAgentTimeoutS", {
195235
+ milliseconds: "options.maxAgentTimeoutMs",
195236
+ seconds: "options.maxAgentTimeoutS"
195237
+ });
195238
+ if (options.reviewBudget) {
195239
+ const reviewBudget = { ...options.reviewBudget };
195240
+ normalizeRequestTimeUnitField(reviewBudget, "maxTotalWallTimeMs", "maxTotalWallTimeS", {
195241
+ milliseconds: "options.reviewBudget.maxTotalWallTimeMs",
195242
+ seconds: "options.reviewBudget.maxTotalWallTimeS"
195243
+ });
195244
+ options.reviewBudget = reviewBudget;
195245
+ }
195246
+ return { ...request, options };
195247
+ }
195248
+ function resolveProgressHeartbeatMs(input) {
195249
+ if (input.progressHeartbeatS === undefined) {
195250
+ return input.progressHeartbeatMs;
195251
+ }
195252
+ return resolveRequestTimeUnit({
195253
+ milliseconds: input.progressHeartbeatMs,
195254
+ seconds: input.progressHeartbeatS
195255
+ }, {
195256
+ milliseconds: "progressHeartbeatMs",
195257
+ seconds: "progressHeartbeatS"
195258
+ }, { allowZero: true })?.milliseconds;
195259
+ }
195260
+ function normalizeRequestTimeUnitField(target, millisecondsKey, secondsKey, fields) {
195261
+ if (target[secondsKey] !== undefined) {
195262
+ const resolved = resolveRequestTimeUnit({
195263
+ milliseconds: target[millisecondsKey],
195264
+ seconds: target[secondsKey]
195265
+ }, fields);
195266
+ if (resolved)
195267
+ target[millisecondsKey] = resolved.milliseconds;
195268
+ }
195269
+ delete target[secondsKey];
195270
+ }
195271
+ function resolveRequestTimeUnit(input, fields, constraints) {
195272
+ try {
195273
+ return resolveTimeUnitPair(input, fields, constraints);
195274
+ } catch (error51) {
195275
+ if (error51 instanceof TimeUnitValidationError) {
195276
+ throw new KyosoRequestError(error51.message, "VALIDATION_ERROR");
195277
+ }
195278
+ throw error51;
195279
+ }
195280
+ }
195281
+
194860
195282
  // src/core/verification.ts
194861
195283
  var REAL_AGENTS = ["codex", "claude"];
194862
195284
  var VERIFIABLE_SEVERITIES = new Set(["critical", "high"]);
@@ -194915,7 +195337,7 @@ function parseVerificationVerdicts(rawText) {
194915
195337
  if (!Array.isArray(parsed.verdicts))
194916
195338
  return;
194917
195339
  return parsed.verdicts.flatMap((item) => {
194918
- if (!isRecord15(item))
195340
+ if (!isRecord16(item))
194919
195341
  return [];
194920
195342
  if (typeof item.findingId !== "string")
194921
195343
  return [];
@@ -194993,7 +195415,7 @@ function verificationNote(reasoning) {
194993
195415
  function isVerdict(value) {
194994
195416
  return value === "confirmed" || value === "refuted" || value === "uncertain";
194995
195417
  }
194996
- function isRecord15(value) {
195418
+ function isRecord16(value) {
194997
195419
  return typeof value === "object" && value !== null && !Array.isArray(value);
194998
195420
  }
194999
195421
 
@@ -195001,7 +195423,7 @@ function isRecord15(value) {
195001
195423
  var MAX_AGENT_RETRY_PROGRESS_EVENTS = 100;
195002
195424
  function requestForRecursionFingerprint(request) {
195003
195425
  try {
195004
- return scanAndRedactSecrets(request).redactedRequest;
195426
+ return scanAndRedactSecrets(normalizeRequestTimeUnits(request)).redactedRequest;
195005
195427
  } catch {
195006
195428
  return { goal: "" };
195007
195429
  }
@@ -195261,15 +195683,17 @@ async function runReview(tool, request, options = {}) {
195261
195683
  });
195262
195684
  validateReviewRequest(tool, request);
195263
195685
  const reviewBudget = resolveReviewBudget(loaded.config.reviewBudget, request.options?.reviewBudget);
195264
- const budgetTracker = new ReviewBudgetTracker(reviewBudget, startedAtEpochMs, configuredReviewModelCallPlan(loaded.config, reviewBudget, options.env ?? process.env, request.options?.judgeProvider));
195265
- assertTrustedWorkspaceRoot(request.workspace?.root, loaded.config.workspace.root, cwd);
195266
- const networkMode = resolveNetworkMode(request.options?.network, loaded.config.network.defaultMode, options.mcpNetworkMode);
195686
+ const normalizedRequest = normalizeRequestTimeUnits(request);
195687
+ const progressHeartbeatMs = resolveProgressHeartbeatMs(options);
195688
+ const budgetTracker = new ReviewBudgetTracker(reviewBudget, startedAtEpochMs, configuredReviewModelCallPlan(loaded.config, reviewBudget, options.env ?? process.env, normalizedRequest.options?.judgeProvider));
195689
+ assertTrustedWorkspaceRoot(normalizedRequest.workspace?.root, loaded.config.workspace.root, cwd);
195690
+ const networkMode = resolveNetworkMode(normalizedRequest.options?.network, loaded.config.network.defaultMode, options.mcpNetworkMode);
195267
195691
  if (networkMode === "unrestricted" && !loaded.config.network.allowUnrestricted) {
195268
195692
  throw new KyosoRequestError("unrestricted network mode is disabled by config", "NETWORK_MODE_DISABLED");
195269
195693
  }
195270
195694
  const disabledPolicy = disabledReviewPolicy(tool, loaded.config, options.entrypoint);
195271
195695
  if (disabledPolicy) {
195272
- const redactedRequest = requestForRecursionFingerprint(request);
195696
+ const redactedRequest = requestForRecursionFingerprint(normalizedRequest);
195273
195697
  const requestFingerprint2 = createRequestFingerprint({
195274
195698
  tool,
195275
195699
  request: redactedRequest,
@@ -195320,7 +195744,7 @@ async function runReview(tool, request, options = {}) {
195320
195744
  warnings.push("Network mode is unrestricted; write policy remains denied.");
195321
195745
  }
195322
195746
  startPhase("context");
195323
- const secretScan = scanAndRedactSecrets(request);
195747
+ const secretScan = scanAndRedactSecrets(normalizedRequest);
195324
195748
  await trace.write({
195325
195749
  type: "secret_scan_completed",
195326
195750
  traceId,
@@ -195328,7 +195752,7 @@ async function runReview(tool, request, options = {}) {
195328
195752
  redactions: secretScan.redactions,
195329
195753
  timestamp: new Date().toISOString()
195330
195754
  });
195331
- const allowSecretOverride = loaded.config.secrets.allowOverride && request.options?.allowSecretRedaction === true;
195755
+ const allowSecretOverride = loaded.config.secrets.allowOverride && normalizedRequest.options?.allowSecretRedaction === true;
195332
195756
  if (secretScan.detected && loaded.config.secrets.blockOnDetectedSecret && !allowSecretOverride) {
195333
195757
  const requestFingerprint2 = createRequestFingerprint({
195334
195758
  tool,
@@ -195415,7 +195839,7 @@ async function runReview(tool, request, options = {}) {
195415
195839
  budgetTracker,
195416
195840
  progressDispatcher: dispatcher,
195417
195841
  signal: options.signal,
195418
- progressHeartbeatMs: options.progressHeartbeatMs
195842
+ progressHeartbeatMs
195419
195843
  });
195420
195844
  completePhase("primary");
195421
195845
  warnings.push(...agentResults.flatMap((result) => (result.warnings ?? []).map((warning) => `Agent ${result.agent} ${warning}`)));