@kyo-so/cli 0.15.2 → 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/.agents/skills/kyoso-review/SKILL.md +1 -1
- package/CHANGELOG.md +16 -0
- package/README.ja.md +17 -13
- package/README.md +17 -13
- package/README.zh-CN.md +17 -13
- package/dist/bin/kyoso.js +386 -119
- package/dist/cli/knownSkillDigests.d.ts +5 -1
- package/dist/cli/pluginRuntimeContract.d.ts +4 -4
- package/dist/config/projectScope.d.ts +1 -1
- package/dist/config/schema.d.ts +22 -1
- package/dist/config/timeUnits.d.ts +29 -0
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/requestTimeUnits.d.ts +6 -0
- package/dist/core/runReview.d.ts +1 -0
- package/dist/core/types.d.ts +9 -1
- package/dist/index.js +333 -87
- package/dist/mcp/schemas.d.ts +2 -0
- package/dist/utils/timeUnits.d.ts +22 -0
- package/examples/kyoso.toml +2 -2
- package/package.json +2 -1
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",
|
|
@@ -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) || !
|
|
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 (!
|
|
185965
|
+
if (!isRecord4(config2))
|
|
185817
185966
|
return false;
|
|
185818
185967
|
const agents = config2.agents;
|
|
185819
|
-
if (!
|
|
185968
|
+
if (!isRecord4(agents))
|
|
185820
185969
|
return false;
|
|
185821
185970
|
const codex = agents.codex;
|
|
185822
|
-
if (!
|
|
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 (!
|
|
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 (!
|
|
186121
|
+
if (!isRecord4(value))
|
|
185973
186122
|
return;
|
|
185974
186123
|
const nested = value[key];
|
|
185975
|
-
return
|
|
186124
|
+
return isRecord4(nested) ? nested : undefined;
|
|
185976
186125
|
}
|
|
185977
|
-
function
|
|
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
|
-
|
|
186006
|
-
|
|
186007
|
-
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
|
186271
|
+
function isRecord5(value) {
|
|
186106
186272
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
186107
186273
|
}
|
|
186108
186274
|
|
|
@@ -188510,17 +188676,17 @@ function isResponseMessage(value) {
|
|
|
188510
188676
|
function isNotificationMessage(value) {
|
|
188511
188677
|
return isJsonRpcEnvelope(value) && !("id" in value) && typeof value["method"] === "string";
|
|
188512
188678
|
}
|
|
188513
|
-
function
|
|
188679
|
+
function isRecord6(value) {
|
|
188514
188680
|
return typeof value === "object" && value !== null;
|
|
188515
188681
|
}
|
|
188516
188682
|
function isJsonRpcEnvelope(value) {
|
|
188517
|
-
return
|
|
188683
|
+
return isRecord6(value) && value["jsonrpc"] === "2.0";
|
|
188518
188684
|
}
|
|
188519
188685
|
function isJsonRpcId(value) {
|
|
188520
188686
|
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
188521
188687
|
}
|
|
188522
188688
|
function isResponseShapedMessage(value) {
|
|
188523
|
-
return
|
|
188689
|
+
return isRecord6(value) && !("method" in value) && (("id" in value) || ("result" in value) || ("error" in value));
|
|
188524
188690
|
}
|
|
188525
188691
|
function isResponseBatch(batch) {
|
|
188526
188692
|
let hasValidCall = false;
|
|
@@ -188530,7 +188696,7 @@ function isResponseBatch(batch) {
|
|
|
188530
188696
|
for (const entry of batch) {
|
|
188531
188697
|
hasValidCall ||= isRequestMessage(entry) || isNotificationMessage(entry);
|
|
188532
188698
|
hasValidResponse ||= isResponseMessage(entry);
|
|
188533
|
-
if (!
|
|
188699
|
+
if (!isRecord6(entry)) {
|
|
188534
188700
|
continue;
|
|
188535
188701
|
}
|
|
188536
188702
|
hasCallShape ||= "method" in entry;
|
|
@@ -188545,13 +188711,13 @@ function isResponseBatch(batch) {
|
|
|
188545
188711
|
return hasResponseShape && !hasCallShape;
|
|
188546
188712
|
}
|
|
188547
188713
|
function cancelRequestId(params) {
|
|
188548
|
-
if (!
|
|
188714
|
+
if (!isRecord6(params) || !isJsonRpcId(params["requestId"])) {
|
|
188549
188715
|
return;
|
|
188550
188716
|
}
|
|
188551
188717
|
return params["requestId"];
|
|
188552
188718
|
}
|
|
188553
188719
|
function isErrorResponse(value) {
|
|
188554
|
-
return
|
|
188720
|
+
return isRecord6(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
|
|
188555
188721
|
}
|
|
188556
188722
|
var Handled = {
|
|
188557
188723
|
yes() {
|
|
@@ -188946,7 +189112,7 @@ class Connection {
|
|
|
188946
189112
|
this.receiveBatch(message);
|
|
188947
189113
|
return;
|
|
188948
189114
|
}
|
|
188949
|
-
if (!
|
|
189115
|
+
if (!isRecord6(message)) {
|
|
188950
189116
|
console.error("Invalid message", { message });
|
|
188951
189117
|
return;
|
|
188952
189118
|
}
|
|
@@ -189007,7 +189173,7 @@ class Connection {
|
|
|
189007
189173
|
if (this.abortController.signal.aborted) {
|
|
189008
189174
|
return Promise.resolve();
|
|
189009
189175
|
}
|
|
189010
|
-
if (!
|
|
189176
|
+
if (!isRecord6(message)) {
|
|
189011
189177
|
console.error("Invalid message", { message });
|
|
189012
189178
|
return Promise.resolve();
|
|
189013
189179
|
}
|
|
@@ -189314,7 +189480,7 @@ function ndJsonStream(output, input) {
|
|
|
189314
189480
|
if (trimmedLine) {
|
|
189315
189481
|
try {
|
|
189316
189482
|
const message = JSON.parse(trimmedLine);
|
|
189317
|
-
if (
|
|
189483
|
+
if (isRecord6(message) || Array.isArray(message)) {
|
|
189318
189484
|
controller.enqueue(message);
|
|
189319
189485
|
} else {
|
|
189320
189486
|
console.warn("Skipping JSON line that is not an object:", trimmedLine);
|
|
@@ -190264,7 +190430,7 @@ function createModelExecutionIdentity(input) {
|
|
|
190264
190430
|
};
|
|
190265
190431
|
}
|
|
190266
190432
|
function normalizeModelExecutionIdentity(value) {
|
|
190267
|
-
if (!
|
|
190433
|
+
if (!isRecord7(value) || !isModelProviderRoute(value.providerRoute)) {
|
|
190268
190434
|
return;
|
|
190269
190435
|
}
|
|
190270
190436
|
return createModelExecutionIdentity({
|
|
@@ -190286,7 +190452,7 @@ function sanitizeIdentityValue(value) {
|
|
|
190286
190452
|
function isModelProviderRoute(value) {
|
|
190287
190453
|
return typeof value === "string" && MODEL_PROVIDER_ROUTES.has(value);
|
|
190288
190454
|
}
|
|
190289
|
-
function
|
|
190455
|
+
function isRecord7(value) {
|
|
190290
190456
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
190291
190457
|
}
|
|
190292
190458
|
|
|
@@ -190300,7 +190466,7 @@ var TOKEN_USAGE_KEYS = [
|
|
|
190300
190466
|
"cachedWriteTokens"
|
|
190301
190467
|
];
|
|
190302
190468
|
function normalizeModelTokenUsage(usage) {
|
|
190303
|
-
if (!
|
|
190469
|
+
if (!isRecord8(usage))
|
|
190304
190470
|
return;
|
|
190305
190471
|
const normalized = {};
|
|
190306
190472
|
for (const key of TOKEN_USAGE_KEYS) {
|
|
@@ -190313,7 +190479,7 @@ function normalizeModelTokenUsage(usage) {
|
|
|
190313
190479
|
function isTokenCount(value) {
|
|
190314
190480
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
190315
190481
|
}
|
|
190316
|
-
function
|
|
190482
|
+
function isRecord8(value) {
|
|
190317
190483
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
190318
190484
|
}
|
|
190319
190485
|
|
|
@@ -190704,12 +190870,12 @@ class AgentOutputAccumulator {
|
|
|
190704
190870
|
var RETRY_ATTEMPT_PATTERN = /Reconnecting\.\.\.\s*(\d+)\/(\d+)/;
|
|
190705
190871
|
var DISPLAY_MESSAGE_FIELDS = ["title", "text", "message", "description"];
|
|
190706
190872
|
function parseCodexRetryUpdate(update) {
|
|
190707
|
-
if (!
|
|
190873
|
+
if (!isRecord9(update) || update.sessionUpdate !== "session_info_update") {
|
|
190708
190874
|
return;
|
|
190709
190875
|
}
|
|
190710
|
-
const meta3 =
|
|
190711
|
-
const codex = meta3 &&
|
|
190712
|
-
const error51 = codex &&
|
|
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;
|
|
190713
190879
|
if (error51?.willRetry !== true)
|
|
190714
190880
|
return;
|
|
190715
190881
|
const rawMessage = typeof error51.message === "string" ? error51.message : findDisplayMessage(update) ?? "model stream retry";
|
|
@@ -190729,7 +190895,7 @@ function findDisplayMessage(update) {
|
|
|
190729
190895
|
}
|
|
190730
190896
|
return;
|
|
190731
190897
|
}
|
|
190732
|
-
function
|
|
190898
|
+
function isRecord9(value) {
|
|
190733
190899
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
190734
190900
|
}
|
|
190735
190901
|
|
|
@@ -191214,7 +191380,7 @@ function isSeverity(value) {
|
|
|
191214
191380
|
return typeof value === "string" && severities.includes(value);
|
|
191215
191381
|
}
|
|
191216
191382
|
function normalizeCisaSecureByDesign(value) {
|
|
191217
|
-
if (!
|
|
191383
|
+
if (!isRecord10(value))
|
|
191218
191384
|
return;
|
|
191219
191385
|
const normalized = {};
|
|
191220
191386
|
const customerSecurityOutcomes = normalizeGateStatus(value.customerSecurityOutcomes);
|
|
@@ -191255,7 +191421,7 @@ function isEvidenceQuality(value) {
|
|
|
191255
191421
|
return typeof value === "string" && evidenceQualities.includes(value);
|
|
191256
191422
|
}
|
|
191257
191423
|
function isStrictAgentOpinion(value) {
|
|
191258
|
-
if (!
|
|
191424
|
+
if (!isRecord10(value) || !hasOnlyKeys(value, STRICT_ROOT_KEYS))
|
|
191259
191425
|
return false;
|
|
191260
191426
|
if (typeof value.summary !== "string")
|
|
191261
191427
|
return false;
|
|
@@ -191265,7 +191431,7 @@ function isStrictAgentOpinion(value) {
|
|
|
191265
191431
|
return value.cisaSecureByDesign === undefined || isStrictCisaSecureByDesign(value.cisaSecureByDesign);
|
|
191266
191432
|
}
|
|
191267
191433
|
function isStrictFinding(value) {
|
|
191268
|
-
if (!
|
|
191434
|
+
if (!isRecord10(value) || !hasOnlyKeys(value, STRICT_FINDING_KEYS)) {
|
|
191269
191435
|
return false;
|
|
191270
191436
|
}
|
|
191271
191437
|
if (!isSeverity(value.severity) || !isCategory(value.category) || !isNonEmptyString(value.title) || !isNonEmptyString(value.evidence) || !isNonEmptyString(value.recommendation) || !isConfidence(value.confidence)) {
|
|
@@ -191277,11 +191443,11 @@ function isStrictFinding(value) {
|
|
|
191277
191443
|
return true;
|
|
191278
191444
|
}
|
|
191279
191445
|
function isStrictFindingFiles(value) {
|
|
191280
|
-
return Array.isArray(value) && value.every((item) =>
|
|
191446
|
+
return Array.isArray(value) && value.every((item) => isRecord10(item) && hasOnlyKeys(item, STRICT_FILE_KEYS) && isNonEmptyString(item.path) && isOptionalLineNumber(item.lineStart) && isOptionalLineNumber(item.lineEnd));
|
|
191281
191447
|
}
|
|
191282
191448
|
function isStrictEvidenceRefs(value) {
|
|
191283
191449
|
return Array.isArray(value) && value.length <= MAX_EVIDENCE_REFS2 && value.every((item) => {
|
|
191284
|
-
if (!
|
|
191450
|
+
if (!isRecord10(item) || !hasOnlyKeys(item, STRICT_EVIDENCE_REF_KEYS)) {
|
|
191285
191451
|
return false;
|
|
191286
191452
|
}
|
|
191287
191453
|
if (item.kind !== "file" && item.kind !== "diff_hunk" && item.kind !== "plan_clause") {
|
|
@@ -191297,7 +191463,7 @@ function isStrictEvidenceRefs(value) {
|
|
|
191297
191463
|
});
|
|
191298
191464
|
}
|
|
191299
191465
|
function isStrictCisaSecureByDesign(value) {
|
|
191300
|
-
if (!
|
|
191466
|
+
if (!isRecord10(value) || !hasOnlyKeys(value, STRICT_CISA_KEYS))
|
|
191301
191467
|
return false;
|
|
191302
191468
|
for (const key of [
|
|
191303
191469
|
"customerSecurityOutcomes",
|
|
@@ -191336,7 +191502,7 @@ function normalizeFindingFiles(value) {
|
|
|
191336
191502
|
if (!Array.isArray(value))
|
|
191337
191503
|
return;
|
|
191338
191504
|
const files = value.flatMap((item) => {
|
|
191339
|
-
if (!
|
|
191505
|
+
if (!isRecord10(item) || typeof item.path !== "string" || item.path.trim().length === 0) {
|
|
191340
191506
|
return [];
|
|
191341
191507
|
}
|
|
191342
191508
|
const file2 = {
|
|
@@ -191356,7 +191522,7 @@ function normalizeEvidenceRefs2(value) {
|
|
|
191356
191522
|
if (!Array.isArray(value))
|
|
191357
191523
|
return;
|
|
191358
191524
|
const references = value.slice(0, MAX_EVIDENCE_REFS2).flatMap((item) => {
|
|
191359
|
-
if (!
|
|
191525
|
+
if (!isRecord10(item) || item.kind !== "file" && item.kind !== "diff_hunk" && item.kind !== "plan_clause") {
|
|
191360
191526
|
return [];
|
|
191361
191527
|
}
|
|
191362
191528
|
const reference = { kind: item.kind };
|
|
@@ -191379,7 +191545,7 @@ function normalizeEvidenceRefs2(value) {
|
|
|
191379
191545
|
function normalizeLineNumber(value) {
|
|
191380
191546
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 && value <= MAX_EVIDENCE_LINE2 ? value : undefined;
|
|
191381
191547
|
}
|
|
191382
|
-
function
|
|
191548
|
+
function isRecord10(value) {
|
|
191383
191549
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
191384
191550
|
}
|
|
191385
191551
|
|
|
@@ -192004,7 +192170,7 @@ function normalizeUsage(usage) {
|
|
|
192004
192170
|
return normalizeModelTokenUsage(usage);
|
|
192005
192171
|
}
|
|
192006
192172
|
function withReportedExecutionIdentity(identity, metadata) {
|
|
192007
|
-
const record2 =
|
|
192173
|
+
const record2 = isRecord11(metadata) ? metadata : {};
|
|
192008
192174
|
return createModelExecutionIdentity({
|
|
192009
192175
|
providerRoute: identity.providerRoute,
|
|
192010
192176
|
requestedModel: identity.requestedModel,
|
|
@@ -192013,9 +192179,9 @@ function withReportedExecutionIdentity(identity, metadata) {
|
|
|
192013
192179
|
});
|
|
192014
192180
|
}
|
|
192015
192181
|
function readChunkMeta(update) {
|
|
192016
|
-
const record2 =
|
|
192017
|
-
const metadata =
|
|
192018
|
-
const codex =
|
|
192182
|
+
const record2 = isRecord11(update) ? update : {};
|
|
192183
|
+
const metadata = isRecord11(record2._meta) ? record2._meta : {};
|
|
192184
|
+
const codex = isRecord11(metadata.codex) ? metadata.codex : {};
|
|
192019
192185
|
const phase = codex.phase === "commentary" || codex.phase === "final_answer" ? codex.phase : "unknown";
|
|
192020
192186
|
return {
|
|
192021
192187
|
...typeof record2.messageId === "string" ? { messageId: record2.messageId } : {},
|
|
@@ -192023,15 +192189,15 @@ function readChunkMeta(update) {
|
|
|
192023
192189
|
};
|
|
192024
192190
|
}
|
|
192025
192191
|
function readCodexThreadStatus(update) {
|
|
192026
|
-
const record2 =
|
|
192192
|
+
const record2 = isRecord11(update) ? update : {};
|
|
192027
192193
|
if (record2.sessionUpdate !== "session_info_update")
|
|
192028
192194
|
return;
|
|
192029
|
-
const metadata =
|
|
192030
|
-
const codex =
|
|
192031
|
-
const 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 : {};
|
|
192032
192198
|
return typeof threadStatus.type === "string" ? threadStatus.type : undefined;
|
|
192033
192199
|
}
|
|
192034
|
-
function
|
|
192200
|
+
function isRecord11(value) {
|
|
192035
192201
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
192036
192202
|
}
|
|
192037
192203
|
function resolveEffortConfigOption(agent, effort) {
|
|
@@ -193736,7 +193902,7 @@ function validateReviewContract(request) {
|
|
|
193736
193902
|
const contract = request.reviewContract;
|
|
193737
193903
|
if (contract === undefined)
|
|
193738
193904
|
return;
|
|
193739
|
-
if (!
|
|
193905
|
+
if (!isRecord12(contract)) {
|
|
193740
193906
|
throw new KyosoRequestError("reviewContract must be an object", "VALIDATION_ERROR");
|
|
193741
193907
|
}
|
|
193742
193908
|
const allowedKeys = new Set(["focus", "nonGoals", "acceptedRisks"]);
|
|
@@ -193753,7 +193919,7 @@ function validateReviewContract(request) {
|
|
|
193753
193919
|
throw new KyosoRequestError("reviewContract.nonGoals must contain at most 20 non-empty strings of 500 characters or fewer", "VALIDATION_ERROR");
|
|
193754
193920
|
}
|
|
193755
193921
|
const acceptedRisks = contract.acceptedRisks;
|
|
193756
|
-
if (acceptedRisks !== undefined && (!Array.isArray(acceptedRisks) || acceptedRisks.length > 20 || acceptedRisks.some((risk) => !
|
|
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))) {
|
|
193757
193923
|
throw new KyosoRequestError("reviewContract.acceptedRisks must contain valid finding fingerprints and bounded rationales", "VALIDATION_ERROR");
|
|
193758
193924
|
}
|
|
193759
193925
|
}
|
|
@@ -193765,13 +193931,13 @@ function validateSelectedFiles(request) {
|
|
|
193765
193931
|
throw new KyosoRequestError("selectedFiles must be an array", "VALIDATION_ERROR");
|
|
193766
193932
|
}
|
|
193767
193933
|
for (const file2 of selectedFiles) {
|
|
193768
|
-
if (!
|
|
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") {
|
|
193769
193935
|
throw new KyosoRequestError("selectedFiles entries require string path/content and valid optional metadata", "VALIDATION_ERROR");
|
|
193770
193936
|
}
|
|
193771
193937
|
normalizeRelativePath(file2.path);
|
|
193772
193938
|
}
|
|
193773
193939
|
}
|
|
193774
|
-
function
|
|
193940
|
+
function isRecord12(value) {
|
|
193775
193941
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
193776
193942
|
}
|
|
193777
193943
|
|
|
@@ -194032,7 +194198,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
|
|
|
194032
194198
|
const parsed = JSON.parse(json2);
|
|
194033
194199
|
const summaryText = typeof parsed.summaryText === "string" && parsed.summaryText.trim().length > 0 ? sanitizeText(parsed.summaryText) : fallbackSummaryText;
|
|
194034
194200
|
const disagreementComments = Array.isArray(parsed.disagreementComments) ? parsed.disagreementComments.flatMap((item) => {
|
|
194035
|
-
if (!
|
|
194201
|
+
if (!isRecord13(item) || typeof item.topic !== "string" || typeof item.judgeComment !== "string") {
|
|
194036
194202
|
return [];
|
|
194037
194203
|
}
|
|
194038
194204
|
return [
|
|
@@ -194048,7 +194214,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
|
|
|
194048
194214
|
return { summaryText, disagreementComments, analysis };
|
|
194049
194215
|
}
|
|
194050
194216
|
function parseAnalysis(value) {
|
|
194051
|
-
if (!
|
|
194217
|
+
if (!isRecord13(value))
|
|
194052
194218
|
return;
|
|
194053
194219
|
if (!Array.isArray(value.blindSpots) || !Array.isArray(value.contradictions) || !Array.isArray(value.partialCoverage)) {
|
|
194054
194220
|
return;
|
|
@@ -194056,7 +194222,7 @@ function parseAnalysis(value) {
|
|
|
194056
194222
|
return {
|
|
194057
194223
|
blindSpots: value.blindSpots.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => typeof item === "string" ? [sanitizeAnalysisText(item)] : []),
|
|
194058
194224
|
contradictions: value.contradictions.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
|
|
194059
|
-
if (!
|
|
194225
|
+
if (!isRecord13(item) || typeof item.topic !== "string" || typeof item.detail !== "string") {
|
|
194060
194226
|
return [];
|
|
194061
194227
|
}
|
|
194062
194228
|
return [
|
|
@@ -194067,7 +194233,7 @@ function parseAnalysis(value) {
|
|
|
194067
194233
|
];
|
|
194068
194234
|
}),
|
|
194069
194235
|
partialCoverage: value.partialCoverage.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
|
|
194070
|
-
if (!
|
|
194236
|
+
if (!isRecord13(item) || typeof item.note !== "string")
|
|
194071
194237
|
return [];
|
|
194072
194238
|
const findingId = typeof item.findingId === "string" ? sanitizeAnalysisText(item.findingId) : undefined;
|
|
194073
194239
|
return [
|
|
@@ -194114,7 +194280,7 @@ function extractFirstJsonObject2(text) {
|
|
|
194114
194280
|
}
|
|
194115
194281
|
return;
|
|
194116
194282
|
}
|
|
194117
|
-
function
|
|
194283
|
+
function isRecord13(value) {
|
|
194118
194284
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
194119
194285
|
}
|
|
194120
194286
|
|
|
@@ -194659,11 +194825,11 @@ function canonicalJson(value) {
|
|
|
194659
194825
|
function canonicalize(value) {
|
|
194660
194826
|
if (Array.isArray(value))
|
|
194661
194827
|
return value.map(canonicalize);
|
|
194662
|
-
if (!
|
|
194828
|
+
if (!isRecord14(value))
|
|
194663
194829
|
return value;
|
|
194664
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)]));
|
|
194665
194831
|
}
|
|
194666
|
-
function
|
|
194832
|
+
function isRecord14(value) {
|
|
194667
194833
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
194668
194834
|
}
|
|
194669
194835
|
|
|
@@ -194671,19 +194837,24 @@ function isRecord13(value) {
|
|
|
194671
194837
|
var REVIEW_BUDGET_KEYS = new Set([
|
|
194672
194838
|
"maxModelCalls",
|
|
194673
194839
|
"maxTotalWallTimeMs",
|
|
194840
|
+
"maxTotalWallTimeS",
|
|
194674
194841
|
"maxAgentOutputBytes",
|
|
194675
194842
|
"maxFindingsPerAgent",
|
|
194676
194843
|
"skipOptionalPhasesWhenTokenUsageUnknown"
|
|
194677
194844
|
]);
|
|
194678
194845
|
var MODEL_CALL_KINDS = ["primary", "verifier", "judge"];
|
|
194679
194846
|
function resolveReviewBudget(ceiling, requested) {
|
|
194680
|
-
if (requested !== undefined && !
|
|
194847
|
+
if (requested !== undefined && !isRecord15(requested)) {
|
|
194681
194848
|
throw new KyosoRequestError("options.reviewBudget must be an object.", "REVIEW_BUDGET_INVALID");
|
|
194682
194849
|
}
|
|
194850
|
+
const hasWallTimeSeconds = requested?.maxTotalWallTimeS !== undefined;
|
|
194683
194851
|
for (const [key, value] of Object.entries(requested ?? {})) {
|
|
194684
194852
|
if (!REVIEW_BUDGET_KEYS.has(key)) {
|
|
194685
194853
|
throw new KyosoRequestError(`options.reviewBudget.${key} is not supported.`, "REVIEW_BUDGET_INVALID");
|
|
194686
194854
|
}
|
|
194855
|
+
if (key === "maxTotalWallTimeS" || key === "maxTotalWallTimeMs" && hasWallTimeSeconds) {
|
|
194856
|
+
continue;
|
|
194857
|
+
}
|
|
194687
194858
|
if (key === "skipOptionalPhasesWhenTokenUsageUnknown") {
|
|
194688
194859
|
if (typeof value !== "boolean") {
|
|
194689
194860
|
throw new KyosoRequestError(`options.reviewBudget.${key} must be a boolean.`, "REVIEW_BUDGET_INVALID");
|
|
@@ -194694,12 +194865,26 @@ function resolveReviewBudget(ceiling, requested) {
|
|
|
194694
194865
|
throw new KyosoRequestError(`options.reviewBudget.${key} must be a positive integer.`, "REVIEW_BUDGET_INVALID");
|
|
194695
194866
|
}
|
|
194696
194867
|
}
|
|
194697
|
-
|
|
194698
|
-
|
|
194699
|
-
|
|
194700
|
-
|
|
194701
|
-
|
|
194702
|
-
|
|
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");
|
|
194703
194888
|
for (const key of numericKeys) {
|
|
194704
194889
|
const value = requested?.[key];
|
|
194705
194890
|
if (value === undefined)
|
|
@@ -194708,13 +194893,19 @@ function resolveReviewBudget(ceiling, requested) {
|
|
|
194708
194893
|
throw new KyosoRequestError(`options.reviewBudget.${key} cannot exceed the user-global ceiling.`, "REVIEW_BUDGET_EXCEEDS_CEILING");
|
|
194709
194894
|
}
|
|
194710
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
|
+
}
|
|
194711
194902
|
if (ceiling.skipOptionalPhasesWhenTokenUsageUnknown && requested?.skipOptionalPhasesWhenTokenUsageUnknown === false) {
|
|
194712
194903
|
throw new KyosoRequestError("options.reviewBudget.skipOptionalPhasesWhenTokenUsageUnknown cannot relax the user-global ceiling.", "REVIEW_BUDGET_EXCEEDS_CEILING");
|
|
194713
194904
|
}
|
|
194714
194905
|
const maxAgentOutputBytes = requested?.maxAgentOutputBytes ?? ceiling.maxAgentOutputBytes;
|
|
194715
194906
|
return {
|
|
194716
194907
|
maxModelCalls: requested?.maxModelCalls ?? ceiling.maxModelCalls,
|
|
194717
|
-
maxTotalWallTimeMs: requested?.maxTotalWallTimeMs ?? ceiling.maxTotalWallTimeMs,
|
|
194908
|
+
maxTotalWallTimeMs: requestedWallTime?.milliseconds ?? requested?.maxTotalWallTimeMs ?? ceiling.maxTotalWallTimeMs,
|
|
194718
194909
|
warnAgentOutputBytes: ceiling.warnAgentOutputBytes,
|
|
194719
194910
|
maxAgentOutputBytes,
|
|
194720
194911
|
maxFindingsPerAgent: requested?.maxFindingsPerAgent ?? ceiling.maxFindingsPerAgent,
|
|
@@ -195031,10 +195222,63 @@ function emptyReviewModelCallPlan() {
|
|
|
195031
195222
|
ceilingEffects: []
|
|
195032
195223
|
};
|
|
195033
195224
|
}
|
|
195034
|
-
function
|
|
195225
|
+
function isRecord15(value) {
|
|
195035
195226
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
195036
195227
|
}
|
|
195037
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
|
+
|
|
195038
195282
|
// src/core/verification.ts
|
|
195039
195283
|
var REAL_AGENTS = ["codex", "claude"];
|
|
195040
195284
|
var VERIFIABLE_SEVERITIES = new Set(["critical", "high"]);
|
|
@@ -195093,7 +195337,7 @@ function parseVerificationVerdicts(rawText) {
|
|
|
195093
195337
|
if (!Array.isArray(parsed.verdicts))
|
|
195094
195338
|
return;
|
|
195095
195339
|
return parsed.verdicts.flatMap((item) => {
|
|
195096
|
-
if (!
|
|
195340
|
+
if (!isRecord16(item))
|
|
195097
195341
|
return [];
|
|
195098
195342
|
if (typeof item.findingId !== "string")
|
|
195099
195343
|
return [];
|
|
@@ -195171,7 +195415,7 @@ function verificationNote(reasoning) {
|
|
|
195171
195415
|
function isVerdict(value) {
|
|
195172
195416
|
return value === "confirmed" || value === "refuted" || value === "uncertain";
|
|
195173
195417
|
}
|
|
195174
|
-
function
|
|
195418
|
+
function isRecord16(value) {
|
|
195175
195419
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
195176
195420
|
}
|
|
195177
195421
|
|
|
@@ -195179,7 +195423,7 @@ function isRecord15(value) {
|
|
|
195179
195423
|
var MAX_AGENT_RETRY_PROGRESS_EVENTS = 100;
|
|
195180
195424
|
function requestForRecursionFingerprint(request) {
|
|
195181
195425
|
try {
|
|
195182
|
-
return scanAndRedactSecrets(request).redactedRequest;
|
|
195426
|
+
return scanAndRedactSecrets(normalizeRequestTimeUnits(request)).redactedRequest;
|
|
195183
195427
|
} catch {
|
|
195184
195428
|
return { goal: "" };
|
|
195185
195429
|
}
|
|
@@ -195439,15 +195683,17 @@ async function runReview(tool, request, options = {}) {
|
|
|
195439
195683
|
});
|
|
195440
195684
|
validateReviewRequest(tool, request);
|
|
195441
195685
|
const reviewBudget = resolveReviewBudget(loaded.config.reviewBudget, request.options?.reviewBudget);
|
|
195442
|
-
const
|
|
195443
|
-
|
|
195444
|
-
const
|
|
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);
|
|
195445
195691
|
if (networkMode === "unrestricted" && !loaded.config.network.allowUnrestricted) {
|
|
195446
195692
|
throw new KyosoRequestError("unrestricted network mode is disabled by config", "NETWORK_MODE_DISABLED");
|
|
195447
195693
|
}
|
|
195448
195694
|
const disabledPolicy = disabledReviewPolicy(tool, loaded.config, options.entrypoint);
|
|
195449
195695
|
if (disabledPolicy) {
|
|
195450
|
-
const redactedRequest = requestForRecursionFingerprint(
|
|
195696
|
+
const redactedRequest = requestForRecursionFingerprint(normalizedRequest);
|
|
195451
195697
|
const requestFingerprint2 = createRequestFingerprint({
|
|
195452
195698
|
tool,
|
|
195453
195699
|
request: redactedRequest,
|
|
@@ -195498,7 +195744,7 @@ async function runReview(tool, request, options = {}) {
|
|
|
195498
195744
|
warnings.push("Network mode is unrestricted; write policy remains denied.");
|
|
195499
195745
|
}
|
|
195500
195746
|
startPhase("context");
|
|
195501
|
-
const secretScan = scanAndRedactSecrets(
|
|
195747
|
+
const secretScan = scanAndRedactSecrets(normalizedRequest);
|
|
195502
195748
|
await trace.write({
|
|
195503
195749
|
type: "secret_scan_completed",
|
|
195504
195750
|
traceId,
|
|
@@ -195506,7 +195752,7 @@ async function runReview(tool, request, options = {}) {
|
|
|
195506
195752
|
redactions: secretScan.redactions,
|
|
195507
195753
|
timestamp: new Date().toISOString()
|
|
195508
195754
|
});
|
|
195509
|
-
const allowSecretOverride = loaded.config.secrets.allowOverride &&
|
|
195755
|
+
const allowSecretOverride = loaded.config.secrets.allowOverride && normalizedRequest.options?.allowSecretRedaction === true;
|
|
195510
195756
|
if (secretScan.detected && loaded.config.secrets.blockOnDetectedSecret && !allowSecretOverride) {
|
|
195511
195757
|
const requestFingerprint2 = createRequestFingerprint({
|
|
195512
195758
|
tool,
|
|
@@ -195593,7 +195839,7 @@ async function runReview(tool, request, options = {}) {
|
|
|
195593
195839
|
budgetTracker,
|
|
195594
195840
|
progressDispatcher: dispatcher,
|
|
195595
195841
|
signal: options.signal,
|
|
195596
|
-
progressHeartbeatMs
|
|
195842
|
+
progressHeartbeatMs
|
|
195597
195843
|
});
|
|
195598
195844
|
completePhase("primary");
|
|
195599
195845
|
warnings.push(...agentResults.flatMap((result) => (result.warnings ?? []).map((warning) => `Agent ${result.agent} ${warning}`)));
|