@kyo-so/cli 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/kyoso.js CHANGED
@@ -8125,7 +8125,7 @@ ${lanes.join(`
8125
8125
  writeOutputIsTTY() {
8126
8126
  return process.stdout.isTTY;
8127
8127
  },
8128
- readFile: readFile2,
8128
+ readFile: readFile3,
8129
8129
  writeFile: writeFile22,
8130
8130
  watchFile: watchFile2,
8131
8131
  watchDirectory,
@@ -8318,7 +8318,7 @@ ${lanes.join(`
8318
8318
  function fsWatchWorker(fileOrDirectory, recursive, callback) {
8319
8319
  return _fs.watch(fileOrDirectory, fsSupportsRecursiveFsWatch ? { persistent: true, recursive: !!recursive } : { persistent: true }, callback);
8320
8320
  }
8321
- function readFile2(fileName, _encoding) {
8321
+ function readFile3(fileName, _encoding) {
8322
8322
  let buffer;
8323
8323
  try {
8324
8324
  buffer = _fs.readFileSync(fileName);
@@ -39385,7 +39385,7 @@ ${lanes.join(`
39385
39385
  const possibleOption = getSpellingSuggestion(unknownOption, diagnostics.optionDeclarations, getOptionName);
39386
39386
  return possibleOption ? createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics.unknownDidYouMeanDiagnostic, unknownOptionErrorText || unknownOption, possibleOption.name) : createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics.unknownOptionDiagnostic, unknownOptionErrorText || unknownOption);
39387
39387
  }
39388
- function parseCommandLineWorker(diagnostics, commandLine, readFile2) {
39388
+ function parseCommandLineWorker(diagnostics, commandLine, readFile3) {
39389
39389
  const options = {};
39390
39390
  let watchOptions;
39391
39391
  const fileNames = [];
@@ -39423,7 +39423,7 @@ ${lanes.join(`
39423
39423
  }
39424
39424
  }
39425
39425
  function parseResponseFile(fileName) {
39426
- const text = tryReadFile(fileName, readFile2 || ((fileName2) => sys.readFile(fileName2)));
39426
+ const text = tryReadFile(fileName, readFile3 || ((fileName2) => sys.readFile(fileName2)));
39427
39427
  if (!isString(text)) {
39428
39428
  errors3.push(text);
39429
39429
  return;
@@ -39526,8 +39526,8 @@ ${lanes.join(`
39526
39526
  unknownDidYouMeanDiagnostic: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1,
39527
39527
  optionTypeMismatchDiagnostic: Diagnostics.Compiler_option_0_expects_an_argument
39528
39528
  };
39529
- function parseCommandLine(commandLine, readFile2) {
39530
- return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine, readFile2);
39529
+ function parseCommandLine(commandLine, readFile3) {
39530
+ return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine, readFile3);
39531
39531
  }
39532
39532
  function getOptionFromName(optionName, allowShort) {
39533
39533
  return getOptionDeclarationFromName(getOptionsNameMap, optionName, allowShort);
@@ -39595,8 +39595,8 @@ ${lanes.join(`
39595
39595
  result.originalFileName = result.fileName;
39596
39596
  return parseJsonSourceFileConfigFileContent(result, host, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), optionsToExtend, getNormalizedAbsolutePath(configFileName, cwd), undefined, extraFileExtensions, extendedConfigCache, watchOptionsToExtend);
39597
39597
  }
39598
- function readConfigFile(fileName, readFile2) {
39599
- const textOrDiagnostic = tryReadFile(fileName, readFile2);
39598
+ function readConfigFile(fileName, readFile3) {
39599
+ const textOrDiagnostic = tryReadFile(fileName, readFile3);
39600
39600
  return isString(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic };
39601
39601
  }
39602
39602
  function parseConfigFileTextToJson(fileName, jsonText) {
@@ -39606,14 +39606,14 @@ ${lanes.join(`
39606
39606
  error: jsonSourceFile.parseDiagnostics.length ? jsonSourceFile.parseDiagnostics[0] : undefined
39607
39607
  };
39608
39608
  }
39609
- function readJsonConfigFile(fileName, readFile2) {
39610
- const textOrDiagnostic = tryReadFile(fileName, readFile2);
39609
+ function readJsonConfigFile(fileName, readFile3) {
39610
+ const textOrDiagnostic = tryReadFile(fileName, readFile3);
39611
39611
  return isString(textOrDiagnostic) ? parseJsonText(fileName, textOrDiagnostic) : { fileName, parseDiagnostics: [textOrDiagnostic] };
39612
39612
  }
39613
- function tryReadFile(fileName, readFile2) {
39613
+ function tryReadFile(fileName, readFile3) {
39614
39614
  let text;
39615
39615
  try {
39616
- text = readFile2(fileName);
39616
+ text = readFile3(fileName);
39617
39617
  } catch (e) {
39618
39618
  return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message);
39619
39619
  }
@@ -107510,12 +107510,12 @@ ${lanes.join(`
107510
107510
  function createCompilerHost(options, setParentNodes) {
107511
107511
  return createCompilerHostWorker(options, setParentNodes);
107512
107512
  }
107513
- function createGetSourceFile(readFile2, setParentNodes) {
107513
+ function createGetSourceFile(readFile3, setParentNodes) {
107514
107514
  return (fileName, languageVersionOrOptions, onError) => {
107515
107515
  let text;
107516
107516
  try {
107517
107517
  mark("beforeIORead");
107518
- text = readFile2(fileName);
107518
+ text = readFile3(fileName);
107519
107519
  mark("afterIORead");
107520
107520
  measure("I/O Read", "beforeIORead", "afterIORead");
107521
107521
  } catch (e) {
@@ -108306,7 +108306,7 @@ ${lanes.join(`
108306
108306
  getRedirectFromOutput,
108307
108307
  forEachResolvedProjectReference: forEachResolvedProjectReference2
108308
108308
  });
108309
- const readFile2 = host.readFile.bind(host);
108309
+ const readFile3 = host.readFile.bind(host);
108310
108310
  (_e = tracing) == null || _e.push(tracing.Phase.Program, "shouldProgramCreateNewSourceFiles", { hasOldProgram: !!oldProgram });
108311
108311
  const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
108312
108312
  (_f = tracing) == null || _f.pop();
@@ -108483,7 +108483,7 @@ ${lanes.join(`
108483
108483
  shouldTransformImportCall,
108484
108484
  emitBuildInfo,
108485
108485
  fileExists,
108486
- readFile: readFile2,
108486
+ readFile: readFile3,
108487
108487
  directoryExists,
108488
108488
  getSymlinkCache,
108489
108489
  realpath: (_o = host.realpath) == null ? undefined : _o.bind(host),
@@ -121385,7 +121385,7 @@ ${lanes.join(`
121385
121385
  if (importingFile !== usableByFileName)
121386
121386
  return;
121387
121387
  return forEachEntry(exportInfo, (info, key2) => {
121388
- const { symbolName: symbolName2, ambientModuleName } = parseKey(key2);
121388
+ const { symbolName: symbolName2, ambientModuleName } = parseKey2(key2);
121389
121389
  const name = preferCapitalized && info[0].capitalizedSymbolName || symbolName2;
121390
121390
  if (matches(name, info[0].targetFlags)) {
121391
121391
  const rehydrated = info.map(rehydrateCachedInfo);
@@ -121449,7 +121449,7 @@ ${lanes.join(`
121449
121449
  const moduleKey = ambientModuleName || "";
121450
121450
  return `${importedName.length} ${getSymbolId(skipAlias(symbol2, checker))} ${importedName} ${moduleKey}`;
121451
121451
  }
121452
- function parseKey(key2) {
121452
+ function parseKey2(key2) {
121453
121453
  const firstSpace = key2.indexOf(" ");
121454
121454
  const secondSpace = key2.indexOf(" ", firstSpace + 1);
121455
121455
  const symbolNameLength = parseInt(key2.substring(0, firstSpace), 10);
@@ -150513,14 +150513,14 @@ ${newComment.split(`
150513
150513
  });
150514
150514
  function mapCode(sourceFile, contents, focusLocations, host, formatContext, preferences) {
150515
150515
  return ts_textChanges_exports.ChangeTracker.with({ host, formatContext, preferences }, (changeTracker) => {
150516
- const parsed = contents.map((c) => parse5(sourceFile, c));
150516
+ const parsed = contents.map((c) => parse6(sourceFile, c));
150517
150517
  const flattenedLocations = focusLocations && flatten(focusLocations);
150518
150518
  for (const nodes of parsed) {
150519
150519
  placeNodeGroup(sourceFile, changeTracker, nodes, flattenedLocations);
150520
150520
  }
150521
150521
  });
150522
150522
  }
150523
- function parse5(sourceFile, content) {
150523
+ function parse6(sourceFile, content) {
150524
150524
  const nodeKinds = [
150525
150525
  {
150526
150526
  parse: () => createSourceFile("__mapcode_content_nodes.ts", content, sourceFile.languageVersion, true, sourceFile.scriptKind),
@@ -169600,12 +169600,13 @@ function languageFromPath(path) {
169600
169600
 
169601
169601
  // src/cli/doctor.ts
169602
169602
  import { accessSync } from "node:fs";
169603
- import { delimiter as delimiter2 } from "node:path";
169603
+ import { delimiter as delimiter2, resolve as resolve4 } from "node:path";
169604
169604
 
169605
169605
  // src/config/loadConfig.ts
169606
- import { access as access2, readFile as readFile3 } from "node:fs/promises";
169606
+ import { access as access2, readFile as readFile4 } from "node:fs/promises";
169607
+ import { homedir as homedir2 } from "node:os";
169607
169608
  import { stderr, stdin } from "node:process";
169608
- import { resolve as resolve2 } from "node:path";
169609
+ import { extname as extname3, join as join2, resolve as resolve2 } from "node:path";
169609
169610
  import { createInterface as createInterface2 } from "node:readline/promises";
169610
169611
 
169611
169612
  // src/config/defaultConfig.ts
@@ -169648,7 +169649,7 @@ var defaultConfig = {
169648
169649
  command: "npx",
169649
169650
  args: ["-y", "@agentclientprotocol/claude-agent-acp@0.57.0"],
169650
169651
  role: "architecture_security_reviewer",
169651
- timeoutMs: 240000,
169652
+ timeoutMs: 300000,
169652
169653
  env: {
169653
169654
  KYOSO_CHILD_AGENT: "1"
169654
169655
  },
@@ -169736,6 +169737,172 @@ var defaultConfig = {
169736
169737
  }
169737
169738
  };
169738
169739
 
169740
+ // src/config/projectScope.ts
169741
+ var PROJECT_GLOBAL_ONLY_MESSAGE = "Move global-only settings to the user global config:";
169742
+ function mergeProjectTomlConfig(baseConfig, projectConfig, options) {
169743
+ const violations = collectProjectScopeViolations(projectConfig);
169744
+ if (violations.length > 0) {
169745
+ throw new Error(formatProjectScopeError(violations, options));
169746
+ }
169747
+ const projectDeny = readPath(projectConfig, ["workspace", "deny"]);
169748
+ const mergeableProjectConfig = omitPath(projectConfig, ["workspace", "deny"]);
169749
+ const merged = deepMerge(baseConfig, mergeableProjectConfig);
169750
+ if (projectDeny !== undefined) {
169751
+ writePath(merged, ["workspace", "deny"], Array.isArray(projectDeny) && allStrings(projectDeny) ? unionStrings(readStringArray(baseConfig, ["workspace", "deny"]), [
169752
+ ...projectDeny
169753
+ ]) : projectDeny);
169754
+ }
169755
+ return merged;
169756
+ }
169757
+ function collectProjectScopeViolations(config) {
169758
+ const leaves = flattenLeaves(config);
169759
+ const violations = [];
169760
+ for (const leaf of leaves) {
169761
+ const path = leaf.path.join(".");
169762
+ if (!isAllowedProjectPath(leaf.path)) {
169763
+ violations.push({ path });
169764
+ continue;
169765
+ }
169766
+ const reason = tightenOnlyReason(leaf.path, leaf.value);
169767
+ if (reason)
169768
+ violations.push({ path, reason });
169769
+ }
169770
+ return violations.sort((left, right) => left.path.localeCompare(right.path));
169771
+ }
169772
+ function isAllowedProjectPath(path) {
169773
+ const [top, second, third, fourth] = path;
169774
+ if (top === "tools" && path.length === 2 && ["planReview", "securityReview", "diffReview"].includes(second ?? "")) {
169775
+ return true;
169776
+ }
169777
+ if (top === "agents" && path.length === 3 && ["codex", "claude"].includes(second ?? "") && ["enabled", "model", "role", "timeoutMs"].includes(third ?? "")) {
169778
+ return true;
169779
+ }
169780
+ if (top === "verification" && path.length === 2 && ["enabled", "maxFindings", "timeoutMs"].includes(second ?? "")) {
169781
+ return true;
169782
+ }
169783
+ if (top === "workspace" && path.length === 2 && ["maxContextBytes", "maxDiffBytes", "deny"].includes(second ?? "")) {
169784
+ return true;
169785
+ }
169786
+ if (top === "network" && second === "defaultMode" && path.length === 2) {
169787
+ return true;
169788
+ }
169789
+ if (top === "secrets" && path.length === 2 && ["blockOnDetectedSecret", "allowOverride"].includes(second ?? "")) {
169790
+ return true;
169791
+ }
169792
+ if (top === "judge" && path.length === 2 && ["mode", "provider", "timeoutMs"].includes(second ?? "")) {
169793
+ return true;
169794
+ }
169795
+ if (top === "securityReview" && second === "cisaSecureByDesign" && path.length >= 3) {
169796
+ if (third === "dimensions") {
169797
+ return path.length === 4 && [
169798
+ "customerSecurityOutcomes",
169799
+ "secureByDefault",
169800
+ "transparencyAndAccountability",
169801
+ "governance"
169802
+ ].includes(fourth ?? "");
169803
+ }
169804
+ return path.length === 3 && ["enabled", "gate"].includes(third ?? "");
169805
+ }
169806
+ return false;
169807
+ }
169808
+ function tightenOnlyReason(path, value) {
169809
+ const dotted = path.join(".");
169810
+ if (dotted === "network.defaultMode" && value !== "model_only") {
169811
+ return 'must be "model_only" in project TOML';
169812
+ }
169813
+ if (dotted === "secrets.blockOnDetectedSecret" && value !== true) {
169814
+ return "must be true in project TOML";
169815
+ }
169816
+ if (dotted === "secrets.allowOverride" && value !== false) {
169817
+ return "must be false in project TOML";
169818
+ }
169819
+ if (path[0] === "securityReview" && path[1] === "cisaSecureByDesign" && value !== true) {
169820
+ return "must be true in project TOML";
169821
+ }
169822
+ return;
169823
+ }
169824
+ function formatProjectScopeError(violations, options) {
169825
+ const entries = violations.map((violation) => violation.reason ? `${violation.path} (${violation.reason})` : violation.path);
169826
+ return [
169827
+ `Project TOML config ${options.projectPath} contains settings that are not allowed in project scope: ${entries.join(", ")}`,
169828
+ `${PROJECT_GLOBAL_ONLY_MESSAGE} ${options.globalConfigPath}. If a key is misspelled, fix the name instead.`
169829
+ ].join(`
169830
+ `);
169831
+ }
169832
+ function flattenLeaves(value, path = []) {
169833
+ if (!isRecord(value))
169834
+ return path.length > 0 ? [{ path, value }] : [];
169835
+ const entries = Object.entries(value);
169836
+ if (entries.length === 0)
169837
+ return path.length > 0 ? [{ path, value }] : [];
169838
+ return entries.flatMap(([key, child]) => flattenLeaves(child, [...path, key]));
169839
+ }
169840
+ function omitPath(value, path) {
169841
+ if (!isRecord(value) || path.length === 0)
169842
+ return value;
169843
+ const [head, ...tail] = path;
169844
+ if (head === undefined)
169845
+ return value;
169846
+ const result = { ...value };
169847
+ if (tail.length === 0) {
169848
+ delete result[head];
169849
+ } else {
169850
+ const child = omitPath(result[head], tail);
169851
+ if (isRecord(child) && Object.keys(child).length === 0) {
169852
+ delete result[head];
169853
+ } else {
169854
+ result[head] = child;
169855
+ }
169856
+ }
169857
+ return result;
169858
+ }
169859
+ function readPath(value, path) {
169860
+ let current = value;
169861
+ for (const key of path) {
169862
+ if (!isRecord(current))
169863
+ return;
169864
+ current = current[key];
169865
+ }
169866
+ return current;
169867
+ }
169868
+ function writePath(target, path, value) {
169869
+ if (!isRecord(target))
169870
+ return;
169871
+ let current = target;
169872
+ for (const key of path.slice(0, -1)) {
169873
+ const child = current[key];
169874
+ if (!isRecord(child)) {
169875
+ current[key] = {};
169876
+ }
169877
+ current = current[key];
169878
+ }
169879
+ const leaf = path.at(-1);
169880
+ if (leaf)
169881
+ current[leaf] = value;
169882
+ }
169883
+ function readStringArray(value, path) {
169884
+ const found = readPath(value, path);
169885
+ return Array.isArray(found) && allStrings(found) ? [...found] : [];
169886
+ }
169887
+ function unionStrings(base, override) {
169888
+ return [...new Set([...base, ...override])];
169889
+ }
169890
+ function allStrings(values) {
169891
+ return values.every((value) => typeof value === "string");
169892
+ }
169893
+ function deepMerge(base, override) {
169894
+ if (!isRecord(base) || !isRecord(override))
169895
+ return override ?? base;
169896
+ const result = { ...base };
169897
+ for (const [key, value] of Object.entries(override)) {
169898
+ result[key] = deepMerge(result[key], value);
169899
+ }
169900
+ return result;
169901
+ }
169902
+ function isRecord(value) {
169903
+ return typeof value === "object" && value !== null && !Array.isArray(value);
169904
+ }
169905
+
169739
169906
  // node_modules/zod/v4/classic/external.js
169740
169907
  var exports_external = {};
169741
169908
  __export(exports_external, {
@@ -184099,6 +184266,1059 @@ var kyosoConfigSchema = exports_external.object({
184099
184266
  includeFileContents: exports_external.boolean()
184100
184267
  })
184101
184268
  });
184269
+ function agentConfigLeafPaths(agent) {
184270
+ return [
184271
+ `agents.${agent}.enabled`,
184272
+ `agents.${agent}.type`,
184273
+ `agents.${agent}.command`,
184274
+ `agents.${agent}.args`,
184275
+ `agents.${agent}.model`,
184276
+ `agents.${agent}.role`,
184277
+ `agents.${agent}.timeoutMs`,
184278
+ `agents.${agent}.env`,
184279
+ `agents.${agent}.auth.mode`,
184280
+ `agents.${agent}.auth.preferExistingLogin`,
184281
+ `agents.${agent}.auth.preferApiKey`,
184282
+ `agents.${agent}.auth.recommendedEnv`,
184283
+ `agents.${agent}.auth.envWhitelist`
184284
+ ];
184285
+ }
184286
+ var kyosoConfigKnownLeafPaths = [
184287
+ "entrypoints.mcp",
184288
+ "entrypoints.cli",
184289
+ "firstClassClient",
184290
+ "tools.planReview",
184291
+ "tools.securityReview",
184292
+ "tools.diffReview",
184293
+ ...agentConfigLeafPaths("codex"),
184294
+ ...agentConfigLeafPaths("claude"),
184295
+ "workspace.mode",
184296
+ "workspace.root",
184297
+ "workspace.readOnly",
184298
+ "workspace.maxContextBytes",
184299
+ "workspace.maxDiffBytes",
184300
+ "workspace.deny",
184301
+ "secrets.mode",
184302
+ "secrets.blockOnDetectedSecret",
184303
+ "secrets.allowOverride",
184304
+ "network.defaultMode",
184305
+ "network.allowUnrestricted",
184306
+ "network.warnOnUnrestricted",
184307
+ "network.mediatedWeb.enabled",
184308
+ "securityReview.cisaSecureByDesign.enabled",
184309
+ "securityReview.cisaSecureByDesign.gate",
184310
+ "securityReview.cisaSecureByDesign.dimensions.customerSecurityOutcomes",
184311
+ "securityReview.cisaSecureByDesign.dimensions.secureByDefault",
184312
+ "securityReview.cisaSecureByDesign.dimensions.transparencyAndAccountability",
184313
+ "securityReview.cisaSecureByDesign.dimensions.governance",
184314
+ "judge.mode",
184315
+ "judge.provider",
184316
+ "judge.timeoutMs",
184317
+ "verification.enabled",
184318
+ "verification.maxFindings",
184319
+ "verification.timeoutMs",
184320
+ "verification.allowDemotion",
184321
+ "audit.enabled",
184322
+ "audit.format",
184323
+ "audit.directory",
184324
+ "audit.includeRawAgentOutput",
184325
+ "audit.includeFileContents"
184326
+ ];
184327
+ var kyosoConfigRecordPrefixes = [
184328
+ "agents.codex.env",
184329
+ "agents.claude.env"
184330
+ ];
184331
+ var kyosoConfigSecuritySensitivePrefixes = [
184332
+ "agents.codex",
184333
+ "agents.claude",
184334
+ "audit",
184335
+ "judge",
184336
+ "network",
184337
+ "secrets",
184338
+ "securityReview",
184339
+ "verification",
184340
+ "workspace"
184341
+ ];
184342
+
184343
+ // src/security/redact.ts
184344
+ var REDACTION = "[KYOSO_REDACTED]";
184345
+
184346
+ // src/core/constants.ts
184347
+ var DEFAULT_AGENT_TIMEOUT_MS = 120000;
184348
+ var RAW_OUTPUT_MAX_CHARS = 16384;
184349
+ var KYOSO_CHILD_AGENT = "KYOSO_CHILD_AGENT";
184350
+ var KYOSO_VERSION = "0.6.0";
184351
+
184352
+ // src/security/sanitizeText.ts
184353
+ var SENSITIVE_TEXT_PATTERNS = [
184354
+ /\bsk-(?:proj-)?[A-Za-z0-9_-]{8,}\b/g,
184355
+ /\bsk-ant-[A-Za-z0-9_-]{8,}\b/g,
184356
+ /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{8,}\b/g,
184357
+ /\bAKIA[0-9A-Z]{8,}\b/g,
184358
+ /\bxox[baprs]-[A-Za-z0-9-]{8,}\b/g,
184359
+ /\bsk_(?:live|test)_[A-Za-z0-9]{8,}\b/g,
184360
+ /\b(?:api[_-]?key|secret|token|password)\b\s*[:=]\s*["']?[A-Za-z0-9_./+=-]{8,}["']?/gi
184361
+ ];
184362
+ function sanitizeText(value) {
184363
+ return SENSITIVE_TEXT_PATTERNS.reduce((text, pattern) => text.replace(pattern, REDACTION), value);
184364
+ }
184365
+ function sanitizeTextForDisplay(value, maxChars = 240) {
184366
+ const compact = sanitizeText(value).replace(/\s+/g, " ").trim();
184367
+ if (compact.length <= maxChars)
184368
+ return compact;
184369
+ return `${compact.slice(0, Math.max(0, maxChars - 3))}...`;
184370
+ }
184371
+ function sanitizeTextForRawOutput(value, maxChars = RAW_OUTPUT_MAX_CHARS) {
184372
+ const sanitized = sanitizeText(value);
184373
+ const limit = Math.max(0, maxChars);
184374
+ if (sanitized.length <= limit)
184375
+ return sanitized;
184376
+ return `${sanitized.slice(0, limit)}
184377
+ [KYOSO_TRUNCATED: ${sanitized.length - limit} chars omitted]`;
184378
+ }
184379
+
184380
+ // src/config/tomlConfigLoader.ts
184381
+ import { readFile as readFile2 } from "node:fs/promises";
184382
+
184383
+ // node_modules/smol-toml/dist/date.js
184384
+ /*!
184385
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
184386
+ * SPDX-License-Identifier: BSD-3-Clause
184387
+ *
184388
+ * Redistribution and use in source and binary forms, with or without
184389
+ * modification, are permitted provided that the following conditions are met:
184390
+ *
184391
+ * 1. Redistributions of source code must retain the above copyright notice, this
184392
+ * list of conditions and the following disclaimer.
184393
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
184394
+ * this list of conditions and the following disclaimer in the
184395
+ * documentation and/or other materials provided with the distribution.
184396
+ * 3. Neither the name of the copyright holder nor the names of its contributors
184397
+ * may be used to endorse or promote products derived from this software without
184398
+ * specific prior written permission.
184399
+ *
184400
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
184401
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
184402
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
184403
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
184404
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
184405
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
184406
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
184407
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
184408
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
184409
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
184410
+ */
184411
+ var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
184412
+
184413
+ class TomlDate extends Date {
184414
+ #hasDate = false;
184415
+ #hasTime = false;
184416
+ #offset = null;
184417
+ constructor(date5) {
184418
+ let hasDate = true;
184419
+ let hasTime = true;
184420
+ let offset = "Z";
184421
+ if (typeof date5 === "string") {
184422
+ let match = date5.match(DATE_TIME_RE);
184423
+ if (match) {
184424
+ if (!match[1]) {
184425
+ hasDate = false;
184426
+ date5 = `0000-01-01T${date5}`;
184427
+ }
184428
+ hasTime = !!match[2];
184429
+ hasTime && date5[10] === " " && (date5 = date5.replace(" ", "T"));
184430
+ if (match[2] && +match[2] > 23) {
184431
+ date5 = "";
184432
+ } else {
184433
+ offset = match[3] || null;
184434
+ date5 = date5.toUpperCase();
184435
+ if (!offset && hasTime)
184436
+ date5 += "Z";
184437
+ }
184438
+ } else {
184439
+ date5 = "";
184440
+ }
184441
+ }
184442
+ super(date5);
184443
+ if (!isNaN(this.getTime())) {
184444
+ this.#hasDate = hasDate;
184445
+ this.#hasTime = hasTime;
184446
+ this.#offset = offset;
184447
+ }
184448
+ }
184449
+ isDateTime() {
184450
+ return this.#hasDate && this.#hasTime;
184451
+ }
184452
+ isLocal() {
184453
+ return !this.#hasDate || !this.#hasTime || !this.#offset;
184454
+ }
184455
+ isDate() {
184456
+ return this.#hasDate && !this.#hasTime;
184457
+ }
184458
+ isTime() {
184459
+ return this.#hasTime && !this.#hasDate;
184460
+ }
184461
+ isValid() {
184462
+ return this.#hasDate || this.#hasTime;
184463
+ }
184464
+ toISOString() {
184465
+ let iso = super.toISOString();
184466
+ if (this.isDate())
184467
+ return iso.slice(0, 10);
184468
+ if (this.isTime())
184469
+ return iso.slice(11, 23);
184470
+ if (this.#offset === null)
184471
+ return iso.slice(0, -1);
184472
+ if (this.#offset === "Z")
184473
+ return iso;
184474
+ let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
184475
+ offset = this.#offset[0] === "-" ? offset : -offset;
184476
+ let offsetDate = new Date(this.getTime() - offset * 60000);
184477
+ return offsetDate.toISOString().slice(0, -1) + this.#offset;
184478
+ }
184479
+ static wrapAsOffsetDateTime(jsDate, offset = "Z") {
184480
+ let date5 = new TomlDate(jsDate);
184481
+ date5.#offset = offset;
184482
+ return date5;
184483
+ }
184484
+ static wrapAsLocalDateTime(jsDate) {
184485
+ let date5 = new TomlDate(jsDate);
184486
+ date5.#offset = null;
184487
+ return date5;
184488
+ }
184489
+ static wrapAsLocalDate(jsDate) {
184490
+ let date5 = new TomlDate(jsDate);
184491
+ date5.#hasTime = false;
184492
+ date5.#offset = null;
184493
+ return date5;
184494
+ }
184495
+ static wrapAsLocalTime(jsDate) {
184496
+ let date5 = new TomlDate(jsDate);
184497
+ date5.#hasDate = false;
184498
+ date5.#offset = null;
184499
+ return date5;
184500
+ }
184501
+ }
184502
+
184503
+ // node_modules/smol-toml/dist/error.js
184504
+ /*!
184505
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
184506
+ * SPDX-License-Identifier: BSD-3-Clause
184507
+ *
184508
+ * Redistribution and use in source and binary forms, with or without
184509
+ * modification, are permitted provided that the following conditions are met:
184510
+ *
184511
+ * 1. Redistributions of source code must retain the above copyright notice, this
184512
+ * list of conditions and the following disclaimer.
184513
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
184514
+ * this list of conditions and the following disclaimer in the
184515
+ * documentation and/or other materials provided with the distribution.
184516
+ * 3. Neither the name of the copyright holder nor the names of its contributors
184517
+ * may be used to endorse or promote products derived from this software without
184518
+ * specific prior written permission.
184519
+ *
184520
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
184521
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
184522
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
184523
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
184524
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
184525
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
184526
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
184527
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
184528
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
184529
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
184530
+ */
184531
+ function getLineColFromPtr(string4, ptr) {
184532
+ let lines = string4.slice(0, ptr).split(/\r\n|\n|\r/g);
184533
+ return [lines.length, lines.pop().length + 1];
184534
+ }
184535
+ function makeCodeBlock(string4, line, column) {
184536
+ let lines = string4.split(/\r\n|\n|\r/g);
184537
+ let codeblock = "";
184538
+ let numberLen = (Math.log10(line + 1) | 0) + 1;
184539
+ for (let i = line - 1;i <= line + 1; i++) {
184540
+ let l = lines[i - 1];
184541
+ if (!l)
184542
+ continue;
184543
+ codeblock += i.toString().padEnd(numberLen, " ");
184544
+ codeblock += ": ";
184545
+ codeblock += l;
184546
+ codeblock += `
184547
+ `;
184548
+ if (i === line) {
184549
+ codeblock += " ".repeat(numberLen + column + 2);
184550
+ codeblock += `^
184551
+ `;
184552
+ }
184553
+ }
184554
+ return codeblock;
184555
+ }
184556
+
184557
+ class TomlError extends Error {
184558
+ line;
184559
+ column;
184560
+ codeblock;
184561
+ constructor(message, options) {
184562
+ const [line, column] = getLineColFromPtr(options.toml, options.ptr);
184563
+ const codeblock = makeCodeBlock(options.toml, line, column);
184564
+ super(`Invalid TOML document: ${message}
184565
+
184566
+ ${codeblock}`, options);
184567
+ this.line = line;
184568
+ this.column = column;
184569
+ this.codeblock = codeblock;
184570
+ }
184571
+ }
184572
+
184573
+ // node_modules/smol-toml/dist/primitive.js
184574
+ /*!
184575
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
184576
+ * SPDX-License-Identifier: BSD-3-Clause
184577
+ *
184578
+ * Redistribution and use in source and binary forms, with or without
184579
+ * modification, are permitted provided that the following conditions are met:
184580
+ *
184581
+ * 1. Redistributions of source code must retain the above copyright notice, this
184582
+ * list of conditions and the following disclaimer.
184583
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
184584
+ * this list of conditions and the following disclaimer in the
184585
+ * documentation and/or other materials provided with the distribution.
184586
+ * 3. Neither the name of the copyright holder nor the names of its contributors
184587
+ * may be used to endorse or promote products derived from this software without
184588
+ * specific prior written permission.
184589
+ *
184590
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
184591
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
184592
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
184593
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
184594
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
184595
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
184596
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
184597
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
184598
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
184599
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
184600
+ */
184601
+ var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
184602
+ var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
184603
+ var LEADING_ZERO = /^[+-]?0[0-9_]/;
184604
+ function parseString(str, ptr) {
184605
+ let c = str[ptr++];
184606
+ let first = c;
184607
+ let isLiteral = c === "'";
184608
+ let isMultiline = c === str[ptr] && c === str[ptr + 1];
184609
+ if (isMultiline) {
184610
+ if (str[ptr += 2] === `
184611
+ `)
184612
+ ptr++;
184613
+ else if (str[ptr] === "\r" && str[ptr + 1] === `
184614
+ `)
184615
+ ptr += 2;
184616
+ }
184617
+ let parsed = "";
184618
+ let sliceStart = ptr;
184619
+ let state = 0;
184620
+ for (let i = ptr;i < str.length; i++) {
184621
+ c = str[i];
184622
+ if (isMultiline && (c === `
184623
+ ` || c === "\r" && str[i + 1] === `
184624
+ `)) {
184625
+ state = state && 3;
184626
+ } else if (c < " " && c !== "\t" || c === "") {
184627
+ throw new TomlError("control characters are not allowed in strings", {
184628
+ toml: str,
184629
+ ptr: i
184630
+ });
184631
+ } else if ((!state || state === 3) && c === first && (!isMultiline || str[i + 1] === first && str[i + 2] === first)) {
184632
+ if (isMultiline) {
184633
+ if (str[i + 3] === first)
184634
+ i++;
184635
+ if (str[i + 3] === first)
184636
+ i++;
184637
+ }
184638
+ return [
184639
+ state ? parsed : parsed + str.slice(sliceStart, i),
184640
+ i + (isMultiline ? 3 : 1)
184641
+ ];
184642
+ } else if (!state) {
184643
+ if (!isLiteral && c === "\\") {
184644
+ parsed += str.slice(sliceStart, sliceStart = i);
184645
+ state = 1;
184646
+ }
184647
+ } else if (state === 1) {
184648
+ if (c === "x" || c === "u" || c === "U") {
184649
+ let value = 0;
184650
+ let len = c === "x" ? 2 : c === "u" ? 4 : 8;
184651
+ for (let j = 0;j < len; j++, i++) {
184652
+ let hex3 = str.charCodeAt(i + 1);
184653
+ let digit = hex3 >= 48 && hex3 <= 57 ? hex3 - 48 : hex3 >= 65 && hex3 <= 70 ? hex3 - 65 + 10 : hex3 >= 97 && hex3 <= 102 ? hex3 - 97 + 10 : -1;
184654
+ if (digit < 0)
184655
+ throw new TomlError("invalid non-hex character in unicode escape", { toml: str, ptr: i + 1 });
184656
+ value = value << 4 | digit;
184657
+ }
184658
+ if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) {
184659
+ throw new TomlError("invalid unicode escape", { toml: str, ptr: i });
184660
+ }
184661
+ parsed += String.fromCodePoint(value);
184662
+ sliceStart = i + 1;
184663
+ state = 0;
184664
+ } else if (c === " " || c === "\t") {
184665
+ state = 2;
184666
+ } else {
184667
+ if (c === "b")
184668
+ parsed += "\b";
184669
+ else if (c === "t")
184670
+ parsed += "\t";
184671
+ else if (c === "n")
184672
+ parsed += `
184673
+ `;
184674
+ else if (c === "f")
184675
+ parsed += "\f";
184676
+ else if (c === "r")
184677
+ parsed += "\r";
184678
+ else if (c === "e")
184679
+ parsed += "\x1B";
184680
+ else if (c === '"')
184681
+ parsed += '"';
184682
+ else if (c === "\\")
184683
+ parsed += "\\";
184684
+ else
184685
+ throw new TomlError("unrecognized escape sequence", { toml: str, ptr: i });
184686
+ sliceStart = i + 1;
184687
+ state = 0;
184688
+ }
184689
+ } else if (c !== " " && c !== "\t") {
184690
+ if (state === 2) {
184691
+ throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
184692
+ toml: str,
184693
+ ptr: sliceStart
184694
+ });
184695
+ }
184696
+ state = !isLiteral && c === "\\" ? 1 : 0;
184697
+ sliceStart = i;
184698
+ }
184699
+ }
184700
+ throw new TomlError("unfinished string", { toml: str, ptr });
184701
+ }
184702
+ function parseValue(value, toml, ptr, integersAsBigInt) {
184703
+ if (value === "true")
184704
+ return true;
184705
+ if (value === "false")
184706
+ return false;
184707
+ if (value === "-inf")
184708
+ return -Infinity;
184709
+ if (value === "inf" || value === "+inf")
184710
+ return Infinity;
184711
+ if (value === "nan" || value === "+nan" || value === "-nan")
184712
+ return NaN;
184713
+ if (value === "-0")
184714
+ return integersAsBigInt ? 0n : 0;
184715
+ let isInt = INT_REGEX.test(value);
184716
+ if (isInt || FLOAT_REGEX.test(value)) {
184717
+ if (LEADING_ZERO.test(value)) {
184718
+ throw new TomlError("leading zeroes are not allowed", {
184719
+ toml,
184720
+ ptr
184721
+ });
184722
+ }
184723
+ value = value.replace(/_/g, "");
184724
+ let numeric = +value;
184725
+ if (isNaN(numeric)) {
184726
+ throw new TomlError("invalid number", {
184727
+ toml,
184728
+ ptr
184729
+ });
184730
+ }
184731
+ if (isInt) {
184732
+ if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
184733
+ throw new TomlError("integer value cannot be represented losslessly", {
184734
+ toml,
184735
+ ptr
184736
+ });
184737
+ }
184738
+ if (isInt || integersAsBigInt === true)
184739
+ numeric = BigInt(value);
184740
+ }
184741
+ return numeric;
184742
+ }
184743
+ const date5 = new TomlDate(value);
184744
+ if (!date5.isValid()) {
184745
+ throw new TomlError("invalid value", {
184746
+ toml,
184747
+ ptr
184748
+ });
184749
+ }
184750
+ return date5;
184751
+ }
184752
+
184753
+ // node_modules/smol-toml/dist/util.js
184754
+ /*!
184755
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
184756
+ * SPDX-License-Identifier: BSD-3-Clause
184757
+ *
184758
+ * Redistribution and use in source and binary forms, with or without
184759
+ * modification, are permitted provided that the following conditions are met:
184760
+ *
184761
+ * 1. Redistributions of source code must retain the above copyright notice, this
184762
+ * list of conditions and the following disclaimer.
184763
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
184764
+ * this list of conditions and the following disclaimer in the
184765
+ * documentation and/or other materials provided with the distribution.
184766
+ * 3. Neither the name of the copyright holder nor the names of its contributors
184767
+ * may be used to endorse or promote products derived from this software without
184768
+ * specific prior written permission.
184769
+ *
184770
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
184771
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
184772
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
184773
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
184774
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
184775
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
184776
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
184777
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
184778
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
184779
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
184780
+ */
184781
+ function indexOfNewline(str, start = 0, end = str.length) {
184782
+ let idx = str.indexOf(`
184783
+ `, start);
184784
+ if (str[idx - 1] === "\r")
184785
+ idx--;
184786
+ return idx <= end ? idx : -1;
184787
+ }
184788
+ function skipComment(str, ptr) {
184789
+ for (let i = ptr;i < str.length; i++) {
184790
+ let c = str[i];
184791
+ if (c === `
184792
+ `)
184793
+ return i;
184794
+ if (c === "\r" && str[i + 1] === `
184795
+ `)
184796
+ return i + 1;
184797
+ if (c < " " && c !== "\t" || c === "") {
184798
+ throw new TomlError("control characters are not allowed in comments", {
184799
+ toml: str,
184800
+ ptr
184801
+ });
184802
+ }
184803
+ }
184804
+ return str.length;
184805
+ }
184806
+ function skipVoid(str, ptr, banNewLines, banComments) {
184807
+ let c;
184808
+ while (true) {
184809
+ while ((c = str[ptr]) === " " || c === "\t" || !banNewLines && (c === `
184810
+ ` || c === "\r" && str[ptr + 1] === `
184811
+ `))
184812
+ ptr++;
184813
+ if (banComments || c !== "#")
184814
+ break;
184815
+ ptr = skipComment(str, ptr);
184816
+ }
184817
+ return ptr;
184818
+ }
184819
+ function skipUntil(str, ptr, sep, end, banNewLines = false) {
184820
+ if (!end) {
184821
+ ptr = indexOfNewline(str, ptr);
184822
+ return ptr < 0 ? str.length : ptr;
184823
+ }
184824
+ for (let i = ptr;i < str.length; i++) {
184825
+ let c = str[i];
184826
+ if (c === "#") {
184827
+ i = indexOfNewline(str, i);
184828
+ } else if (c === sep) {
184829
+ return i + 1;
184830
+ } else if (c === end || banNewLines && (c === `
184831
+ ` || c === "\r" && str[i + 1] === `
184832
+ `)) {
184833
+ return i;
184834
+ }
184835
+ }
184836
+ throw new TomlError("cannot find end of structure", {
184837
+ toml: str,
184838
+ ptr
184839
+ });
184840
+ }
184841
+
184842
+ // node_modules/smol-toml/dist/extract.js
184843
+ /*!
184844
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
184845
+ * SPDX-License-Identifier: BSD-3-Clause
184846
+ *
184847
+ * Redistribution and use in source and binary forms, with or without
184848
+ * modification, are permitted provided that the following conditions are met:
184849
+ *
184850
+ * 1. Redistributions of source code must retain the above copyright notice, this
184851
+ * list of conditions and the following disclaimer.
184852
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
184853
+ * this list of conditions and the following disclaimer in the
184854
+ * documentation and/or other materials provided with the distribution.
184855
+ * 3. Neither the name of the copyright holder nor the names of its contributors
184856
+ * may be used to endorse or promote products derived from this software without
184857
+ * specific prior written permission.
184858
+ *
184859
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
184860
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
184861
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
184862
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
184863
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
184864
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
184865
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
184866
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
184867
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
184868
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
184869
+ */
184870
+ function sliceAndTrimEndOf(str, startPtr, endPtr) {
184871
+ let value = str.slice(startPtr, endPtr);
184872
+ let commentIdx = value.indexOf("#");
184873
+ if (commentIdx > -1) {
184874
+ skipComment(str, commentIdx);
184875
+ value = value.slice(0, commentIdx);
184876
+ }
184877
+ return [value.trimEnd(), commentIdx];
184878
+ }
184879
+ function extractValue(str, ptr, end, depth, integersAsBigInt) {
184880
+ if (depth === 0) {
184881
+ throw new TomlError("document contains excessively nested structures. aborting.", {
184882
+ toml: str,
184883
+ ptr
184884
+ });
184885
+ }
184886
+ let c = str[ptr];
184887
+ if (c === "[" || c === "{") {
184888
+ let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt);
184889
+ if (end) {
184890
+ endPtr2 = skipVoid(str, endPtr2);
184891
+ if (str[endPtr2] === ",")
184892
+ endPtr2++;
184893
+ else if (str[endPtr2] !== end) {
184894
+ throw new TomlError("expected comma or end of structure", {
184895
+ toml: str,
184896
+ ptr: endPtr2
184897
+ });
184898
+ }
184899
+ }
184900
+ return [value, endPtr2];
184901
+ }
184902
+ if (c === '"' || c === "'") {
184903
+ let [parsed, endPtr2] = parseString(str, ptr);
184904
+ if (end) {
184905
+ endPtr2 = skipVoid(str, endPtr2);
184906
+ if (str[endPtr2] && str[endPtr2] !== "," && str[endPtr2] !== end && str[endPtr2] !== `
184907
+ ` && str[endPtr2] !== "\r") {
184908
+ throw new TomlError("unexpected character encountered", {
184909
+ toml: str,
184910
+ ptr: endPtr2
184911
+ });
184912
+ }
184913
+ if (str[endPtr2] === ",")
184914
+ endPtr2++;
184915
+ }
184916
+ return [parsed, endPtr2];
184917
+ }
184918
+ let endPtr = skipUntil(str, ptr, ",", end);
184919
+ let slice = sliceAndTrimEndOf(str, ptr, endPtr - (str[endPtr - 1] === "," ? 1 : 0));
184920
+ if (!slice[0]) {
184921
+ throw new TomlError("incomplete key-value declaration: no value specified", {
184922
+ toml: str,
184923
+ ptr
184924
+ });
184925
+ }
184926
+ if (end && slice[1] > -1) {
184927
+ endPtr = skipVoid(str, ptr + slice[1]);
184928
+ if (str[endPtr] === ",")
184929
+ endPtr++;
184930
+ }
184931
+ return [
184932
+ parseValue(slice[0], str, ptr, integersAsBigInt),
184933
+ endPtr
184934
+ ];
184935
+ }
184936
+
184937
+ // node_modules/smol-toml/dist/struct.js
184938
+ /*!
184939
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
184940
+ * SPDX-License-Identifier: BSD-3-Clause
184941
+ *
184942
+ * Redistribution and use in source and binary forms, with or without
184943
+ * modification, are permitted provided that the following conditions are met:
184944
+ *
184945
+ * 1. Redistributions of source code must retain the above copyright notice, this
184946
+ * list of conditions and the following disclaimer.
184947
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
184948
+ * this list of conditions and the following disclaimer in the
184949
+ * documentation and/or other materials provided with the distribution.
184950
+ * 3. Neither the name of the copyright holder nor the names of its contributors
184951
+ * may be used to endorse or promote products derived from this software without
184952
+ * specific prior written permission.
184953
+ *
184954
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
184955
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
184956
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
184957
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
184958
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
184959
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
184960
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
184961
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
184962
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
184963
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
184964
+ */
184965
+ var KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
184966
+ function parseKey(str, ptr, end = "=") {
184967
+ let dot = ptr - 1;
184968
+ let parsed = [];
184969
+ let endPtr = str.indexOf(end, ptr);
184970
+ if (endPtr < 0) {
184971
+ throw new TomlError("incomplete key-value: cannot find end of key", {
184972
+ toml: str,
184973
+ ptr
184974
+ });
184975
+ }
184976
+ do {
184977
+ let c = str[ptr = ++dot];
184978
+ if (c !== " " && c !== "\t") {
184979
+ if (c === '"' || c === "'") {
184980
+ if (c === str[ptr + 1] && c === str[ptr + 2]) {
184981
+ throw new TomlError("multiline strings are not allowed in keys", {
184982
+ toml: str,
184983
+ ptr
184984
+ });
184985
+ }
184986
+ let [part, eos] = parseString(str, ptr);
184987
+ dot = str.indexOf(".", eos);
184988
+ let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot);
184989
+ let newLine = indexOfNewline(strEnd);
184990
+ if (newLine > -1) {
184991
+ throw new TomlError("newlines are not allowed in keys", {
184992
+ toml: str,
184993
+ ptr: ptr + dot + newLine
184994
+ });
184995
+ }
184996
+ if (strEnd.trimStart()) {
184997
+ throw new TomlError("found extra tokens after the string part", {
184998
+ toml: str,
184999
+ ptr: eos
185000
+ });
185001
+ }
185002
+ if (endPtr < eos) {
185003
+ endPtr = str.indexOf(end, eos);
185004
+ if (endPtr < 0) {
185005
+ throw new TomlError("incomplete key-value: cannot find end of key", {
185006
+ toml: str,
185007
+ ptr
185008
+ });
185009
+ }
185010
+ }
185011
+ parsed.push(part);
185012
+ } else {
185013
+ dot = str.indexOf(".", ptr);
185014
+ let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot);
185015
+ if (!KEY_PART_RE.test(part)) {
185016
+ throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", {
185017
+ toml: str,
185018
+ ptr
185019
+ });
185020
+ }
185021
+ parsed.push(part.trimEnd());
185022
+ }
185023
+ }
185024
+ } while (dot + 1 && dot < endPtr);
185025
+ return [parsed, skipVoid(str, endPtr + 1, true, true)];
185026
+ }
185027
+ function parseInlineTable(str, ptr, depth, integersAsBigInt) {
185028
+ let res = {};
185029
+ let seen = new Set;
185030
+ let c;
185031
+ ptr++;
185032
+ while ((c = str[ptr++]) !== "}" && c) {
185033
+ if (c === ",") {
185034
+ throw new TomlError("expected value, found comma", {
185035
+ toml: str,
185036
+ ptr: ptr - 1
185037
+ });
185038
+ } else if (c === "#")
185039
+ ptr = skipComment(str, ptr);
185040
+ else if (c !== " " && c !== "\t" && c !== `
185041
+ ` && c !== "\r") {
185042
+ let k;
185043
+ let t = res;
185044
+ let hasOwn = false;
185045
+ let [key, keyEndPtr] = parseKey(str, ptr - 1);
185046
+ for (let i = 0;i < key.length; i++) {
185047
+ if (i)
185048
+ t = hasOwn ? t[k] : t[k] = {};
185049
+ k = key[i];
185050
+ if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
185051
+ throw new TomlError("trying to redefine an already defined value", {
185052
+ toml: str,
185053
+ ptr
185054
+ });
185055
+ }
185056
+ if (!hasOwn && k === "__proto__") {
185057
+ Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
185058
+ }
185059
+ }
185060
+ if (hasOwn) {
185061
+ throw new TomlError("trying to redefine an already defined value", {
185062
+ toml: str,
185063
+ ptr
185064
+ });
185065
+ }
185066
+ let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1, integersAsBigInt);
185067
+ seen.add(value);
185068
+ t[k] = value;
185069
+ ptr = valueEndPtr;
185070
+ }
185071
+ }
185072
+ if (!c) {
185073
+ throw new TomlError("unfinished table encountered", {
185074
+ toml: str,
185075
+ ptr
185076
+ });
185077
+ }
185078
+ return [res, ptr];
185079
+ }
185080
+ function parseArray(str, ptr, depth, integersAsBigInt) {
185081
+ let res = [];
185082
+ let c;
185083
+ ptr++;
185084
+ while ((c = str[ptr++]) !== "]" && c) {
185085
+ if (c === ",") {
185086
+ throw new TomlError("expected value, found comma", {
185087
+ toml: str,
185088
+ ptr: ptr - 1
185089
+ });
185090
+ } else if (c === "#")
185091
+ ptr = skipComment(str, ptr);
185092
+ else if (c !== " " && c !== "\t" && c !== `
185093
+ ` && c !== "\r") {
185094
+ let e = extractValue(str, ptr - 1, "]", depth - 1, integersAsBigInt);
185095
+ res.push(e[0]);
185096
+ ptr = e[1];
185097
+ }
185098
+ }
185099
+ if (!c) {
185100
+ throw new TomlError("unfinished array encountered", {
185101
+ toml: str,
185102
+ ptr
185103
+ });
185104
+ }
185105
+ return [res, ptr];
185106
+ }
185107
+
185108
+ // node_modules/smol-toml/dist/parse.js
185109
+ /*!
185110
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
185111
+ * SPDX-License-Identifier: BSD-3-Clause
185112
+ *
185113
+ * Redistribution and use in source and binary forms, with or without
185114
+ * modification, are permitted provided that the following conditions are met:
185115
+ *
185116
+ * 1. Redistributions of source code must retain the above copyright notice, this
185117
+ * list of conditions and the following disclaimer.
185118
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
185119
+ * this list of conditions and the following disclaimer in the
185120
+ * documentation and/or other materials provided with the distribution.
185121
+ * 3. Neither the name of the copyright holder nor the names of its contributors
185122
+ * may be used to endorse or promote products derived from this software without
185123
+ * specific prior written permission.
185124
+ *
185125
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
185126
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
185127
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
185128
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
185129
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
185130
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
185131
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
185132
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
185133
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
185134
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
185135
+ */
185136
+ function peekTable(key, table, meta3, type) {
185137
+ let t = table;
185138
+ let m = meta3;
185139
+ let k;
185140
+ let hasOwn = false;
185141
+ let state;
185142
+ for (let i = 0;i < key.length; i++) {
185143
+ if (i) {
185144
+ t = hasOwn ? t[k] : t[k] = {};
185145
+ m = (state = m[k]).c;
185146
+ if (type === 0 && (state.t === 1 || state.t === 2)) {
185147
+ return null;
185148
+ }
185149
+ if (state.t === 2) {
185150
+ let l = t.length - 1;
185151
+ t = t[l];
185152
+ m = m[l].c;
185153
+ }
185154
+ }
185155
+ k = key[i];
185156
+ if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) {
185157
+ return null;
185158
+ }
185159
+ if (!hasOwn) {
185160
+ if (k === "__proto__") {
185161
+ Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
185162
+ Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
185163
+ }
185164
+ m[k] = {
185165
+ t: i < key.length - 1 && type === 2 ? 3 : type,
185166
+ d: false,
185167
+ i: 0,
185168
+ c: {}
185169
+ };
185170
+ }
185171
+ }
185172
+ state = m[k];
185173
+ if (state.t !== type && !(type === 1 && state.t === 3)) {
185174
+ return null;
185175
+ }
185176
+ if (type === 2) {
185177
+ if (!state.d) {
185178
+ state.d = true;
185179
+ t[k] = [];
185180
+ }
185181
+ t[k].push(t = {});
185182
+ state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} };
185183
+ }
185184
+ if (state.d) {
185185
+ return null;
185186
+ }
185187
+ state.d = true;
185188
+ if (type === 1) {
185189
+ t = hasOwn ? t[k] : t[k] = {};
185190
+ } else if (type === 0 && hasOwn) {
185191
+ return null;
185192
+ }
185193
+ return [k, t, state.c];
185194
+ }
185195
+ function parse5(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
185196
+ let res = {};
185197
+ let meta3 = {};
185198
+ let tbl = res;
185199
+ let m = meta3;
185200
+ for (let ptr = skipVoid(toml, 0);ptr < toml.length; ) {
185201
+ if (toml[ptr] === "[") {
185202
+ let isTableArray = toml[++ptr] === "[";
185203
+ let k = parseKey(toml, ptr += +isTableArray, "]");
185204
+ if (isTableArray) {
185205
+ if (toml[k[1] - 1] !== "]") {
185206
+ throw new TomlError("expected end of table declaration", {
185207
+ toml,
185208
+ ptr: k[1] - 1
185209
+ });
185210
+ }
185211
+ k[1]++;
185212
+ }
185213
+ let p = peekTable(k[0], res, meta3, isTableArray ? 2 : 1);
185214
+ if (!p) {
185215
+ throw new TomlError("trying to redefine an already defined table or value", {
185216
+ toml,
185217
+ ptr
185218
+ });
185219
+ }
185220
+ m = p[2];
185221
+ tbl = p[1];
185222
+ ptr = k[1];
185223
+ } else {
185224
+ let k = parseKey(toml, ptr);
185225
+ let p = peekTable(k[0], tbl, m, 0);
185226
+ if (!p) {
185227
+ throw new TomlError("trying to redefine an already defined table or value", {
185228
+ toml,
185229
+ ptr
185230
+ });
185231
+ }
185232
+ let v = extractValue(toml, k[1], undefined, maxDepth, integersAsBigInt);
185233
+ p[1][p[0]] = v[0];
185234
+ ptr = v[1];
185235
+ }
185236
+ ptr = skipVoid(toml, ptr, true);
185237
+ if (toml[ptr] && toml[ptr] !== `
185238
+ ` && toml[ptr] !== "\r") {
185239
+ throw new TomlError("each key-value declaration must be followed by an end-of-line", {
185240
+ toml,
185241
+ ptr
185242
+ });
185243
+ }
185244
+ ptr = skipVoid(toml, ptr);
185245
+ }
185246
+ return res;
185247
+ }
185248
+
185249
+ // node_modules/smol-toml/dist/stringify.js
185250
+ /*!
185251
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
185252
+ * SPDX-License-Identifier: BSD-3-Clause
185253
+ *
185254
+ * Redistribution and use in source and binary forms, with or without
185255
+ * modification, are permitted provided that the following conditions are met:
185256
+ *
185257
+ * 1. Redistributions of source code must retain the above copyright notice, this
185258
+ * list of conditions and the following disclaimer.
185259
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
185260
+ * this list of conditions and the following disclaimer in the
185261
+ * documentation and/or other materials provided with the distribution.
185262
+ * 3. Neither the name of the copyright holder nor the names of its contributors
185263
+ * may be used to endorse or promote products derived from this software without
185264
+ * specific prior written permission.
185265
+ *
185266
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
185267
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
185268
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
185269
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
185270
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
185271
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
185272
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
185273
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
185274
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
185275
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
185276
+ */
185277
+
185278
+ // node_modules/smol-toml/dist/index.js
185279
+ /*!
185280
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
185281
+ * SPDX-License-Identifier: BSD-3-Clause
185282
+ *
185283
+ * Redistribution and use in source and binary forms, with or without
185284
+ * modification, are permitted provided that the following conditions are met:
185285
+ *
185286
+ * 1. Redistributions of source code must retain the above copyright notice, this
185287
+ * list of conditions and the following disclaimer.
185288
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
185289
+ * this list of conditions and the following disclaimer in the
185290
+ * documentation and/or other materials provided with the distribution.
185291
+ * 3. Neither the name of the copyright holder nor the names of its contributors
185292
+ * may be used to endorse or promote products derived from this software without
185293
+ * specific prior written permission.
185294
+ *
185295
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
185296
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
185297
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
185298
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
185299
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
185300
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
185301
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
185302
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
185303
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
185304
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
185305
+ */
185306
+
185307
+ // src/config/tomlConfigLoader.ts
185308
+ async function loadTomlConfigFile(configPath) {
185309
+ const source = await readFile2(configPath, "utf8");
185310
+ try {
185311
+ return parse5(source);
185312
+ } catch (error51) {
185313
+ throw new Error(formatTomlError(configPath, error51));
185314
+ }
185315
+ }
185316
+ function formatTomlError(configPath, error51) {
185317
+ if (error51 instanceof TomlError) {
185318
+ return `TOML config parse failed for ${configPath} at ${error51.line}:${error51.column}: ${error51.message}`;
185319
+ }
185320
+ return `TOML config parse failed for ${configPath}: ${error51 instanceof Error ? error51.message : String(error51)}`;
185321
+ }
184102
185322
 
184103
185323
  // src/config/tsConfigLoader.ts
184104
185324
  var import_typescript = __toESM(require_typescript(), 1);
@@ -184143,14 +185363,14 @@ ${transpiled}
184143
185363
 
184144
185364
  // src/config/trustedConfig.ts
184145
185365
  import { createHash } from "node:crypto";
184146
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
185366
+ import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
184147
185367
  import { homedir } from "node:os";
184148
185368
  import { dirname as dirname3, join, resolve } from "node:path";
184149
185369
  function hashConfigSource(source) {
184150
185370
  return createHash("sha256").update(source).digest("hex");
184151
185371
  }
184152
185372
  function defaultTrustedConfigStorePath(env = process.env) {
184153
- return env.KYOSO_TRUST_STORE_PATH ? resolve(env.KYOSO_TRUST_STORE_PATH) : join(homedir(), ".kyoso", "trusted-configs.json");
185373
+ return env.KYOSO_TRUST_STORE_PATH ? resolve(env.KYOSO_TRUST_STORE_PATH) : join(env.HOME ? resolve(env.HOME) : homedir(), ".kyoso", "trusted-configs.json");
184154
185374
  }
184155
185375
  async function isTrustedConfig(storePath, configPath, configHash) {
184156
185376
  const store = await readTrustedConfigStore(storePath);
@@ -184169,7 +185389,7 @@ async function trustConfig(storePath, configPath, configHash) {
184169
185389
  async function readTrustedConfigStore(storePath) {
184170
185390
  let parsed;
184171
185391
  try {
184172
- parsed = JSON.parse(await readFile2(storePath, "utf8"));
185392
+ parsed = JSON.parse(await readFile3(storePath, "utf8"));
184173
185393
  } catch (error51) {
184174
185394
  if (isMissingPathError(error51))
184175
185395
  return {};
@@ -184177,7 +185397,7 @@ async function readTrustedConfigStore(storePath) {
184177
185397
  return {};
184178
185398
  throw error51;
184179
185399
  }
184180
- if (!isRecord(parsed))
185400
+ if (!isRecord2(parsed))
184181
185401
  return {};
184182
185402
  const store = {};
184183
185403
  for (const [configPath, configHash] of Object.entries(parsed)) {
@@ -184186,7 +185406,7 @@ async function readTrustedConfigStore(storePath) {
184186
185406
  }
184187
185407
  return store;
184188
185408
  }
184189
- function isRecord(value) {
185409
+ function isRecord2(value) {
184190
185410
  return typeof value === "object" && value !== null && !Array.isArray(value);
184191
185411
  }
184192
185412
  function isMissingPathError(error51) {
@@ -184194,44 +185414,178 @@ function isMissingPathError(error51) {
184194
185414
  }
184195
185415
 
184196
185416
  // src/config/loadConfig.ts
185417
+ var KNOWN_GLOBAL_CONFIG_LEAF_PATHS = new Set(kyosoConfigKnownLeafPaths);
185418
+ var GLOBAL_CONFIG_RECORD_PREFIXES = kyosoConfigRecordPrefixes.map((path) => path.split("."));
185419
+ var SECURITY_SENSITIVE_GLOBAL_PREFIXES = kyosoConfigSecuritySensitivePrefixes.map((path) => path.split("."));
184197
185420
  async function loadConfig(options = {}) {
184198
185421
  const cwd = options.cwd ?? process.cwd();
185422
+ const env = options.env ?? process.env;
185423
+ const globalConfigPath = resolveGlobalTomlConfigPath(env);
184199
185424
  const warnings = [];
184200
- let userConfig = {};
185425
+ const sources = [];
185426
+ let mergedConfig = defaultConfig;
184201
185427
  let configPath;
184202
185428
  let configHash;
184203
185429
  let configTrustStatus = options.ignoreConfig ? "ignored" : "not_found";
184204
185430
  if (!options.ignoreConfig) {
184205
- const candidate = resolve2(cwd, options.configPath ?? "kyoso.config.ts");
184206
- if (await exists2(candidate)) {
184207
- configPath = candidate;
184208
- const source = await readFile3(candidate, "utf8");
184209
- configHash = hashConfigSource(source);
184210
- const trustStorePath = options.trustStorePath ?? defaultTrustedConfigStorePath();
184211
- const trusted = await isTrustedConfig(trustStorePath, candidate, configHash);
184212
- const trustDecision = await resolveTrustDecision({
184213
- configPath: candidate,
184214
- configHash,
184215
- trusted,
185431
+ if (await exists2(globalConfigPath)) {
185432
+ const globalConfig2 = await loadTomlConfigFile(globalConfigPath);
185433
+ const globalConfigWarnings = collectGlobalConfigWarnings(globalConfigPath, globalConfig2);
185434
+ const securitySensitiveWarnings = globalConfigWarnings.filter((warning) => warning.startsWith("security-sensitive unknown settings "));
185435
+ if (securitySensitiveWarnings.length > 0 && !options.allowUnknownConfig) {
185436
+ throw new Error(`Security-sensitive unknown config settings rejected. Fix the key name or pass --allow-unknown-config to continue with warnings: ${securitySensitiveWarnings.join("; ")}`);
185437
+ }
185438
+ warnings.push(...globalConfigWarnings);
185439
+ mergedConfig = deepMerge2(mergedConfig, globalConfig2);
185440
+ sources.push({ path: globalConfigPath, layer: "global_toml" });
185441
+ }
185442
+ if (options.configPath) {
185443
+ const explicitConfigPath = resolve2(cwd, options.configPath);
185444
+ if (!await exists2(explicitConfigPath)) {
185445
+ throw new Error(`Config file not found: ${explicitConfigPath} (from --config)`);
185446
+ }
185447
+ const loaded = await loadProjectConfig({
185448
+ configPath: explicitConfigPath,
185449
+ baseConfig: mergedConfig,
185450
+ globalConfigPath,
184216
185451
  options
184217
185452
  });
184218
- configTrustStatus = trustDecision.status;
184219
- if (trustDecision.execute) {
184220
- userConfig = await loadUserConfig(candidate, source);
184221
- if (trustDecision.shouldPersist) {
184222
- await trustConfig(trustStorePath, candidate, configHash);
184223
- }
184224
- } else {
184225
- warnings.push(`untrusted config was not executed: ${candidate}; run \`kyoso doctor --trust-config\` or pass \`--trust-config\` once to trust it`);
185453
+ mergedConfig = loaded.mergedConfig;
185454
+ configPath = loaded.configPath;
185455
+ configHash = loaded.configHash;
185456
+ configTrustStatus = loaded.configTrustStatus;
185457
+ sources.push(loaded.source);
185458
+ warnings.push(...loaded.warnings);
185459
+ } else {
185460
+ const projectTomlPath = resolve2(cwd, "kyoso.toml");
185461
+ const projectTsPath = resolve2(cwd, "kyoso.config.ts");
185462
+ const hasProjectToml = await exists2(projectTomlPath);
185463
+ const hasProjectTs = await exists2(projectTsPath);
185464
+ if (hasProjectToml) {
185465
+ mergedConfig = mergeProjectTomlConfig(mergedConfig, await loadTomlConfigFile(projectTomlPath), { projectPath: projectTomlPath, globalConfigPath });
185466
+ configPath = projectTomlPath;
185467
+ sources.push({ path: projectTomlPath, layer: "project_toml" });
185468
+ if (hasProjectTs) {
185469
+ warnings.push(`kyoso.config.ts was ignored because kyoso.toml takes precedence: ${projectTsPath}`);
185470
+ }
185471
+ } else if (hasProjectTs) {
185472
+ const loaded = await loadProjectTsConfig({
185473
+ configPath: projectTsPath,
185474
+ baseConfig: mergedConfig,
185475
+ options
185476
+ });
185477
+ mergedConfig = loaded.mergedConfig;
185478
+ configPath = loaded.configPath;
185479
+ configHash = loaded.configHash;
185480
+ configTrustStatus = loaded.configTrustStatus;
185481
+ sources.push(loaded.source);
185482
+ warnings.push(...loaded.warnings);
184226
185483
  }
184227
185484
  }
184228
185485
  }
184229
- const parsed = kyosoConfigSchema.parse(deepMerge(defaultConfig, userConfig));
185486
+ const parsed = kyosoConfigSchema.parse(mergedConfig);
184230
185487
  return {
184231
185488
  config: parsed,
184232
185489
  configPath,
184233
185490
  configHash,
184234
185491
  configTrustStatus,
185492
+ sources,
185493
+ warnings
185494
+ };
185495
+ }
185496
+ function resolveGlobalTomlConfigPath(env = process.env) {
185497
+ const configHome = env.XDG_CONFIG_HOME ? resolve2(env.XDG_CONFIG_HOME) : join2(env.HOME ? resolve2(env.HOME) : homedir2(), ".config");
185498
+ return join2(configHome, "kyoso", "config.toml");
185499
+ }
185500
+ function collectGlobalConfigWarnings(configPath, config2) {
185501
+ const unknownSettings = flattenLeaves(config2).map((leaf) => leaf.path).filter((path) => !isKnownGlobalConfigPath(path)).map((path) => ({
185502
+ path: sanitizeWarningText(path.join(".")),
185503
+ securitySensitive: isSecuritySensitiveGlobalPath(path)
185504
+ })).sort((left, right) => left.path.localeCompare(right.path));
185505
+ const warnings = [];
185506
+ const securitySensitivePaths = unknownSettings.filter((setting) => setting.securitySensitive).map((setting) => setting.path);
185507
+ const generalPaths = unknownSettings.filter((setting) => !setting.securitySensitive).map((setting) => setting.path);
185508
+ const sanitizedConfigPath = sanitizeWarningText(configPath);
185509
+ if (securitySensitivePaths.length > 0) {
185510
+ warnings.push(`security-sensitive unknown settings in ${sanitizedConfigPath} were ignored: ${formatUnknownPaths(securitySensitivePaths)}`);
185511
+ }
185512
+ if (generalPaths.length > 0) {
185513
+ warnings.push(`unknown settings in ${sanitizedConfigPath} were ignored: ${formatUnknownPaths(generalPaths)}`);
185514
+ }
185515
+ return warnings;
185516
+ }
185517
+ function sanitizeWarningText(value) {
185518
+ const withoutControlChars = value.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, "").replace(/[\u0000-\u001f\u007f-\u009f]/g, "");
185519
+ return sanitizeText(withoutControlChars);
185520
+ }
185521
+ function formatUnknownPaths(paths) {
185522
+ return paths.map((path) => JSON.stringify(path)).join("; ");
185523
+ }
185524
+ function isSecuritySensitiveGlobalPath(path) {
185525
+ return SECURITY_SENSITIVE_GLOBAL_PREFIXES.some((prefix) => pathStartsWith(path, prefix));
185526
+ }
185527
+ function isKnownGlobalConfigPath(path) {
185528
+ if (KNOWN_GLOBAL_CONFIG_LEAF_PATHS.has(path.join(".")))
185529
+ return true;
185530
+ return GLOBAL_CONFIG_RECORD_PREFIXES.some((prefix) => pathStartsWith(path, prefix));
185531
+ }
185532
+ function pathStartsWith(path, prefix) {
185533
+ return path.length >= prefix.length && prefix.every((part, index) => path[index] === part);
185534
+ }
185535
+ async function loadProjectConfig(input2) {
185536
+ const extension = extname3(input2.configPath);
185537
+ if (extension === ".toml") {
185538
+ return {
185539
+ mergedConfig: mergeProjectTomlConfig(input2.baseConfig, await loadTomlConfigFile(input2.configPath), {
185540
+ projectPath: input2.configPath,
185541
+ globalConfigPath: input2.globalConfigPath
185542
+ }),
185543
+ configPath: input2.configPath,
185544
+ configTrustStatus: "not_found",
185545
+ source: { path: input2.configPath, layer: "project_toml" },
185546
+ warnings: []
185547
+ };
185548
+ }
185549
+ if (extension === ".ts") {
185550
+ return await loadProjectTsConfig(input2);
185551
+ }
185552
+ throw new Error(`Unsupported config file extension for ${input2.configPath}. Expected .toml or .ts.`);
185553
+ }
185554
+ async function loadProjectTsConfig(input2) {
185555
+ const warnings = [
185556
+ 'kyoso.config.ts is deprecated; migrate to kyoso.toml (see README "Configuration")'
185557
+ ];
185558
+ const source = await readFile4(input2.configPath, "utf8");
185559
+ const configHash = hashConfigSource(source);
185560
+ const trustStorePath = input2.options.trustStorePath ?? defaultTrustedConfigStorePath(input2.options.env);
185561
+ const trusted = await isTrustedConfig(trustStorePath, input2.configPath, configHash);
185562
+ const trustDecision = await resolveTrustDecision({
185563
+ configPath: input2.configPath,
185564
+ configHash,
185565
+ trusted,
185566
+ options: input2.options
185567
+ });
185568
+ if (trustDecision.execute) {
185569
+ const userConfig = await loadUserConfig(input2.configPath, source);
185570
+ if (trustDecision.shouldPersist) {
185571
+ await trustConfig(trustStorePath, input2.configPath, configHash);
185572
+ }
185573
+ return {
185574
+ mergedConfig: deepMerge2(input2.baseConfig, userConfig),
185575
+ configPath: input2.configPath,
185576
+ configHash,
185577
+ configTrustStatus: trustDecision.status,
185578
+ source: { path: input2.configPath, layer: "project_ts" },
185579
+ warnings
185580
+ };
185581
+ }
185582
+ warnings.push(`untrusted config was not executed: ${input2.configPath}; run \`kyoso doctor --trust-config\` or pass \`--trust-config\` once to trust it`);
185583
+ return {
185584
+ mergedConfig: input2.baseConfig,
185585
+ configPath: input2.configPath,
185586
+ configHash,
185587
+ configTrustStatus: trustDecision.status,
185588
+ source: { path: input2.configPath, layer: "project_ts" },
184235
185589
  warnings
184236
185590
  };
184237
185591
  }
@@ -184281,16 +185635,16 @@ async function promptForConfigTrust(configPath, configHash) {
184281
185635
  rl.close();
184282
185636
  }
184283
185637
  }
184284
- function deepMerge(base, override) {
184285
- if (!isRecord2(base) || !isRecord2(override))
185638
+ function deepMerge2(base, override) {
185639
+ if (!isRecord3(base) || !isRecord3(override))
184286
185640
  return override ?? base;
184287
185641
  const result = { ...base };
184288
185642
  for (const [key, value] of Object.entries(override)) {
184289
- result[key] = deepMerge(result[key], value);
185643
+ result[key] = deepMerge2(result[key], value);
184290
185644
  }
184291
185645
  return result;
184292
185646
  }
184293
- function isRecord2(value) {
185647
+ function isRecord3(value) {
184294
185648
  return typeof value === "object" && value !== null && !Array.isArray(value);
184295
185649
  }
184296
185650
  async function exists2(path) {
@@ -184302,43 +185656,6 @@ async function exists2(path) {
184302
185656
  }
184303
185657
  }
184304
185658
 
184305
- // src/security/redact.ts
184306
- var REDACTION = "[KYOSO_REDACTED]";
184307
-
184308
- // src/core/constants.ts
184309
- var DEFAULT_AGENT_TIMEOUT_MS = 120000;
184310
- var RAW_OUTPUT_MAX_CHARS = 16384;
184311
- var KYOSO_CHILD_AGENT = "KYOSO_CHILD_AGENT";
184312
- var KYOSO_VERSION = "0.5.0";
184313
-
184314
- // src/security/sanitizeText.ts
184315
- var SENSITIVE_TEXT_PATTERNS = [
184316
- /\bsk-(?:proj-)?[A-Za-z0-9_-]{8,}\b/g,
184317
- /\bsk-ant-[A-Za-z0-9_-]{8,}\b/g,
184318
- /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{8,}\b/g,
184319
- /\bAKIA[0-9A-Z]{8,}\b/g,
184320
- /\bxox[baprs]-[A-Za-z0-9-]{8,}\b/g,
184321
- /\bsk_(?:live|test)_[A-Za-z0-9]{8,}\b/g,
184322
- /\b(?:api[_-]?key|secret|token|password)\b\s*[:=]\s*["']?[A-Za-z0-9_./+=-]{8,}["']?/gi
184323
- ];
184324
- function sanitizeText(value) {
184325
- return SENSITIVE_TEXT_PATTERNS.reduce((text, pattern) => text.replace(pattern, REDACTION), value);
184326
- }
184327
- function sanitizeTextForDisplay(value, maxChars = 240) {
184328
- const compact = sanitizeText(value).replace(/\s+/g, " ").trim();
184329
- if (compact.length <= maxChars)
184330
- return compact;
184331
- return `${compact.slice(0, Math.max(0, maxChars - 3))}...`;
184332
- }
184333
- function sanitizeTextForRawOutput(value, maxChars = RAW_OUTPUT_MAX_CHARS) {
184334
- const sanitized = sanitizeText(value);
184335
- const limit = Math.max(0, maxChars);
184336
- if (sanitized.length <= limit)
184337
- return sanitized;
184338
- return `${sanitized.slice(0, limit)}
184339
- [KYOSO_TRUNCATED: ${sanitized.length - limit} chars omitted]`;
184340
- }
184341
-
184342
185659
  // src/judge/prompt.ts
184343
185660
  var ANALYSIS_MAX_ITEMS = 5;
184344
185661
  var ANALYSIS_MAX_CHARS = 500;
@@ -184387,7 +185704,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
184387
185704
  const parsed = JSON.parse(json2);
184388
185705
  const summaryText = typeof parsed.summaryText === "string" && parsed.summaryText.trim().length > 0 ? sanitizeText(parsed.summaryText) : fallbackSummaryText;
184389
185706
  const disagreementComments = Array.isArray(parsed.disagreementComments) ? parsed.disagreementComments.flatMap((item) => {
184390
- if (!isRecord3(item) || typeof item.topic !== "string" || typeof item.judgeComment !== "string") {
185707
+ if (!isRecord4(item) || typeof item.topic !== "string" || typeof item.judgeComment !== "string") {
184391
185708
  return [];
184392
185709
  }
184393
185710
  return [
@@ -184403,7 +185720,7 @@ function parseJudgeOutput(text, fallbackSummaryText) {
184403
185720
  return { summaryText, disagreementComments, analysis };
184404
185721
  }
184405
185722
  function parseAnalysis(value) {
184406
- if (!isRecord3(value))
185723
+ if (!isRecord4(value))
184407
185724
  return;
184408
185725
  if (!Array.isArray(value.blindSpots) || !Array.isArray(value.contradictions) || !Array.isArray(value.partialCoverage)) {
184409
185726
  return;
@@ -184411,7 +185728,7 @@ function parseAnalysis(value) {
184411
185728
  return {
184412
185729
  blindSpots: value.blindSpots.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => typeof item === "string" ? [sanitizeAnalysisText(item)] : []),
184413
185730
  contradictions: value.contradictions.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
184414
- if (!isRecord3(item) || typeof item.topic !== "string" || typeof item.detail !== "string") {
185731
+ if (!isRecord4(item) || typeof item.topic !== "string" || typeof item.detail !== "string") {
184415
185732
  return [];
184416
185733
  }
184417
185734
  return [
@@ -184422,7 +185739,7 @@ function parseAnalysis(value) {
184422
185739
  ];
184423
185740
  }),
184424
185741
  partialCoverage: value.partialCoverage.slice(0, ANALYSIS_MAX_ITEMS).flatMap((item) => {
184425
- if (!isRecord3(item) || typeof item.note !== "string")
185742
+ if (!isRecord4(item) || typeof item.note !== "string")
184426
185743
  return [];
184427
185744
  const findingId = typeof item.findingId === "string" ? sanitizeAnalysisText(item.findingId) : undefined;
184428
185745
  return [
@@ -184469,7 +185786,7 @@ function extractFirstJsonObject(text) {
184469
185786
  }
184470
185787
  return;
184471
185788
  }
184472
- function isRecord3(value) {
185789
+ function isRecord4(value) {
184473
185790
  return typeof value === "object" && value !== null && !Array.isArray(value);
184474
185791
  }
184475
185792
 
@@ -184616,9 +185933,9 @@ function hasEnv(env, key) {
184616
185933
  // src/cli/setup.ts
184617
185934
  import { spawnSync } from "node:child_process";
184618
185935
  import { existsSync, readFileSync } from "node:fs";
184619
- import { cp, mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
184620
- import { homedir as homedir2 } from "node:os";
184621
- import { delimiter, dirname as dirname4, join as join2 } from "node:path";
185936
+ import { cp, mkdir as mkdir3, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
185937
+ import { homedir as homedir3 } from "node:os";
185938
+ import { delimiter, dirname as dirname4, join as join3 } from "node:path";
184622
185939
  import { fileURLToPath } from "node:url";
184623
185940
  async function runSetup(options) {
184624
185941
  const client = parseClient(options.client);
@@ -184626,7 +185943,7 @@ async function runSetup(options) {
184626
185943
  const command = options.command ? parseCommandSpec(options.command) : commandForRunner(runner);
184627
185944
  const context = {
184628
185945
  cwd: options.cwd,
184629
- home: options.env?.HOME ?? homedir2(),
185946
+ home: options.env?.HOME ?? homedir3(),
184630
185947
  env: options.env ?? process.env,
184631
185948
  write: options.write,
184632
185949
  scope: options.global ? "global" : "project",
@@ -184672,21 +185989,21 @@ function buildClaudeMcpEntry(command) {
184672
185989
  function skillDestination(client, scope, cwd, home) {
184673
185990
  if (client === "codex") {
184674
185991
  const root2 = scope === "global" ? home : cwd;
184675
- return join2(root2, ".agents", "skills", "kyoso-review");
185992
+ return join3(root2, ".agents", "skills", "kyoso-review");
184676
185993
  }
184677
185994
  const root = scope === "global" ? home : cwd;
184678
- return join2(root, ".claude", "skills", "kyoso-review");
185995
+ return join3(root, ".claude", "skills", "kyoso-review");
184679
185996
  }
184680
185997
  function detectSetup(options) {
184681
- const home = options.home ?? homedir2();
185998
+ const home = options.home ?? homedir3();
184682
185999
  return {
184683
186000
  codex: {
184684
- mcp: hasCodexMcp(join2(home, ".codex", "config.toml")),
184685
- skill: existsSync(join2(options.cwd, ".agents", "skills", "kyoso-review", "SKILL.md")) || existsSync(join2(home, ".agents", "skills", "kyoso-review", "SKILL.md"))
186001
+ mcp: hasCodexMcp(join3(home, ".codex", "config.toml")),
186002
+ skill: existsSync(join3(options.cwd, ".agents", "skills", "kyoso-review", "SKILL.md")) || existsSync(join3(home, ".agents", "skills", "kyoso-review", "SKILL.md"))
184686
186003
  },
184687
186004
  "claude-code": {
184688
- mcp: hasClaudeMcp(join2(options.cwd, ".mcp.json")) || hasClaudeMcp(join2(home, ".claude.json")),
184689
- skill: existsSync(join2(options.cwd, ".claude", "skills", "kyoso-review", "SKILL.md")) || existsSync(join2(home, ".claude", "skills", "kyoso-review", "SKILL.md"))
186005
+ mcp: hasClaudeMcp(join3(options.cwd, ".mcp.json")) || hasClaudeMcp(join3(home, ".claude.json")),
186006
+ skill: existsSync(join3(options.cwd, ".claude", "skills", "kyoso-review", "SKILL.md")) || existsSync(join3(home, ".claude", "skills", "kyoso-review", "SKILL.md"))
184690
186007
  }
184691
186008
  };
184692
186009
  }
@@ -184715,7 +186032,7 @@ async function setupClaudeCode(context) {
184715
186032
  ];
184716
186033
  }
184717
186034
  async function ensureCodexMcp(context) {
184718
- const configPath = join2(context.home, ".codex", "config.toml");
186035
+ const configPath = join3(context.home, ".codex", "config.toml");
184719
186036
  const snippet = buildCodexMcpToml(context.mcpCommand);
184720
186037
  const current = await readOptionalFile(configPath);
184721
186038
  if (hasCodexMcpContent(current)) {
@@ -184747,10 +186064,10 @@ async function ensureClaudeMcp(context) {
184747
186064
  if (context.scope === "global") {
184748
186065
  return ensureClaudeGlobalMcp(context);
184749
186066
  }
184750
- const configPath = join2(context.cwd, ".mcp.json");
186067
+ const configPath = join3(context.cwd, ".mcp.json");
184751
186068
  const current = await readJsonObject(configPath);
184752
186069
  const mcpServers = recordValue(current.mcpServers);
184753
- if (isRecord4(mcpServers.kyoso)) {
186070
+ if (isRecord5(mcpServers.kyoso)) {
184754
186071
  return {
184755
186072
  title: "Claude Code MCP",
184756
186073
  status: "skipped",
@@ -184784,7 +186101,7 @@ async function ensureClaudeMcp(context) {
184784
186101
  };
184785
186102
  }
184786
186103
  function ensureClaudeGlobalMcp(context) {
184787
- const configPath = join2(context.home, ".claude.json");
186104
+ const configPath = join3(context.home, ".claude.json");
184788
186105
  if (hasClaudeMcp(configPath)) {
184789
186106
  return {
184790
186107
  title: "Claude Code MCP",
@@ -184816,7 +186133,7 @@ function ensureClaudeGlobalMcp(context) {
184816
186133
  };
184817
186134
  }
184818
186135
  async function ensureSkill(options) {
184819
- const destinationSkill = join2(options.destinationDir, "SKILL.md");
186136
+ const destinationSkill = join3(options.destinationDir, "SKILL.md");
184820
186137
  if (existsSync(destinationSkill)) {
184821
186138
  return {
184822
186139
  title: options.title,
@@ -184937,8 +186254,8 @@ function resolveBundledSkillDir() {
184937
186254
  const start = dirname4(fileURLToPath(import.meta.url));
184938
186255
  let current = start;
184939
186256
  for (let depth = 0;depth < 5; depth += 1) {
184940
- const candidate = join2(current, ".agents", "skills", "kyoso-review");
184941
- if (existsSync(join2(candidate, "SKILL.md")))
186257
+ const candidate = join3(current, ".agents", "skills", "kyoso-review");
186258
+ if (existsSync(join3(candidate, "SKILL.md")))
184942
186259
  return candidate;
184943
186260
  current = dirname4(current);
184944
186261
  }
@@ -184946,7 +186263,7 @@ function resolveBundledSkillDir() {
184946
186263
  }
184947
186264
  async function readOptionalFile(path) {
184948
186265
  try {
184949
- return await readFile4(path, "utf8");
186266
+ return await readFile5(path, "utf8");
184950
186267
  } catch (error51) {
184951
186268
  if (isMissingPathError2(error51))
184952
186269
  return "";
@@ -184958,7 +186275,7 @@ async function readJsonObject(path) {
184958
186275
  if (content.trim().length === 0)
184959
186276
  return {};
184960
186277
  const parsed = JSON.parse(content);
184961
- if (!isRecord4(parsed))
186278
+ if (!isRecord5(parsed))
184962
186279
  throw new Error(`${path} must contain a JSON object`);
184963
186280
  return parsed;
184964
186281
  }
@@ -184979,9 +186296,9 @@ function hasClaudeMcp(path) {
184979
186296
  }
184980
186297
  }
184981
186298
  function jsonHasKyosoMcp(value) {
184982
- if (!isRecord4(value))
186299
+ if (!isRecord5(value))
184983
186300
  return false;
184984
- if (isRecord4(value.mcpServers) && isRecord4(value.mcpServers.kyoso)) {
186301
+ if (isRecord5(value.mcpServers) && isRecord5(value.mcpServers.kyoso)) {
184985
186302
  return true;
184986
186303
  }
184987
186304
  return Object.values(value).some((child) => jsonHasKyosoMcp(child));
@@ -184992,7 +186309,7 @@ function readTextSync(path) {
184992
186309
  function recordValue(value) {
184993
186310
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
184994
186311
  }
184995
- function isRecord4(value) {
186312
+ function isRecord5(value) {
184996
186313
  return typeof value === "object" && value !== null && !Array.isArray(value);
184997
186314
  }
184998
186315
  function diffForAppend(path, snippet) {
@@ -185069,7 +186386,7 @@ function shellQuote(value) {
185069
186386
  }
185070
186387
  function commandExists(command, env) {
185071
186388
  const paths = env.PATH?.split(delimiter) ?? [];
185072
- return paths.some((path) => existsSync(join2(path, command)));
186389
+ return paths.some((path) => existsSync(join3(path, command)));
185073
186390
  }
185074
186391
  function isMissingPathError2(error51) {
185075
186392
  return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
@@ -185079,11 +186396,16 @@ function isMissingPathError2(error51) {
185079
186396
  async function runDoctor(options) {
185080
186397
  const env = options.env ?? process.env;
185081
186398
  const loaded = await loadConfig(options);
186399
+ const globalConfigPath = resolveGlobalTomlConfigPath(env);
186400
+ const projectTomlPath = resolve4(options.cwd, "kyoso.toml");
186401
+ const projectTsPath = resolve4(options.cwd, "kyoso.config.ts");
185082
186402
  const lines = ["Kyoso doctor", "", "Runtime"];
185083
186403
  lines.push(` Bun: ${commandExists2("bun", env) ? "ok" : "warning not found"}`);
185084
186404
  lines.push(` Node/npm: ${commandExists2("npm", env) ? "ok" : "warning npm not found"}`);
185085
186405
  lines.push("", "Config");
185086
- lines.push(` kyoso.config.ts: ${loaded.configPath ? `found ${loaded.configPath}` : "not found; using defaults"}`);
186406
+ lines.push(` global config.toml: ${formatLayer(loaded, "global_toml", globalConfigPath)}`);
186407
+ lines.push(` kyoso.toml: ${formatLayer(loaded, "project_toml", projectTomlPath)}`);
186408
+ lines.push(` kyoso.config.ts: ${formatProjectTsLayer(loaded, projectTsPath)}`);
185087
186409
  lines.push(` trusted config: ${formatTrustStatus(loaded.configTrustStatus)}`);
185088
186410
  if (loaded.configHash)
185089
186411
  lines.push(` config hash: ${loaded.configHash}`);
@@ -185119,7 +186441,7 @@ async function runDoctor(options) {
185119
186441
  lines.push(` ${agent === "codex" ? "Codex" : "Claude"}: ${exists3 ? "ok" : "warning command not found"}`);
185120
186442
  lines.push(` command: ${[config2.command, ...config2.args].join(" ")}`);
185121
186443
  if (!exists3 && config2.command === "npx" && commandExists2("bunx", env)) {
185122
- lines.push(' hint: replace command "npx" with "bunx" in kyoso.config.ts');
186444
+ lines.push(' hint: set agents.<name>.command = "bunx" in config.toml');
185123
186445
  }
185124
186446
  if (agent === "claude") {
185125
186447
  const hasApiKey = hasEnv2(env, "ANTHROPIC_API_KEY");
@@ -185157,6 +186479,19 @@ async function runDoctor(options) {
185157
186479
  return lines.join(`
185158
186480
  `);
185159
186481
  }
186482
+ function formatLayer(loaded, layer, defaultPath) {
186483
+ const source = loaded.sources.find((candidate) => candidate.layer === layer);
186484
+ return source ? `found ${source.path}` : `not found ${defaultPath}`;
186485
+ }
186486
+ function formatProjectTsLayer(loaded, defaultPath) {
186487
+ const source = loaded.sources.find((candidate) => candidate.layer === "project_ts");
186488
+ if (source)
186489
+ return `found ${source.path} (deprecated)`;
186490
+ if (loaded.warnings.some((warning) => warning.includes("was ignored"))) {
186491
+ return `ignored ${defaultPath} (kyoso.toml takes precedence)`;
186492
+ }
186493
+ return `not found ${defaultPath}`;
186494
+ }
185160
186495
  function formatTrustStatus(status) {
185161
186496
  if (status === "trusted_by_flag")
185162
186497
  return "trusted by --trust-config";
@@ -185190,26 +186525,31 @@ function commandExists2(command, env) {
185190
186525
  }
185191
186526
 
185192
186527
  // src/cli/init.ts
185193
- import { readFile as readFile5, writeFile as writeFile4 } from "node:fs/promises";
185194
- import { join as join3 } from "node:path";
186528
+ import { access as access3, readFile as readFile6, writeFile as writeFile4 } from "node:fs/promises";
186529
+ import { join as join4 } from "node:path";
185195
186530
  async function runInit(options) {
185196
- const configPath = join3(options.cwd, "kyoso.config.ts");
185197
- const skillPath = join3(options.cwd, ".agents/skills/kyoso-review/SKILL.md");
185198
- const gitignorePath = join3(options.cwd, ".gitignore");
186531
+ const configPath = join4(options.cwd, "kyoso.toml");
186532
+ const tsConfigPath = join4(options.cwd, "kyoso.config.ts");
186533
+ const skillPath = join4(options.cwd, ".agents/skills/kyoso-review/SKILL.md");
186534
+ const gitignorePath = join4(options.cwd, ".gitignore");
185199
186535
  const configResult = await writeFileWithOverwritePrompt(configPath, CONFIG_TEMPLATE, options.force);
185200
186536
  const skillResult = await writeFileWithOverwritePrompt(skillPath, SKILL_TEMPLATE, options.force);
185201
186537
  const gitignoreResult = await ensureGitignoreEntry(gitignorePath, ".kyoso/");
185202
- return [
185203
- `kyoso.config.ts: ${configResult}`,
186538
+ const lines = [
186539
+ `kyoso.toml: ${configResult}`,
185204
186540
  `.agents/skills/kyoso-review/SKILL.md: ${skillResult}`,
185205
186541
  `.gitignore .kyoso/: ${gitignoreResult}`
185206
- ].join(`
186542
+ ];
186543
+ if (await exists3(tsConfigPath)) {
186544
+ lines.push("kyoso.config.ts: found deprecated config; kyoso.toml takes precedence");
186545
+ }
186546
+ return lines.join(`
185207
186547
  `);
185208
186548
  }
185209
186549
  async function ensureGitignoreEntry(path, entry) {
185210
186550
  let content = "";
185211
186551
  try {
185212
- content = await readFile5(path, "utf8");
186552
+ content = await readFile6(path, "utf8");
185213
186553
  } catch (error51) {
185214
186554
  if (!isMissingPathError3(error51))
185215
186555
  throw error51;
@@ -185230,13 +186570,19 @@ async function ensureGitignoreEntry(path, entry) {
185230
186570
  function isMissingPathError3(error51) {
185231
186571
  return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
185232
186572
  }
185233
- var CONFIG_TEMPLATE = `import { defineConfig } from "@kyo-so/cli";
186573
+ async function exists3(path) {
186574
+ try {
186575
+ await access3(path);
186576
+ return true;
186577
+ } catch {
186578
+ return false;
186579
+ }
186580
+ }
186581
+ var CONFIG_TEMPLATE = `# Kyoso project config.
186582
+ # Project TOML is declarative and does not require trust approval.
185234
186583
 
185235
- export default defineConfig({
185236
- network: {
185237
- defaultMode: "model_only",
185238
- },
185239
- });
186584
+ [network]
186585
+ defaultMode = "model_only"
185240
186586
  `;
185241
186587
  var SKILL_TEMPLATE = `---
185242
186588
  name: kyoso-review
@@ -185424,10 +186770,10 @@ var require_code$1 = /* @__PURE__ */ __commonJSMin((exports) => {
185424
186770
  function interpolate(x) {
185425
186771
  return typeof x == "number" || typeof x == "boolean" || x === null ? x : safeStringify(Array.isArray(x) ? x.join(",") : x);
185426
186772
  }
185427
- function stringify(x) {
186773
+ function stringify2(x) {
185428
186774
  return new _Code(safeStringify(x));
185429
186775
  }
185430
- exports.stringify = stringify;
186776
+ exports.stringify = stringify2;
185431
186777
  function safeStringify(x) {
185432
186778
  return JSON.stringify(x).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
185433
186779
  }
@@ -188133,7 +189479,7 @@ var require_compile = /* @__PURE__ */ __commonJSMin((exports) => {
188133
189479
  const schOrFunc = root.refs[ref];
188134
189480
  if (schOrFunc)
188135
189481
  return schOrFunc;
188136
- let _sch = resolve4.call(this, root, ref);
189482
+ let _sch = resolve5.call(this, root, ref);
188137
189483
  if (_sch === undefined) {
188138
189484
  const schema = (_a3 = root.localRefs) === null || _a3 === undefined ? undefined : _a3[ref];
188139
189485
  const { schemaId } = this.opts;
@@ -188164,7 +189510,7 @@ var require_compile = /* @__PURE__ */ __commonJSMin((exports) => {
188164
189510
  function sameSchemaEnv(s1, s2) {
188165
189511
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
188166
189512
  }
188167
- function resolve4(root, ref) {
189513
+ function resolve5(root, ref) {
188168
189514
  let sch;
188169
189515
  while (typeof (sch = this.refs[ref]) == "string")
188170
189516
  ref = sch;
@@ -188665,22 +190011,22 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin((exports, module) => {
188665
190011
  const { SCHEMES, getSchemeHandler } = require_schemes();
188666
190012
  function normalize(uri, options) {
188667
190013
  if (typeof uri === "string")
188668
- uri = serialize(parse5(uri, options), options);
190014
+ uri = serialize(parse6(uri, options), options);
188669
190015
  else if (typeof uri === "object")
188670
- uri = parse5(serialize(uri, options), options);
190016
+ uri = parse6(serialize(uri, options), options);
188671
190017
  return uri;
188672
190018
  }
188673
- function resolve4(baseURI, relativeURI, options) {
190019
+ function resolve5(baseURI, relativeURI, options) {
188674
190020
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
188675
- const resolved = resolveComponent(parse5(baseURI, schemelessOptions), parse5(relativeURI, schemelessOptions), schemelessOptions, true);
190021
+ const resolved = resolveComponent(parse6(baseURI, schemelessOptions), parse6(relativeURI, schemelessOptions), schemelessOptions, true);
188676
190022
  schemelessOptions.skipEscape = true;
188677
190023
  return serialize(resolved, schemelessOptions);
188678
190024
  }
188679
190025
  function resolveComponent(base, relative, options, skipNormalization) {
188680
190026
  const target = {};
188681
190027
  if (!skipNormalization) {
188682
- base = parse5(serialize(base, options), options);
188683
- relative = parse5(serialize(relative, options), options);
190028
+ base = parse6(serialize(base, options), options);
190029
+ relative = parse6(serialize(relative, options), options);
188684
190030
  }
188685
190031
  options = options || {};
188686
190032
  if (!options.tolerant && relative.scheme) {
@@ -188730,7 +190076,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin((exports, module) => {
188730
190076
  function equal(uriA, uriB, options) {
188731
190077
  if (typeof uriA === "string") {
188732
190078
  uriA = unescape(uriA);
188733
- uriA = serialize(normalizeComponentEncoding(parse5(uriA, options), true), {
190079
+ uriA = serialize(normalizeComponentEncoding(parse6(uriA, options), true), {
188734
190080
  ...options,
188735
190081
  skipEscape: true
188736
190082
  });
@@ -188741,7 +190087,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin((exports, module) => {
188741
190087
  });
188742
190088
  if (typeof uriB === "string") {
188743
190089
  uriB = unescape(uriB);
188744
- uriB = serialize(normalizeComponentEncoding(parse5(uriB, options), true), {
190090
+ uriB = serialize(normalizeComponentEncoding(parse6(uriB, options), true), {
188745
190091
  ...options,
188746
190092
  skipEscape: true
188747
190093
  });
@@ -188806,7 +190152,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin((exports, module) => {
188806
190152
  return uriTokens.join("");
188807
190153
  }
188808
190154
  const URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
188809
- function parse5(uri, opts) {
190155
+ function parse6(uri, opts) {
188810
190156
  const options = Object.assign({}, opts);
188811
190157
  const parsed = {
188812
190158
  scheme: undefined,
@@ -188881,11 +190227,11 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin((exports, module) => {
188881
190227
  const fastUri = {
188882
190228
  SCHEMES,
188883
190229
  normalize,
188884
- resolve: resolve4,
190230
+ resolve: resolve5,
188885
190231
  resolveComponent,
188886
190232
  equal,
188887
190233
  serialize,
188888
- parse: parse5
190234
+ parse: parse6
188889
190235
  };
188890
190236
  module.exports = fastUri;
188891
190237
  module.exports.default = fastUri;
@@ -196023,14 +197369,14 @@ function inputRequiredRoundsExceededMessage(method, maxRounds) {
196023
197369
  return `Multi-round-trip request '${method}' still required input after ${maxRounds} rounds (inputRequired.maxRounds)`;
196024
197370
  }
196025
197371
  function sleep(ms, signal) {
196026
- return new Promise((resolve4, reject) => {
197372
+ return new Promise((resolve5, reject) => {
196027
197373
  if (signal?.aborted) {
196028
197374
  reject(signal.reason instanceof SdkError ? signal.reason : new SdkError(SdkErrorCode.RequestTimeout, String(signal.reason)));
196029
197375
  return;
196030
197376
  }
196031
197377
  const timer = setTimeout(() => {
196032
197378
  signal?.removeEventListener("abort", onAbort);
196033
- resolve4();
197379
+ resolve5();
196034
197380
  }, ms);
196035
197381
  const onAbort = () => {
196036
197382
  clearTimeout(timer);
@@ -196792,7 +198138,7 @@ var Protocol = class {
196792
198138
  const flowStartedAt = Date.now();
196793
198139
  let onAbort;
196794
198140
  let cleanupMessageId;
196795
- return new Promise((resolve4, reject) => {
198141
+ return new Promise((resolve5, reject) => {
196796
198142
  const earlyReject = (error51) => {
196797
198143
  reject(error51);
196798
198144
  };
@@ -196868,7 +198214,7 @@ var Protocol = class {
196868
198214
  return reject(decoded.error);
196869
198215
  if (decoded.kind === "input_required") {
196870
198216
  if (options?.allowInputRequired === true)
196871
- return resolve4(manualInputRequiredValue(decoded));
198217
+ return resolve5(manualInputRequiredValue(decoded));
196872
198218
  const flow = {
196873
198219
  codec: codec2,
196874
198220
  request,
@@ -196880,12 +198226,12 @@ var Protocol = class {
196880
198226
  params
196881
198227
  }, resultSchema, legOptions)
196882
198228
  };
196883
- return resolve4(this._resolveNonCompleteResult(decoded, flow));
198229
+ return resolve5(this._resolveNonCompleteResult(decoded, flow));
196884
198230
  }
196885
198231
  const result = decoded.result;
196886
198232
  validateStandardSchema(resultSchema, result).then((parseResult) => {
196887
198233
  if (parseResult.success)
196888
- resolve4(parseResult.data);
198234
+ resolve5(parseResult.data);
196889
198235
  else
196890
198236
  reject(new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${request.method}: ${parseResult.error}`));
196891
198237
  }, reject);
@@ -198429,7 +199775,7 @@ var StdioServerTransport = class {
198429
199775
  send(message) {
198430
199776
  if (this._closed)
198431
199777
  return Promise.reject(/* @__PURE__ */ new Error("StdioServerTransport is closed"));
198432
- return new Promise((resolve4, reject) => {
199778
+ return new Promise((resolve5, reject) => {
198433
199779
  const json2 = serializeMessage(message);
198434
199780
  let settled = false;
198435
199781
  const onError = (error51) => {
@@ -198446,7 +199792,7 @@ var StdioServerTransport = class {
198446
199792
  settled = true;
198447
199793
  this._stdout.off("error", onError);
198448
199794
  this._stdout.off("drain", onDrain);
198449
- resolve4();
199795
+ resolve5();
198450
199796
  };
198451
199797
  this._stdout.once("error", onError);
198452
199798
  if (this._stdout.write(json2)) {
@@ -198454,7 +199800,7 @@ var StdioServerTransport = class {
198454
199800
  return;
198455
199801
  settled = true;
198456
199802
  this._stdout.off("error", onError);
198457
- resolve4();
199803
+ resolve5();
198458
199804
  } else if (!settled)
198459
199805
  this._stdout.once("drain", onDrain);
198460
199806
  });
@@ -198462,12 +199808,12 @@ var StdioServerTransport = class {
198462
199808
  };
198463
199809
 
198464
199810
  // src/core/runReview.ts
198465
- import { resolve as resolve5 } from "node:path";
199811
+ import { resolve as resolve6 } from "node:path";
198466
199812
 
198467
199813
  // src/acp/AcpAgentProcess.ts
198468
199814
  import { spawn } from "node:child_process";
198469
- import { readFile as readFile6, realpath } from "node:fs/promises";
198470
- import { isAbsolute, relative, resolve as resolve4 } from "node:path";
199815
+ import { readFile as readFile7, realpath } from "node:fs/promises";
199816
+ import { isAbsolute, relative, resolve as resolve5 } from "node:path";
198471
199817
  import { Readable, Writable } from "node:stream";
198472
199818
 
198473
199819
  // node_modules/@agentclientprotocol/sdk/dist/schema/index.js
@@ -200341,14 +201687,14 @@ function ndJsonStream(output2, input2) {
200341
201687
  }
200342
201688
  // node_modules/@agentclientprotocol/sdk/dist/jsonrpc.js
200343
201689
  var CANCEL_REQUEST_METHOD = "$/cancel_request";
200344
- function isRecord5(value) {
201690
+ function isRecord6(value) {
200345
201691
  return typeof value === "object" && value !== null;
200346
201692
  }
200347
201693
  function isJsonRpcId(value) {
200348
201694
  return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
200349
201695
  }
200350
201696
  function cancelRequestId(params) {
200351
- if (!isRecord5(params) || !isJsonRpcId(params["requestId"])) {
201697
+ if (!isRecord6(params) || !isJsonRpcId(params["requestId"])) {
200352
201698
  return;
200353
201699
  }
200354
201700
  return params["requestId"];
@@ -200572,12 +201918,12 @@ class Connection {
200572
201918
  }
200573
201919
  const id = this.nextRequestId++;
200574
201920
  let cancel = () => {};
200575
- const responsePromise = new Promise((resolve4, reject) => {
201921
+ const responsePromise = new Promise((resolve5, reject) => {
200576
201922
  const pendingResponse = {
200577
201923
  resolve: (response) => {
200578
201924
  try {
200579
201925
  const value = mapResponse ? mapResponse(response) : response;
200580
- resolve4(value);
201926
+ resolve5(value);
200581
201927
  } catch (error51) {
200582
201928
  reject(error51);
200583
201929
  }
@@ -200642,8 +201988,8 @@ class Connection {
200642
201988
  initialize(stream, handlers) {
200643
201989
  this.stream = stream;
200644
201990
  this.staticHandlers = handlers;
200645
- this.closedPromise = new Promise((resolve4) => {
200646
- this.abortController.signal.addEventListener("abort", () => resolve4());
201991
+ this.closedPromise = new Promise((resolve5) => {
201992
+ this.abortController.signal.addEventListener("abort", () => resolve5());
200647
201993
  });
200648
201994
  this.receive();
200649
201995
  }
@@ -200850,25 +202196,25 @@ class ConnectionBuilder {
200850
202196
  describe: () => this.connectionName ?? "onReceiveMessage"
200851
202197
  });
200852
202198
  }
200853
- onReceiveRequest(method, parse5, handler) {
202199
+ onReceiveRequest(method, parse6, handler) {
200854
202200
  return this.withHandler({
200855
202201
  handleMessage: async (message, cx) => {
200856
202202
  if (message.kind !== "request" || message.method !== method) {
200857
202203
  return Handled.no(message);
200858
202204
  }
200859
- const request = parse5(message.params);
202205
+ const request = parse6(message.params);
200860
202206
  return await handler(request, message.responder, cx) ?? Handled.yes();
200861
202207
  },
200862
202208
  describe: () => `${this.connectionName ?? "request"}:${method}`
200863
202209
  });
200864
202210
  }
200865
- onReceiveNotification(method, parse5, handler) {
202211
+ onReceiveNotification(method, parse6, handler) {
200866
202212
  return this.withHandler({
200867
202213
  handleMessage: async (message, cx) => {
200868
202214
  if (message.kind !== "notification" || message.method !== method) {
200869
202215
  return Handled.no(message);
200870
202216
  }
200871
- const notification = parse5(message.params);
202217
+ const notification = parse6(message.params);
200872
202218
  return await handler(notification, cx) ?? Handled.yes();
200873
202219
  },
200874
202220
  describe: () => `${this.connectionName ?? "notification"}:${method}`
@@ -201218,8 +202564,8 @@ class AsyncQueue {
201218
202564
  if (this.failed) {
201219
202565
  return Promise.reject(this.failure);
201220
202566
  }
201221
- return new Promise((resolve4, reject) => {
201222
- this.waiters.push({ resolve: resolve4, reject });
202567
+ return new Promise((resolve5, reject) => {
202568
+ this.waiters.push({ resolve: resolve5, reject });
201223
202569
  });
201224
202570
  }
201225
202571
  }
@@ -201921,7 +203267,7 @@ function isSeverity(value) {
201921
203267
  return typeof value === "string" && severities.includes(value);
201922
203268
  }
201923
203269
  function normalizeCisaSecureByDesign(value) {
201924
- if (!isRecord6(value))
203270
+ if (!isRecord7(value))
201925
203271
  return;
201926
203272
  const normalized = {};
201927
203273
  const customerSecurityOutcomes = normalizeGateStatus(value.customerSecurityOutcomes);
@@ -201962,7 +203308,7 @@ function normalizeFindingFiles(value) {
201962
203308
  if (!Array.isArray(value))
201963
203309
  return;
201964
203310
  const files = value.flatMap((item) => {
201965
- if (!isRecord6(item) || typeof item.path !== "string" || item.path.trim().length === 0) {
203311
+ if (!isRecord7(item) || typeof item.path !== "string" || item.path.trim().length === 0) {
201966
203312
  return [];
201967
203313
  }
201968
203314
  const file2 = {
@@ -201981,7 +203327,7 @@ function normalizeFindingFiles(value) {
201981
203327
  function normalizeLineNumber(value) {
201982
203328
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : undefined;
201983
203329
  }
201984
- function isRecord6(value) {
203330
+ function isRecord7(value) {
201985
203331
  return typeof value === "object" && value !== null && !Array.isArray(value);
201986
203332
  }
201987
203333
 
@@ -202169,7 +203515,7 @@ async function readWorkspaceFile(workspaceDir, requestedPath, line, limit) {
202169
203515
  const readablePath = await resolveReadableFile(workspaceRoot, absolute);
202170
203516
  if (!readablePath)
202171
203517
  continue;
202172
- content = await readFile6(readablePath, "utf8").catch(() => {
203518
+ content = await readFile7(readablePath, "utf8").catch(() => {
202173
203519
  return;
202174
203520
  });
202175
203521
  if (content !== undefined)
@@ -202196,13 +203542,13 @@ async function resolveReadableFile(workspaceRoot, absolute) {
202196
203542
  return realPath;
202197
203543
  }
202198
203544
  function resolveReadablePaths(workspaceRoot, requestedPath) {
202199
- const primary = resolve4(workspaceRoot, requestedPath);
203545
+ const primary = resolve5(workspaceRoot, requestedPath);
202200
203546
  assertWithinWorkspace(workspaceRoot, primary);
202201
203547
  const relativePath = relative(workspaceRoot, primary).replaceAll("\\", "/");
202202
203548
  if (relativePath.startsWith("context/") || relativePath.startsWith("repo/")) {
202203
203549
  return [primary];
202204
203550
  }
202205
- const repoPath = resolve4(workspaceRoot, "repo", relativePath);
203551
+ const repoPath = resolve5(workspaceRoot, "repo", relativePath);
202206
203552
  assertWithinWorkspace(workspaceRoot, repoPath);
202207
203553
  return isAbsolute(requestedPath) ? [primary, repoPath] : [repoPath, primary];
202208
203554
  }
@@ -202922,7 +204268,7 @@ function normalizeTitle(value) {
202922
204268
 
202923
204269
  // src/audit/trace.ts
202924
204270
  import { mkdir as mkdir4, appendFile } from "node:fs/promises";
202925
- import { dirname as dirname5, isAbsolute as isAbsolute2, join as join4 } from "node:path";
204271
+ import { dirname as dirname5, isAbsolute as isAbsolute2, join as join5 } from "node:path";
202926
204272
 
202927
204273
  // src/context/pathPolicy.ts
202928
204274
  import { normalize, sep } from "node:path";
@@ -203016,7 +204362,7 @@ function createTraceWriter(options) {
203016
204362
  }
203017
204363
  const date5 = new Date().toISOString().slice(0, 10);
203018
204364
  const directory = validateAuditDirectory(options.directory, warnings);
203019
- const tracePath = join4(options.cwd, directory, date5, `${options.traceId}.jsonl`);
204365
+ const tracePath = join5(options.cwd, directory, date5, `${options.traceId}.jsonl`);
203020
204366
  return {
203021
204367
  tracePath,
203022
204368
  warnings,
@@ -203197,6 +204543,10 @@ function renderMarkdownResult(tool, result, options = {}) {
203197
204543
  lines.push(...result.testsToAdd.length > 0 ? result.testsToAdd.map((test) => `- ${test}`) : ["- None."]);
203198
204544
  lines.push("", "## Residual Risks", "");
203199
204545
  lines.push(...result.residualRisks.length > 0 ? result.residualRisks.map((risk) => `- ${risk}`) : ["- None."]);
204546
+ if (result.audit.warnings && result.audit.warnings.length > 0) {
204547
+ lines.push("", "## Warnings", "");
204548
+ lines.push(...result.audit.warnings.map((warning) => `- ${escapeMarkdownText(warning)}`));
204549
+ }
203200
204550
  if (result.crossModelAnalysis) {
203201
204551
  lines.push("", "## Cross-Model Analysis", "");
203202
204552
  if (result.reviewMode === "single_agent") {
@@ -203261,6 +204611,9 @@ function formatVerification(finding) {
203261
204611
  function formatList(items) {
203262
204612
  return items.length > 0 ? items.map((item) => `- ${item}`) : ["- None."];
203263
204613
  }
204614
+ function escapeMarkdownText(value) {
204615
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replace(/[\r\n]+/g, " ").replace(/([\\`*_{}\[\]()#+!|])/g, "\\$1");
204616
+ }
203264
204617
 
203265
204618
  // src/security/recursionGuard.ts
203266
204619
  function assertNotChildAgent(env = process.env) {
@@ -203454,12 +204807,12 @@ function decide(input2) {
203454
204807
 
203455
204808
  // src/workspace/createSnapshot.ts
203456
204809
  import { chmod, mkdir as mkdir5, mkdtemp, writeFile as writeFile5 } from "node:fs/promises";
203457
- import { dirname as dirname6, join as join5 } from "node:path";
204810
+ import { dirname as dirname6, join as join6 } from "node:path";
203458
204811
  import { tmpdir } from "node:os";
203459
204812
  async function createSnapshot(traceId, tool, request, options = {}) {
203460
- const root = await mkdtemp(join5(tmpdir(), `kyoso-${traceId}-`));
203461
- const repoDir = join5(root, "repo");
203462
- const contextDir = join5(root, "context");
204813
+ const root = await mkdtemp(join6(tmpdir(), `kyoso-${traceId}-`));
204814
+ const repoDir = join6(root, "repo");
204815
+ const contextDir = join6(root, "context");
203463
204816
  await mkdir5(repoDir, { recursive: true });
203464
204817
  await mkdir5(contextDir, { recursive: true });
203465
204818
  let fileCount = 0;
@@ -203469,7 +204822,7 @@ async function createSnapshot(traceId, tool, request, options = {}) {
203469
204822
  continue;
203470
204823
  if (!isAllowedPath(relative2, options.allowPatterns ?? []))
203471
204824
  continue;
203472
- const dest = join5(repoDir, relative2);
204825
+ const dest = join6(repoDir, relative2);
203473
204826
  await mkdir5(dirname6(dest), { recursive: true });
203474
204827
  await writeFile5(dest, file2.content, "utf8");
203475
204828
  await chmod(dest, 292).catch(() => {
@@ -203477,16 +204830,16 @@ async function createSnapshot(traceId, tool, request, options = {}) {
203477
204830
  });
203478
204831
  fileCount += 1;
203479
204832
  }
203480
- await writeFile5(join5(contextDir, "request.json"), JSON.stringify(stripContents(request), null, 2), "utf8");
203481
- await writeFile5(join5(contextDir, "selected_files_manifest.json"), JSON.stringify(buildSelectedFilesManifest(request), null, 2), "utf8");
203482
- await writeFile5(join5(contextDir, "instructions.codex.md"), buildAgentPrompt(tool, request, "codex", options.agentRoles?.codex ?? "implementation_reviewer"), "utf8");
203483
- await writeFile5(join5(contextDir, "instructions.claude.md"), buildAgentPrompt(tool, request, "claude", options.agentRoles?.claude ?? "architecture_security_reviewer"), "utf8");
204833
+ await writeFile5(join6(contextDir, "request.json"), JSON.stringify(stripContents(request), null, 2), "utf8");
204834
+ await writeFile5(join6(contextDir, "selected_files_manifest.json"), JSON.stringify(buildSelectedFilesManifest(request), null, 2), "utf8");
204835
+ await writeFile5(join6(contextDir, "instructions.codex.md"), buildAgentPrompt(tool, request, "codex", options.agentRoles?.codex ?? "implementation_reviewer"), "utf8");
204836
+ await writeFile5(join6(contextDir, "instructions.claude.md"), buildAgentPrompt(tool, request, "claude", options.agentRoles?.claude ?? "architecture_security_reviewer"), "utf8");
203484
204837
  if (request.repoSummary)
203485
- await writeFile5(join5(contextDir, "repo_summary.md"), request.repoSummary, "utf8");
204838
+ await writeFile5(join6(contextDir, "repo_summary.md"), request.repoSummary, "utf8");
203486
204839
  if (request.currentPlan)
203487
- await writeFile5(join5(contextDir, "current_plan.md"), request.currentPlan, "utf8");
204840
+ await writeFile5(join6(contextDir, "current_plan.md"), request.currentPlan, "utf8");
203488
204841
  if (request.diff?.unifiedDiff)
203489
- await writeFile5(join5(contextDir, "diff.patch"), request.diff.unifiedDiff, "utf8");
204842
+ await writeFile5(join6(contextDir, "diff.patch"), request.diff.unifiedDiff, "utf8");
203490
204843
  return { root, repoDir, contextDir, fileCount };
203491
204844
  }
203492
204845
  function stripContents(request) {
@@ -203576,7 +204929,7 @@ function parseVerificationVerdicts(rawText) {
203576
204929
  if (!Array.isArray(parsed.verdicts))
203577
204930
  return;
203578
204931
  return parsed.verdicts.flatMap((item) => {
203579
- if (!isRecord7(item))
204932
+ if (!isRecord8(item))
203580
204933
  return [];
203581
204934
  if (typeof item.findingId !== "string")
203582
204935
  return [];
@@ -203654,7 +205007,7 @@ function verificationNote(reasoning) {
203654
205007
  function isVerdict(value) {
203655
205008
  return value === "confirmed" || value === "refuted" || value === "uncertain";
203656
205009
  }
203657
- function isRecord7(value) {
205010
+ function isRecord8(value) {
203658
205011
  return typeof value === "object" && value !== null && !Array.isArray(value);
203659
205012
  }
203660
205013
 
@@ -203707,14 +205060,17 @@ async function runReview(tool, request, options = {}) {
203707
205060
  config: options.config,
203708
205061
  configHash: options.configHash,
203709
205062
  configTrustStatus: "trusted",
205063
+ sources: [],
203710
205064
  warnings: []
203711
205065
  } : await loadConfig({
203712
205066
  cwd,
203713
205067
  configPath: options.configPath,
203714
205068
  ignoreConfig: options.ignoreConfig,
203715
205069
  trustConfig: options.trustConfig,
205070
+ allowUnknownConfig: options.allowUnknownConfig,
203716
205071
  promptForTrust: options.promptForTrust,
203717
205072
  trustStorePath: options.trustStorePath,
205073
+ env: options.env,
203718
205074
  trustPrompt: options.trustPrompt
203719
205075
  });
203720
205076
  const trace = createTraceWriter({
@@ -203737,6 +205093,7 @@ async function runReview(tool, request, options = {}) {
203737
205093
  traceId,
203738
205094
  configHash: loaded.configHash,
203739
205095
  configPath: loaded.configPath,
205096
+ configSources: loaded.sources,
203740
205097
  configTrustStatus: loaded.configTrustStatus,
203741
205098
  timestamp: new Date().toISOString()
203742
205099
  });
@@ -204285,7 +205642,7 @@ function mergeDenyPatterns(configDeny, requestDeny) {
204285
205642
  function assertTrustedWorkspaceRoot(requestRoot, configRoot, cwd) {
204286
205643
  if (!requestRoot)
204287
205644
  return;
204288
- if (resolve5(cwd, requestRoot) !== resolve5(cwd, configRoot)) {
205645
+ if (resolve6(cwd, requestRoot) !== resolve6(cwd, configRoot)) {
204289
205646
  throw new KyosoRequestError("workspace.root is not trusted by config", "UNTRUSTED_WORKSPACE_ROOT");
204290
205647
  }
204291
205648
  }
@@ -204368,6 +205725,7 @@ async function main() {
204368
205725
  const configPath = stringFlag(parsed.flags, "config");
204369
205726
  const ignoreConfig = booleanFlag(parsed.flags, "ignore-config");
204370
205727
  const trustConfig2 = booleanFlag(parsed.flags, "trust-config");
205728
+ const allowUnknownConfig = booleanFlag(parsed.flags, "allow-unknown-config");
204371
205729
  if (parsed.command === "mcp") {
204372
205730
  const network = networkFlag(parsed.flags);
204373
205731
  await startMcpServer({
@@ -204375,6 +205733,7 @@ async function main() {
204375
205733
  configPath,
204376
205734
  ignoreConfig,
204377
205735
  trustConfig: trustConfig2,
205736
+ allowUnknownConfig,
204378
205737
  mcpNetworkMode: network
204379
205738
  });
204380
205739
  return;
@@ -204385,6 +205744,7 @@ async function main() {
204385
205744
  configPath,
204386
205745
  ignoreConfig,
204387
205746
  trustConfig: trustConfig2,
205747
+ allowUnknownConfig,
204388
205748
  promptForTrust: canPromptForConfigTrust()
204389
205749
  }));
204390
205750
  return;
@@ -204412,6 +205772,7 @@ async function main() {
204412
205772
  configPath,
204413
205773
  ignoreConfig,
204414
205774
  trustConfig: trustConfig2,
205775
+ allowUnknownConfig,
204415
205776
  promptForTrust: canPromptForConfigTrust()
204416
205777
  });
204417
205778
  console.log(booleanFlag(parsed.flags, "json") ? JSON.stringify(result, null, 2) : result.summaryMarkdown);
@@ -204494,12 +205855,12 @@ function canPromptForConfigTrust() {
204494
205855
  var HELP = `Kyoso
204495
205856
 
204496
205857
  Usage:
204497
- kyoso mcp [--config kyoso.config.ts] [--ignore-config] [--trust-config] [--network model_only|unrestricted]
205858
+ kyoso mcp [--config kyoso.toml|kyoso.config.ts] [--ignore-config] [--trust-config] [--allow-unknown-config] [--network model_only|unrestricted]
204498
205859
  kyoso setup [codex|claude-code] [--write] [--runner npx|bunx] [--command <command>] [--global]
204499
- kyoso plan --goal <text> [--plan <path-or-text>] [--file <path>] [--json] [--trust-config]
204500
- kyoso security --goal <text> [--diff <path>] [--file <path>] [--allow-secret-redaction] [--trust-config]
204501
- kyoso diff --base main --head HEAD [--json] [--trust-config]
204502
- kyoso doctor [--trust-config]
205860
+ kyoso plan --goal <text> [--plan <path-or-text>] [--file <path>] [--json] [--trust-config] [--allow-unknown-config]
205861
+ kyoso security --goal <text> [--diff <path>] [--file <path>] [--allow-secret-redaction] [--trust-config] [--allow-unknown-config]
205862
+ kyoso diff --base main --head HEAD [--json] [--trust-config] [--allow-unknown-config]
205863
+ kyoso doctor [--trust-config] [--allow-unknown-config]
204503
205864
  kyoso init [--force]
204504
205865
  `;
204505
205866
  main().catch((error51) => {