@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/bin/kyoso.js
CHANGED
|
@@ -183964,7 +183964,7 @@ var JUDGE_MAX_OUTPUT_TOKENS = 4096;
|
|
|
183964
183964
|
var RAW_OUTPUT_MAX_CHARS = 16384;
|
|
183965
183965
|
var TRACE_DIR = ".kyoso/traces";
|
|
183966
183966
|
var KYOSO_CHILD_AGENT = "KYOSO_CHILD_AGENT";
|
|
183967
|
-
var KYOSO_VERSION = "0.
|
|
183967
|
+
var KYOSO_VERSION = "0.16.0";
|
|
183968
183968
|
|
|
183969
183969
|
// src/utils/pathContainment.ts
|
|
183970
183970
|
import { resolve, sep as sep2 } from "node:path";
|
|
@@ -184405,22 +184405,27 @@ var kyosoConfigOverridePaths = [
|
|
|
184405
184405
|
"agents.codex.model",
|
|
184406
184406
|
"agents.codex.provider",
|
|
184407
184407
|
"agents.codex.openRouter.streamIdleTimeoutMs",
|
|
184408
|
+
"agents.codex.openRouter.streamIdleTimeoutS",
|
|
184408
184409
|
"agents.codex.openRouter.streamMaxRetries",
|
|
184409
184410
|
"agents.codex.openRouter.requestMaxRetries",
|
|
184410
184411
|
"agents.codex.effort",
|
|
184411
184412
|
"agents.codex.role",
|
|
184412
184413
|
"agents.codex.timeoutMs",
|
|
184414
|
+
"agents.codex.timeoutS",
|
|
184413
184415
|
"agents.claude.enabled",
|
|
184414
184416
|
"agents.claude.model",
|
|
184415
184417
|
"agents.claude.effort",
|
|
184416
184418
|
"agents.claude.role",
|
|
184417
184419
|
"agents.claude.timeoutMs",
|
|
184420
|
+
"agents.claude.timeoutS",
|
|
184418
184421
|
"verification.enabled",
|
|
184419
184422
|
"verification.maxFindings",
|
|
184420
184423
|
"verification.timeoutMs",
|
|
184424
|
+
"verification.timeoutS",
|
|
184421
184425
|
"judge.mode",
|
|
184422
184426
|
"judge.provider",
|
|
184423
|
-
"judge.timeoutMs"
|
|
184427
|
+
"judge.timeoutMs",
|
|
184428
|
+
"judge.timeoutS"
|
|
184424
184429
|
];
|
|
184425
184430
|
var CONFIG_OVERRIDE_PATHS = new Set(kyosoConfigOverridePaths);
|
|
184426
184431
|
function isAllowedConfigOverridePath(path) {
|
|
@@ -184893,6 +184898,7 @@ function agentConfigLeafPaths(agent) {
|
|
|
184893
184898
|
`agents.${agent}.effort`,
|
|
184894
184899
|
`agents.${agent}.role`,
|
|
184895
184900
|
`agents.${agent}.timeoutMs`,
|
|
184901
|
+
`agents.${agent}.timeoutS`,
|
|
184896
184902
|
`agents.${agent}.env`,
|
|
184897
184903
|
`agents.${agent}.auth.mode`,
|
|
184898
184904
|
`agents.${agent}.auth.preferExistingLogin`,
|
|
@@ -184901,7 +184907,7 @@ function agentConfigLeafPaths(agent) {
|
|
|
184901
184907
|
`agents.${agent}.auth.envWhitelist`
|
|
184902
184908
|
];
|
|
184903
184909
|
if (agent === "codex") {
|
|
184904
|
-
paths.push("agents.codex.provider", "agents.codex.allowProjectProvider", "agents.codex.openRouter.streamIdleTimeoutMs", "agents.codex.openRouter.streamMaxRetries", "agents.codex.openRouter.requestMaxRetries");
|
|
184910
|
+
paths.push("agents.codex.provider", "agents.codex.allowProjectProvider", "agents.codex.openRouter.streamIdleTimeoutMs", "agents.codex.openRouter.streamIdleTimeoutS", "agents.codex.openRouter.streamMaxRetries", "agents.codex.openRouter.requestMaxRetries");
|
|
184905
184911
|
}
|
|
184906
184912
|
return paths;
|
|
184907
184913
|
}
|
|
@@ -184938,12 +184944,15 @@ var kyosoConfigKnownLeafPaths = [
|
|
|
184938
184944
|
"judge.mode",
|
|
184939
184945
|
"judge.provider",
|
|
184940
184946
|
"judge.timeoutMs",
|
|
184947
|
+
"judge.timeoutS",
|
|
184941
184948
|
"verification.enabled",
|
|
184942
184949
|
"verification.maxFindings",
|
|
184943
184950
|
"verification.timeoutMs",
|
|
184951
|
+
"verification.timeoutS",
|
|
184944
184952
|
"verification.allowDemotion",
|
|
184945
184953
|
"reviewBudget.maxModelCalls",
|
|
184946
184954
|
"reviewBudget.maxTotalWallTimeMs",
|
|
184955
|
+
"reviewBudget.maxTotalWallTimeS",
|
|
184947
184956
|
"reviewBudget.warnAgentOutputBytes",
|
|
184948
184957
|
"reviewBudget.maxAgentOutputBytes",
|
|
184949
184958
|
"reviewBudget.maxFindingsPerAgent",
|
|
@@ -186039,6 +186048,146 @@ function isMissingPathError2(error51) {
|
|
|
186039
186048
|
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
|
|
186040
186049
|
}
|
|
186041
186050
|
|
|
186051
|
+
// src/utils/timeUnits.ts
|
|
186052
|
+
class TimeUnitValidationError extends Error {
|
|
186053
|
+
field;
|
|
186054
|
+
constructor(field, message) {
|
|
186055
|
+
super(`${field} ${message}`);
|
|
186056
|
+
this.name = "TimeUnitValidationError";
|
|
186057
|
+
this.field = field;
|
|
186058
|
+
}
|
|
186059
|
+
}
|
|
186060
|
+
function validateMilliseconds(value, field, constraints = {}) {
|
|
186061
|
+
assertFiniteNumber(value, field);
|
|
186062
|
+
if (!Number.isSafeInteger(value)) {
|
|
186063
|
+
throw new TimeUnitValidationError(field, "must be a safe integer number of milliseconds.");
|
|
186064
|
+
}
|
|
186065
|
+
assertMinimumMilliseconds(value, field, constraints);
|
|
186066
|
+
return value;
|
|
186067
|
+
}
|
|
186068
|
+
function secondsToMilliseconds(value, field, constraints = {}) {
|
|
186069
|
+
assertFiniteNumber(value, field);
|
|
186070
|
+
const milliseconds = value * 1000;
|
|
186071
|
+
if (!Number.isSafeInteger(milliseconds)) {
|
|
186072
|
+
throw new TimeUnitValidationError(field, "must convert to a safe integer number of milliseconds.");
|
|
186073
|
+
}
|
|
186074
|
+
assertMinimumMilliseconds(milliseconds, field, constraints);
|
|
186075
|
+
return milliseconds;
|
|
186076
|
+
}
|
|
186077
|
+
function resolveTimeUnitPair(input2, fields, constraints = {}) {
|
|
186078
|
+
const hasMilliseconds = input2.milliseconds !== undefined;
|
|
186079
|
+
const hasSeconds = input2.seconds !== undefined;
|
|
186080
|
+
if (!hasMilliseconds && !hasSeconds)
|
|
186081
|
+
return;
|
|
186082
|
+
const milliseconds = hasMilliseconds ? validateMilliseconds(input2.milliseconds, fields.milliseconds, constraints) : undefined;
|
|
186083
|
+
const secondsMilliseconds = hasSeconds ? secondsToMilliseconds(input2.seconds, fields.seconds, constraints) : undefined;
|
|
186084
|
+
if (secondsMilliseconds !== undefined) {
|
|
186085
|
+
return {
|
|
186086
|
+
milliseconds: secondsMilliseconds,
|
|
186087
|
+
source: "seconds",
|
|
186088
|
+
sourceField: fields.seconds
|
|
186089
|
+
};
|
|
186090
|
+
}
|
|
186091
|
+
return {
|
|
186092
|
+
milliseconds,
|
|
186093
|
+
source: "milliseconds",
|
|
186094
|
+
sourceField: fields.milliseconds
|
|
186095
|
+
};
|
|
186096
|
+
}
|
|
186097
|
+
function assertFiniteNumber(value, field) {
|
|
186098
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
186099
|
+
throw new TimeUnitValidationError(field, "must be a finite number.");
|
|
186100
|
+
}
|
|
186101
|
+
}
|
|
186102
|
+
function assertMinimumMilliseconds(value, field, constraints) {
|
|
186103
|
+
if (constraints.allowZero && value === 0)
|
|
186104
|
+
return;
|
|
186105
|
+
const minimumMilliseconds = constraints.minimumMilliseconds ?? 1;
|
|
186106
|
+
if (value < minimumMilliseconds) {
|
|
186107
|
+
throw new TimeUnitValidationError(field, `must be at least ${minimumMilliseconds} milliseconds.`);
|
|
186108
|
+
}
|
|
186109
|
+
}
|
|
186110
|
+
|
|
186111
|
+
// src/config/timeUnits.ts
|
|
186112
|
+
var configTimeUnitPairs = [
|
|
186113
|
+
{
|
|
186114
|
+
parentPath: ["agents", "codex"],
|
|
186115
|
+
millisecondsKey: "timeoutMs",
|
|
186116
|
+
secondsKey: "timeoutS"
|
|
186117
|
+
},
|
|
186118
|
+
{
|
|
186119
|
+
parentPath: ["agents", "claude"],
|
|
186120
|
+
millisecondsKey: "timeoutMs",
|
|
186121
|
+
secondsKey: "timeoutS"
|
|
186122
|
+
},
|
|
186123
|
+
{
|
|
186124
|
+
parentPath: ["agents", "codex", "openRouter"],
|
|
186125
|
+
millisecondsKey: "streamIdleTimeoutMs",
|
|
186126
|
+
secondsKey: "streamIdleTimeoutS",
|
|
186127
|
+
constraints: { minimumMilliseconds: 1000 }
|
|
186128
|
+
},
|
|
186129
|
+
{
|
|
186130
|
+
parentPath: ["judge"],
|
|
186131
|
+
millisecondsKey: "timeoutMs",
|
|
186132
|
+
secondsKey: "timeoutS"
|
|
186133
|
+
},
|
|
186134
|
+
{
|
|
186135
|
+
parentPath: ["verification"],
|
|
186136
|
+
millisecondsKey: "timeoutMs",
|
|
186137
|
+
secondsKey: "timeoutS"
|
|
186138
|
+
},
|
|
186139
|
+
{
|
|
186140
|
+
parentPath: ["reviewBudget"],
|
|
186141
|
+
millisecondsKey: "maxTotalWallTimeMs",
|
|
186142
|
+
secondsKey: "maxTotalWallTimeS"
|
|
186143
|
+
}
|
|
186144
|
+
];
|
|
186145
|
+
function normalizeConfigTimeUnits(input2) {
|
|
186146
|
+
let normalized = input2;
|
|
186147
|
+
for (const pair of configTimeUnitPairs) {
|
|
186148
|
+
normalized = updateRecordAtPath(normalized, pair.parentPath, (parent) => normalizePair(parent, pair));
|
|
186149
|
+
}
|
|
186150
|
+
return normalized;
|
|
186151
|
+
}
|
|
186152
|
+
function normalizePair(parent, pair) {
|
|
186153
|
+
const hasSecondsProperty = Object.hasOwn(parent, pair.secondsKey);
|
|
186154
|
+
if (!hasSecondsProperty)
|
|
186155
|
+
return parent;
|
|
186156
|
+
const normalized = { ...parent };
|
|
186157
|
+
if (parent[pair.secondsKey] === undefined) {
|
|
186158
|
+
delete normalized[pair.secondsKey];
|
|
186159
|
+
return normalized;
|
|
186160
|
+
}
|
|
186161
|
+
const parentPath = pair.parentPath.join(".");
|
|
186162
|
+
const resolved = resolveTimeUnitPair({
|
|
186163
|
+
milliseconds: parent[pair.millisecondsKey],
|
|
186164
|
+
seconds: parent[pair.secondsKey]
|
|
186165
|
+
}, {
|
|
186166
|
+
milliseconds: `${parentPath}.${pair.millisecondsKey}`,
|
|
186167
|
+
seconds: `${parentPath}.${pair.secondsKey}`
|
|
186168
|
+
}, pair.constraints);
|
|
186169
|
+
if (resolved)
|
|
186170
|
+
normalized[pair.millisecondsKey] = resolved.milliseconds;
|
|
186171
|
+
delete normalized[pair.secondsKey];
|
|
186172
|
+
return normalized;
|
|
186173
|
+
}
|
|
186174
|
+
function updateRecordAtPath(input2, path, update) {
|
|
186175
|
+
if (path.length === 0) {
|
|
186176
|
+
return isRecord3(input2) ? update(input2) : input2;
|
|
186177
|
+
}
|
|
186178
|
+
if (!isRecord3(input2))
|
|
186179
|
+
return input2;
|
|
186180
|
+
const [key, ...rest] = path;
|
|
186181
|
+
if (key === undefined)
|
|
186182
|
+
return input2;
|
|
186183
|
+
const current = input2[key];
|
|
186184
|
+
const updated = updateRecordAtPath(current, rest, update);
|
|
186185
|
+
return updated === current ? input2 : { ...input2, [key]: updated };
|
|
186186
|
+
}
|
|
186187
|
+
function isRecord3(value) {
|
|
186188
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
186189
|
+
}
|
|
186190
|
+
|
|
186042
186191
|
// src/config/loadConfig.ts
|
|
186043
186192
|
var configValidationContexts = new WeakMap;
|
|
186044
186193
|
function getConfigValidationContext(error51) {
|
|
@@ -186078,7 +186227,7 @@ async function loadConfig(options = {}) {
|
|
|
186078
186227
|
let configTrustStatus = options.ignoreConfig ? "ignored" : "not_found";
|
|
186079
186228
|
if (!options.ignoreConfig) {
|
|
186080
186229
|
if (await exists2(globalConfigPath)) {
|
|
186081
|
-
const globalConfig2 = await loadTomlConfigFile(globalConfigPath);
|
|
186230
|
+
const globalConfig2 = normalizeConfigTimeUnits(await loadTomlConfigFile(globalConfigPath));
|
|
186082
186231
|
validateExplicitReviewBudgetThresholds(globalConfig2, defaultConfig);
|
|
186083
186232
|
const globalConfigWarnings = collectGlobalConfigWarnings(globalConfigPath, globalConfig2);
|
|
186084
186233
|
const securitySensitiveWarnings = globalConfigWarnings.filter((warning) => warning.startsWith("security-sensitive unknown settings "));
|
|
@@ -186205,7 +186354,7 @@ async function loadProjectConfig(input2) {
|
|
|
186205
186354
|
const { canonicalDirectory, canonicalPath, requestedPath } = input2.projectConfig;
|
|
186206
186355
|
const extension = extname3(requestedPath);
|
|
186207
186356
|
if (extension === ".toml") {
|
|
186208
|
-
const projectTomlConfig = await loadTomlConfigFile(canonicalPath);
|
|
186357
|
+
const projectTomlConfig = normalizeConfigTimeUnits(await loadTomlConfigFile(canonicalPath));
|
|
186209
186358
|
const projectChangesOpenRouterPolicy = projectConfigChangesOpenRouterPolicy(projectTomlConfig, input2.baseConfig);
|
|
186210
186359
|
await assertProjectOpenRouterAuthorization({
|
|
186211
186360
|
projectConfig: projectTomlConfig,
|
|
@@ -186251,7 +186400,7 @@ function configSelectsOpenRouter(config2) {
|
|
|
186251
186400
|
return flattenLeaves(config2).some((leaf) => leaf.path.join(".") === "agents.codex.provider" && leaf.value === CODEX_OPENROUTER_PROVIDER);
|
|
186252
186401
|
}
|
|
186253
186402
|
function applyProjectCodexProviderReset(baseConfig, projectConfig, mergedConfig) {
|
|
186254
|
-
if (!projectConfigSelectsDefaultProvider(projectConfig) || !configSelectsOpenRouter(baseConfig) || !
|
|
186403
|
+
if (!projectConfigSelectsDefaultProvider(projectConfig) || !configSelectsOpenRouter(baseConfig) || !isRecord4(mergedConfig) || !isRecord4(mergedConfig.agents) || !isRecord4(mergedConfig.agents.codex)) {
|
|
186255
186404
|
return mergedConfig;
|
|
186256
186405
|
}
|
|
186257
186406
|
const shouldClearInheritedModel = !projectConfigSuppliesCodexModel(projectConfig);
|
|
@@ -186283,13 +186432,13 @@ async function assertProjectOpenRouterAuthorization(input2) {
|
|
|
186283
186432
|
});
|
|
186284
186433
|
}
|
|
186285
186434
|
async function projectProviderIsAuthorized(config2, projectDirectory) {
|
|
186286
|
-
if (!
|
|
186435
|
+
if (!isRecord4(config2))
|
|
186287
186436
|
return false;
|
|
186288
186437
|
const agents = config2.agents;
|
|
186289
|
-
if (!
|
|
186438
|
+
if (!isRecord4(agents))
|
|
186290
186439
|
return false;
|
|
186291
186440
|
const codex = agents.codex;
|
|
186292
|
-
if (!
|
|
186441
|
+
if (!isRecord4(codex) || !Array.isArray(codex.allowProjectProvider)) {
|
|
186293
186442
|
return false;
|
|
186294
186443
|
}
|
|
186295
186444
|
for (const directory of codex.allowProjectProvider) {
|
|
@@ -186332,7 +186481,7 @@ async function loadProjectTsConfig(input2) {
|
|
|
186332
186481
|
options: input2.options
|
|
186333
186482
|
});
|
|
186334
186483
|
if (trustDecision.execute) {
|
|
186335
|
-
const userConfig = await loadUserConfig(canonicalPath, source);
|
|
186484
|
+
const userConfig = normalizeConfigTimeUnits(await loadUserConfig(canonicalPath, source));
|
|
186336
186485
|
validateExplicitReviewBudgetThresholds(userConfig, input2.baseConfig);
|
|
186337
186486
|
const projectChangesOpenRouterPolicy = projectConfigChangesOpenRouterPolicy(userConfig, input2.baseConfig);
|
|
186338
186487
|
await assertProjectOpenRouterAuthorization({
|
|
@@ -186419,7 +186568,7 @@ async function promptForConfigTrust(configPath, configHash) {
|
|
|
186419
186568
|
}
|
|
186420
186569
|
}
|
|
186421
186570
|
function deepMerge2(base, override) {
|
|
186422
|
-
if (!
|
|
186571
|
+
if (!isRecord4(base) || !isRecord4(override))
|
|
186423
186572
|
return override ?? base;
|
|
186424
186573
|
const result = { ...base };
|
|
186425
186574
|
for (const [key, value] of Object.entries(override)) {
|
|
@@ -186439,12 +186588,12 @@ function validateExplicitReviewBudgetThresholds(config2, baseConfig) {
|
|
|
186439
186588
|
}
|
|
186440
186589
|
}
|
|
186441
186590
|
function readRecord(value, key) {
|
|
186442
|
-
if (!
|
|
186591
|
+
if (!isRecord4(value))
|
|
186443
186592
|
return;
|
|
186444
186593
|
const nested = value[key];
|
|
186445
|
-
return
|
|
186594
|
+
return isRecord4(nested) ? nested : undefined;
|
|
186446
186595
|
}
|
|
186447
|
-
function
|
|
186596
|
+
function isRecord4(value) {
|
|
186448
186597
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
186449
186598
|
}
|
|
186450
186599
|
async function exists2(path) {
|
|
@@ -186479,7 +186628,7 @@ function createModelExecutionIdentity(input2) {
|
|
|
186479
186628
|
};
|
|
186480
186629
|
}
|
|
186481
186630
|
function normalizeModelExecutionIdentity(value) {
|
|
186482
|
-
if (!
|
|
186631
|
+
if (!isRecord5(value) || !isModelProviderRoute(value.providerRoute)) {
|
|
186483
186632
|
return;
|
|
186484
186633
|
}
|
|
186485
186634
|
return createModelExecutionIdentity({
|
|
@@ -186501,7 +186650,7 @@ function sanitizeIdentityValue(value) {
|
|
|
186501
186650
|
function isModelProviderRoute(value) {
|
|
186502
186651
|
return typeof value === "string" && MODEL_PROVIDER_ROUTES.has(value);
|
|
186503
186652
|
}
|
|
186504
|
-
function
|
|
186653
|
+
function isRecord5(value) {
|
|
186505
186654
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
186506
186655
|
}
|
|
186507
186656
|
|
|
@@ -186515,7 +186664,7 @@ var TOKEN_USAGE_KEYS = [
|
|
|
186515
186664
|
"cachedWriteTokens"
|
|
186516
186665
|
];
|
|
186517
186666
|
function normalizeModelTokenUsage(usage) {
|
|
186518
|
-
if (!
|
|
186667
|
+
if (!isRecord6(usage))
|
|
186519
186668
|
return;
|
|
186520
186669
|
const normalized = {};
|
|
186521
186670
|
for (const key of TOKEN_USAGE_KEYS) {
|
|
@@ -186528,7 +186677,7 @@ function normalizeModelTokenUsage(usage) {
|
|
|
186528
186677
|
function isTokenCount(value) {
|
|
186529
186678
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
186530
186679
|
}
|
|
186531
|
-
function
|
|
186680
|
+
function isRecord6(value) {
|
|
186532
186681
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
186533
186682
|
}
|
|
186534
186683
|
|
|
@@ -186580,7 +186729,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
|
|
|
186580
186729
|
const parsed = JSON.parse(json2);
|
|
186581
186730
|
const summaryText = typeof parsed.summaryText === "string" && parsed.summaryText.trim().length > 0 ? sanitizeText(parsed.summaryText) : fallbackSummaryText;
|
|
186582
186731
|
const disagreementComments = Array.isArray(parsed.disagreementComments) ? parsed.disagreementComments.flatMap((item) => {
|
|
186583
|
-
if (!
|
|
186732
|
+
if (!isRecord7(item) || typeof item.topic !== "string" || typeof item.judgeComment !== "string") {
|
|
186584
186733
|
return [];
|
|
186585
186734
|
}
|
|
186586
186735
|
return [
|
|
@@ -186596,7 +186745,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
|
|
|
186596
186745
|
return { summaryText, disagreementComments, analysis };
|
|
186597
186746
|
}
|
|
186598
186747
|
function parseAnalysis(value) {
|
|
186599
|
-
if (!
|
|
186748
|
+
if (!isRecord7(value))
|
|
186600
186749
|
return;
|
|
186601
186750
|
if (!Array.isArray(value.blindSpots) || !Array.isArray(value.contradictions) || !Array.isArray(value.partialCoverage)) {
|
|
186602
186751
|
return;
|
|
@@ -186604,7 +186753,7 @@ function parseAnalysis(value) {
|
|
|
186604
186753
|
return {
|
|
186605
186754
|
blindSpots: value.blindSpots.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => typeof item === "string" ? [sanitizeAnalysisText(item)] : []),
|
|
186606
186755
|
contradictions: value.contradictions.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
|
|
186607
|
-
if (!
|
|
186756
|
+
if (!isRecord7(item) || typeof item.topic !== "string" || typeof item.detail !== "string") {
|
|
186608
186757
|
return [];
|
|
186609
186758
|
}
|
|
186610
186759
|
return [
|
|
@@ -186615,7 +186764,7 @@ function parseAnalysis(value) {
|
|
|
186615
186764
|
];
|
|
186616
186765
|
}),
|
|
186617
186766
|
partialCoverage: value.partialCoverage.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
|
|
186618
|
-
if (!
|
|
186767
|
+
if (!isRecord7(item) || typeof item.note !== "string")
|
|
186619
186768
|
return [];
|
|
186620
186769
|
const findingId = typeof item.findingId === "string" ? sanitizeAnalysisText(item.findingId) : undefined;
|
|
186621
186770
|
return [
|
|
@@ -186662,7 +186811,7 @@ function extractFirstJsonObject(text) {
|
|
|
186662
186811
|
}
|
|
186663
186812
|
return;
|
|
186664
186813
|
}
|
|
186665
|
-
function
|
|
186814
|
+
function isRecord7(value) {
|
|
186666
186815
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
186667
186816
|
}
|
|
186668
186817
|
|
|
@@ -187156,9 +187305,9 @@ var PLUGIN_RUNTIME_COMPATIBILITY_SCHEMA_VERSION = 2;
|
|
|
187156
187305
|
var MINIMUM_SUPPORTED_CODEX_VERSION = "0.144.0-alpha.4";
|
|
187157
187306
|
var PLUGIN_RUNTIME_EXPECTED_CONTRACT = {
|
|
187158
187307
|
distribution: {
|
|
187159
|
-
pluginVersion: "0.7.
|
|
187308
|
+
pluginVersion: "0.7.7",
|
|
187160
187309
|
mcpCommand: "npx",
|
|
187161
|
-
mcpPackagePin: "@kyo-so/cli@0.15.
|
|
187310
|
+
mcpPackagePin: "@kyo-so/cli@0.15.2",
|
|
187162
187311
|
mcpExecutable: "kyoso"
|
|
187163
187312
|
},
|
|
187164
187313
|
marketplace: {
|
|
@@ -187404,7 +187553,7 @@ function parseJson(value) {
|
|
|
187404
187553
|
}
|
|
187405
187554
|
}
|
|
187406
187555
|
function parsePluginList(value) {
|
|
187407
|
-
if (!
|
|
187556
|
+
if (!isRecord8(value))
|
|
187408
187557
|
return;
|
|
187409
187558
|
const allowedKeys = new Set(PLUGIN_LIST_JSON_SCHEMA.collections);
|
|
187410
187559
|
if (Object.keys(value).some((key) => !allowedKeys.has(key))) {
|
|
@@ -187432,7 +187581,7 @@ function parsePluginEntries(value) {
|
|
|
187432
187581
|
return;
|
|
187433
187582
|
const entries = [];
|
|
187434
187583
|
for (const item of value) {
|
|
187435
|
-
if (!
|
|
187584
|
+
if (!isRecord8(item))
|
|
187436
187585
|
return;
|
|
187437
187586
|
if (typeof item.pluginId !== "string" || typeof item.installed !== "boolean" || typeof item.enabled !== "boolean") {
|
|
187438
187587
|
return;
|
|
@@ -187458,7 +187607,7 @@ function parseMcpList(value) {
|
|
|
187458
187607
|
return;
|
|
187459
187608
|
const matches = [];
|
|
187460
187609
|
for (const item of value) {
|
|
187461
|
-
if (!
|
|
187610
|
+
if (!isRecord8(item) || typeof item.name !== "string")
|
|
187462
187611
|
return "unknown";
|
|
187463
187612
|
if (item.name !== "kyoso")
|
|
187464
187613
|
continue;
|
|
@@ -187540,7 +187689,7 @@ function comparePrerelease(left, right) {
|
|
|
187540
187689
|
}
|
|
187541
187690
|
return 0;
|
|
187542
187691
|
}
|
|
187543
|
-
function
|
|
187692
|
+
function isRecord8(value) {
|
|
187544
187693
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
187545
187694
|
}
|
|
187546
187695
|
|
|
@@ -187701,7 +187850,7 @@ function findKyosoPackage(executable) {
|
|
|
187701
187850
|
if (existsSync(packagePath)) {
|
|
187702
187851
|
try {
|
|
187703
187852
|
const parsed = JSON.parse(readFileSync(packagePath, "utf8"));
|
|
187704
|
-
if (
|
|
187853
|
+
if (isRecord9(parsed) && parsed.name === "@kyo-so/cli" && typeof parsed.version === "string" && parsed.version.trim().length > 0) {
|
|
187705
187854
|
return { directory, version: parsed.version };
|
|
187706
187855
|
}
|
|
187707
187856
|
} catch {}
|
|
@@ -187870,7 +188019,7 @@ function isWithin(path, parent) {
|
|
|
187870
188019
|
const relativePath = relative(resolve5(parent), resolve5(path));
|
|
187871
188020
|
return relativePath === "" || !relativePath.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) && relativePath !== ".." && !isAbsolute4(relativePath);
|
|
187872
188021
|
}
|
|
187873
|
-
function
|
|
188022
|
+
function isRecord9(value) {
|
|
187874
188023
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
187875
188024
|
}
|
|
187876
188025
|
|
|
@@ -187915,7 +188064,7 @@ var GENERATED_MCP_ENV_VAR_NAMES = new Set([
|
|
|
187915
188064
|
"CLAUDE_CODE_OAUTH_TOKEN"
|
|
187916
188065
|
]);
|
|
187917
188066
|
function inspectManualMcpInvocation(value) {
|
|
187918
|
-
if (!
|
|
188067
|
+
if (!isRecord10(value)) {
|
|
187919
188068
|
return { kind: "unknown", reason: "MCP entry is not an object." };
|
|
187920
188069
|
}
|
|
187921
188070
|
if (typeof value.command !== "string" || value.command.length === 0) {
|
|
@@ -187961,7 +188110,7 @@ function applyEnvironmentSafety(invocation, environment) {
|
|
|
187961
188110
|
return environment ?? invocation;
|
|
187962
188111
|
}
|
|
187963
188112
|
function isGeneratedMcpEnvironment(value) {
|
|
187964
|
-
if (!
|
|
188113
|
+
if (!isRecord10(value))
|
|
187965
188114
|
return false;
|
|
187966
188115
|
return Object.entries(value).every(([name, placeholder]) => GENERATED_MCP_ENV_VALUE_NAMES.has(name) && placeholder === `\${${name}}`);
|
|
187967
188116
|
}
|
|
@@ -188069,7 +188218,7 @@ function versionFromKnownPackageSpec(packageSpec) {
|
|
|
188069
188218
|
const version2 = packageSpec.slice(prefix.length);
|
|
188070
188219
|
return isCompleteSemVer(version2) ? version2 : undefined;
|
|
188071
188220
|
}
|
|
188072
|
-
function
|
|
188221
|
+
function isRecord10(value) {
|
|
188073
188222
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
188074
188223
|
}
|
|
188075
188224
|
function isString(value) {
|
|
@@ -188102,8 +188251,14 @@ import {
|
|
|
188102
188251
|
} from "node:path";
|
|
188103
188252
|
|
|
188104
188253
|
// src/cli/knownSkillDigests.ts
|
|
188105
|
-
var CURRENT_SKILL_DIGEST = "sha256:
|
|
188254
|
+
var CURRENT_SKILL_DIGEST = "sha256:1ea8914f4657741fcd544822326f80e82033078f8e2b11b1f5aad420072dcb39";
|
|
188106
188255
|
var KNOWN_SKILL_DIGESTS_BY_VERSION = {
|
|
188256
|
+
"0.15.2": [
|
|
188257
|
+
{
|
|
188258
|
+
digest: "sha256:d28acaadf490df9e58e12f195804f181a683d0d33344275d7989efbee26a4504",
|
|
188259
|
+
kind: "historical"
|
|
188260
|
+
}
|
|
188261
|
+
],
|
|
188107
188262
|
"0.13.1": [
|
|
188108
188263
|
{
|
|
188109
188264
|
digest: "sha256:8654e68ea61f2acea29027056802bf627ad737f084c9a86ab052946943538409",
|
|
@@ -189366,7 +189521,7 @@ function parseJsonObject(path, content) {
|
|
|
189366
189521
|
if (content.trim().length === 0)
|
|
189367
189522
|
return {};
|
|
189368
189523
|
const parsed = JSON.parse(content);
|
|
189369
|
-
if (!
|
|
189524
|
+
if (!isRecord11(parsed))
|
|
189370
189525
|
throw new Error(`${path} must contain a JSON object`);
|
|
189371
189526
|
return parsed;
|
|
189372
189527
|
}
|
|
@@ -189375,7 +189530,7 @@ function inspectCodexAppendSafety(content, cwd, home) {
|
|
|
189375
189530
|
return { ok: true };
|
|
189376
189531
|
try {
|
|
189377
189532
|
const parsed = parse5(content);
|
|
189378
|
-
if (!
|
|
189533
|
+
if (!isRecord11(parsed)) {
|
|
189379
189534
|
return {
|
|
189380
189535
|
ok: false,
|
|
189381
189536
|
detail: "Codex config is not a TOML object and was left unchanged."
|
|
@@ -189387,13 +189542,13 @@ function inspectCodexAppendSafety(content, cwd, home) {
|
|
|
189387
189542
|
detail: "Codex has a project-scoped MCP or Plugin override; the global config was left unchanged."
|
|
189388
189543
|
};
|
|
189389
189544
|
}
|
|
189390
|
-
if ("mcp_servers" in parsed && !
|
|
189545
|
+
if ("mcp_servers" in parsed && !isRecord11(parsed.mcp_servers)) {
|
|
189391
189546
|
return {
|
|
189392
189547
|
ok: false,
|
|
189393
189548
|
detail: "Codex mcp_servers is malformed and was left unchanged."
|
|
189394
189549
|
};
|
|
189395
189550
|
}
|
|
189396
|
-
if (
|
|
189551
|
+
if (isRecord11(parsed.mcp_servers) && "kyoso" in parsed.mcp_servers) {
|
|
189397
189552
|
return {
|
|
189398
189553
|
ok: false,
|
|
189399
189554
|
detail: "Codex already defines mcp_servers.kyoso in a form setup cannot safely extend; migrate it manually."
|
|
@@ -189429,7 +189584,7 @@ function inspectCodexMcpContent(content, path, cwd, home) {
|
|
|
189429
189584
|
value: undefined
|
|
189430
189585
|
});
|
|
189431
189586
|
}
|
|
189432
|
-
if (!
|
|
189587
|
+
if (!isRecord11(parsed) || !isRecord11(parsed.mcp_servers)) {
|
|
189433
189588
|
return manualMcpRegistration({
|
|
189434
189589
|
path,
|
|
189435
189590
|
scope: "codex-global",
|
|
@@ -189457,7 +189612,7 @@ function inspectCodexMcpContent(content, path, cwd, home) {
|
|
|
189457
189612
|
function inspectClaudeProjectMcp(current, path) {
|
|
189458
189613
|
if (!("mcpServers" in current))
|
|
189459
189614
|
return;
|
|
189460
|
-
if (!
|
|
189615
|
+
if (!isRecord11(current.mcpServers)) {
|
|
189461
189616
|
return manualMcpRegistration({
|
|
189462
189617
|
path,
|
|
189463
189618
|
scope: "claude-project",
|
|
@@ -190087,7 +190242,7 @@ function detectCodexMcp(path, cwd, home) {
|
|
|
190087
190242
|
value: undefined
|
|
190088
190243
|
}));
|
|
190089
190244
|
}
|
|
190090
|
-
if (!
|
|
190245
|
+
if (!isRecord11(parsed)) {
|
|
190091
190246
|
return singleMcpDetection(manualMcpRegistration({
|
|
190092
190247
|
path,
|
|
190093
190248
|
scope: "codex-global",
|
|
@@ -190097,7 +190252,7 @@ function detectCodexMcp(path, cwd, home) {
|
|
|
190097
190252
|
}
|
|
190098
190253
|
if (!("mcp_servers" in parsed))
|
|
190099
190254
|
return missingMcpDetection();
|
|
190100
|
-
if (!
|
|
190255
|
+
if (!isRecord11(parsed.mcp_servers)) {
|
|
190101
190256
|
return singleMcpDetection(manualMcpRegistration({
|
|
190102
190257
|
path,
|
|
190103
190258
|
scope: "codex-global",
|
|
@@ -190147,7 +190302,7 @@ function detectClaudeMcp(path, cwd, home) {
|
|
|
190147
190302
|
}
|
|
190148
190303
|
function jsonMcpRegistrations(value, path, cwd, home) {
|
|
190149
190304
|
const directScope = path.endsWith(".mcp.json") ? "claude-project" : "claude-global";
|
|
190150
|
-
if (!
|
|
190305
|
+
if (!isRecord11(value)) {
|
|
190151
190306
|
return [
|
|
190152
190307
|
manualMcpRegistration({
|
|
190153
190308
|
path,
|
|
@@ -190160,7 +190315,7 @@ function jsonMcpRegistrations(value, path, cwd, home) {
|
|
|
190160
190315
|
const registrations = directMcpRegistrations(value, path, directScope);
|
|
190161
190316
|
if (!("projects" in value))
|
|
190162
190317
|
return registrations;
|
|
190163
|
-
if (!
|
|
190318
|
+
if (!isRecord11(value.projects)) {
|
|
190164
190319
|
return [
|
|
190165
190320
|
...registrations,
|
|
190166
190321
|
manualMcpRegistration({
|
|
@@ -190175,7 +190330,7 @@ function jsonMcpRegistrations(value, path, cwd, home) {
|
|
|
190175
190330
|
for (const [projectPath, projectConfig] of Object.entries(value.projects)) {
|
|
190176
190331
|
if (normalizeProjectPath(projectPath, home) !== currentProject)
|
|
190177
190332
|
continue;
|
|
190178
|
-
if (!
|
|
190333
|
+
if (!isRecord11(projectConfig)) {
|
|
190179
190334
|
registrations.push(manualMcpRegistration({
|
|
190180
190335
|
path,
|
|
190181
190336
|
scope: "claude-global-project",
|
|
@@ -190191,7 +190346,7 @@ function jsonMcpRegistrations(value, path, cwd, home) {
|
|
|
190191
190346
|
function directMcpRegistrations(value, path, scope) {
|
|
190192
190347
|
if (!("mcpServers" in value))
|
|
190193
190348
|
return [];
|
|
190194
|
-
if (!
|
|
190349
|
+
if (!isRecord11(value.mcpServers)) {
|
|
190195
190350
|
return [
|
|
190196
190351
|
manualMcpRegistration({
|
|
190197
190352
|
path,
|
|
@@ -190215,7 +190370,7 @@ function directMcpRegistrations(value, path, scope) {
|
|
|
190215
190370
|
function nestedMcpEntryStatus(value, path) {
|
|
190216
190371
|
let current = value;
|
|
190217
190372
|
for (const key of path) {
|
|
190218
|
-
if (!
|
|
190373
|
+
if (!isRecord11(current))
|
|
190219
190374
|
return "unknown";
|
|
190220
190375
|
if (!(key in current))
|
|
190221
190376
|
return "missing";
|
|
@@ -190224,11 +190379,11 @@ function nestedMcpEntryStatus(value, path) {
|
|
|
190224
190379
|
return mcpEntryStatus(current);
|
|
190225
190380
|
}
|
|
190226
190381
|
function hasUnprobedProjectIntegrationOverride(value, cwd, home) {
|
|
190227
|
-
if (!
|
|
190382
|
+
if (!isRecord11(value) || !isRecord11(value.projects))
|
|
190228
190383
|
return false;
|
|
190229
190384
|
const currentProject = normalizeProjectPath(cwd, home);
|
|
190230
190385
|
for (const [projectPath, projectConfig] of Object.entries(value.projects)) {
|
|
190231
|
-
if (normalizeProjectPath(projectPath, home) !== currentProject || !
|
|
190386
|
+
if (normalizeProjectPath(projectPath, home) !== currentProject || !isRecord11(projectConfig)) {
|
|
190232
190387
|
continue;
|
|
190233
190388
|
}
|
|
190234
190389
|
if ("mcp_servers" in projectConfig || "plugins" in projectConfig) {
|
|
@@ -190251,7 +190406,7 @@ function normalizeProjectPath(path, home) {
|
|
|
190251
190406
|
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
190252
190407
|
}
|
|
190253
190408
|
function mcpEntryStatus(value) {
|
|
190254
|
-
if (!
|
|
190409
|
+
if (!isRecord11(value))
|
|
190255
190410
|
return "unknown";
|
|
190256
190411
|
if (!("enabled" in value))
|
|
190257
190412
|
return "enabled";
|
|
@@ -190302,7 +190457,7 @@ function readTextSync(path) {
|
|
|
190302
190457
|
function recordValue(value) {
|
|
190303
190458
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
190304
190459
|
}
|
|
190305
|
-
function
|
|
190460
|
+
function isRecord11(value) {
|
|
190306
190461
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
190307
190462
|
}
|
|
190308
190463
|
function diffForAppend(path, snippet) {
|
|
@@ -190506,12 +190661,13 @@ async function runDoctor(options) {
|
|
|
190506
190661
|
}
|
|
190507
190662
|
const judgeRoute = resolveJudgeCallRoute(loaded.config.judge.mode, loaded.config.judge.provider, env);
|
|
190508
190663
|
const reviewTiming = calculateReviewTiming(loaded.config, judgeRoute.llmAvailable);
|
|
190664
|
+
const recommendedReviewWallTimeS = Math.ceil(reviewTiming.recommendedReviewWallTimeMs / 1000);
|
|
190509
190665
|
lines.push("", "Review timing");
|
|
190510
190666
|
lines.push(` review-wide deadline: ${loaded.config.reviewBudget.maxTotalWallTimeMs} ms`, ` sequential phases: primary ${reviewTiming.primaryPhaseMs} + verification ${reviewTiming.verificationPhaseMs} + LLM judge ${reviewTiming.judgePhaseMs} = ${reviewTiming.sequentialPhaseMs} ms`, ` recommended review-wide deadline: ${reviewTiming.recommendedReviewWallTimeMs} ms`);
|
|
190511
190667
|
if (loaded.config.reviewBudget.maxTotalWallTimeMs < reviewTiming.sequentialPhaseMs) {
|
|
190512
|
-
lines.push(` warning: review-wide deadline is insufficient: ${loaded.config.reviewBudget.maxTotalWallTimeMs} ms is below the configured sequential phase time of ${reviewTiming.sequentialPhaseMs} ms; later phases cannot receive their configured timeout.`, ` hint: set user-global reviewBudget.
|
|
190668
|
+
lines.push(` warning: review-wide deadline is insufficient: ${loaded.config.reviewBudget.maxTotalWallTimeMs} ms is below the configured sequential phase time of ${reviewTiming.sequentialPhaseMs} ms; later phases cannot receive their configured timeout.`, ` hint: set user-global reviewBudget.maxTotalWallTimeS to at least ${recommendedReviewWallTimeS}.`);
|
|
190513
190669
|
} else if (loaded.config.reviewBudget.maxTotalWallTimeMs < reviewTiming.recommendedReviewWallTimeMs) {
|
|
190514
|
-
lines.push(` warning: review-wide deadline has low margin: ${loaded.config.reviewBudget.maxTotalWallTimeMs} ms is below the recommended ${reviewTiming.recommendedReviewWallTimeMs} ms; scheduling and finalization margin is reduced.`, ` hint: set user-global reviewBudget.
|
|
190670
|
+
lines.push(` warning: review-wide deadline has low margin: ${loaded.config.reviewBudget.maxTotalWallTimeMs} ms is below the recommended ${reviewTiming.recommendedReviewWallTimeMs} ms; scheduling and finalization margin is reduced.`, ` hint: set user-global reviewBudget.maxTotalWallTimeS to at least ${recommendedReviewWallTimeS}.`);
|
|
190515
190671
|
}
|
|
190516
190672
|
const judgeProvider = judgeRoute.llmAvailable ? judgeRoute.provider : "deterministic_fallback";
|
|
190517
190673
|
lines.push("", "Judge");
|
|
@@ -193384,17 +193540,17 @@ function isResponseMessage(value) {
|
|
|
193384
193540
|
function isNotificationMessage(value) {
|
|
193385
193541
|
return isJsonRpcEnvelope(value) && !("id" in value) && typeof value["method"] === "string";
|
|
193386
193542
|
}
|
|
193387
|
-
function
|
|
193543
|
+
function isRecord12(value) {
|
|
193388
193544
|
return typeof value === "object" && value !== null;
|
|
193389
193545
|
}
|
|
193390
193546
|
function isJsonRpcEnvelope(value) {
|
|
193391
|
-
return
|
|
193547
|
+
return isRecord12(value) && value["jsonrpc"] === "2.0";
|
|
193392
193548
|
}
|
|
193393
193549
|
function isJsonRpcId(value) {
|
|
193394
193550
|
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
193395
193551
|
}
|
|
193396
193552
|
function isResponseShapedMessage(value) {
|
|
193397
|
-
return
|
|
193553
|
+
return isRecord12(value) && !("method" in value) && (("id" in value) || ("result" in value) || ("error" in value));
|
|
193398
193554
|
}
|
|
193399
193555
|
function isResponseBatch(batch) {
|
|
193400
193556
|
let hasValidCall = false;
|
|
@@ -193404,7 +193560,7 @@ function isResponseBatch(batch) {
|
|
|
193404
193560
|
for (const entry of batch) {
|
|
193405
193561
|
hasValidCall ||= isRequestMessage(entry) || isNotificationMessage(entry);
|
|
193406
193562
|
hasValidResponse ||= isResponseMessage(entry);
|
|
193407
|
-
if (!
|
|
193563
|
+
if (!isRecord12(entry)) {
|
|
193408
193564
|
continue;
|
|
193409
193565
|
}
|
|
193410
193566
|
hasCallShape ||= "method" in entry;
|
|
@@ -193419,13 +193575,13 @@ function isResponseBatch(batch) {
|
|
|
193419
193575
|
return hasResponseShape && !hasCallShape;
|
|
193420
193576
|
}
|
|
193421
193577
|
function cancelRequestId(params) {
|
|
193422
|
-
if (!
|
|
193578
|
+
if (!isRecord12(params) || !isJsonRpcId(params["requestId"])) {
|
|
193423
193579
|
return;
|
|
193424
193580
|
}
|
|
193425
193581
|
return params["requestId"];
|
|
193426
193582
|
}
|
|
193427
193583
|
function isErrorResponse(value) {
|
|
193428
|
-
return
|
|
193584
|
+
return isRecord12(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
|
|
193429
193585
|
}
|
|
193430
193586
|
var Handled = {
|
|
193431
193587
|
yes() {
|
|
@@ -193820,7 +193976,7 @@ class Connection {
|
|
|
193820
193976
|
this.receiveBatch(message);
|
|
193821
193977
|
return;
|
|
193822
193978
|
}
|
|
193823
|
-
if (!
|
|
193979
|
+
if (!isRecord12(message)) {
|
|
193824
193980
|
console.error("Invalid message", { message });
|
|
193825
193981
|
return;
|
|
193826
193982
|
}
|
|
@@ -193881,7 +194037,7 @@ class Connection {
|
|
|
193881
194037
|
if (this.abortController.signal.aborted) {
|
|
193882
194038
|
return Promise.resolve();
|
|
193883
194039
|
}
|
|
193884
|
-
if (!
|
|
194040
|
+
if (!isRecord12(message)) {
|
|
193885
194041
|
console.error("Invalid message", { message });
|
|
193886
194042
|
return Promise.resolve();
|
|
193887
194043
|
}
|
|
@@ -194188,7 +194344,7 @@ function ndJsonStream(output2, input2) {
|
|
|
194188
194344
|
if (trimmedLine) {
|
|
194189
194345
|
try {
|
|
194190
194346
|
const message = JSON.parse(trimmedLine);
|
|
194191
|
-
if (
|
|
194347
|
+
if (isRecord12(message) || Array.isArray(message)) {
|
|
194192
194348
|
controller.enqueue(message);
|
|
194193
194349
|
} else {
|
|
194194
194350
|
console.warn("Skipping JSON line that is not an object:", trimmedLine);
|
|
@@ -195220,12 +195376,12 @@ class AgentOutputAccumulator {
|
|
|
195220
195376
|
var RETRY_ATTEMPT_PATTERN = /Reconnecting\.\.\.\s*(\d+)\/(\d+)/;
|
|
195221
195377
|
var DISPLAY_MESSAGE_FIELDS = ["title", "text", "message", "description"];
|
|
195222
195378
|
function parseCodexRetryUpdate(update) {
|
|
195223
|
-
if (!
|
|
195379
|
+
if (!isRecord13(update) || update.sessionUpdate !== "session_info_update") {
|
|
195224
195380
|
return;
|
|
195225
195381
|
}
|
|
195226
|
-
const meta3 =
|
|
195227
|
-
const codex = meta3 &&
|
|
195228
|
-
const error51 = codex &&
|
|
195382
|
+
const meta3 = isRecord13(update._meta) ? update._meta : undefined;
|
|
195383
|
+
const codex = meta3 && isRecord13(meta3.codex) ? meta3.codex : undefined;
|
|
195384
|
+
const error51 = codex && isRecord13(codex.error) ? codex.error : undefined;
|
|
195229
195385
|
if (error51?.willRetry !== true)
|
|
195230
195386
|
return;
|
|
195231
195387
|
const rawMessage = typeof error51.message === "string" ? error51.message : findDisplayMessage(update) ?? "model stream retry";
|
|
@@ -195245,7 +195401,7 @@ function findDisplayMessage(update) {
|
|
|
195245
195401
|
}
|
|
195246
195402
|
return;
|
|
195247
195403
|
}
|
|
195248
|
-
function
|
|
195404
|
+
function isRecord13(value) {
|
|
195249
195405
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
195250
195406
|
}
|
|
195251
195407
|
|
|
@@ -195730,7 +195886,7 @@ function isSeverity(value) {
|
|
|
195730
195886
|
return typeof value === "string" && severities.includes(value);
|
|
195731
195887
|
}
|
|
195732
195888
|
function normalizeCisaSecureByDesign(value) {
|
|
195733
|
-
if (!
|
|
195889
|
+
if (!isRecord14(value))
|
|
195734
195890
|
return;
|
|
195735
195891
|
const normalized = {};
|
|
195736
195892
|
const customerSecurityOutcomes = normalizeGateStatus(value.customerSecurityOutcomes);
|
|
@@ -195771,7 +195927,7 @@ function isEvidenceQuality(value) {
|
|
|
195771
195927
|
return typeof value === "string" && evidenceQualities.includes(value);
|
|
195772
195928
|
}
|
|
195773
195929
|
function isStrictAgentOpinion(value) {
|
|
195774
|
-
if (!
|
|
195930
|
+
if (!isRecord14(value) || !hasOnlyKeys(value, STRICT_ROOT_KEYS))
|
|
195775
195931
|
return false;
|
|
195776
195932
|
if (typeof value.summary !== "string")
|
|
195777
195933
|
return false;
|
|
@@ -195781,7 +195937,7 @@ function isStrictAgentOpinion(value) {
|
|
|
195781
195937
|
return value.cisaSecureByDesign === undefined || isStrictCisaSecureByDesign(value.cisaSecureByDesign);
|
|
195782
195938
|
}
|
|
195783
195939
|
function isStrictFinding(value) {
|
|
195784
|
-
if (!
|
|
195940
|
+
if (!isRecord14(value) || !hasOnlyKeys(value, STRICT_FINDING_KEYS)) {
|
|
195785
195941
|
return false;
|
|
195786
195942
|
}
|
|
195787
195943
|
if (!isSeverity(value.severity) || !isCategory(value.category) || !isNonEmptyString(value.title) || !isNonEmptyString(value.evidence) || !isNonEmptyString(value.recommendation) || !isConfidence(value.confidence)) {
|
|
@@ -195793,11 +195949,11 @@ function isStrictFinding(value) {
|
|
|
195793
195949
|
return true;
|
|
195794
195950
|
}
|
|
195795
195951
|
function isStrictFindingFiles(value) {
|
|
195796
|
-
return Array.isArray(value) && value.every((item) =>
|
|
195952
|
+
return Array.isArray(value) && value.every((item) => isRecord14(item) && hasOnlyKeys(item, STRICT_FILE_KEYS) && isNonEmptyString(item.path) && isOptionalLineNumber(item.lineStart) && isOptionalLineNumber(item.lineEnd));
|
|
195797
195953
|
}
|
|
195798
195954
|
function isStrictEvidenceRefs(value) {
|
|
195799
195955
|
return Array.isArray(value) && value.length <= MAX_EVIDENCE_REFS2 && value.every((item) => {
|
|
195800
|
-
if (!
|
|
195956
|
+
if (!isRecord14(item) || !hasOnlyKeys(item, STRICT_EVIDENCE_REF_KEYS)) {
|
|
195801
195957
|
return false;
|
|
195802
195958
|
}
|
|
195803
195959
|
if (item.kind !== "file" && item.kind !== "diff_hunk" && item.kind !== "plan_clause") {
|
|
@@ -195813,7 +195969,7 @@ function isStrictEvidenceRefs(value) {
|
|
|
195813
195969
|
});
|
|
195814
195970
|
}
|
|
195815
195971
|
function isStrictCisaSecureByDesign(value) {
|
|
195816
|
-
if (!
|
|
195972
|
+
if (!isRecord14(value) || !hasOnlyKeys(value, STRICT_CISA_KEYS))
|
|
195817
195973
|
return false;
|
|
195818
195974
|
for (const key of [
|
|
195819
195975
|
"customerSecurityOutcomes",
|
|
@@ -195852,7 +196008,7 @@ function normalizeFindingFiles(value) {
|
|
|
195852
196008
|
if (!Array.isArray(value))
|
|
195853
196009
|
return;
|
|
195854
196010
|
const files = value.flatMap((item) => {
|
|
195855
|
-
if (!
|
|
196011
|
+
if (!isRecord14(item) || typeof item.path !== "string" || item.path.trim().length === 0) {
|
|
195856
196012
|
return [];
|
|
195857
196013
|
}
|
|
195858
196014
|
const file2 = {
|
|
@@ -195872,7 +196028,7 @@ function normalizeEvidenceRefs2(value) {
|
|
|
195872
196028
|
if (!Array.isArray(value))
|
|
195873
196029
|
return;
|
|
195874
196030
|
const references = value.slice(0, MAX_EVIDENCE_REFS2).flatMap((item) => {
|
|
195875
|
-
if (!
|
|
196031
|
+
if (!isRecord14(item) || item.kind !== "file" && item.kind !== "diff_hunk" && item.kind !== "plan_clause") {
|
|
195876
196032
|
return [];
|
|
195877
196033
|
}
|
|
195878
196034
|
const reference = { kind: item.kind };
|
|
@@ -195895,7 +196051,7 @@ function normalizeEvidenceRefs2(value) {
|
|
|
195895
196051
|
function normalizeLineNumber(value) {
|
|
195896
196052
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 && value <= MAX_EVIDENCE_LINE2 ? value : undefined;
|
|
195897
196053
|
}
|
|
195898
|
-
function
|
|
196054
|
+
function isRecord14(value) {
|
|
195899
196055
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
195900
196056
|
}
|
|
195901
196057
|
|
|
@@ -196520,7 +196676,7 @@ function normalizeUsage3(usage) {
|
|
|
196520
196676
|
return normalizeModelTokenUsage(usage);
|
|
196521
196677
|
}
|
|
196522
196678
|
function withReportedExecutionIdentity(identity, metadata) {
|
|
196523
|
-
const record2 =
|
|
196679
|
+
const record2 = isRecord15(metadata) ? metadata : {};
|
|
196524
196680
|
return createModelExecutionIdentity({
|
|
196525
196681
|
providerRoute: identity.providerRoute,
|
|
196526
196682
|
requestedModel: identity.requestedModel,
|
|
@@ -196529,9 +196685,9 @@ function withReportedExecutionIdentity(identity, metadata) {
|
|
|
196529
196685
|
});
|
|
196530
196686
|
}
|
|
196531
196687
|
function readChunkMeta(update) {
|
|
196532
|
-
const record2 =
|
|
196533
|
-
const metadata =
|
|
196534
|
-
const codex =
|
|
196688
|
+
const record2 = isRecord15(update) ? update : {};
|
|
196689
|
+
const metadata = isRecord15(record2._meta) ? record2._meta : {};
|
|
196690
|
+
const codex = isRecord15(metadata.codex) ? metadata.codex : {};
|
|
196535
196691
|
const phase = codex.phase === "commentary" || codex.phase === "final_answer" ? codex.phase : "unknown";
|
|
196536
196692
|
return {
|
|
196537
196693
|
...typeof record2.messageId === "string" ? { messageId: record2.messageId } : {},
|
|
@@ -196539,15 +196695,15 @@ function readChunkMeta(update) {
|
|
|
196539
196695
|
};
|
|
196540
196696
|
}
|
|
196541
196697
|
function readCodexThreadStatus(update) {
|
|
196542
|
-
const record2 =
|
|
196698
|
+
const record2 = isRecord15(update) ? update : {};
|
|
196543
196699
|
if (record2.sessionUpdate !== "session_info_update")
|
|
196544
196700
|
return;
|
|
196545
|
-
const metadata =
|
|
196546
|
-
const codex =
|
|
196547
|
-
const threadStatus =
|
|
196701
|
+
const metadata = isRecord15(record2._meta) ? record2._meta : {};
|
|
196702
|
+
const codex = isRecord15(metadata.codex) ? metadata.codex : {};
|
|
196703
|
+
const threadStatus = isRecord15(codex.threadStatus) ? codex.threadStatus : {};
|
|
196548
196704
|
return typeof threadStatus.type === "string" ? threadStatus.type : undefined;
|
|
196549
196705
|
}
|
|
196550
|
-
function
|
|
196706
|
+
function isRecord15(value) {
|
|
196551
196707
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
196552
196708
|
}
|
|
196553
196709
|
function resolveEffortConfigOption(agent, effort) {
|
|
@@ -210950,9 +211106,14 @@ import { resolve as resolve10 } from "node:path";
|
|
|
210950
211106
|
// src/config/configOverrides.ts
|
|
210951
211107
|
var NUMBER_VALUE = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i;
|
|
210952
211108
|
var UNSET_NUMBER_OVERRIDE_PATHS = new Set([
|
|
211109
|
+
"agents.codex.timeoutS",
|
|
211110
|
+
"agents.claude.timeoutS",
|
|
210953
211111
|
"agents.codex.openRouter.streamIdleTimeoutMs",
|
|
211112
|
+
"agents.codex.openRouter.streamIdleTimeoutS",
|
|
210954
211113
|
"agents.codex.openRouter.streamMaxRetries",
|
|
210955
|
-
"agents.codex.openRouter.requestMaxRetries"
|
|
211114
|
+
"agents.codex.openRouter.requestMaxRetries",
|
|
211115
|
+
"judge.timeoutS",
|
|
211116
|
+
"verification.timeoutS"
|
|
210956
211117
|
]);
|
|
210957
211118
|
function applyConfigOverrides(config2, assignments) {
|
|
210958
211119
|
if (assignments.length === 0)
|
|
@@ -210963,9 +211124,21 @@ function applyConfigOverrides(config2, assignments) {
|
|
|
210963
211124
|
for (const override of overrides) {
|
|
210964
211125
|
writePath2(overridden, override.path, parseConfigOverrideValue(override.value, readPath2(baseConfig, override.path), override.path));
|
|
210965
211126
|
}
|
|
210966
|
-
|
|
210967
|
-
|
|
210968
|
-
|
|
211127
|
+
let normalized;
|
|
211128
|
+
try {
|
|
211129
|
+
normalized = normalizeConfigTimeUnits(overridden);
|
|
211130
|
+
} catch (error51) {
|
|
211131
|
+
if (!(error51 instanceof TimeUnitValidationError))
|
|
211132
|
+
throw error51;
|
|
211133
|
+
const assignment2 = findAssignmentForPath(overrides, error51.field);
|
|
211134
|
+
if (!assignment2) {
|
|
211135
|
+
throw new Error(`Invalid config time value: ${error51.message}`);
|
|
211136
|
+
}
|
|
211137
|
+
throw new Error(`Invalid --set value ${JSON.stringify(assignment2)}: ${error51.message}`);
|
|
211138
|
+
}
|
|
211139
|
+
clearInheritedOpenRouterConfigForProviderReset(baseConfig, normalized, overrides);
|
|
211140
|
+
assertOpenRouterProviderOverrideIncludesModel(baseConfig, normalized, overrides);
|
|
211141
|
+
const parsed = kyosoConfigSchema.safeParse(normalized);
|
|
210969
211142
|
if (parsed.success)
|
|
210970
211143
|
return parsed.data;
|
|
210971
211144
|
const issue2 = parsed.error.issues[0];
|
|
@@ -210995,7 +211168,7 @@ function clearInheritedOpenRouterConfigForProviderReset(baseConfig, overridden,
|
|
|
210995
211168
|
return;
|
|
210996
211169
|
}
|
|
210997
211170
|
const codex = readPath2(overridden, ["agents", "codex"]);
|
|
210998
|
-
if (!
|
|
211171
|
+
if (!isRecord16(codex))
|
|
210999
211172
|
return;
|
|
211000
211173
|
if (!suppliesModel)
|
|
211001
211174
|
delete codex.model;
|
|
@@ -211044,7 +211217,7 @@ function parseConfigOverrideValue(value, currentValue, path) {
|
|
|
211044
211217
|
function readPath2(target, path) {
|
|
211045
211218
|
let current = target;
|
|
211046
211219
|
for (const key of path) {
|
|
211047
|
-
if (!
|
|
211220
|
+
if (!isRecord16(current))
|
|
211048
211221
|
return;
|
|
211049
211222
|
current = current[key];
|
|
211050
211223
|
}
|
|
@@ -211054,7 +211227,7 @@ function writePath2(target, path, value) {
|
|
|
211054
211227
|
let current = target;
|
|
211055
211228
|
for (const key of path.slice(0, -1)) {
|
|
211056
211229
|
const child = current[key];
|
|
211057
|
-
if (!
|
|
211230
|
+
if (!isRecord16(child)) {
|
|
211058
211231
|
throw new Error(`Cannot apply --set key ${JSON.stringify(path.join("."))}.`);
|
|
211059
211232
|
}
|
|
211060
211233
|
current = child;
|
|
@@ -211063,7 +211236,7 @@ function writePath2(target, path, value) {
|
|
|
211063
211236
|
if (leaf)
|
|
211064
211237
|
current[leaf] = value;
|
|
211065
211238
|
}
|
|
211066
|
-
function
|
|
211239
|
+
function isRecord16(value) {
|
|
211067
211240
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
211068
211241
|
}
|
|
211069
211242
|
|
|
@@ -212301,7 +212474,7 @@ function validateReviewContract(request) {
|
|
|
212301
212474
|
const contract = request.reviewContract;
|
|
212302
212475
|
if (contract === undefined)
|
|
212303
212476
|
return;
|
|
212304
|
-
if (!
|
|
212477
|
+
if (!isRecord17(contract)) {
|
|
212305
212478
|
throw new KyosoRequestError("reviewContract must be an object", "VALIDATION_ERROR");
|
|
212306
212479
|
}
|
|
212307
212480
|
const allowedKeys = new Set(["focus", "nonGoals", "acceptedRisks"]);
|
|
@@ -212318,7 +212491,7 @@ function validateReviewContract(request) {
|
|
|
212318
212491
|
throw new KyosoRequestError("reviewContract.nonGoals must contain at most 20 non-empty strings of 500 characters or fewer", "VALIDATION_ERROR");
|
|
212319
212492
|
}
|
|
212320
212493
|
const acceptedRisks = contract.acceptedRisks;
|
|
212321
|
-
if (acceptedRisks !== undefined && (!Array.isArray(acceptedRisks) || acceptedRisks.length > 20 || acceptedRisks.some((risk) => !
|
|
212494
|
+
if (acceptedRisks !== undefined && (!Array.isArray(acceptedRisks) || acceptedRisks.length > 20 || acceptedRisks.some((risk) => !isRecord17(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))) {
|
|
212322
212495
|
throw new KyosoRequestError("reviewContract.acceptedRisks must contain valid finding fingerprints and bounded rationales", "VALIDATION_ERROR");
|
|
212323
212496
|
}
|
|
212324
212497
|
}
|
|
@@ -212330,13 +212503,13 @@ function validateSelectedFiles(request) {
|
|
|
212330
212503
|
throw new KyosoRequestError("selectedFiles must be an array", "VALIDATION_ERROR");
|
|
212331
212504
|
}
|
|
212332
212505
|
for (const file2 of selectedFiles) {
|
|
212333
|
-
if (!
|
|
212506
|
+
if (!isRecord17(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") {
|
|
212334
212507
|
throw new KyosoRequestError("selectedFiles entries require string path/content and valid optional metadata", "VALIDATION_ERROR");
|
|
212335
212508
|
}
|
|
212336
212509
|
normalizeRelativePath(file2.path);
|
|
212337
212510
|
}
|
|
212338
212511
|
}
|
|
212339
|
-
function
|
|
212512
|
+
function isRecord17(value) {
|
|
212340
212513
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
212341
212514
|
}
|
|
212342
212515
|
|
|
@@ -212867,11 +213040,11 @@ function canonicalJson(value) {
|
|
|
212867
213040
|
function canonicalize(value) {
|
|
212868
213041
|
if (Array.isArray(value))
|
|
212869
213042
|
return value.map(canonicalize);
|
|
212870
|
-
if (!
|
|
213043
|
+
if (!isRecord18(value))
|
|
212871
213044
|
return value;
|
|
212872
213045
|
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)]));
|
|
212873
213046
|
}
|
|
212874
|
-
function
|
|
213047
|
+
function isRecord18(value) {
|
|
212875
213048
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
212876
213049
|
}
|
|
212877
213050
|
|
|
@@ -212879,19 +213052,24 @@ function isRecord17(value) {
|
|
|
212879
213052
|
var REVIEW_BUDGET_KEYS = new Set([
|
|
212880
213053
|
"maxModelCalls",
|
|
212881
213054
|
"maxTotalWallTimeMs",
|
|
213055
|
+
"maxTotalWallTimeS",
|
|
212882
213056
|
"maxAgentOutputBytes",
|
|
212883
213057
|
"maxFindingsPerAgent",
|
|
212884
213058
|
"skipOptionalPhasesWhenTokenUsageUnknown"
|
|
212885
213059
|
]);
|
|
212886
213060
|
var MODEL_CALL_KINDS = ["primary", "verifier", "judge"];
|
|
212887
213061
|
function resolveReviewBudget(ceiling, requested) {
|
|
212888
|
-
if (requested !== undefined && !
|
|
213062
|
+
if (requested !== undefined && !isRecord19(requested)) {
|
|
212889
213063
|
throw new KyosoRequestError("options.reviewBudget must be an object.", "REVIEW_BUDGET_INVALID");
|
|
212890
213064
|
}
|
|
213065
|
+
const hasWallTimeSeconds = requested?.maxTotalWallTimeS !== undefined;
|
|
212891
213066
|
for (const [key, value] of Object.entries(requested ?? {})) {
|
|
212892
213067
|
if (!REVIEW_BUDGET_KEYS.has(key)) {
|
|
212893
213068
|
throw new KyosoRequestError(`options.reviewBudget.${key} is not supported.`, "REVIEW_BUDGET_INVALID");
|
|
212894
213069
|
}
|
|
213070
|
+
if (key === "maxTotalWallTimeS" || key === "maxTotalWallTimeMs" && hasWallTimeSeconds) {
|
|
213071
|
+
continue;
|
|
213072
|
+
}
|
|
212895
213073
|
if (key === "skipOptionalPhasesWhenTokenUsageUnknown") {
|
|
212896
213074
|
if (typeof value !== "boolean") {
|
|
212897
213075
|
throw new KyosoRequestError(`options.reviewBudget.${key} must be a boolean.`, "REVIEW_BUDGET_INVALID");
|
|
@@ -212902,12 +213080,26 @@ function resolveReviewBudget(ceiling, requested) {
|
|
|
212902
213080
|
throw new KyosoRequestError(`options.reviewBudget.${key} must be a positive integer.`, "REVIEW_BUDGET_INVALID");
|
|
212903
213081
|
}
|
|
212904
213082
|
}
|
|
212905
|
-
|
|
212906
|
-
|
|
212907
|
-
|
|
212908
|
-
|
|
212909
|
-
|
|
212910
|
-
|
|
213083
|
+
let requestedWallTime;
|
|
213084
|
+
if (hasWallTimeSeconds) {
|
|
213085
|
+
try {
|
|
213086
|
+
requestedWallTime = resolveTimeUnitPair({
|
|
213087
|
+
milliseconds: requested?.maxTotalWallTimeMs,
|
|
213088
|
+
seconds: requested?.maxTotalWallTimeS
|
|
213089
|
+
}, {
|
|
213090
|
+
milliseconds: "options.reviewBudget.maxTotalWallTimeMs",
|
|
213091
|
+
seconds: "options.reviewBudget.maxTotalWallTimeS"
|
|
213092
|
+
});
|
|
213093
|
+
} catch (error51) {
|
|
213094
|
+
if (error51 instanceof TimeUnitValidationError) {
|
|
213095
|
+
throw new KyosoRequestError(error51.message, "REVIEW_BUDGET_INVALID");
|
|
213096
|
+
}
|
|
213097
|
+
throw error51;
|
|
213098
|
+
}
|
|
213099
|
+
}
|
|
213100
|
+
const numericKeys = ["maxModelCalls", "maxAgentOutputBytes", "maxFindingsPerAgent"];
|
|
213101
|
+
if (!hasWallTimeSeconds)
|
|
213102
|
+
numericKeys.push("maxTotalWallTimeMs");
|
|
212911
213103
|
for (const key of numericKeys) {
|
|
212912
213104
|
const value = requested?.[key];
|
|
212913
213105
|
if (value === undefined)
|
|
@@ -212916,13 +213108,19 @@ function resolveReviewBudget(ceiling, requested) {
|
|
|
212916
213108
|
throw new KyosoRequestError(`options.reviewBudget.${key} cannot exceed the user-global ceiling.`, "REVIEW_BUDGET_EXCEEDS_CEILING");
|
|
212917
213109
|
}
|
|
212918
213110
|
}
|
|
213111
|
+
if (hasWallTimeSeconds && requested?.maxTotalWallTimeMs !== undefined && requested.maxTotalWallTimeMs > ceiling.maxTotalWallTimeMs) {
|
|
213112
|
+
throw new KyosoRequestError("options.reviewBudget.maxTotalWallTimeMs cannot exceed the user-global ceiling.", "REVIEW_BUDGET_EXCEEDS_CEILING");
|
|
213113
|
+
}
|
|
213114
|
+
if (requestedWallTime && requestedWallTime.milliseconds > ceiling.maxTotalWallTimeMs) {
|
|
213115
|
+
throw new KyosoRequestError(`${requestedWallTime.sourceField} cannot exceed the user-global ceiling.`, "REVIEW_BUDGET_EXCEEDS_CEILING");
|
|
213116
|
+
}
|
|
212919
213117
|
if (ceiling.skipOptionalPhasesWhenTokenUsageUnknown && requested?.skipOptionalPhasesWhenTokenUsageUnknown === false) {
|
|
212920
213118
|
throw new KyosoRequestError("options.reviewBudget.skipOptionalPhasesWhenTokenUsageUnknown cannot relax the user-global ceiling.", "REVIEW_BUDGET_EXCEEDS_CEILING");
|
|
212921
213119
|
}
|
|
212922
213120
|
const maxAgentOutputBytes = requested?.maxAgentOutputBytes ?? ceiling.maxAgentOutputBytes;
|
|
212923
213121
|
return {
|
|
212924
213122
|
maxModelCalls: requested?.maxModelCalls ?? ceiling.maxModelCalls,
|
|
212925
|
-
maxTotalWallTimeMs: requested?.maxTotalWallTimeMs ?? ceiling.maxTotalWallTimeMs,
|
|
213123
|
+
maxTotalWallTimeMs: requestedWallTime?.milliseconds ?? requested?.maxTotalWallTimeMs ?? ceiling.maxTotalWallTimeMs,
|
|
212926
213124
|
warnAgentOutputBytes: ceiling.warnAgentOutputBytes,
|
|
212927
213125
|
maxAgentOutputBytes,
|
|
212928
213126
|
maxFindingsPerAgent: requested?.maxFindingsPerAgent ?? ceiling.maxFindingsPerAgent,
|
|
@@ -213239,10 +213437,63 @@ function emptyReviewModelCallPlan() {
|
|
|
213239
213437
|
ceilingEffects: []
|
|
213240
213438
|
};
|
|
213241
213439
|
}
|
|
213242
|
-
function
|
|
213440
|
+
function isRecord19(value) {
|
|
213243
213441
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
213244
213442
|
}
|
|
213245
213443
|
|
|
213444
|
+
// src/core/requestTimeUnits.ts
|
|
213445
|
+
function normalizeRequestTimeUnits(request) {
|
|
213446
|
+
if (!request.options)
|
|
213447
|
+
return request;
|
|
213448
|
+
const options = { ...request.options };
|
|
213449
|
+
normalizeRequestTimeUnitField(options, "maxAgentTimeoutMs", "maxAgentTimeoutS", {
|
|
213450
|
+
milliseconds: "options.maxAgentTimeoutMs",
|
|
213451
|
+
seconds: "options.maxAgentTimeoutS"
|
|
213452
|
+
});
|
|
213453
|
+
if (options.reviewBudget) {
|
|
213454
|
+
const reviewBudget = { ...options.reviewBudget };
|
|
213455
|
+
normalizeRequestTimeUnitField(reviewBudget, "maxTotalWallTimeMs", "maxTotalWallTimeS", {
|
|
213456
|
+
milliseconds: "options.reviewBudget.maxTotalWallTimeMs",
|
|
213457
|
+
seconds: "options.reviewBudget.maxTotalWallTimeS"
|
|
213458
|
+
});
|
|
213459
|
+
options.reviewBudget = reviewBudget;
|
|
213460
|
+
}
|
|
213461
|
+
return { ...request, options };
|
|
213462
|
+
}
|
|
213463
|
+
function resolveProgressHeartbeatMs(input2) {
|
|
213464
|
+
if (input2.progressHeartbeatS === undefined) {
|
|
213465
|
+
return input2.progressHeartbeatMs;
|
|
213466
|
+
}
|
|
213467
|
+
return resolveRequestTimeUnit({
|
|
213468
|
+
milliseconds: input2.progressHeartbeatMs,
|
|
213469
|
+
seconds: input2.progressHeartbeatS
|
|
213470
|
+
}, {
|
|
213471
|
+
milliseconds: "progressHeartbeatMs",
|
|
213472
|
+
seconds: "progressHeartbeatS"
|
|
213473
|
+
}, { allowZero: true })?.milliseconds;
|
|
213474
|
+
}
|
|
213475
|
+
function normalizeRequestTimeUnitField(target, millisecondsKey, secondsKey, fields) {
|
|
213476
|
+
if (target[secondsKey] !== undefined) {
|
|
213477
|
+
const resolved = resolveRequestTimeUnit({
|
|
213478
|
+
milliseconds: target[millisecondsKey],
|
|
213479
|
+
seconds: target[secondsKey]
|
|
213480
|
+
}, fields);
|
|
213481
|
+
if (resolved)
|
|
213482
|
+
target[millisecondsKey] = resolved.milliseconds;
|
|
213483
|
+
}
|
|
213484
|
+
delete target[secondsKey];
|
|
213485
|
+
}
|
|
213486
|
+
function resolveRequestTimeUnit(input2, fields, constraints) {
|
|
213487
|
+
try {
|
|
213488
|
+
return resolveTimeUnitPair(input2, fields, constraints);
|
|
213489
|
+
} catch (error51) {
|
|
213490
|
+
if (error51 instanceof TimeUnitValidationError) {
|
|
213491
|
+
throw new KyosoRequestError(error51.message, "VALIDATION_ERROR");
|
|
213492
|
+
}
|
|
213493
|
+
throw error51;
|
|
213494
|
+
}
|
|
213495
|
+
}
|
|
213496
|
+
|
|
213246
213497
|
// src/core/verification.ts
|
|
213247
213498
|
var REAL_AGENTS = ["codex", "claude"];
|
|
213248
213499
|
var VERIFIABLE_SEVERITIES = new Set(["critical", "high"]);
|
|
@@ -213301,7 +213552,7 @@ function parseVerificationVerdicts(rawText) {
|
|
|
213301
213552
|
if (!Array.isArray(parsed.verdicts))
|
|
213302
213553
|
return;
|
|
213303
213554
|
return parsed.verdicts.flatMap((item) => {
|
|
213304
|
-
if (!
|
|
213555
|
+
if (!isRecord20(item))
|
|
213305
213556
|
return [];
|
|
213306
213557
|
if (typeof item.findingId !== "string")
|
|
213307
213558
|
return [];
|
|
@@ -213379,7 +213630,7 @@ function verificationNote(reasoning) {
|
|
|
213379
213630
|
function isVerdict(value) {
|
|
213380
213631
|
return value === "confirmed" || value === "refuted" || value === "uncertain";
|
|
213381
213632
|
}
|
|
213382
|
-
function
|
|
213633
|
+
function isRecord20(value) {
|
|
213383
213634
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
213384
213635
|
}
|
|
213385
213636
|
|
|
@@ -213387,7 +213638,7 @@ function isRecord19(value) {
|
|
|
213387
213638
|
var MAX_AGENT_RETRY_PROGRESS_EVENTS = 100;
|
|
213388
213639
|
function requestForRecursionFingerprint(request) {
|
|
213389
213640
|
try {
|
|
213390
|
-
return scanAndRedactSecrets(request).redactedRequest;
|
|
213641
|
+
return scanAndRedactSecrets(normalizeRequestTimeUnits(request)).redactedRequest;
|
|
213391
213642
|
} catch {
|
|
213392
213643
|
return { goal: "" };
|
|
213393
213644
|
}
|
|
@@ -213647,15 +213898,17 @@ async function runReview(tool, request, options = {}) {
|
|
|
213647
213898
|
});
|
|
213648
213899
|
validateReviewRequest(tool, request);
|
|
213649
213900
|
const reviewBudget = resolveReviewBudget(loaded.config.reviewBudget, request.options?.reviewBudget);
|
|
213650
|
-
const
|
|
213651
|
-
|
|
213652
|
-
const
|
|
213901
|
+
const normalizedRequest = normalizeRequestTimeUnits(request);
|
|
213902
|
+
const progressHeartbeatMs = resolveProgressHeartbeatMs(options);
|
|
213903
|
+
const budgetTracker = new ReviewBudgetTracker(reviewBudget, startedAtEpochMs, configuredReviewModelCallPlan(loaded.config, reviewBudget, options.env ?? process.env, normalizedRequest.options?.judgeProvider));
|
|
213904
|
+
assertTrustedWorkspaceRoot(normalizedRequest.workspace?.root, loaded.config.workspace.root, cwd);
|
|
213905
|
+
const networkMode = resolveNetworkMode(normalizedRequest.options?.network, loaded.config.network.defaultMode, options.mcpNetworkMode);
|
|
213653
213906
|
if (networkMode === "unrestricted" && !loaded.config.network.allowUnrestricted) {
|
|
213654
213907
|
throw new KyosoRequestError("unrestricted network mode is disabled by config", "NETWORK_MODE_DISABLED");
|
|
213655
213908
|
}
|
|
213656
213909
|
const disabledPolicy = disabledReviewPolicy(tool, loaded.config, options.entrypoint);
|
|
213657
213910
|
if (disabledPolicy) {
|
|
213658
|
-
const redactedRequest = requestForRecursionFingerprint(
|
|
213911
|
+
const redactedRequest = requestForRecursionFingerprint(normalizedRequest);
|
|
213659
213912
|
const requestFingerprint2 = createRequestFingerprint({
|
|
213660
213913
|
tool,
|
|
213661
213914
|
request: redactedRequest,
|
|
@@ -213706,7 +213959,7 @@ async function runReview(tool, request, options = {}) {
|
|
|
213706
213959
|
warnings.push("Network mode is unrestricted; write policy remains denied.");
|
|
213707
213960
|
}
|
|
213708
213961
|
startPhase("context");
|
|
213709
|
-
const secretScan = scanAndRedactSecrets(
|
|
213962
|
+
const secretScan = scanAndRedactSecrets(normalizedRequest);
|
|
213710
213963
|
await trace.write({
|
|
213711
213964
|
type: "secret_scan_completed",
|
|
213712
213965
|
traceId,
|
|
@@ -213714,7 +213967,7 @@ async function runReview(tool, request, options = {}) {
|
|
|
213714
213967
|
redactions: secretScan.redactions,
|
|
213715
213968
|
timestamp: new Date().toISOString()
|
|
213716
213969
|
});
|
|
213717
|
-
const allowSecretOverride = loaded.config.secrets.allowOverride &&
|
|
213970
|
+
const allowSecretOverride = loaded.config.secrets.allowOverride && normalizedRequest.options?.allowSecretRedaction === true;
|
|
213718
213971
|
if (secretScan.detected && loaded.config.secrets.blockOnDetectedSecret && !allowSecretOverride) {
|
|
213719
213972
|
const requestFingerprint2 = createRequestFingerprint({
|
|
213720
213973
|
tool,
|
|
@@ -213801,7 +214054,7 @@ async function runReview(tool, request, options = {}) {
|
|
|
213801
214054
|
budgetTracker,
|
|
213802
214055
|
progressDispatcher: dispatcher,
|
|
213803
214056
|
signal: options.signal,
|
|
213804
|
-
progressHeartbeatMs
|
|
214057
|
+
progressHeartbeatMs
|
|
213805
214058
|
});
|
|
213806
214059
|
completePhase("primary");
|
|
213807
214060
|
warnings.push(...agentResults.flatMap((result) => (result.warnings ?? []).map((warning) => `Agent ${result.agent} ${warning}`)));
|
|
@@ -215349,9 +215602,11 @@ var kyosoReviewRequestSchema = object({
|
|
|
215349
215602
|
options: object({
|
|
215350
215603
|
network: _enum2(["model_only", "unrestricted"]).optional(),
|
|
215351
215604
|
maxAgentTimeoutMs: number2().int().positive().optional(),
|
|
215605
|
+
maxAgentTimeoutS: secondsSchema("options.maxAgentTimeoutS").optional(),
|
|
215352
215606
|
reviewBudget: object({
|
|
215353
215607
|
maxModelCalls: number2().int().positive().optional(),
|
|
215354
215608
|
maxTotalWallTimeMs: number2().int().positive().optional(),
|
|
215609
|
+
maxTotalWallTimeS: secondsSchema("options.reviewBudget.maxTotalWallTimeS").optional(),
|
|
215355
215610
|
maxAgentOutputBytes: number2().int().positive().optional(),
|
|
215356
215611
|
maxFindingsPerAgent: number2().int().positive().optional(),
|
|
215357
215612
|
skipOptionalPhasesWhenTokenUsageUnknown: boolean2().optional()
|
|
@@ -215361,6 +215616,18 @@ var kyosoReviewRequestSchema = object({
|
|
|
215361
215616
|
allowSecretRedaction: boolean2().optional()
|
|
215362
215617
|
}).optional()
|
|
215363
215618
|
});
|
|
215619
|
+
function secondsSchema(field) {
|
|
215620
|
+
return number2().superRefine((value, context) => {
|
|
215621
|
+
try {
|
|
215622
|
+
secondsToMilliseconds(value, field);
|
|
215623
|
+
} catch (error51) {
|
|
215624
|
+
context.addIssue({
|
|
215625
|
+
code: "custom",
|
|
215626
|
+
message: error51 instanceof TimeUnitValidationError ? error51.message : `${field} is invalid.`
|
|
215627
|
+
});
|
|
215628
|
+
}
|
|
215629
|
+
});
|
|
215630
|
+
}
|
|
215364
215631
|
|
|
215365
215632
|
// src/mcp/server.ts
|
|
215366
215633
|
var KYOSO_MCP_INSTRUCTIONS = "Kyoso is a multi-agent planning and review gate. Use it only when the user explicitly asks for Kyoso, multi-agent review, plan review, security review, CISA Secure by Design review, or diff review. Kyoso does not apply code changes. It returns structured review results and Markdown summaries.";
|