norn-cli 4.6.3 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -15274,7 +15274,7 @@ var require_mime_types = __commonJS({
15274
15274
  "node_modules/mime-types/index.js"(exports2) {
15275
15275
  "use strict";
15276
15276
  var db = require_mime_db();
15277
- var extname9 = require("path").extname;
15277
+ var extname10 = require("path").extname;
15278
15278
  var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/;
15279
15279
  var TEXT_TYPE_REGEXP = /^text\//i;
15280
15280
  exports2.charset = charset;
@@ -15328,7 +15328,7 @@ var require_mime_types = __commonJS({
15328
15328
  if (!path44 || typeof path44 !== "string") {
15329
15329
  return false;
15330
15330
  }
15331
- var extension3 = extname9("x." + path44).toLowerCase().substr(1);
15331
+ var extension3 = extname10("x." + path44).toLowerCase().substr(1);
15332
15332
  if (!extension3) {
15333
15333
  return false;
15334
15334
  }
@@ -16437,7 +16437,7 @@ var require_form_data = __commonJS({
16437
16437
  var http5 = require("http");
16438
16438
  var https5 = require("https");
16439
16439
  var parseUrl = require("url").parse;
16440
- var fs38 = require("fs");
16440
+ var fs39 = require("fs");
16441
16441
  var Stream6 = require("stream").Stream;
16442
16442
  var crypto13 = require("crypto");
16443
16443
  var mime = require_mime_types();
@@ -16504,7 +16504,7 @@ var require_form_data = __commonJS({
16504
16504
  if (value.end != void 0 && value.end != Infinity && value.start != void 0) {
16505
16505
  callback(null, value.end + 1 - (value.start ? value.start : 0));
16506
16506
  } else {
16507
- fs38.stat(value.path, function(err, stat4) {
16507
+ fs39.stat(value.path, function(err, stat4) {
16508
16508
  if (err) {
16509
16509
  callback(err);
16510
16510
  return;
@@ -20212,15 +20212,15 @@ var require_pg_connection_string = __commonJS({
20212
20212
  if (config2.sslcert || config2.sslkey || config2.sslrootcert || config2.sslmode) {
20213
20213
  config2.ssl = {};
20214
20214
  }
20215
- const fs38 = config2.sslcert || config2.sslkey || config2.sslrootcert ? require("fs") : null;
20215
+ const fs39 = config2.sslcert || config2.sslkey || config2.sslrootcert ? require("fs") : null;
20216
20216
  if (config2.sslcert) {
20217
- config2.ssl.cert = fs38.readFileSync(config2.sslcert).toString();
20217
+ config2.ssl.cert = fs39.readFileSync(config2.sslcert).toString();
20218
20218
  }
20219
20219
  if (config2.sslkey) {
20220
- config2.ssl.key = fs38.readFileSync(config2.sslkey).toString();
20220
+ config2.ssl.key = fs39.readFileSync(config2.sslkey).toString();
20221
20221
  }
20222
20222
  if (config2.sslrootcert) {
20223
- config2.ssl.ca = fs38.readFileSync(config2.sslrootcert).toString();
20223
+ config2.ssl.ca = fs39.readFileSync(config2.sslrootcert).toString();
20224
20224
  }
20225
20225
  if (options.useLibpqCompat && config2.uselibpqcompat) {
20226
20226
  throw new Error("Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.");
@@ -22157,15 +22157,15 @@ var require_lib = __commonJS({
22157
22157
  "node_modules/pgpass/lib/index.js"(exports2, module2) {
22158
22158
  "use strict";
22159
22159
  var path44 = require("path");
22160
- var fs38 = require("fs");
22160
+ var fs39 = require("fs");
22161
22161
  var helper = require_helper();
22162
22162
  module2.exports = function(connInfo, cb) {
22163
22163
  var file2 = helper.getFileName();
22164
- fs38.stat(file2, function(err, stat4) {
22164
+ fs39.stat(file2, function(err, stat4) {
22165
22165
  if (err || !helper.usePgPass(stat4, file2)) {
22166
22166
  return cb(void 0);
22167
22167
  }
22168
- var st = fs38.createReadStream(file2);
22168
+ var st = fs39.createReadStream(file2);
22169
22169
  helper.getPassword(connInfo, st, cb);
22170
22170
  });
22171
22171
  };
@@ -41656,7 +41656,7 @@ var require_msal_node = __commonJS({
41656
41656
  var crypto13 = require("crypto");
41657
41657
  var msalCommon = require_lib4();
41658
41658
  var jwt2 = require_jsonwebtoken();
41659
- var fs38 = require("fs");
41659
+ var fs39 = require("fs");
41660
41660
  var path44 = require("path");
41661
41661
  var Serializer = class {
41662
41662
  /**
@@ -51405,7 +51405,7 @@ Headers: ${JSON.stringify(headers)}`
51405
51405
  if (!identityEndpoint || !imdsEndpoint) {
51406
51406
  const fileDetectionPath = AZURE_ARC_FILE_DETECTION[process.platform];
51407
51407
  try {
51408
- fs38.accessSync(fileDetectionPath, fs38.constants.F_OK | fs38.constants.R_OK);
51408
+ fs39.accessSync(fileDetectionPath, fs39.constants.F_OK | fs39.constants.R_OK);
51409
51409
  identityEndpoint = DEFAULT_AZURE_ARC_IDENTITY_ENDPOINT;
51410
51410
  imdsEndpoint = HIMDS_EXECUTABLE_HELPER_STRING;
51411
51411
  } catch (err) {
@@ -51517,7 +51517,7 @@ Headers: ${JSON.stringify(headers)}`
51517
51517
  }
51518
51518
  let secretFileSize;
51519
51519
  try {
51520
- secretFileSize = await fs38.statSync(secretFilePath).size;
51520
+ secretFileSize = await fs39.statSync(secretFilePath).size;
51521
51521
  } catch (e2) {
51522
51522
  throw createManagedIdentityError(unableToReadSecretFile);
51523
51523
  }
@@ -51526,7 +51526,7 @@ Headers: ${JSON.stringify(headers)}`
51526
51526
  }
51527
51527
  let secret;
51528
51528
  try {
51529
- secret = fs38.readFileSync(secretFilePath, EncodingTypes.UTF8);
51529
+ secret = fs39.readFileSync(secretFilePath, EncodingTypes.UTF8);
51530
51530
  } catch (e2) {
51531
51531
  throw createManagedIdentityError(unableToReadSecretFile);
51532
51532
  }
@@ -68241,8 +68241,8 @@ var require_primordials = __commonJS({
68241
68241
  ArrayPrototypeIndexOf(self2, el) {
68242
68242
  return self2.indexOf(el);
68243
68243
  },
68244
- ArrayPrototypeJoin(self2, sep11) {
68245
- return self2.join(sep11);
68244
+ ArrayPrototypeJoin(self2, sep10) {
68245
+ return self2.join(sep10);
68246
68246
  },
68247
68247
  ArrayPrototypeMap(self2, fn) {
68248
68248
  return self2.map(fn);
@@ -100776,12 +100776,12 @@ var require_dist5 = __commonJS({
100776
100776
  throw new Error(`Unknown format "${name}"`);
100777
100777
  return f3;
100778
100778
  };
100779
- function addFormats(ajv2, list, fs38, exportName) {
100779
+ function addFormats(ajv2, list, fs39, exportName) {
100780
100780
  var _a6;
100781
100781
  var _b;
100782
100782
  (_a6 = (_b = ajv2.opts.code).formats) !== null && _a6 !== void 0 ? _a6 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
100783
100783
  for (const f3 of list)
100784
- ajv2.addFormat(f3, fs38[f3]);
100784
+ ajv2.addFormat(f3, fs39[f3]);
100785
100785
  }
100786
100786
  module2.exports = exports2 = formatsPlugin;
100787
100787
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -100794,7 +100794,7 @@ var require_windows = __commonJS({
100794
100794
  "node_modules/isexe/windows.js"(exports2, module2) {
100795
100795
  module2.exports = isexe;
100796
100796
  isexe.sync = sync;
100797
- var fs38 = require("fs");
100797
+ var fs39 = require("fs");
100798
100798
  function checkPathExt(path44, options) {
100799
100799
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
100800
100800
  if (!pathext) {
@@ -100819,12 +100819,12 @@ var require_windows = __commonJS({
100819
100819
  return checkPathExt(path44, options);
100820
100820
  }
100821
100821
  function isexe(path44, options, cb) {
100822
- fs38.stat(path44, function(er, stat4) {
100822
+ fs39.stat(path44, function(er, stat4) {
100823
100823
  cb(er, er ? false : checkStat(stat4, path44, options));
100824
100824
  });
100825
100825
  }
100826
100826
  function sync(path44, options) {
100827
- return checkStat(fs38.statSync(path44), path44, options);
100827
+ return checkStat(fs39.statSync(path44), path44, options);
100828
100828
  }
100829
100829
  }
100830
100830
  });
@@ -100834,14 +100834,14 @@ var require_mode = __commonJS({
100834
100834
  "node_modules/isexe/mode.js"(exports2, module2) {
100835
100835
  module2.exports = isexe;
100836
100836
  isexe.sync = sync;
100837
- var fs38 = require("fs");
100837
+ var fs39 = require("fs");
100838
100838
  function isexe(path44, options, cb) {
100839
- fs38.stat(path44, function(er, stat4) {
100839
+ fs39.stat(path44, function(er, stat4) {
100840
100840
  cb(er, er ? false : checkStat(stat4, options));
100841
100841
  });
100842
100842
  }
100843
100843
  function sync(path44, options) {
100844
- return checkStat(fs38.statSync(path44), options);
100844
+ return checkStat(fs39.statSync(path44), options);
100845
100845
  }
100846
100846
  function checkStat(stat4, options) {
100847
100847
  return stat4.isFile() && checkMode(stat4, options);
@@ -100865,7 +100865,7 @@ var require_mode = __commonJS({
100865
100865
  // node_modules/isexe/index.js
100866
100866
  var require_isexe = __commonJS({
100867
100867
  "node_modules/isexe/index.js"(exports2, module2) {
100868
- var fs38 = require("fs");
100868
+ var fs39 = require("fs");
100869
100869
  var core;
100870
100870
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
100871
100871
  core = require_windows();
@@ -101129,16 +101129,16 @@ var require_shebang_command = __commonJS({
101129
101129
  var require_readShebang = __commonJS({
101130
101130
  "node_modules/cross-spawn/lib/util/readShebang.js"(exports2, module2) {
101131
101131
  "use strict";
101132
- var fs38 = require("fs");
101132
+ var fs39 = require("fs");
101133
101133
  var shebangCommand = require_shebang_command();
101134
101134
  function readShebang(command) {
101135
101135
  const size = 150;
101136
101136
  const buffer = Buffer.alloc(size);
101137
101137
  let fd;
101138
101138
  try {
101139
- fd = fs38.openSync(command, "r");
101140
- fs38.readSync(fd, buffer, 0, size, 0);
101141
- fs38.closeSync(fd);
101139
+ fd = fs39.openSync(command, "r");
101140
+ fs39.readSync(fd, buffer, 0, size, 0);
101141
+ fs39.closeSync(fd);
101142
101142
  } catch (e2) {
101143
101143
  }
101144
101144
  return shebangCommand(buffer.toString());
@@ -102253,12 +102253,12 @@ function redactSensitive(body) {
102253
102253
  async function checkCredentialsFileSafety(path44, onWarn = (m2) => console.warn(`anthropic-sdk: ${m2}`)) {
102254
102254
  if (typeof process === "undefined" || process.platform === "win32")
102255
102255
  return;
102256
- const fs38 = await import("node:fs");
102256
+ const fs39 = await import("node:fs");
102257
102257
  let resolved = path44;
102258
102258
  let st;
102259
102259
  try {
102260
- resolved = await fs38.promises.realpath(path44);
102261
- st = await fs38.promises.stat(resolved);
102260
+ resolved = await fs39.promises.realpath(path44);
102261
+ st = await fs39.promises.stat(resolved);
102262
102262
  } catch {
102263
102263
  return;
102264
102264
  }
@@ -102274,27 +102274,27 @@ async function checkCredentialsFileSafety(path44, onWarn = (m2) => console.warn(
102274
102274
  }
102275
102275
  }
102276
102276
  async function writeCredentialsFileAtomic(targetPath, data) {
102277
- const fs38 = await import("node:fs");
102277
+ const fs39 = await import("node:fs");
102278
102278
  const path44 = await import("node:path");
102279
102279
  const dir = path44.dirname(targetPath);
102280
- await fs38.promises.mkdir(dir, { recursive: true, mode: 448 });
102280
+ await fs39.promises.mkdir(dir, { recursive: true, mode: 448 });
102281
102281
  const tmpPath = `${targetPath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
102282
102282
  try {
102283
- const fh = await fs38.promises.open(tmpPath, "w", 384);
102283
+ const fh = await fs39.promises.open(tmpPath, "w", 384);
102284
102284
  try {
102285
102285
  await fh.writeFile(JSON.stringify(data, null, 2));
102286
102286
  await fh.sync();
102287
102287
  } finally {
102288
102288
  await fh.close();
102289
102289
  }
102290
- await fs38.promises.rename(tmpPath, targetPath);
102290
+ await fs39.promises.rename(tmpPath, targetPath);
102291
102291
  } catch (err) {
102292
- await fs38.promises.unlink(tmpPath).catch(() => {
102292
+ await fs39.promises.unlink(tmpPath).catch(() => {
102293
102293
  });
102294
102294
  throw err;
102295
102295
  }
102296
102296
  try {
102297
- const dirFh = await fs38.promises.open(dir, "r");
102297
+ const dirFh = await fs39.promises.open(dir, "r");
102298
102298
  try {
102299
102299
  await dirFh.sync();
102300
102300
  } finally {
@@ -102658,12 +102658,12 @@ var init_credentials = __esm({
102658
102658
  return null;
102659
102659
  }
102660
102660
  validateProfileName(profileName);
102661
- const fs38 = await import("node:fs");
102661
+ const fs39 = await import("node:fs");
102662
102662
  const path44 = await import("node:path");
102663
102663
  const configPath = path44.join(rootConfigPath, "configs", `${profileName}.json`);
102664
102664
  let configRaw;
102665
102665
  try {
102666
- configRaw = await fs38.promises.readFile(configPath, "utf-8");
102666
+ configRaw = await fs39.promises.readFile(configPath, "utf-8");
102667
102667
  } catch (err) {
102668
102668
  if (err?.code !== "ENOENT") {
102669
102669
  throw new Error(`failed to read config file ${configPath}: ${err}`);
@@ -102791,11 +102791,11 @@ var init_credentials = __esm({
102791
102791
  if (profileName) {
102792
102792
  return profileName;
102793
102793
  }
102794
- const fs38 = await import("node:fs");
102794
+ const fs39 = await import("node:fs");
102795
102795
  const path44 = await import("node:path");
102796
102796
  const filePath = path44.join(rootConfigPath, "active_config");
102797
102797
  try {
102798
- return (await fs38.promises.readFile(filePath, "utf-8")).trim() || "default";
102798
+ return (await fs39.promises.readFile(filePath, "utf-8")).trim() || "default";
102799
102799
  } catch (err) {
102800
102800
  if (err?.code !== "ENOENT") {
102801
102801
  throw new Error(`failed to read ${filePath}: ${err}`);
@@ -102812,10 +102812,10 @@ function identityTokenFromFile(path44) {
102812
102812
  throw new AnthropicError("Identity token file path is empty");
102813
102813
  }
102814
102814
  return async () => {
102815
- const fs38 = await import("node:fs");
102815
+ const fs39 = await import("node:fs");
102816
102816
  let content;
102817
102817
  try {
102818
- content = await fs38.promises.readFile(path44, "utf-8");
102818
+ content = await fs39.promises.readFile(path44, "utf-8");
102819
102819
  } catch (err) {
102820
102820
  throw new AnthropicError(`Failed to read identity token file at ${path44}: ${err}`);
102821
102821
  }
@@ -102906,11 +102906,11 @@ var init_oidc_federation = __esm({
102906
102906
  // node_modules/@anthropic-ai/sdk/lib/credentials/user-oauth.mjs
102907
102907
  function userOAuthProvider(config2) {
102908
102908
  return async (opts) => {
102909
- const fs38 = await import("node:fs");
102909
+ const fs39 = await import("node:fs");
102910
102910
  await checkCredentialsFileSafety(config2.credentialsPath, config2.onSafetyWarning);
102911
102911
  let raw;
102912
102912
  try {
102913
- raw = await fs38.promises.readFile(config2.credentialsPath, "utf-8");
102913
+ raw = await fs39.promises.readFile(config2.credentialsPath, "utf-8");
102914
102914
  } catch (err) {
102915
102915
  throw new WorkloadIdentityError(`Credentials file not found at ${config2.credentialsPath}: ${err}`);
102916
102916
  }
@@ -103082,11 +103082,11 @@ function resolveIdentityTokenProvider(auth2) {
103082
103082
  }
103083
103083
  function cachedExchangeProvider(exchange, credentialsPath, onCacheWriteError, onSafetyWarning) {
103084
103084
  return async (opts) => {
103085
- const fs38 = await import("node:fs");
103085
+ const fs39 = await import("node:fs");
103086
103086
  await checkCredentialsFileSafety(credentialsPath, onSafetyWarning);
103087
103087
  let existing;
103088
103088
  try {
103089
- const raw = await fs38.promises.readFile(credentialsPath, "utf-8");
103089
+ const raw = await fs39.promises.readFile(credentialsPath, "utf-8");
103090
103090
  existing = JSON.parse(raw);
103091
103091
  const token = existing?.["access_token"];
103092
103092
  if (token && !opts?.forceRefresh) {
@@ -106778,7 +106778,7 @@ var init_promise = __esm({
106778
106778
  // node_modules/@anthropic-ai/sdk/tools/agent-toolset/fs-util.mjs
106779
106779
  async function realpathOrSelf(p) {
106780
106780
  try {
106781
- return await fs15.realpath(p);
106781
+ return await fs16.realpath(p);
106782
106782
  } catch {
106783
106783
  return p;
106784
106784
  }
@@ -106790,18 +106790,18 @@ async function canonicalize(abs) {
106790
106790
  for (; ; ) {
106791
106791
  let real;
106792
106792
  try {
106793
- real = await fs15.realpath(prefix);
106793
+ real = await fs16.realpath(prefix);
106794
106794
  } catch {
106795
106795
  let isLink = false;
106796
106796
  try {
106797
- isLink = (await fs15.lstat(prefix)).isSymbolicLink();
106797
+ isLink = (await fs16.lstat(prefix)).isSymbolicLink();
106798
106798
  } catch {
106799
106799
  }
106800
106800
  if (isLink) {
106801
106801
  if (++hops > 40) {
106802
106802
  throw new ToolError(`path ${JSON.stringify(abs)} has too many levels of symbolic links`);
106803
106803
  }
106804
- prefix = path17.resolve(path17.dirname(prefix), await fs15.readlink(prefix));
106804
+ prefix = path17.resolve(path17.dirname(prefix), await fs16.readlink(prefix));
106805
106805
  continue;
106806
106806
  }
106807
106807
  const parent = path17.dirname(prefix);
@@ -106831,17 +106831,17 @@ async function atomicWriteFile(targetPath, content) {
106831
106831
  const tempPath = path17.join(dir, `.tmp-${process.pid}-${(0, import_node_crypto.randomUUID)()}`);
106832
106832
  let handle;
106833
106833
  try {
106834
- handle = await fs15.open(tempPath, "wx", FILE_CREATE_MODE);
106834
+ handle = await fs16.open(tempPath, "wx", FILE_CREATE_MODE);
106835
106835
  await handle.writeFile(content, "utf-8");
106836
106836
  await handle.sync();
106837
106837
  await handle.close();
106838
106838
  handle = void 0;
106839
- await fs15.rename(tempPath, targetPath);
106839
+ await fs16.rename(tempPath, targetPath);
106840
106840
  } catch (err) {
106841
106841
  if (handle)
106842
106842
  await handle.close().catch(() => {
106843
106843
  });
106844
- await fs15.unlink(tempPath).catch(() => {
106844
+ await fs16.unlink(tempPath).catch(() => {
106845
106845
  });
106846
106846
  throw err;
106847
106847
  }
@@ -106871,10 +106871,10 @@ function fsErrorMessage(err, file2) {
106871
106871
  return `${file2}: ${err instanceof Error ? err.message : String(err)}`;
106872
106872
  }
106873
106873
  }
106874
- var fs15, path17, import_node_crypto, DIR_CREATE_MODE, FILE_CREATE_MODE;
106874
+ var fs16, path17, import_node_crypto, DIR_CREATE_MODE, FILE_CREATE_MODE;
106875
106875
  var init_fs_util = __esm({
106876
106876
  "node_modules/@anthropic-ai/sdk/tools/agent-toolset/fs-util.mjs"() {
106877
- fs15 = __toESM(require("node:fs/promises"), 1);
106877
+ fs16 = __toESM(require("node:fs/promises"), 1);
106878
106878
  path17 = __toESM(require("node:path"), 1);
106879
106879
  import_node_crypto = require("node:crypto");
106880
106880
  init_ToolError();
@@ -106909,8 +106909,8 @@ async function setupSkills(ctx) {
106909
106909
  continue;
106910
106910
  }
106911
106911
  const resp = await client.beta.skills.versions.download(versionId, { skill_id: skill.skill_id });
106912
- await fs16.rm(dest, { recursive: true, force: true });
106913
- await fs16.mkdir(dest, { recursive: true, mode: DIR_CREATE_MODE });
106912
+ await fs17.rm(dest, { recursive: true, force: true });
106913
+ await fs17.mkdir(dest, { recursive: true, mode: DIR_CREATE_MODE });
106914
106914
  created.push(dest);
106915
106915
  await extractSkillArchive(resp, dest);
106916
106916
  log.info("downloaded skill", {
@@ -106929,7 +106929,7 @@ async function setupSkills(ctx) {
106929
106929
  }
106930
106930
  return async () => {
106931
106931
  for (const dest of created) {
106932
- await fs16.rm(dest, { recursive: true, force: true }).catch((e2) => {
106932
+ await fs17.rm(dest, { recursive: true, force: true }).catch((e2) => {
106933
106933
  log.warn("failed to clean up skill", { component: "agent-tool-context", dest, error: String(e2) });
106934
106934
  });
106935
106935
  }
@@ -107010,19 +107010,19 @@ async function extractSkillArchive(resp, dest) {
107010
107010
  assertSafeMemberNames(listing);
107011
107011
  assertNoSpecialMembers(await runArchiveTool(archiveCmd, isZip ? ["-Z", tmp] : ["-tvf", tmp]));
107012
107012
  const top = archiveTopDir(listing);
107013
- await fs16.mkdir(stage, { recursive: true, mode: DIR_CREATE_MODE });
107013
+ await fs17.mkdir(stage, { recursive: true, mode: DIR_CREATE_MODE });
107014
107014
  await runArchiveTool(archiveCmd, isZip ? ["-oq", tmp, "-d", stage] : ["-xf", tmp, "-C", stage]);
107015
107015
  const srcRoot = top ? path18.join(stage, top) : stage;
107016
- for (const entry of await fs16.readdir(srcRoot)) {
107017
- await fs16.rename(path18.join(srcRoot, entry), path18.join(dest, entry));
107016
+ for (const entry of await fs17.readdir(srcRoot)) {
107017
+ await fs17.rename(path18.join(srcRoot, entry), path18.join(dest, entry));
107018
107018
  }
107019
107019
  } finally {
107020
- await fs16.rm(tmp, { force: true });
107021
- await fs16.rm(stage, { recursive: true, force: true });
107020
+ await fs17.rm(tmp, { force: true });
107021
+ await fs17.rm(stage, { recursive: true, force: true });
107022
107022
  }
107023
107023
  }
107024
107024
  async function readHead(file2, n) {
107025
- const handle = await fs16.open(file2, "r");
107025
+ const handle = await fs17.open(file2, "r");
107026
107026
  try {
107027
107027
  const buf = Buffer.alloc(n);
107028
107028
  const { bytesRead } = await handle.read(buf, 0, n, 0);
@@ -107031,10 +107031,10 @@ async function readHead(file2, n) {
107031
107031
  await handle.close();
107032
107032
  }
107033
107033
  }
107034
- var fs16, fssync, path18, import_node_child_process6, import_node_util6, import_node_stream2, import_promises3, execFileAsync5;
107034
+ var fs17, fssync, path18, import_node_child_process6, import_node_util6, import_node_stream2, import_promises3, execFileAsync5;
107035
107035
  var init_skills = __esm({
107036
107036
  "node_modules/@anthropic-ai/sdk/tools/agent-toolset/skills.mjs"() {
107037
- fs16 = __toESM(require("node:fs/promises"), 1);
107037
+ fs17 = __toESM(require("node:fs/promises"), 1);
107038
107038
  fssync = __toESM(require("node:fs"), 1);
107039
107039
  path18 = __toESM(require("node:path"), 1);
107040
107040
  import_node_child_process6 = require("node:child_process");
@@ -107170,7 +107170,7 @@ function betaReadTool(ctx) {
107170
107170
  const abs = await resolvePath(ctx, file_path);
107171
107171
  let data;
107172
107172
  try {
107173
- const st = await fs17.stat(abs);
107173
+ const st = await fs18.stat(abs);
107174
107174
  if (!st.isFile()) {
107175
107175
  throw new ToolError(`read: ${file_path} is not a regular file`);
107176
107176
  }
@@ -107178,7 +107178,7 @@ function betaReadTool(ctx) {
107178
107178
  if (limit3 !== null && st.size > limit3) {
107179
107179
  throw new ToolError(`read: ${file_path} is ${st.size} bytes, exceeds ${limit3}-byte limit. Use bash (head/tail/sed) to read a slice.`);
107180
107180
  }
107181
- data = await fs17.readFile(abs, "utf8");
107181
+ data = await fs18.readFile(abs, "utf8");
107182
107182
  } catch (e2) {
107183
107183
  if (e2 instanceof ToolError)
107184
107184
  throw e2;
@@ -107210,7 +107210,7 @@ function betaWriteTool(ctx) {
107210
107210
  throw new ToolError("write: file_path is required");
107211
107211
  const abs = await resolvePath(ctx, file_path);
107212
107212
  try {
107213
- await fs17.mkdir(path19.dirname(abs), { recursive: true, mode: DIR_CREATE_MODE });
107213
+ await fs18.mkdir(path19.dirname(abs), { recursive: true, mode: DIR_CREATE_MODE });
107214
107214
  await atomicWriteFile(abs, content ?? "");
107215
107215
  } catch (e2) {
107216
107216
  throw new ToolError(`write: ${fsErrorMessage(e2, file_path)}`);
@@ -107241,7 +107241,7 @@ function betaEditTool(ctx) {
107241
107241
  const abs = await resolvePath(ctx, file_path);
107242
107242
  let data;
107243
107243
  try {
107244
- const st = await fs17.stat(abs);
107244
+ const st = await fs18.stat(abs);
107245
107245
  if (!st.isFile()) {
107246
107246
  throw new ToolError(`edit: ${file_path} is not a regular file`);
107247
107247
  }
@@ -107249,7 +107249,7 @@ function betaEditTool(ctx) {
107249
107249
  if (limit3 !== null && st.size > limit3) {
107250
107250
  throw new ToolError(`edit: ${file_path} is ${st.size} bytes, exceeds ${limit3}-byte limit. Use bash (sed/awk) to edit a large file.`);
107251
107251
  }
107252
- data = await fs17.readFile(abs, "utf8");
107252
+ data = await fs18.readFile(abs, "utf8");
107253
107253
  } catch (e2) {
107254
107254
  if (e2 instanceof ToolError)
107255
107255
  throw e2;
@@ -107303,7 +107303,7 @@ function betaGlobTool(ctx) {
107303
107303
  if (!ctx.unrestrictedPaths && pat.split(/[\\/]/).includes("..")) {
107304
107304
  throw new ToolError('glob: ".." is not permitted in the pattern');
107305
107305
  }
107306
- const realRoot = ctx.unrestrictedPaths ? root : await fs17.realpath(root).catch(() => root);
107306
+ const realRoot = ctx.unrestrictedPaths ? root : await fs18.realpath(root).catch(() => root);
107307
107307
  const matches = [];
107308
107308
  try {
107309
107309
  for await (const entry of fsGlob(pat, {
@@ -107317,7 +107317,7 @@ function betaGlobTool(ctx) {
107317
107317
  if (!ctx.unrestrictedPaths) {
107318
107318
  let real;
107319
107319
  try {
107320
- real = await fs17.realpath(full);
107320
+ real = await fs18.realpath(full);
107321
107321
  } catch {
107322
107322
  continue;
107323
107323
  }
@@ -107326,7 +107326,7 @@ function betaGlobTool(ctx) {
107326
107326
  }
107327
107327
  let mtime = 0;
107328
107328
  try {
107329
- mtime = (await fs17.stat(full)).mtimeMs;
107329
+ mtime = (await fs18.stat(full)).mtimeMs;
107330
107330
  } catch {
107331
107331
  }
107332
107332
  matches.push({ path: full, mtime });
@@ -107417,7 +107417,7 @@ async function runWalkGrep(pattern, root, signal) {
107417
107417
  hits.push(line2);
107418
107418
  return true;
107419
107419
  };
107420
- const stat4 = await fs17.stat(root).catch(() => null);
107420
+ const stat4 = await fs18.stat(root).catch(() => null);
107421
107421
  if (stat4?.isFile()) {
107422
107422
  await grepFile(root, re, push);
107423
107423
  } else {
@@ -107460,7 +107460,7 @@ async function walk(root, rel, fn, signal) {
107460
107460
  return false;
107461
107461
  let entries;
107462
107462
  try {
107463
- entries = await fs17.readdir(path19.join(root, rel2), { withFileTypes: true });
107463
+ entries = await fs18.readdir(path19.join(root, rel2), { withFileTypes: true });
107464
107464
  } catch {
107465
107465
  return true;
107466
107466
  }
@@ -107489,18 +107489,18 @@ async function findRg() {
107489
107489
  for (const d of dirs) {
107490
107490
  const candidate = path19.join(d, "rg");
107491
107491
  try {
107492
- await fs17.access(candidate, fssync2.constants.X_OK);
107492
+ await fs18.access(candidate, fssync2.constants.X_OK);
107493
107493
  return candidate;
107494
107494
  } catch {
107495
107495
  }
107496
107496
  }
107497
107497
  return null;
107498
107498
  }
107499
- var fs17, fssync2, path19, cp, crypto8, readline, _BashSession_instances, _BashSession_proc, _BashSession_buf, _BashSession_truncated, _BashSession_closed, _BashSession_waiting, _BashSession_append, BASH_OUTPUT_LIMIT, BASH_DEFAULT_TIMEOUT_MS, DEFAULT_MAX_FILE_BYTES, GREP_OUTPUT_LIMIT, GREP_MAX_LINE_LENGTH, GLOB_RESULT_LIMIT, BashTimeoutError, ANSI_RE, fsGlob, BashSession, WALK_MAX_DEPTH, WALK_MAX_ENTRIES;
107499
+ var fs18, fssync2, path19, cp, crypto8, readline, _BashSession_instances, _BashSession_proc, _BashSession_buf, _BashSession_truncated, _BashSession_closed, _BashSession_waiting, _BashSession_append, BASH_OUTPUT_LIMIT, BASH_DEFAULT_TIMEOUT_MS, DEFAULT_MAX_FILE_BYTES, GREP_OUTPUT_LIMIT, GREP_MAX_LINE_LENGTH, GLOB_RESULT_LIMIT, BashTimeoutError, ANSI_RE, fsGlob, BashSession, WALK_MAX_DEPTH, WALK_MAX_ENTRIES;
107500
107500
  var init_node = __esm({
107501
107501
  "node_modules/@anthropic-ai/sdk/tools/agent-toolset/node.mjs"() {
107502
107502
  init_tslib();
107503
- fs17 = __toESM(require("node:fs/promises"), 1);
107503
+ fs18 = __toESM(require("node:fs/promises"), 1);
107504
107504
  fssync2 = __toESM(require("node:fs"), 1);
107505
107505
  path19 = __toESM(require("node:path"), 1);
107506
107506
  cp = __toESM(require("node:child_process"), 1);
@@ -107526,7 +107526,7 @@ var init_node = __esm({
107526
107526
  }
107527
107527
  };
107528
107528
  ANSI_RE = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
107529
- fsGlob = fs17.glob;
107529
+ fsGlob = fs18.glob;
107530
107530
  BashSession = class {
107531
107531
  constructor(dir, env4 = scrubbedShellEnv()) {
107532
107532
  _BashSession_instances.add(this);
@@ -124447,7 +124447,7 @@ var require_util4 = __commonJS({
124447
124447
  exports2.removeUndefinedValuesInObject = removeUndefinedValuesInObject;
124448
124448
  exports2.isValidFile = isValidFile;
124449
124449
  exports2.getWellKnownCertificateConfigFileLocation = getWellKnownCertificateConfigFileLocation;
124450
- var fs38 = require("fs");
124450
+ var fs39 = require("fs");
124451
124451
  var os4 = require("os");
124452
124452
  var path44 = require("path");
124453
124453
  var WELL_KNOWN_CERTIFICATE_CONFIG_FILE = "certificate_config.json";
@@ -124535,7 +124535,7 @@ var require_util4 = __commonJS({
124535
124535
  }
124536
124536
  async function isValidFile(filePath) {
124537
124537
  try {
124538
- const stats = await fs38.promises.lstat(filePath);
124538
+ const stats = await fs39.promises.lstat(filePath);
124539
124539
  return stats.isFile();
124540
124540
  } catch (e2) {
124541
124541
  return false;
@@ -125947,10 +125947,10 @@ var require_getCredentials = __commonJS({
125947
125947
  Object.defineProperty(exports2, "__esModule", { value: true });
125948
125948
  exports2.getCredentials = getCredentials;
125949
125949
  var path44 = require("path");
125950
- var fs38 = require("fs");
125950
+ var fs39 = require("fs");
125951
125951
  var util_1 = require("util");
125952
125952
  var errorWithCode_1 = require_errorWithCode();
125953
- var readFile4 = fs38.readFile ? (0, util_1.promisify)(fs38.readFile) : async () => {
125953
+ var readFile4 = fs39.readFile ? (0, util_1.promisify)(fs39.readFile) : async () => {
125954
125954
  throw new errorWithCode_1.ErrorWithCode("use key rather than keyFile.", "MISSING_CREDENTIALS");
125955
125955
  };
125956
125956
  var ExtensionFiles;
@@ -127627,12 +127627,12 @@ var require_filesubjecttokensupplier = __commonJS({
127627
127627
  Object.defineProperty(exports2, "__esModule", { value: true });
127628
127628
  exports2.FileSubjectTokenSupplier = void 0;
127629
127629
  var util_1 = require("util");
127630
- var fs38 = require("fs");
127631
- var readFile4 = (0, util_1.promisify)(fs38.readFile ?? (() => {
127630
+ var fs39 = require("fs");
127631
+ var readFile4 = (0, util_1.promisify)(fs39.readFile ?? (() => {
127632
127632
  }));
127633
- var realpath3 = (0, util_1.promisify)(fs38.realpath ?? (() => {
127633
+ var realpath3 = (0, util_1.promisify)(fs39.realpath ?? (() => {
127634
127634
  }));
127635
- var lstat2 = (0, util_1.promisify)(fs38.lstat ?? (() => {
127635
+ var lstat2 = (0, util_1.promisify)(fs39.lstat ?? (() => {
127636
127636
  }));
127637
127637
  var FileSubjectTokenSupplier = class {
127638
127638
  filePath;
@@ -127750,7 +127750,7 @@ var require_certificatesubjecttokensupplier = __commonJS({
127750
127750
  Object.defineProperty(exports2, "__esModule", { value: true });
127751
127751
  exports2.CertificateSubjectTokenSupplier = exports2.InvalidConfigurationError = exports2.CertificateSourceUnavailableError = exports2.CERTIFICATE_CONFIGURATION_ENV_VARIABLE = void 0;
127752
127752
  var util_1 = require_util4();
127753
- var fs38 = require("fs");
127753
+ var fs39 = require("fs");
127754
127754
  var crypto_1 = require("crypto");
127755
127755
  var https5 = require("https");
127756
127756
  exports2.CERTIFICATE_CONFIGURATION_ENV_VARIABLE = "GOOGLE_API_CERTIFICATE_CONFIG";
@@ -127844,7 +127844,7 @@ var require_certificatesubjecttokensupplier = __commonJS({
127844
127844
  const configPath = this.certificateConfigPath;
127845
127845
  let fileContents;
127846
127846
  try {
127847
- fileContents = await fs38.promises.readFile(configPath, "utf8");
127847
+ fileContents = await fs39.promises.readFile(configPath, "utf8");
127848
127848
  } catch (err) {
127849
127849
  throw new CertificateSourceUnavailableError(`Failed to read certificate config file at: ${configPath}`);
127850
127850
  }
@@ -127869,14 +127869,14 @@ var require_certificatesubjecttokensupplier = __commonJS({
127869
127869
  async #getKeyAndCert(certPath, keyPath) {
127870
127870
  let cert, key;
127871
127871
  try {
127872
- cert = await fs38.promises.readFile(certPath);
127872
+ cert = await fs39.promises.readFile(certPath);
127873
127873
  new crypto_1.X509Certificate(cert);
127874
127874
  } catch (err) {
127875
127875
  const message = err instanceof Error ? err.message : String(err);
127876
127876
  throw new CertificateSourceUnavailableError(`Failed to read certificate file at ${certPath}: ${message}`);
127877
127877
  }
127878
127878
  try {
127879
- key = await fs38.promises.readFile(keyPath);
127879
+ key = await fs39.promises.readFile(keyPath);
127880
127880
  (0, crypto_1.createPrivateKey)(key);
127881
127881
  } catch (err) {
127882
127882
  const message = err instanceof Error ? err.message : String(err);
@@ -127895,7 +127895,7 @@ var require_certificatesubjecttokensupplier = __commonJS({
127895
127895
  return JSON.stringify([leafCert.raw.toString("base64")]);
127896
127896
  }
127897
127897
  try {
127898
- const chainPems = await fs38.promises.readFile(this.trustChainPath, "utf8");
127898
+ const chainPems = await fs39.promises.readFile(this.trustChainPath, "utf8");
127899
127899
  const pemBlocks = chainPems.match(/-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----/g) ?? [];
127900
127900
  const chainCerts = pemBlocks.map((pem, index) => {
127901
127901
  try {
@@ -128597,7 +128597,7 @@ var require_pluggable_auth_handler = __commonJS({
128597
128597
  exports2.PluggableAuthHandler = exports2.ExecutableError = void 0;
128598
128598
  var executable_response_1 = require_executable_response();
128599
128599
  var childProcess2 = require("child_process");
128600
- var fs38 = require("fs");
128600
+ var fs39 = require("fs");
128601
128601
  var ExecutableError = class extends Error {
128602
128602
  /**
128603
128603
  * The exit code returned by the executable.
@@ -128682,14 +128682,14 @@ var require_pluggable_auth_handler = __commonJS({
128682
128682
  }
128683
128683
  let filePath;
128684
128684
  try {
128685
- filePath = await fs38.promises.realpath(this.outputFile);
128685
+ filePath = await fs39.promises.realpath(this.outputFile);
128686
128686
  } catch {
128687
128687
  return void 0;
128688
128688
  }
128689
- if (!(await fs38.promises.lstat(filePath)).isFile()) {
128689
+ if (!(await fs39.promises.lstat(filePath)).isFile()) {
128690
128690
  return void 0;
128691
128691
  }
128692
- const responseString = await fs38.promises.readFile(filePath, {
128692
+ const responseString = await fs39.promises.readFile(filePath, {
128693
128693
  encoding: "utf8"
128694
128694
  });
128695
128695
  if (responseString === "") {
@@ -129100,7 +129100,7 @@ var require_gdchclient = __commonJS({
129100
129100
  Object.defineProperty(exports2, "__esModule", { value: true });
129101
129101
  exports2.GdchClient = exports2.GDCH_SERVICE_ACCOUNT_TYPE = void 0;
129102
129102
  var crypto13 = require("crypto");
129103
- var fs38 = require("fs");
129103
+ var fs39 = require("fs");
129104
129104
  var https5 = require("https");
129105
129105
  var oauth2client_1 = require_oauth2client();
129106
129106
  var DEFAULT_LIFETIME_IN_SECONDS = 3600;
@@ -129323,7 +129323,7 @@ var require_gdchclient = __commonJS({
129323
129323
  const currentPath = this.caCertPath;
129324
129324
  this.caAgentPromise = (async () => {
129325
129325
  try {
129326
- const ca = await fs38.promises.readFile(currentPath);
129326
+ const ca = await fs39.promises.readFile(currentPath);
129327
129327
  return new https5.Agent({ ca });
129328
129328
  } catch (err) {
129329
129329
  if (this.cachedCaCertPath === currentPath) {
@@ -129383,7 +129383,7 @@ var require_googleauth = __commonJS({
129383
129383
  Object.defineProperty(exports2, "__esModule", { value: true });
129384
129384
  exports2.GoogleAuth = exports2.GoogleAuthExceptionMessages = void 0;
129385
129385
  var child_process_1 = require("child_process");
129386
- var fs38 = require("fs");
129386
+ var fs39 = require("fs");
129387
129387
  var gaxios_1 = require_src2();
129388
129388
  var gcpMetadata = require_src4();
129389
129389
  var os4 = require("os");
@@ -129685,7 +129685,7 @@ var require_googleauth = __commonJS({
129685
129685
  return null;
129686
129686
  }
129687
129687
  const location = path44.join(configDir, "application_default_credentials.json");
129688
- if (!fs38.existsSync(location)) {
129688
+ if (!fs39.existsSync(location)) {
129689
129689
  return null;
129690
129690
  }
129691
129691
  const client = await this._getApplicationCredentialsFromFilePath(location, options);
@@ -129702,8 +129702,8 @@ var require_googleauth = __commonJS({
129702
129702
  throw new Error("The file path is invalid.");
129703
129703
  }
129704
129704
  try {
129705
- filePath = fs38.realpathSync(filePath);
129706
- if (!fs38.lstatSync(filePath).isFile()) {
129705
+ filePath = fs39.realpathSync(filePath);
129706
+ if (!fs39.lstatSync(filePath).isFile()) {
129707
129707
  throw new Error();
129708
129708
  }
129709
129709
  } catch (err) {
@@ -129712,7 +129712,7 @@ var require_googleauth = __commonJS({
129712
129712
  }
129713
129713
  throw err;
129714
129714
  }
129715
- const readStream2 = fs38.createReadStream(filePath);
129715
+ const readStream2 = fs39.createReadStream(filePath);
129716
129716
  return this.fromStream(readStream2, options);
129717
129717
  }
129718
129718
  /**
@@ -130040,7 +130040,7 @@ var require_googleauth = __commonJS({
130040
130040
  return this._cacheClientFromJSON(this.jsonContent, this.clientOptions);
130041
130041
  } else if (this.keyFilename) {
130042
130042
  const filePath = path44.resolve(this.keyFilename);
130043
- const stream4 = fs38.createReadStream(filePath);
130043
+ const stream4 = fs39.createReadStream(filePath);
130044
130044
  return await this.fromStreamAsync(stream4, this.clientOptions);
130045
130045
  } else if (this.apiKey) {
130046
130046
  const client = await this.fromAPIKey(this.apiKey, this.clientOptions);
@@ -144718,7 +144718,7 @@ function isPlainObject$1(value) {
144718
144718
  return false;
144719
144719
  }
144720
144720
  }
144721
- function formEncoder(sep11) {
144721
+ function formEncoder(sep10) {
144722
144722
  return (key, value, options) => {
144723
144723
  let out = "";
144724
144724
  const pairs = (options === null || options === void 0 ? void 0 : options.explode) ? explode(key, value) : [[key, value]];
@@ -144729,7 +144729,7 @@ function formEncoder(sep11) {
144729
144729
  return (options === null || options === void 0 ? void 0 : options.charEncoding) === "percent" ? encodeURIComponent(v) : v;
144730
144730
  };
144731
144731
  const encodeValue = (v) => encodeString(serializeValue(v));
144732
- const encodedSep = encodeString(sep11);
144732
+ const encodedSep = encodeString(sep10);
144733
144733
  pairs.forEach(([pk, pv]) => {
144734
144734
  var _a6, _b;
144735
144735
  let tmp = "";
@@ -149279,13 +149279,13 @@ function getApiKeyFromEnv() {
149279
149279
  }
149280
149280
  return envGoogleApiKey || envGeminiApiKey || void 0;
149281
149281
  }
149282
- var import_p_retry, import_google_auth_library, import_fs, fs19, import_promises4, import_node_stream5, import_promises5, path20, _defaultBaseGeminiUrl, _defaultBaseVertexUrl, BaseModule, Outcome, Language, FunctionResponseScheduling, Type, AuthType, HttpElementLocation, ApiSpec, Environment, SafetyPolicy, PhishBlockThreshold, Behavior, DynamicRetrievalConfigMode, ThinkingLevel, PersonGeneration, ProminentPeople, HarmCategory, HarmBlockMethod, HarmBlockThreshold, FunctionCallingConfigMode, FinishReason, HarmProbability, HarmSeverity, UrlRetrievalStatus, BlockedReason, TrafficType, MediaModality, ModelStage, MediaResolution, Modality, Delivery, AspectRatio, ImageSize, TuningMode, AdapterSize, ResponseParseType, MatchOperation, ReinforcementTuningThinkingLevel, JobState, TuningJobState, AggregationMetric, PairwiseChoice, VideoOrientation, TuningSpeed, TuningTask, DocumentState, ServiceTier, PartMediaResolutionLevel, ToolType, ResourceScope, FeatureSelectionPreference, EmbeddingApiType, SafetyFilterLevel, ImagePromptLanguage, MaskReferenceMode, ControlReferenceType, SubjectReferenceType, EditMode, SegmentMode, VideoGenerationReferenceType, VideoGenerationMaskMode, VideoCompressionQuality, ImageResizeMode, TuningMethod, FileState, FileSource, TurnCompleteReason, VadSignalType, VoiceActivityType, StartSensitivity, EndSensitivity, ActivityHandling, TurnCoverage, Scale, MusicGenerationMode, LiveMusicPlaybackControl, ToolResponse, FunctionResponseFileData, FunctionResponseBlob, FunctionResponsePart, FunctionResponse, HttpResponse, GenerateContentResponsePromptFeedback, GenerateContentResponseUsageMetadata, GenerateContentResponse, EmbedContentResponse, GenerateImagesResponse, EditImageResponse, UpscaleImageResponse, RecontextImageResponse, SegmentImageResponse, ListModelsResponse, DeleteModelResponse, AudioResponseFormat, ImageResponseFormat, TextResponseFormat, VideoResponseFormat, ResponseFormat, CountTokensResponse, ComputeTokensResponse, GenerateVideosResponse, GenerateVideosOperation, ReinforcementTuningParseResponseConfig, ReinforcementTuningAutoraterScorerParsedResponseConversionScorer, EvaluateDatasetResponse, ListTuningJobsResponse, CancelTuningJobResponse, ValidateRewardResponse, DeleteCachedContentResponse, ListCachedContentsResponse, ListDocumentsResponse, ListFileSearchStoresResponse, UploadToFileSearchStoreResumableResponse, ImportFileResponse, ImportFileOperation, ListFilesResponse, CreateFileResponse, DeleteFileResponse, RegisterFilesResponse, InlinedResponse, SingleEmbedContentResponse, InlinedEmbedContentResponse, ListBatchJobsResponse, ReplayResponse, RawReferenceImage, MaskReferenceImage, ControlReferenceImage, StyleReferenceImage, SubjectReferenceImage, ContentReferenceImage, LiveServerMessage, LiveClientToolResponse, LiveSendToolResponseParameters, LiveMusicServerMessage, UploadToFileSearchStoreResponse, UploadToFileSearchStoreOperation, PagedItem, Pager, Batches3, Caches, Chats, Chat, ApiError, Files2, CONTENT_TYPE_HEADER, SERVER_TIMEOUT_HEADER, USER_AGENT_HEADER, GOOGLE_API_CLIENT_HEADER, SDK_VERSION, LIBRARY_LABEL, VERTEX_AI_API_DEFAULT_VERSION, GOOGLE_AI_API_DEFAULT_VERSION, MULTI_REGIONAL_LOCATIONS, DEFAULT_RETRY_ATTEMPTS, DEFAULT_RETRY_INITIAL_DELAY, DEFAULT_RETRY_MAX_DELAY, DEFAULT_RETRY_EXP_BASE, DEFAULT_RETRY_JITTER, DEFAULT_RETRY_HTTP_STATUS_CODES, ApiClient, MCP_LABEL, hasMcpToolUsageFromMcpToTool, McpCallableTool, LiveMusic, LiveMusicSession, FUNCTION_RESPONSE_REQUIRES_ID, Live, defaultLiveSendClientContentParamerters, Session, DEFAULT_MAX_REMOTE_CALLS, Models3, Operations, Tokens, Documents, FileSearchStores, envMemo, GoogleGenAISecurityProvider, GoogleGenAIAuthHook, HTTPClientError, UnexpectedClientError, InvalidRequestError2, RequestAbortedError, RequestTimeoutError, ConnectionError, GoogleGenAiError, GeminiNextGenAPIClientError, APIError2, APIUserAbortError2, APIConnectionError2, APIConnectionTimeoutError2, BadRequestError2, AuthenticationError2, PermissionDeniedError2, NotFoundError2, ConflictError2, UnprocessableEntityError2, RateLimitError2, InternalServerError2, SDKHooks, hasOwn2, ServerList, SDK_METADATA, encodeForm, encodeSimple, encodeFormQuery, DEFAULT_FETCHER, HTTPClient, mediaParamSeparator, codeRangeRE$1, defaultBackoff, PermanentError, TemporaryError, codeRangeRE, gt, webWorkerLike, isBrowserLike, ClientSDK, jsonLikeContentTypeRE, jsonlLikeContentTypeRE, GoogleGenAiDefaultError, Stream4, CR3, LF3, BOUNDARIES, MAX_BOUNDARY_LEN, DEFAULT_CONTENT_TYPES, headerValRE, SecurityErrorCode, SecurityError, _a3, APIPromise2, Agents2, Environments2, CancelInteractionByIdServerError, CancelInteractionByIdClientError, CreateInteractionServerError, CreateInteractionClientError, DeleteInteractionServerError, DeleteInteractionClientError, GetInteractionByIdServerError, GetInteractionByIdClientError, Interactions, Triggers, Webhooks2, GoogleGenAI$1, LEGACY_LYRIA_MODELS, GeminiNextGenInteractions, GeminiNextGenAgents, GeminiNextGenWebhooks, GeminiNextGenTriggers, GeminiNextGenEnvironments, GOOGLE_API_KEY_HEADER, REQUIRED_VERTEX_AI_SCOPE, NodeAuth, NodeDownloader, NodeWebSocketFactory, NodeWebSocket, Tunings, MAX_CHUNK_SIZE, MAX_RETRY_COUNT, INITIAL_RETRY_DELAY_MS, DELAY_MULTIPLIER, X_GOOG_UPLOAD_STATUS_HEADER_FIELD, NodeUploader, NodeFiles, LANGUAGE_LABEL_PREFIX, GoogleGenAI2;
149282
+ var import_p_retry, import_google_auth_library, import_fs, fs20, import_promises4, import_node_stream5, import_promises5, path20, _defaultBaseGeminiUrl, _defaultBaseVertexUrl, BaseModule, Outcome, Language, FunctionResponseScheduling, Type, AuthType, HttpElementLocation, ApiSpec, Environment, SafetyPolicy, PhishBlockThreshold, Behavior, DynamicRetrievalConfigMode, ThinkingLevel, PersonGeneration, ProminentPeople, HarmCategory, HarmBlockMethod, HarmBlockThreshold, FunctionCallingConfigMode, FinishReason, HarmProbability, HarmSeverity, UrlRetrievalStatus, BlockedReason, TrafficType, MediaModality, ModelStage, MediaResolution, Modality, Delivery, AspectRatio, ImageSize, TuningMode, AdapterSize, ResponseParseType, MatchOperation, ReinforcementTuningThinkingLevel, JobState, TuningJobState, AggregationMetric, PairwiseChoice, VideoOrientation, TuningSpeed, TuningTask, DocumentState, ServiceTier, PartMediaResolutionLevel, ToolType, ResourceScope, FeatureSelectionPreference, EmbeddingApiType, SafetyFilterLevel, ImagePromptLanguage, MaskReferenceMode, ControlReferenceType, SubjectReferenceType, EditMode, SegmentMode, VideoGenerationReferenceType, VideoGenerationMaskMode, VideoCompressionQuality, ImageResizeMode, TuningMethod, FileState, FileSource, TurnCompleteReason, VadSignalType, VoiceActivityType, StartSensitivity, EndSensitivity, ActivityHandling, TurnCoverage, Scale, MusicGenerationMode, LiveMusicPlaybackControl, ToolResponse, FunctionResponseFileData, FunctionResponseBlob, FunctionResponsePart, FunctionResponse, HttpResponse, GenerateContentResponsePromptFeedback, GenerateContentResponseUsageMetadata, GenerateContentResponse, EmbedContentResponse, GenerateImagesResponse, EditImageResponse, UpscaleImageResponse, RecontextImageResponse, SegmentImageResponse, ListModelsResponse, DeleteModelResponse, AudioResponseFormat, ImageResponseFormat, TextResponseFormat, VideoResponseFormat, ResponseFormat, CountTokensResponse, ComputeTokensResponse, GenerateVideosResponse, GenerateVideosOperation, ReinforcementTuningParseResponseConfig, ReinforcementTuningAutoraterScorerParsedResponseConversionScorer, EvaluateDatasetResponse, ListTuningJobsResponse, CancelTuningJobResponse, ValidateRewardResponse, DeleteCachedContentResponse, ListCachedContentsResponse, ListDocumentsResponse, ListFileSearchStoresResponse, UploadToFileSearchStoreResumableResponse, ImportFileResponse, ImportFileOperation, ListFilesResponse, CreateFileResponse, DeleteFileResponse, RegisterFilesResponse, InlinedResponse, SingleEmbedContentResponse, InlinedEmbedContentResponse, ListBatchJobsResponse, ReplayResponse, RawReferenceImage, MaskReferenceImage, ControlReferenceImage, StyleReferenceImage, SubjectReferenceImage, ContentReferenceImage, LiveServerMessage, LiveClientToolResponse, LiveSendToolResponseParameters, LiveMusicServerMessage, UploadToFileSearchStoreResponse, UploadToFileSearchStoreOperation, PagedItem, Pager, Batches3, Caches, Chats, Chat, ApiError, Files2, CONTENT_TYPE_HEADER, SERVER_TIMEOUT_HEADER, USER_AGENT_HEADER, GOOGLE_API_CLIENT_HEADER, SDK_VERSION, LIBRARY_LABEL, VERTEX_AI_API_DEFAULT_VERSION, GOOGLE_AI_API_DEFAULT_VERSION, MULTI_REGIONAL_LOCATIONS, DEFAULT_RETRY_ATTEMPTS, DEFAULT_RETRY_INITIAL_DELAY, DEFAULT_RETRY_MAX_DELAY, DEFAULT_RETRY_EXP_BASE, DEFAULT_RETRY_JITTER, DEFAULT_RETRY_HTTP_STATUS_CODES, ApiClient, MCP_LABEL, hasMcpToolUsageFromMcpToTool, McpCallableTool, LiveMusic, LiveMusicSession, FUNCTION_RESPONSE_REQUIRES_ID, Live, defaultLiveSendClientContentParamerters, Session, DEFAULT_MAX_REMOTE_CALLS, Models3, Operations, Tokens, Documents, FileSearchStores, envMemo, GoogleGenAISecurityProvider, GoogleGenAIAuthHook, HTTPClientError, UnexpectedClientError, InvalidRequestError2, RequestAbortedError, RequestTimeoutError, ConnectionError, GoogleGenAiError, GeminiNextGenAPIClientError, APIError2, APIUserAbortError2, APIConnectionError2, APIConnectionTimeoutError2, BadRequestError2, AuthenticationError2, PermissionDeniedError2, NotFoundError2, ConflictError2, UnprocessableEntityError2, RateLimitError2, InternalServerError2, SDKHooks, hasOwn2, ServerList, SDK_METADATA, encodeForm, encodeSimple, encodeFormQuery, DEFAULT_FETCHER, HTTPClient, mediaParamSeparator, codeRangeRE$1, defaultBackoff, PermanentError, TemporaryError, codeRangeRE, gt, webWorkerLike, isBrowserLike, ClientSDK, jsonLikeContentTypeRE, jsonlLikeContentTypeRE, GoogleGenAiDefaultError, Stream4, CR3, LF3, BOUNDARIES, MAX_BOUNDARY_LEN, DEFAULT_CONTENT_TYPES, headerValRE, SecurityErrorCode, SecurityError, _a3, APIPromise2, Agents2, Environments2, CancelInteractionByIdServerError, CancelInteractionByIdClientError, CreateInteractionServerError, CreateInteractionClientError, DeleteInteractionServerError, DeleteInteractionClientError, GetInteractionByIdServerError, GetInteractionByIdClientError, Interactions, Triggers, Webhooks2, GoogleGenAI$1, LEGACY_LYRIA_MODELS, GeminiNextGenInteractions, GeminiNextGenAgents, GeminiNextGenWebhooks, GeminiNextGenTriggers, GeminiNextGenEnvironments, GOOGLE_API_KEY_HEADER, REQUIRED_VERTEX_AI_SCOPE, NodeAuth, NodeDownloader, NodeWebSocketFactory, NodeWebSocket, Tunings, MAX_CHUNK_SIZE, MAX_RETRY_COUNT, INITIAL_RETRY_DELAY_MS, DELAY_MULTIPLIER, X_GOOG_UPLOAD_STATUS_HEADER_FIELD, NodeUploader, NodeFiles, LANGUAGE_LABEL_PREFIX, GoogleGenAI2;
149283
149283
  var init_node2 = __esm({
149284
149284
  "node_modules/@google/genai/dist/node/index.mjs"() {
149285
149285
  import_p_retry = __toESM(require_p_retry(), 1);
149286
149286
  import_google_auth_library = __toESM(require_src5(), 1);
149287
149287
  import_fs = require("fs");
149288
- fs19 = __toESM(require("fs/promises"), 1);
149288
+ fs20 = __toESM(require("fs/promises"), 1);
149289
149289
  import_promises4 = require("fs/promises");
149290
149290
  import_node_stream5 = require("node:stream");
149291
149291
  import_promises5 = require("node:stream/promises");
@@ -156581,7 +156581,7 @@ var init_node2 = __esm({
156581
156581
  async stat(file2) {
156582
156582
  const fileStat = { size: 0, type: void 0 };
156583
156583
  if (typeof file2 === "string") {
156584
- const originalStat = await fs19.stat(file2);
156584
+ const originalStat = await fs20.stat(file2);
156585
156585
  fileStat.size = originalStat.size;
156586
156586
  fileStat.type = this.inferMimeType(file2);
156587
156587
  return fileStat;
@@ -156729,7 +156729,7 @@ var init_node2 = __esm({
156729
156729
  let fileHandle;
156730
156730
  const fileName = path20.basename(file2);
156731
156731
  try {
156732
- fileHandle = await fs19.open(file2, "r");
156732
+ fileHandle = await fs20.open(file2, "r");
156733
156733
  if (!fileHandle) {
156734
156734
  throw new Error(`Failed to open file`);
156735
156735
  }
@@ -157476,7 +157476,7 @@ var init_source = __esm({
157476
157476
  });
157477
157477
 
157478
157478
  // src/cli.ts
157479
- var fs37 = __toESM(require("fs"));
157479
+ var fs38 = __toESM(require("fs"));
157480
157480
  var fsPromises = __toESM(require("fs/promises"));
157481
157481
  var path43 = __toESM(require("path"));
157482
157482
 
@@ -158939,6 +158939,7 @@ function parseNornAgentFile(content, sourcePath) {
158939
158939
  const models = /* @__PURE__ */ new Map();
158940
158940
  const mcpServers = /* @__PURE__ */ new Map();
158941
158941
  const knowledgeBases = /* @__PURE__ */ new Map();
158942
+ const databases = /* @__PURE__ */ new Map();
158942
158943
  const agents = [];
158943
158944
  const errors = [];
158944
158945
  const agentNames = /* @__PURE__ */ new Map();
@@ -158946,8 +158947,10 @@ function parseNornAgentFile(content, sourcePath) {
158946
158947
  let pendingModel;
158947
158948
  let pendingMcp;
158948
158949
  let pendingKnowledge;
158950
+ let pendingDatabase;
158949
158951
  let sawAgent = false;
158950
158952
  let sawMcpDeclaration = false;
158953
+ let sawDatabaseDeclaration = false;
158951
158954
  const reportBareMcpAlias = (mcp) => {
158952
158955
  errors.push(parseError(
158953
158956
  mcp.lineNumber,
@@ -159102,6 +159105,36 @@ end mcp
159102
159105
  sourcePath
159103
159106
  });
159104
159107
  };
159108
+ const finishDatabase = (lineNumber) => {
159109
+ if (!pendingDatabase) {
159110
+ errors.push(parseError(lineNumber, "Unexpected 'end database' without a matching database block.", "agent-database-end-unexpected"));
159111
+ return;
159112
+ }
159113
+ const database = pendingDatabase;
159114
+ pendingDatabase = void 0;
159115
+ for (const required2 of ["adapter", "connectionString"]) {
159116
+ if (!database.values[required2]) {
159117
+ errors.push(parseError(database.lineNumber, `Database '${database.alias}' requires ${required2}.`, `agent-database-${required2}-missing`));
159118
+ database.invalid = true;
159119
+ }
159120
+ }
159121
+ const access2 = database.values.access?.value.toLowerCase() ?? "read";
159122
+ if (access2 !== "read" && access2 !== "full") {
159123
+ errors.push(parseError(database.values.access.lineNumber, `Database '${database.alias}' access must be read or full.`, "agent-database-access-invalid"));
159124
+ database.invalid = true;
159125
+ }
159126
+ if (!database.invalid) {
159127
+ databases.set(database.alias.toLowerCase(), {
159128
+ alias: database.alias,
159129
+ adapter: database.values.adapter.value,
159130
+ connectionStringTemplate: database.values.connectionString.value,
159131
+ access: access2,
159132
+ lineNumber: database.lineNumber,
159133
+ endLineNumber: lineNumber,
159134
+ sourcePath
159135
+ });
159136
+ }
159137
+ };
159105
159138
  const finishModel = (lineNumber) => {
159106
159139
  if (!pendingModel) {
159107
159140
  errors.push(parseError(lineNumber, "Unexpected 'end model' without a matching model block.", "agent-model-end-unexpected"));
@@ -159236,8 +159269,10 @@ end mcp
159236
159269
  ...pending.grantedMcpServers.length > 0 ? { grantedMcpServers: pending.grantedMcpServers } : {},
159237
159270
  callableAgents: pending.callableAgents,
159238
159271
  ...pending.knowledge.length > 0 ? { knowledge: pending.knowledge } : {},
159272
+ ...pending.databases.length > 0 ? { grantedDatabases: pending.databases } : {},
159239
159273
  mcpServers,
159240
159274
  knowledgeBases,
159275
+ databases,
159241
159276
  accepts: pending.accepts,
159242
159277
  returns: pending.returns,
159243
159278
  maxTokens: pending.maxTokens?.value,
@@ -159258,6 +159293,44 @@ end mcp
159258
159293
  const rawLine = lines[index];
159259
159294
  const withoutComment = stripInlineComment(rawLine);
159260
159295
  const trimmed = withoutComment.trim();
159296
+ if (pendingDatabase) {
159297
+ if (!trimmed) {
159298
+ continue;
159299
+ }
159300
+ if (/^end\s+database$/i.test(trimmed)) {
159301
+ finishDatabase(index);
159302
+ continue;
159303
+ }
159304
+ const directive = trimmed.match(/^(adapter|connectionString|access)\s+(.+)$/i);
159305
+ if (directive) {
159306
+ const key = ["adapter", "connectionString", "access"].find((value) => value.toLowerCase() === directive[1].toLowerCase());
159307
+ if (pendingDatabase.values[key]) {
159308
+ errors.push(parseError(index, `Database '${pendingDatabase.alias}' declares ${key} more than once.`, "agent-database-directive-duplicate"));
159309
+ pendingDatabase.invalid = true;
159310
+ } else {
159311
+ pendingDatabase.values[key] = { value: normalizeDirectiveValue(directive[2]), lineNumber: index };
159312
+ }
159313
+ continue;
159314
+ }
159315
+ if (/^command\b/i.test(trimmed)) {
159316
+ errors.push(parseError(
159317
+ index,
159318
+ `Database '${pendingDatabase.alias}' uses a script path in adapter; remove command and set adapter to ./path/to/adapter.js.`,
159319
+ "agent-database-command-removed"
159320
+ ));
159321
+ pendingDatabase.invalid = true;
159322
+ continue;
159323
+ }
159324
+ if (/^(agent|model|mcp|knowledge|database)\b/i.test(trimmed)) {
159325
+ errors.push(parseError(pendingDatabase.lineNumber, `Database '${pendingDatabase.alias}' is missing 'end database'.`, "agent-database-end-missing"));
159326
+ pendingDatabase = void 0;
159327
+ index--;
159328
+ continue;
159329
+ }
159330
+ errors.push(parseError(index, `Unknown directive in database '${pendingDatabase.alias}': '${trimmed}'.`, "agent-database-directive-unknown"));
159331
+ pendingDatabase.invalid = true;
159332
+ continue;
159333
+ }
159261
159334
  if (pendingKnowledge) {
159262
159335
  if (!trimmed) {
159263
159336
  continue;
@@ -159310,7 +159383,7 @@ end mcp
159310
159383
  }
159311
159384
  continue;
159312
159385
  }
159313
- if (/^(agent|model|mcp|knowledge)\b/i.test(trimmed)) {
159386
+ if (/^(agent|model|mcp|knowledge|database)\b/i.test(trimmed)) {
159314
159387
  errors.push(parseError(
159315
159388
  pendingKnowledge.lineNumber,
159316
159389
  `Knowledge '${pendingKnowledge.alias}' is missing 'end knowledge'.`,
@@ -159408,7 +159481,7 @@ end mcp
159408
159481
  }
159409
159482
  if (/^mcp\b/i.test(trimmed)) {
159410
159483
  errors.push(parseError(index, `Nested mcp blocks are not allowed (inside '${pendingMcp.alias}').`, "agent-mcp-nested"));
159411
- } else if (/^(agent|model|knowledge)\b/i.test(trimmed)) {
159484
+ } else if (/^(agent|model|knowledge|database)\b/i.test(trimmed)) {
159412
159485
  errors.push(parseError(pendingMcp.lineNumber, `MCP server '${pendingMcp.alias}' is missing 'end mcp'.`, "agent-mcp-unterminated"));
159413
159486
  pendingMcp = void 0;
159414
159487
  index--;
@@ -159459,7 +159532,7 @@ end mcp
159459
159532
  }
159460
159533
  if (/^model\b/i.test(trimmed)) {
159461
159534
  errors.push(parseError(index, `Nested model blocks are not allowed (inside '${pendingModel.alias}').`, "agent-model-nested"));
159462
- } else if (/^(agent|knowledge)\b/i.test(trimmed)) {
159535
+ } else if (/^(agent|knowledge|database|mcp)\b/i.test(trimmed)) {
159463
159536
  errors.push(parseError(pendingModel.lineNumber, `Model '${pendingModel.alias}' is missing 'end model'.`, "agent-model-end-missing"));
159464
159537
  pendingModel = void 0;
159465
159538
  index--;
@@ -159568,6 +159641,20 @@ end model`,
159568
159641
  };
159569
159642
  continue;
159570
159643
  }
159644
+ const databaseMatch = trimmed.match(new RegExp(`^database\\s+(${IDENTIFIER})$`, "i"));
159645
+ if (databaseMatch) {
159646
+ sawDatabaseDeclaration = true;
159647
+ const alias = databaseMatch[1];
159648
+ const invalid = sawAgent || databases.has(alias.toLowerCase());
159649
+ if (sawAgent) {
159650
+ errors.push(parseError(index, "Database blocks must be declared before the first agent block.", "agent-database-not-at-top"));
159651
+ }
159652
+ if (databases.has(alias.toLowerCase())) {
159653
+ errors.push(parseError(index, `Duplicate database alias '${alias}'.`, "agent-database-duplicate"));
159654
+ }
159655
+ pendingDatabase = { alias, lineNumber: index, values: {}, invalid };
159656
+ continue;
159657
+ }
159571
159658
  if (/^end\s+mcp$/i.test(trimmed)) {
159572
159659
  finishMcp(index);
159573
159660
  continue;
@@ -159576,6 +159663,10 @@ end model`,
159576
159663
  finishKnowledge(index);
159577
159664
  continue;
159578
159665
  }
159666
+ if (/^end\s+database$/i.test(trimmed)) {
159667
+ finishDatabase(index);
159668
+ continue;
159669
+ }
159579
159670
  const agentMatch = trimmed.match(new RegExp(`^agent\\s+(${IDENTIFIER})$`, "i"));
159580
159671
  if (agentMatch) {
159581
159672
  sawAgent = true;
@@ -159595,6 +159686,7 @@ end model`,
159595
159686
  tools: [],
159596
159687
  grantedMcpServers: [],
159597
159688
  knowledge: [],
159689
+ databases: [],
159598
159690
  callableAgents: [],
159599
159691
  invalid
159600
159692
  };
@@ -159610,6 +159702,8 @@ end model`,
159610
159702
  errors.push(parseError(index, "Malformed MCP declaration. Expected: mcp <Alias>, then transport and its directives, then end mcp.", "agent-mcp-malformed"));
159611
159703
  } else if (/^knowledge\b/i.test(trimmed)) {
159612
159704
  errors.push(parseError(index, "Malformed knowledge declaration. Expected: knowledge <Alias>, then source/exclude directives, then end knowledge.", "agent-knowledge-malformed"));
159705
+ } else if (/^database\b/i.test(trimmed)) {
159706
+ errors.push(parseError(index, "Malformed database declaration. Expected: database <Alias>, then adapter/connectionString/access directives, then end database.", "agent-database-malformed"));
159613
159707
  } else if (/^agent\b/i.test(trimmed)) {
159614
159708
  errors.push(parseError(index, "Malformed agent declaration. Expected: agent <Name>.", "agent-declaration-malformed"));
159615
159709
  } else {
@@ -159683,6 +159777,27 @@ end model`,
159683
159777
  }
159684
159778
  continue;
159685
159779
  }
159780
+ const databaseGrantMatch = trimmed.match(/^database(?:\s+(.*))?$/i);
159781
+ if (databaseGrantMatch) {
159782
+ const aliases = (databaseGrantMatch[1] ?? "").split(",").map((value) => value.trim());
159783
+ if (aliases.some((alias) => !new RegExp(`^${IDENTIFIER}$`).test(alias))) {
159784
+ errors.push(parseError(index, `Invalid database grant '${trimmed}'. Expected: database <Alias>[, <Alias>\u2026].`, "agent-database-grant-invalid"));
159785
+ pending.invalid = true;
159786
+ continue;
159787
+ }
159788
+ for (const alias of aliases) {
159789
+ if (pending.databases.some((grant) => grant.alias.toLowerCase() === alias.toLowerCase())) {
159790
+ errors.push(parseError(index, `Agent '${pending.name}' grants database '${alias}' more than once.`, "agent-database-grant-duplicate"));
159791
+ pending.invalid = true;
159792
+ } else if (!databases.has(alias.toLowerCase())) {
159793
+ errors.push(parseError(index, `Unknown database alias '${alias}' in agent '${pending.name}'.`, "agent-database-alias-unknown"));
159794
+ pending.invalid = true;
159795
+ } else {
159796
+ pending.databases.push({ alias, lineNumber: index });
159797
+ }
159798
+ }
159799
+ continue;
159800
+ }
159686
159801
  const returnsMatch = trimmed.match(/^returns\s+(.+)$/i);
159687
159802
  if (returnsMatch) {
159688
159803
  if (pending.returns) {
@@ -159881,7 +159996,7 @@ end model`,
159881
159996
  errors.push(parseError(index, 'Malformed describe block. Expected: describe "..." (multi-line allowed) or describe file <path>.', "agent-describe-malformed"));
159882
159997
  } else if (/^system\b/i.test(trimmed)) {
159883
159998
  errors.push(parseError(index, 'Malformed system prompt. Expected: system "..." (multi-line allowed) or system file <path>.', "agent-system-malformed"));
159884
- } else if (new RegExp(`^(accepts|returns|tools|agents|model|knowledge|${Object.keys(LIMIT_DIRECTIVES).join("|")})\\b`, "i").test(trimmed)) {
159999
+ } else if (new RegExp(`^(accepts|returns|tools|agents|model|knowledge|database|${Object.keys(LIMIT_DIRECTIVES).join("|")})\\b`, "i").test(trimmed)) {
159885
160000
  errors.push(parseError(index, `Malformed agent directive: '${trimmed}'.`, "agent-directive-malformed"));
159886
160001
  } else if (/^agent\b/i.test(trimmed)) {
159887
160002
  errors.push(parseError(index, `Nested agent blocks are not allowed (inside '${pending.name}').`, "agent-nested"));
@@ -159910,10 +160025,13 @@ end model`,
159910
160025
  "agent-knowledge-end-missing"
159911
160026
  ));
159912
160027
  }
159913
- if (!sawMcpDeclaration && models.size === 0) {
160028
+ if (pendingDatabase) {
160029
+ errors.push(parseError(pendingDatabase.lineNumber, `Database '${pendingDatabase.alias}' is missing 'end database'.`, "agent-database-end-missing"));
160030
+ }
160031
+ if (!sawMcpDeclaration && !sawDatabaseDeclaration && models.size === 0) {
159914
160032
  errors.push(parseError(0, "An agent sidecar must declare at least one model block.", "agent-model-required"));
159915
160033
  }
159916
- if (!sawMcpDeclaration && agentNames.size === 0) {
160034
+ if (!sawMcpDeclaration && !sawDatabaseDeclaration && agentNames.size === 0) {
159917
160035
  errors.push(parseError(0, "An agent sidecar must declare at least one agent.", "agent-required"));
159918
160036
  }
159919
160037
  const localScope = new Map(agents.map((agent) => [agent.name.toLowerCase(), agent]));
@@ -159921,7 +160039,7 @@ end model`,
159921
160039
  const { sourcePath: _sourcePath, ...parseValidationError } = validationError;
159922
160040
  errors.push(parseValidationError);
159923
160041
  }
159924
- return { sourcePath, models, mcpServers, knowledgeBases, agents, errors };
160042
+ return { sourcePath, models, mcpServers, knowledgeBases, databases, agents, errors };
159925
160043
  }
159926
160044
 
159927
160045
  // src/nornConfig.ts
@@ -160107,7 +160225,7 @@ function isNornProjectConfig(value) {
160107
160225
  if (value.version !== 1) {
160108
160226
  return false;
160109
160227
  }
160110
- return isNornHttpConfig(value.http) && isKnownSection(value.sql) && isKnownSection(value.mcp) && isNornContractsConfig(value.contracts) && isNornAgentsConfig(value.agents) && isNornKnowledgeConfig(value.knowledge);
160228
+ return value.sql === void 0 && isNornHttpConfig(value.http) && isKnownSection(value.mcp) && isNornContractsConfig(value.contracts) && isNornAgentsConfig(value.agents) && isNornKnowledgeConfig(value.knowledge);
160111
160229
  }
160112
160230
  function loadNornConfig(startPath) {
160113
160231
  const filePath = findNearestConfigFile(startPath, NORN_CONFIG_FILENAME);
@@ -160485,6 +160603,7 @@ async function resolveImports(text, baseDir, readFile4, alreadyImported = /* @__
160485
160603
  const endpointSources = /* @__PURE__ */ new Map();
160486
160604
  const namedRequestSources = /* @__PURE__ */ new Map();
160487
160605
  const sequenceSources = /* @__PURE__ */ new Map();
160606
+ const directDatabases = /* @__PURE__ */ new Map();
160488
160607
  if (!sqlOperationsBySource.has(sourceFilePath)) {
160489
160608
  sqlOperationsBySource.set(sourceFilePath, /* @__PURE__ */ new Map());
160490
160609
  }
@@ -160572,6 +160691,18 @@ async function resolveImports(text, baseDir, readFile4, alreadyImported = /* @__
160572
160691
  blocking: true
160573
160692
  });
160574
160693
  }
160694
+ for (const [alias, database] of parsedAgents.databases) {
160695
+ if (directDatabases.has(alias)) {
160696
+ errors.push({
160697
+ path: imp.path,
160698
+ error: `Database '${database.alias}' is declared by more than one directly imported sidecar.`,
160699
+ lineNumber: imp.lineNumber,
160700
+ blocking: true
160701
+ });
160702
+ } else {
160703
+ directDatabases.set(alias, database);
160704
+ }
160705
+ }
160575
160706
  const mcpScope = mcpServersBySource.get(sourceFilePath);
160576
160707
  for (const [alias, declaration] of parsedAgents.mcpServers) {
160577
160708
  const existing = mcpScope.get(alias);
@@ -160758,6 +160889,9 @@ end sequence`);
160758
160889
  }
160759
160890
  }
160760
160891
  const directAgentScope = agentDefinitionsBySource.get(sourceFilePath);
160892
+ for (const operation of sqlOperationsBySource.get(sourceFilePath).values()) {
160893
+ operation.database = directDatabases.get(operation.connectionName.toLowerCase());
160894
+ }
160761
160895
  const directAgentImportsByPath = new Map(
160762
160896
  imports.filter((imp) => isAgentSidecarPath(imp.path)).map((imp) => [path4.resolve(baseDir, imp.path), imp])
160763
160897
  );
@@ -168223,6 +168357,7 @@ function validatePreparedRequest(parsed, context) {
168223
168357
 
168224
168358
  // src/sqlConfig.ts
168225
168359
  var path9 = __toESM(require("path"));
168360
+ var fs11 = __toESM(require("fs"));
168226
168361
 
168227
168362
  // src/sqlBuiltInAdapters.ts
168228
168363
  var fs10 = __toESM(require("fs"));
@@ -168291,7 +168426,7 @@ function usesWindowsIntegratedSqlServerAuth(connectionString) {
168291
168426
  return /(?:^|;)\s*Integrated\s+Security\s*=\s*(?:true|yes|sspi)\s*(?:;|$)/i.test(connectionString) || /(?:^|;)\s*Trusted_Connection\s*=\s*(?:true|yes|sspi)\s*(?:;|$)/i.test(connectionString);
168292
168427
  }
168293
168428
  function buildMissingConnectionError(adapterLabel, profile) {
168294
- return `Missing required ${adapterLabel} connection string. Expected 'connectionString ${profile} = ...' in .nornenv.`;
168429
+ return `Missing required ${adapterLabel} connection string for database '${profile}'. Declare connectionString in its .nornai database block.`;
168295
168430
  }
168296
168431
  function getBundledSqlClientDirectory() {
168297
168432
  return path8.resolve(__dirname, "..", "vendor", "microsoft.data.sqlclient", "windows-netfx");
@@ -168676,6 +168811,9 @@ async function runBuiltInPostgresAdapter(request) {
168676
168811
  const client = new Client(connectionString);
168677
168812
  try {
168678
168813
  await client.connect();
168814
+ if (request.readOnly) {
168815
+ await client.query("BEGIN READ ONLY");
168816
+ }
168679
168817
  const compiled = compilePostgresSql(request.operation.sql, request.params || {});
168680
168818
  const result = await client.query(compiled.text, compiled.values);
168681
168819
  if (request.mode === "query") {
@@ -168708,7 +168846,7 @@ async function runBuiltInSqlServerAdapter(request) {
168708
168846
  fail(buildMissingConnectionError("SQL Server", request.connection.profile));
168709
168847
  }
168710
168848
  if (usesWindowsIntegratedSqlServerAuth(connectionString)) {
168711
- fail("This SQL Server connection string uses Windows/Integrated authentication. Use adapter 'sqlserver-windows' in norn.config.json sql.connections.");
168849
+ fail("This SQL Server connection string uses Windows/Integrated authentication. Use adapter 'sqlserver-windows' in the .nornai database block.");
168712
168850
  }
168713
168851
  const pool = new mssql.ConnectionPool(connectionString);
168714
168852
  try {
@@ -168768,6 +168906,9 @@ async function runBuiltInSqlServerIntegratedAdapter(request) {
168768
168906
  function isBuiltInSqlAdapter(adapterId) {
168769
168907
  return BUILT_IN_SQL_ADAPTER_MAP.has(adapterId.toLowerCase());
168770
168908
  }
168909
+ function getBuiltInSqlAdapterIds() {
168910
+ return BUILT_IN_SQL_ADAPTERS.map((adapter2) => adapter2.id);
168911
+ }
168771
168912
  async function runBuiltInSqlAdapter(adapterId, request) {
168772
168913
  switch (adapterId.toLowerCase()) {
168773
168914
  case "postgres":
@@ -168782,107 +168923,66 @@ async function runBuiltInSqlAdapter(adapterId, request) {
168782
168923
  }
168783
168924
 
168784
168925
  // src/sqlConfig.ts
168785
- function isConnectionsConfig(value) {
168786
- return isObjectRecord(value) && Object.values(value).every(
168787
- (connection) => isStringRecord(connection) && typeof connection.adapter === "string" && typeof connection.profile === "string"
168788
- );
168789
- }
168790
- function isAdaptersConfig(value) {
168791
- return isObjectRecord(value) && Object.values(value).every((adapter2) => {
168792
- if (!isObjectRecord(adapter2)) {
168793
- return false;
168794
- }
168795
- const command = adapter2.command;
168796
- return Array.isArray(command) && command.length > 0 && command.every((part) => typeof part === "string" && part.length > 0);
168797
- });
168798
- }
168799
- function isSqlConfigSection(value) {
168800
- if (!isObjectRecord(value)) {
168801
- return false;
168802
- }
168803
- if (value.connections !== void 0 && !isConnectionsConfig(value.connections)) {
168804
- return false;
168805
- }
168806
- if (value.adapters !== void 0 && !isAdaptersConfig(value.adapters)) {
168807
- return false;
168808
- }
168809
- return true;
168810
- }
168811
- function loadSqlConfigSection(startPath) {
168812
- const { filePath, section } = loadNornConfigSection(startPath, "sql", isSqlConfigSection);
168813
- return {
168814
- filePath,
168815
- config: section
168816
- };
168817
- }
168818
168926
  function loadNornSqlProjectConfig(startPath) {
168819
- const { filePath, config: config2 } = loadSqlConfigSection(startPath);
168820
- if (!config2.connections) {
168821
- throw new Error(`Could not find sql.connections in ${NORN_CONFIG_FILENAME}`);
168822
- }
168823
- return {
168824
- filePath,
168825
- config: {
168826
- version: 1,
168827
- connections: config2.connections
168927
+ const filePath = path9.resolve(startPath);
168928
+ if (!filePath.endsWith(".norn") || !fs11.existsSync(filePath)) {
168929
+ throw new Error("Database connections are declared in a .nornai file imported by a .norn file.");
168930
+ }
168931
+ const connections = {};
168932
+ const content = fs11.readFileSync(filePath, "utf8");
168933
+ const imports = [...content.matchAll(/^\s*import\s+["']([^"']+)["']/gm)];
168934
+ for (const match2 of imports) {
168935
+ if (!isAgentSidecarPath(match2[1])) {
168936
+ continue;
168937
+ }
168938
+ const sidecarPath = path9.resolve(path9.dirname(filePath), match2[1]);
168939
+ const parsed = parseNornAgentFile(fs11.readFileSync(sidecarPath, "utf8"), sidecarPath);
168940
+ const databaseErrors = parsed.errors.filter((error2) => error2.code.startsWith("agent-database-"));
168941
+ if (databaseErrors.length) {
168942
+ throw new Error(databaseErrors.map((error2) => `${path9.basename(sidecarPath)}:${error2.lineNumber + 1}: ${error2.message}`).join("\n"));
168943
+ }
168944
+ for (const database of parsed.databases.values()) {
168945
+ if (Object.keys(connections).some((alias) => alias.toLowerCase() === database.alias.toLowerCase())) {
168946
+ throw new Error(`Database '${database.alias}' is declared by more than one imported sidecar.`);
168947
+ }
168948
+ connections[database.alias] = {
168949
+ adapter: database.adapter,
168950
+ profile: database.alias,
168951
+ connectionStringTemplate: database.connectionStringTemplate,
168952
+ sourcePath: database.sourcePath,
168953
+ access: database.access
168954
+ };
168828
168955
  }
168829
- };
168830
- }
168831
- function loadNornSqlAdaptersConfig(startPath) {
168832
- const { filePath, config: config2 } = loadSqlConfigSection(startPath);
168833
- if (!config2.adapters) {
168834
- throw new Error(`Could not find sql.adapters in ${NORN_CONFIG_FILENAME}`);
168835
168956
  }
168836
168957
  return {
168837
168958
  filePath,
168838
168959
  config: {
168839
168960
  version: 1,
168840
- adapters: config2.adapters
168961
+ connections
168841
168962
  }
168842
168963
  };
168843
168964
  }
168844
168965
  function resolveSqlConnection(startPath, alias) {
168845
168966
  const { filePath, config: config2 } = loadNornSqlProjectConfig(startPath);
168846
- const connection = config2.connections[alias];
168967
+ const connection = Object.entries(config2.connections).find(([name]) => name.toLowerCase() === alias.toLowerCase())?.[1];
168847
168968
  if (!connection) {
168848
- throw new Error(`Connection alias '${alias}' was not found in ${NORN_CONFIG_FILENAME} sql.connections`);
168969
+ throw new Error(`Database '${alias}' was not declared in a directly imported .nornai file.`);
168849
168970
  }
168850
168971
  return {
168851
168972
  alias,
168852
168973
  adapter: connection.adapter,
168853
168974
  profile: connection.profile,
168854
- configPath: filePath
168975
+ configPath: filePath,
168976
+ connectionStringTemplate: connection.connectionStringTemplate,
168977
+ sourcePath: connection.sourcePath,
168978
+ access: connection.access
168855
168979
  };
168856
168980
  }
168857
- function resolveCommandParts(configPath, command) {
168858
- const configDir = path9.dirname(configPath);
168859
- return command.map((part, index) => {
168860
- if (!part) {
168861
- return part;
168862
- }
168863
- if (index === 0) {
168864
- if (path9.isAbsolute(part) || !part.startsWith(".") && !part.includes(path9.sep) && !part.includes("/")) {
168865
- return part;
168866
- }
168867
- return path9.resolve(configDir, part);
168868
- }
168869
- if (part.startsWith(".")) {
168870
- return path9.resolve(configDir, part);
168871
- }
168872
- return part;
168873
- });
168874
- }
168875
- function resolveSqlAdapterCommand(startPath, adapterId) {
168876
- const { filePath, config: config2 } = loadNornSqlAdaptersConfig(startPath);
168877
- const adapter2 = config2.adapters[adapterId];
168878
- if (!adapter2) {
168879
- throw new Error(`Adapter '${adapterId}' was not found in ${NORN_CONFIG_FILENAME} sql.adapters`);
168981
+ function customAdapterPath(sourcePath, adapterId) {
168982
+ if (!path9.isAbsolute(adapterId) && !/^\.{1,2}[\\/]/.test(adapterId)) {
168983
+ return void 0;
168880
168984
  }
168881
- return {
168882
- adapterId,
168883
- command: resolveCommandParts(filePath, adapter2.command),
168884
- configPath: filePath
168885
- };
168985
+ return path9.resolve(path9.dirname(sourcePath), adapterId);
168886
168986
  }
168887
168987
  function resolveSqlAdapterTarget(startPath, adapterId) {
168888
168988
  if (isBuiltInSqlAdapter(adapterId)) {
@@ -168891,14 +168991,36 @@ function resolveSqlAdapterTarget(startPath, adapterId) {
168891
168991
  adapterId
168892
168992
  };
168893
168993
  }
168894
- const resolved = resolveSqlAdapterCommand(startPath, adapterId);
168994
+ const validation = validateSqlAdapterReference(startPath, adapterId);
168995
+ if (!validation.ok) {
168996
+ throw new Error(validation.message);
168997
+ }
168998
+ const filePath = customAdapterPath(startPath, adapterId);
168999
+ const extension2 = path9.extname(filePath).toLowerCase();
169000
+ const command = [".js", ".cjs", ".mjs"].includes(extension2) ? [process.execPath, filePath] : [filePath];
168895
169001
  return {
168896
169002
  kind: "custom",
168897
- adapterId: resolved.adapterId,
168898
- command: resolved.command,
168899
- configPath: resolved.configPath
169003
+ adapterId,
169004
+ command,
169005
+ configPath: startPath
168900
169006
  };
168901
169007
  }
169008
+ function validateSqlAdapterReference(startPath, adapterId) {
169009
+ if (isBuiltInSqlAdapter(adapterId)) {
169010
+ return { ok: true, kind: "builtin" };
169011
+ }
169012
+ const filePath = customAdapterPath(startPath, adapterId);
169013
+ if (!filePath) {
169014
+ return { ok: false, message: `Adapter '${adapterId}' is not built in. Use a relative file path such as ./scripts/adapter.js, or ${getBuiltInSqlAdapterIds().join(", ")}.` };
169015
+ }
169016
+ try {
169017
+ if (fs11.statSync(filePath).isFile()) {
169018
+ return { ok: true, kind: "custom" };
169019
+ }
169020
+ } catch {
169021
+ }
169022
+ return { ok: false, message: `Database adapter file '${adapterId}' does not exist relative to '${path9.basename(startPath)}'.` };
169023
+ }
168902
169024
 
168903
169025
  // src/sqlAdapterRunner.ts
168904
169026
  var import_child_process3 = require("child_process");
@@ -169041,8 +169163,262 @@ async function runSqlAdapter(target, request, workingDir, signal) {
169041
169163
  return runExternalSqlAdapter(target.command, request, workingDir, signal);
169042
169164
  }
169043
169165
 
169166
+ // src/environmentTemplates.ts
169167
+ var TEMPLATE_TOKEN_REGEX = /\{\{([^{}]+)\}\}/g;
169168
+ var ENV_REFERENCE_REGEX = /^(?:\$env\.)?([a-zA-Z_][a-zA-Z0-9_]*)$/;
169169
+ var ENV_TEMPLATE_SCOPES_KEY = "$nornEnvTemplateScopes";
169170
+ function attachEnvironmentTemplateScopes(variables, commonVariables, environmentVariables) {
169171
+ Object.defineProperty(variables, ENV_TEMPLATE_SCOPES_KEY, {
169172
+ value: {
169173
+ commonNames: new Set(Object.keys(commonVariables)),
169174
+ environmentNames: new Set(Object.keys(environmentVariables ?? {}))
169175
+ },
169176
+ enumerable: false,
169177
+ configurable: true,
169178
+ writable: false
169179
+ });
169180
+ return variables;
169181
+ }
169182
+ function getEnvironmentTemplateScopes(variables) {
169183
+ const value = variables[ENV_TEMPLATE_SCOPES_KEY];
169184
+ if (!value || typeof value !== "object") {
169185
+ return void 0;
169186
+ }
169187
+ const candidate = value;
169188
+ if (!(candidate.commonNames instanceof Set) || !(candidate.environmentNames instanceof Set)) {
169189
+ return void 0;
169190
+ }
169191
+ return candidate;
169192
+ }
169193
+ function valueToTemplateString(value) {
169194
+ if (value === void 0 || value === null) {
169195
+ return "";
169196
+ }
169197
+ if (typeof value === "object") {
169198
+ return JSON.stringify(value);
169199
+ }
169200
+ return String(value);
169201
+ }
169202
+ function parseTemplateReference(rawReference) {
169203
+ const trimmed = rawReference.trim();
169204
+ const match2 = trimmed.match(ENV_REFERENCE_REGEX);
169205
+ return match2?.[1];
169206
+ }
169207
+ function resolveEnvironmentTemplateValue(variableName, variables, secretNames = /* @__PURE__ */ new Set()) {
169208
+ const resolving = /* @__PURE__ */ new Set();
169209
+ const cache = /* @__PURE__ */ new Map();
169210
+ const scopes = getEnvironmentTemplateScopes(variables);
169211
+ const resolveVariable = (name) => {
169212
+ const cached2 = cache.get(name);
169213
+ if (cached2) {
169214
+ return cached2;
169215
+ }
169216
+ if (resolving.has(name)) {
169217
+ const cycle = [...resolving, name].join(" -> ");
169218
+ return {
169219
+ value: `{{${name}}}`,
169220
+ secret: secretNames.has(name),
169221
+ dependencies: /* @__PURE__ */ new Set([name]),
169222
+ errors: [{
169223
+ kind: "cycle",
169224
+ variableName: name,
169225
+ reference: name,
169226
+ message: `Circular .nornenv template reference detected: ${cycle}`
169227
+ }]
169228
+ };
169229
+ }
169230
+ if (!Object.prototype.hasOwnProperty.call(variables, name)) {
169231
+ return {
169232
+ value: `{{${name}}}`,
169233
+ secret: false,
169234
+ dependencies: /* @__PURE__ */ new Set([name]),
169235
+ errors: [{
169236
+ kind: "unresolved",
169237
+ variableName: name,
169238
+ reference: name,
169239
+ message: `.nornenv template reference '${name}' was not found in the active environment.`
169240
+ }]
169241
+ };
169242
+ }
169243
+ resolving.add(name);
169244
+ const rawValue = valueToTemplateString(variables[name]);
169245
+ const dependencies = /* @__PURE__ */ new Set();
169246
+ const errors = [];
169247
+ let secret = secretNames.has(name);
169248
+ const value = rawValue.replace(TEMPLATE_TOKEN_REGEX, (token, rawReference) => {
169249
+ const referenceName = parseTemplateReference(rawReference);
169250
+ if (!referenceName) {
169251
+ errors.push({
169252
+ kind: "unsupported",
169253
+ variableName: name,
169254
+ reference: rawReference.trim(),
169255
+ message: `.nornenv template reference '${rawReference.trim()}' is not supported. Use {{name}} or {{$env.name}}.`
169256
+ });
169257
+ return token;
169258
+ }
169259
+ const resolved = resolveVariable(referenceName);
169260
+ dependencies.add(referenceName);
169261
+ for (const dependency of resolved.dependencies) {
169262
+ dependencies.add(dependency);
169263
+ }
169264
+ if (scopes?.environmentNames.has(name) && scopes.environmentNames.has(referenceName)) {
169265
+ errors.push({
169266
+ kind: "scope",
169267
+ variableName: name,
169268
+ reference: referenceName,
169269
+ message: `.nornenv template reference '${referenceName}' is not in scope. Values inside [env:...] sections can reference common variables and inherited ancestor variables only.`
169270
+ });
169271
+ }
169272
+ if (resolved.secret) {
169273
+ secret = true;
169274
+ }
169275
+ errors.push(...resolved.errors);
169276
+ return resolved.value;
169277
+ });
169278
+ resolving.delete(name);
169279
+ const resolution = {
169280
+ value,
169281
+ secret,
169282
+ dependencies,
169283
+ errors
169284
+ };
169285
+ cache.set(name, resolution);
169286
+ return resolution;
169287
+ };
169288
+ return resolveVariable(variableName);
169289
+ }
169290
+ function collectResolvedEnvironmentSecretValues(variables, secretNames) {
169291
+ const values = /* @__PURE__ */ new Map();
169292
+ for (const name of secretNames) {
169293
+ if (!Object.prototype.hasOwnProperty.call(variables, name)) {
169294
+ continue;
169295
+ }
169296
+ const resolved = resolveEnvironmentTemplateValue(name, variables, secretNames);
169297
+ if (resolved.errors.length === 0) {
169298
+ values.set(name, resolved.value);
169299
+ }
169300
+ }
169301
+ return values;
169302
+ }
169303
+
169304
+ // src/agents/databaseTools.ts
169305
+ function resolveDatabaseConnectionTemplate(alias, template, runtimeVariables) {
169306
+ const environment = runtimeVariables.$env;
169307
+ const scoped = { ...runtimeVariables, $env: { ...environment } };
169308
+ for (const match2 of template.matchAll(/\{\{(?:\$env\.)?([A-Za-z_][A-Za-z0-9_]*)\}\}/g)) {
169309
+ const name = match2[1];
169310
+ if (environment && name in environment) {
169311
+ const resolved = resolveEnvironmentTemplateValue(name, environment);
169312
+ if (resolved.errors.length) {
169313
+ throw new Error(`Database '${alias}' could not resolve environment value '${name}': ${resolved.errors[0].message}`);
169314
+ }
169315
+ scoped.$env[name] = resolved.value;
169316
+ if (name in runtimeVariables) {
169317
+ scoped[name] = resolved.value;
169318
+ }
169319
+ }
169320
+ }
169321
+ const value = substituteVariables(template, scoped).replace(/\{\{\$env\.([A-Za-z_][A-Za-z0-9_]*)\}\}/g, (match2, name) => process.env[name] || match2);
169322
+ if (!value || /\{\{[^}]+\}\}/.test(value)) {
169323
+ throw new Error(`Database '${alias}' has an unresolved connectionString reference.`);
169324
+ }
169325
+ return value;
169326
+ }
169327
+ function resolveDatabaseConnectionString(database, runtimeVariables) {
169328
+ return resolveDatabaseConnectionTemplate(database.alias, database.connectionStringTemplate, runtimeVariables);
169329
+ }
169330
+ function assertReadOnlySql(sql) {
169331
+ let visible = "";
169332
+ for (let index = 0; index < sql.length; ) {
169333
+ const char = sql[index];
169334
+ const next = sql[index + 1];
169335
+ if (char === "-" && next === "-") {
169336
+ const end = sql.indexOf("\n", index + 2);
169337
+ index = end < 0 ? sql.length : end;
169338
+ visible += " ";
169339
+ continue;
169340
+ }
169341
+ if (char === "/" && next === "*") {
169342
+ const end = sql.indexOf("*/", index + 2);
169343
+ if (end < 0) {
169344
+ throw new Error("Read-only SQL has an unterminated comment.");
169345
+ }
169346
+ index = end + 2;
169347
+ visible += " ";
169348
+ continue;
169349
+ }
169350
+ const quote = char === "'" || char === '"' ? char : void 0;
169351
+ const dollar = char === "$" ? sql.slice(index).match(/^\$[A-Za-z_0-9]*\$/)?.[0] : void 0;
169352
+ if (quote || dollar) {
169353
+ const delimiter2 = quote || dollar;
169354
+ index += delimiter2.length;
169355
+ let closed = false;
169356
+ while (index < sql.length) {
169357
+ if (sql.startsWith(delimiter2, index)) {
169358
+ index += delimiter2.length;
169359
+ if (quote && sql.startsWith(delimiter2, index)) {
169360
+ index += delimiter2.length;
169361
+ } else {
169362
+ closed = true;
169363
+ break;
169364
+ }
169365
+ } else {
169366
+ index++;
169367
+ }
169368
+ }
169369
+ if (!closed) {
169370
+ throw new Error("Read-only SQL has an unterminated string.");
169371
+ }
169372
+ visible += " ";
169373
+ continue;
169374
+ }
169375
+ visible += char;
169376
+ index++;
169377
+ }
169378
+ const statement = visible.trim().replace(/;\s*$/, "").trim();
169379
+ if (!/^select\b/i.test(statement) || statement.includes(";") || /\binto\b|\bfor\s+update\b/i.test(statement)) {
169380
+ throw new Error("This database grants read access only. Use one SELECT statement without INTO or FOR UPDATE.");
169381
+ }
169382
+ }
169383
+ var SCHEMA_SQL = `SELECT table_schema, table_name, column_name, data_type, is_nullable, ordinal_position
169384
+ FROM information_schema.columns
169385
+ WHERE table_schema NOT IN ('information_schema', 'pg_catalog')
169386
+ ORDER BY table_schema, table_name, ordinal_position`;
169387
+ async function executeDatabaseTool(database, operation, input2, runtimeVariables, workingDir, signal) {
169388
+ const sql = operation === "inspect" ? SCHEMA_SQL : input2.sql;
169389
+ if (typeof sql !== "string" || !sql.trim()) {
169390
+ throw new Error("Database query requires a nonempty sql string.");
169391
+ }
169392
+ if (database.access === "read" || operation === "inspect") {
169393
+ assertReadOnlySql(sql);
169394
+ }
169395
+ const mode = operation === "inspect" || /^\s*(select|with|show|explain)\b/i.test(sql) ? "query" : "command";
169396
+ const request = {
169397
+ protocolVersion: 1,
169398
+ mode,
169399
+ operation: {
169400
+ name: operation === "inspect" ? "inspect_database" : "query_database",
169401
+ type: mode,
169402
+ sql,
169403
+ parameters: [],
169404
+ connectionName: database.alias,
169405
+ sourcePath: database.sourcePath
169406
+ },
169407
+ params: {},
169408
+ connection: {
169409
+ name: database.alias,
169410
+ profile: database.alias,
169411
+ values: { connectionString: resolveDatabaseConnectionString(database, runtimeVariables) }
169412
+ },
169413
+ context: { workingDir },
169414
+ readOnly: database.access === "read" || operation === "inspect"
169415
+ };
169416
+ const result = await runSqlAdapter(resolveSqlAdapterTarget(database.sourcePath, database.adapter), request, workingDir, signal);
169417
+ return result.result;
169418
+ }
169419
+
169044
169420
  // src/mcpClient.ts
169045
- var fs12 = __toESM(require("fs"));
169421
+ var fs13 = __toESM(require("fs"));
169046
169422
  var path13 = __toESM(require("path"));
169047
169423
 
169048
169424
  // node_modules/zod/v3/helpers/util.js
@@ -184854,7 +185230,7 @@ function splitCommandLine(value) {
184854
185230
  }
184855
185231
  return parts;
184856
185232
  }
184857
- function resolveCommandParts2(originPath, command, envVariables) {
185233
+ function resolveCommandParts(originPath, command, envVariables) {
184858
185234
  const configDir = path10.dirname(originPath);
184859
185235
  return command.map((part, index) => {
184860
185236
  const resolvedPart = resolveTemplateString(part, envVariables);
@@ -184900,7 +185276,7 @@ function resolveServerConfig(filePath, config2, envVariables) {
184900
185276
  if (config2.transport === "stdio") {
184901
185277
  return {
184902
185278
  transport: "stdio",
184903
- command: resolveCommandParts2(filePath, config2.command, envVariables),
185279
+ command: resolveCommandParts(filePath, config2.command, envVariables),
184904
185280
  cwd: resolveRelativeDirectory(filePath, config2.cwd, envVariables)
184905
185281
  };
184906
185282
  }
@@ -184997,7 +185373,7 @@ function resolveMcpServerDeclaration(declaration, envVariables) {
184997
185373
  transport: "stdio",
184998
185374
  // Reuse the config path's own resolution so a bare name stays a PATH lookup and a
184999
185375
  // relative one resolves against the declaring file — here, the sidecar.
185000
- command: resolveCommandParts2(declaration.sourcePath, command),
185376
+ command: resolveCommandParts(declaration.sourcePath, command),
185001
185377
  cwd: resolveRelativeDirectory(
185002
185378
  declaration.sourcePath,
185003
185379
  declaration.cwdTemplate === void 0 ? void 0 : resolveTemplate(declaration.cwdTemplate, declaration, "cwd", envVariables)
@@ -185062,7 +185438,7 @@ function resolveMcpTarget(alias, options) {
185062
185438
  var path12 = __toESM(require("path"));
185063
185439
 
185064
185440
  // src/cacheDir.ts
185065
- var fs11 = __toESM(require("fs"));
185441
+ var fs12 = __toESM(require("fs"));
185066
185442
  var path11 = __toESM(require("path"));
185067
185443
  var NORN_CACHE_DIR = ".norn-cache";
185068
185444
  var CACHE_GITIGNORE_FILE = ".gitignore";
@@ -185071,7 +185447,7 @@ var PROJECT_ROOT_MARKERS = [".git", "package.json", "pnpm-workspace.yaml", "pack
185071
185447
  function getSearchStartDirectory(targetPath) {
185072
185448
  const resolvedPath = path11.resolve(targetPath);
185073
185449
  try {
185074
- const stats = fs11.statSync(resolvedPath);
185450
+ const stats = fs12.statSync(resolvedPath);
185075
185451
  return stats.isDirectory() ? resolvedPath : path11.dirname(resolvedPath);
185076
185452
  } catch {
185077
185453
  return path11.dirname(resolvedPath);
@@ -185081,7 +185457,7 @@ function findProjectRoot(targetPath) {
185081
185457
  let dir = getSearchStartDirectory(targetPath);
185082
185458
  let projectRoot;
185083
185459
  while (true) {
185084
- if (PROJECT_ROOT_MARKERS.some((marker) => fs11.existsSync(path11.join(dir, marker)))) {
185460
+ if (PROJECT_ROOT_MARKERS.some((marker) => fs12.existsSync(path11.join(dir, marker)))) {
185085
185461
  projectRoot = dir;
185086
185462
  }
185087
185463
  const parent = path11.dirname(dir);
@@ -185095,19 +185471,19 @@ function findProjectRoot(targetPath) {
185095
185471
  function ensureNornCacheGitignore(cacheDir) {
185096
185472
  const gitignorePath = path11.join(cacheDir, CACHE_GITIGNORE_FILE);
185097
185473
  try {
185098
- const hasDesiredContent = fs11.existsSync(gitignorePath) && fs11.readFileSync(gitignorePath, "utf8") === CACHE_GITIGNORE_CONTENT;
185474
+ const hasDesiredContent = fs12.existsSync(gitignorePath) && fs12.readFileSync(gitignorePath, "utf8") === CACHE_GITIGNORE_CONTENT;
185099
185475
  if (hasDesiredContent) {
185100
185476
  return;
185101
185477
  }
185102
- fs11.writeFileSync(gitignorePath, CACHE_GITIGNORE_CONTENT, "utf8");
185478
+ fs12.writeFileSync(gitignorePath, CACHE_GITIGNORE_CONTENT, "utf8");
185103
185479
  } catch {
185104
185480
  }
185105
185481
  }
185106
185482
  function ensureNornCacheDir(rootPath) {
185107
185483
  const cacheDir = path11.join(rootPath, NORN_CACHE_DIR);
185108
185484
  try {
185109
- if (!fs11.existsSync(cacheDir)) {
185110
- fs11.mkdirSync(cacheDir, { recursive: true });
185485
+ if (!fs12.existsSync(cacheDir)) {
185486
+ fs12.mkdirSync(cacheDir, { recursive: true });
185111
185487
  }
185112
185488
  ensureNornCacheGitignore(cacheDir);
185113
185489
  return cacheDir;
@@ -185119,11 +185495,11 @@ function getNornCacheFilePath(rootPath, fileName) {
185119
185495
  return path11.join(rootPath, NORN_CACHE_DIR, fileName);
185120
185496
  }
185121
185497
  function loadVersionedJsonCache(options) {
185122
- if (!options.cachePath || !fs11.existsSync(options.cachePath)) {
185498
+ if (!options.cachePath || !fs12.existsSync(options.cachePath)) {
185123
185499
  return options.createDefault();
185124
185500
  }
185125
185501
  try {
185126
- const content = fs11.readFileSync(options.cachePath, "utf-8");
185502
+ const content = fs12.readFileSync(options.cachePath, "utf-8");
185127
185503
  const parsed = JSON.parse(content);
185128
185504
  if (parsed.version !== options.version) {
185129
185505
  return options.createDefault();
@@ -185141,7 +185517,7 @@ function saveVersionedJsonCache(cachePath, cache, ensureDirectory) {
185141
185517
  return false;
185142
185518
  }
185143
185519
  try {
185144
- fs11.writeFileSync(cachePath, JSON.stringify(cache, null, 2), "utf-8");
185520
+ fs12.writeFileSync(cachePath, JSON.stringify(cache, null, 2), "utf-8");
185145
185521
  return true;
185146
185522
  } catch {
185147
185523
  return false;
@@ -185224,7 +185600,7 @@ var NornJsonSchemaValidator = class {
185224
185600
  function getNornClientVersion() {
185225
185601
  try {
185226
185602
  const packageJsonPath = path13.resolve(__dirname, "..", "package.json");
185227
- const packageJson = JSON.parse(fs12.readFileSync(packageJsonPath, "utf-8"));
185603
+ const packageJson = JSON.parse(fs13.readFileSync(packageJsonPath, "utf-8"));
185228
185604
  return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
185229
185605
  } catch {
185230
185606
  return "0.0.0";
@@ -185631,7 +186007,7 @@ function prepareRequestFromContent(requestContent, variables, apiDefinitions) {
185631
186007
  }
185632
186008
 
185633
186009
  // src/contracts/contractMode.ts
185634
- var fs13 = __toESM(require("fs"));
186010
+ var fs14 = __toESM(require("fs"));
185635
186011
  var path14 = __toESM(require("path"));
185636
186012
 
185637
186013
  // src/swaggerParser.ts
@@ -185887,7 +186263,7 @@ function isContractModeEnabled(startPath) {
185887
186263
  return false;
185888
186264
  }
185889
186265
  try {
185890
- const config2 = JSON.parse(fs13.readFileSync(configPath, "utf-8"));
186266
+ const config2 = JSON.parse(fs14.readFileSync(configPath, "utf-8"));
185891
186267
  return config2?.contracts?.mode === "auto";
185892
186268
  } catch {
185893
186269
  return false;
@@ -185895,11 +186271,11 @@ function isContractModeEnabled(startPath) {
185895
186271
  }
185896
186272
  function readManifestFiles(contractsDir) {
185897
186273
  const manifestPath = path14.join(contractsDir, MANIFEST_FILENAME);
185898
- if (!fs13.existsSync(manifestPath)) {
186274
+ if (!fs14.existsSync(manifestPath)) {
185899
186275
  return void 0;
185900
186276
  }
185901
186277
  try {
185902
- const parsed = JSON.parse(fs13.readFileSync(manifestPath, "utf-8"));
186278
+ const parsed = JSON.parse(fs14.readFileSync(manifestPath, "utf-8"));
185903
186279
  return Array.isArray(parsed?.files) ? parsed.files.filter((f3) => typeof f3 === "string") : void 0;
185904
186280
  } catch {
185905
186281
  return void 0;
@@ -185935,144 +186311,6 @@ function validateResponseContract(endpoint, statusCode, body, leftExpression) {
185935
186311
  };
185936
186312
  }
185937
186313
 
185938
- // src/environmentTemplates.ts
185939
- var TEMPLATE_TOKEN_REGEX = /\{\{([^{}]+)\}\}/g;
185940
- var ENV_REFERENCE_REGEX = /^(?:\$env\.)?([a-zA-Z_][a-zA-Z0-9_]*)$/;
185941
- var ENV_TEMPLATE_SCOPES_KEY = "$nornEnvTemplateScopes";
185942
- function attachEnvironmentTemplateScopes(variables, commonVariables, environmentVariables) {
185943
- Object.defineProperty(variables, ENV_TEMPLATE_SCOPES_KEY, {
185944
- value: {
185945
- commonNames: new Set(Object.keys(commonVariables)),
185946
- environmentNames: new Set(Object.keys(environmentVariables ?? {}))
185947
- },
185948
- enumerable: false,
185949
- configurable: true,
185950
- writable: false
185951
- });
185952
- return variables;
185953
- }
185954
- function getEnvironmentTemplateScopes(variables) {
185955
- const value = variables[ENV_TEMPLATE_SCOPES_KEY];
185956
- if (!value || typeof value !== "object") {
185957
- return void 0;
185958
- }
185959
- const candidate = value;
185960
- if (!(candidate.commonNames instanceof Set) || !(candidate.environmentNames instanceof Set)) {
185961
- return void 0;
185962
- }
185963
- return candidate;
185964
- }
185965
- function valueToTemplateString(value) {
185966
- if (value === void 0 || value === null) {
185967
- return "";
185968
- }
185969
- if (typeof value === "object") {
185970
- return JSON.stringify(value);
185971
- }
185972
- return String(value);
185973
- }
185974
- function parseTemplateReference(rawReference) {
185975
- const trimmed = rawReference.trim();
185976
- const match2 = trimmed.match(ENV_REFERENCE_REGEX);
185977
- return match2?.[1];
185978
- }
185979
- function resolveEnvironmentTemplateValue(variableName, variables, secretNames = /* @__PURE__ */ new Set()) {
185980
- const resolving = /* @__PURE__ */ new Set();
185981
- const cache = /* @__PURE__ */ new Map();
185982
- const scopes = getEnvironmentTemplateScopes(variables);
185983
- const resolveVariable = (name) => {
185984
- const cached2 = cache.get(name);
185985
- if (cached2) {
185986
- return cached2;
185987
- }
185988
- if (resolving.has(name)) {
185989
- const cycle = [...resolving, name].join(" -> ");
185990
- return {
185991
- value: `{{${name}}}`,
185992
- secret: secretNames.has(name),
185993
- dependencies: /* @__PURE__ */ new Set([name]),
185994
- errors: [{
185995
- kind: "cycle",
185996
- variableName: name,
185997
- reference: name,
185998
- message: `Circular .nornenv template reference detected: ${cycle}`
185999
- }]
186000
- };
186001
- }
186002
- if (!Object.prototype.hasOwnProperty.call(variables, name)) {
186003
- return {
186004
- value: `{{${name}}}`,
186005
- secret: false,
186006
- dependencies: /* @__PURE__ */ new Set([name]),
186007
- errors: [{
186008
- kind: "unresolved",
186009
- variableName: name,
186010
- reference: name,
186011
- message: `.nornenv template reference '${name}' was not found in the active environment.`
186012
- }]
186013
- };
186014
- }
186015
- resolving.add(name);
186016
- const rawValue = valueToTemplateString(variables[name]);
186017
- const dependencies = /* @__PURE__ */ new Set();
186018
- const errors = [];
186019
- let secret = secretNames.has(name);
186020
- const value = rawValue.replace(TEMPLATE_TOKEN_REGEX, (token, rawReference) => {
186021
- const referenceName = parseTemplateReference(rawReference);
186022
- if (!referenceName) {
186023
- errors.push({
186024
- kind: "unsupported",
186025
- variableName: name,
186026
- reference: rawReference.trim(),
186027
- message: `.nornenv template reference '${rawReference.trim()}' is not supported. Use {{name}} or {{$env.name}}.`
186028
- });
186029
- return token;
186030
- }
186031
- const resolved = resolveVariable(referenceName);
186032
- dependencies.add(referenceName);
186033
- for (const dependency of resolved.dependencies) {
186034
- dependencies.add(dependency);
186035
- }
186036
- if (scopes?.environmentNames.has(name) && scopes.environmentNames.has(referenceName)) {
186037
- errors.push({
186038
- kind: "scope",
186039
- variableName: name,
186040
- reference: referenceName,
186041
- message: `.nornenv template reference '${referenceName}' is not in scope. Values inside [env:...] sections can reference common variables and inherited ancestor variables only.`
186042
- });
186043
- }
186044
- if (resolved.secret) {
186045
- secret = true;
186046
- }
186047
- errors.push(...resolved.errors);
186048
- return resolved.value;
186049
- });
186050
- resolving.delete(name);
186051
- const resolution = {
186052
- value,
186053
- secret,
186054
- dependencies,
186055
- errors
186056
- };
186057
- cache.set(name, resolution);
186058
- return resolution;
186059
- };
186060
- return resolveVariable(variableName);
186061
- }
186062
- function collectResolvedEnvironmentSecretValues(variables, secretNames) {
186063
- const values = /* @__PURE__ */ new Map();
186064
- for (const name of secretNames) {
186065
- if (!Object.prototype.hasOwnProperty.call(variables, name)) {
186066
- continue;
186067
- }
186068
- const resolved = resolveEnvironmentTemplateValue(name, variables, secretNames);
186069
- if (resolved.errors.length === 0) {
186070
- values.set(name, resolved.value);
186071
- }
186072
- }
186073
- return values;
186074
- }
186075
-
186076
186314
  // src/mcpToolSchema.ts
186077
186315
  function getInputSchemaObject(source) {
186078
186316
  if (!source.inputSchema || typeof source.inputSchema !== "object" || Array.isArray(source.inputSchema)) {
@@ -186138,7 +186376,7 @@ function describeAgentActivity(event) {
186138
186376
  }
186139
186377
 
186140
186378
  // src/agents/judgeExpectations.ts
186141
- var fs14 = __toESM(require("fs"));
186379
+ var fs15 = __toESM(require("fs"));
186142
186380
  var path15 = __toESM(require("path"));
186143
186381
  var JUDGE_STATEMENT = /^\s*judge\b(.*)$/i;
186144
186382
  var JUDGE_SUBJECT_AND_AGENT = /^(.+?)\s+with\s+(\S+)\s*$/i;
@@ -186179,7 +186417,7 @@ function readExpectationFileFrom(options, resolvedPath) {
186179
186417
  if (options.readExpectationFile) {
186180
186418
  return options.readExpectationFile(resolvedPath);
186181
186419
  }
186182
- return fs14.readFileSync(resolvedPath, "utf8");
186420
+ return fs15.readFileSync(resolvedPath, "utf8");
186183
186421
  }
186184
186422
  function readInlineExpectation(value) {
186185
186423
  const verbatim = value.startsWith('@"');
@@ -199114,7 +199352,7 @@ function createDefaultAgentProviderRegistry() {
199114
199352
  }
199115
199353
 
199116
199354
  // src/agents/agentRunner.ts
199117
- var fs20 = __toESM(require("fs"));
199355
+ var fs21 = __toESM(require("fs"));
199118
199356
  var path23 = __toESM(require("path"));
199119
199357
  var import_crypto8 = require("crypto");
199120
199358
 
@@ -199701,7 +199939,7 @@ function hasReturnsContract(agent) {
199701
199939
  return Boolean(agent.returns || agent.builtInContracts?.returns);
199702
199940
  }
199703
199941
  function readAgentSchema(schemaPath) {
199704
- const parsed = JSON.parse(fs20.readFileSync(schemaPath, "utf8"));
199942
+ const parsed = JSON.parse(fs21.readFileSync(schemaPath, "utf8"));
199705
199943
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
199706
199944
  throw new Error(`Agent schema '${schemaPath}' must contain a JSON object.`);
199707
199945
  }
@@ -200433,7 +200671,7 @@ ${TOOL_RESULT_RECOVERY_INSTRUCTIONS}`;
200433
200671
  overrideKeys.add(key);
200434
200672
  }
200435
200673
  let callerLimitBreaches = 0;
200436
- const reservedAgentNames = ["load_knowledge", "norn_read_tool_result", "norn_search_tool_results"];
200674
+ const reservedAgentNames = ["load_knowledge", "query_database", "inspect_database", "norn_read_tool_result", "norn_search_tool_results"];
200437
200675
  if (this.options.onJournalEvent || requestToolsOverride?.some((tool) => tool.kind === "journal")) {
200438
200676
  reservedAgentNames.push("report_progress");
200439
200677
  }
@@ -200473,6 +200711,54 @@ ${TOOL_RESULT_RECOVERY_INSTRUCTIONS}`;
200473
200711
  }));
200474
200712
  }
200475
200713
  }
200714
+ if (agent.grantedDatabases?.length) {
200715
+ const permitted = agent.grantedDatabases.map((grant) => agent.databases?.get(grant.alias.toLowerCase())).filter((database) => database !== void 0);
200716
+ for (const [toolName2, operation, description, inputSchema] of [
200717
+ ["query_database", "query", "Execute SQL against a granted database, subject to its access mode.", {
200718
+ type: "object",
200719
+ properties: { database: { type: "string", enum: permitted.map((database) => database.alias) }, sql: { type: "string" } },
200720
+ required: ["database", "sql"],
200721
+ additionalProperties: false
200722
+ }],
200723
+ ["inspect_database", "inspect", "List schemas, tables, columns, and column types in a granted database.", {
200724
+ type: "object",
200725
+ properties: { database: { type: "string", enum: permitted.map((database) => database.alias) } },
200726
+ required: ["database"],
200727
+ additionalProperties: false
200728
+ }]
200729
+ ]) {
200730
+ const offeredOverride = requestToolsOverride?.find((tool) => tool.kind === "database" && tool.name === toolName2);
200731
+ providerTools.push(this.createRecordedProviderTool(parentHop, {
200732
+ name: toolName2,
200733
+ providerName: offeredOverride?.providerName ?? `norn_${toolName2}`,
200734
+ kind: "database",
200735
+ description: offeredOverride?.description ?? description,
200736
+ inputSchema: offeredOverride?.inputSchema ?? inputSchema
200737
+ }, async (input2, context) => {
200738
+ const databaseName = input2.database;
200739
+ const database = typeof databaseName === "string" ? permitted.find((candidate) => candidate.alias.toLowerCase() === databaseName.toLowerCase()) : void 0;
200740
+ if (!database) {
200741
+ throw new Error(`Database '${String(databaseName)}' is not granted to agent '${agent.name}'.`);
200742
+ }
200743
+ const replayed = await this.options.executeDatabaseToolOverride?.(parentHop.hopPath, toolName2, input2);
200744
+ if (replayed) {
200745
+ context.recordedMs = replayed.ms;
200746
+ return replayed.output;
200747
+ }
200748
+ if (requestToolsOverride && !offeredOverride) {
200749
+ throw new Error(`Recorded request did not offer database tool '${toolName2}'.`);
200750
+ }
200751
+ return executeDatabaseTool(
200752
+ database,
200753
+ operation,
200754
+ input2,
200755
+ this.options.runtimeVariables,
200756
+ path23.dirname(this.options.startPath || process.cwd()),
200757
+ this.options.signal
200758
+ );
200759
+ }));
200760
+ }
200761
+ }
200476
200762
  const expansion = agent.grantedMcpServers?.length ? await this.expandServerGrants(agent, parentHop) : void 0;
200477
200763
  for (const reference of [...agent.tools, ...expansion?.references ?? []]) {
200478
200764
  const offeredOverride = requestToolsOverride?.find(
@@ -200855,11 +201141,11 @@ ${TOOL_RESULT_RECOVERY_INSTRUCTIONS}`;
200855
201141
 
200856
201142
  // src/agents/agentRecording.ts
200857
201143
  var import_crypto10 = require("crypto");
200858
- var fs23 = __toESM(require("fs"));
201144
+ var fs24 = __toESM(require("fs"));
200859
201145
  var path26 = __toESM(require("path"));
200860
201146
 
200861
201147
  // src/environmentParser.ts
200862
- var fs22 = __toESM(require("fs"));
201148
+ var fs23 = __toESM(require("fs"));
200863
201149
  var path25 = __toESM(require("path"));
200864
201150
 
200865
201151
  // src/secrets/crypto.ts
@@ -200928,7 +201214,7 @@ function decryptSecretValue(encryptedValue, sharedKey) {
200928
201214
  }
200929
201215
 
200930
201216
  // src/secrets/keyStore.ts
200931
- var fs21 = __toESM(require("fs"));
201217
+ var fs22 = __toESM(require("fs"));
200932
201218
  var path24 = __toESM(require("path"));
200933
201219
  var CACHE_FILE2 = "secret-keys.json";
200934
201220
  var CACHE_VERSION2 = 1;
@@ -200941,7 +201227,7 @@ function getCacheFilePath(cacheDir) {
200941
201227
  function cacheFileExists(cacheDir) {
200942
201228
  const cacheFilePath = getCacheFilePath(cacheDir);
200943
201229
  try {
200944
- return fs21.existsSync(cacheFilePath) && fs21.statSync(cacheFilePath).isFile();
201230
+ return fs22.existsSync(cacheFilePath) && fs22.statSync(cacheFilePath).isFile();
200945
201231
  } catch {
200946
201232
  return false;
200947
201233
  }
@@ -200964,7 +201250,7 @@ function getProjectSecretKeyCacheDirs(projectRoot) {
200964
201250
  }
200965
201251
  let entries;
200966
201252
  try {
200967
- entries = fs21.readdirSync(dir, { withFileTypes: true });
201253
+ entries = fs22.readdirSync(dir, { withFileTypes: true });
200968
201254
  } catch {
200969
201255
  continue;
200970
201256
  }
@@ -201015,8 +201301,8 @@ function ensureCacheDir(targetPath) {
201015
201301
  const existing = findExistingSecretKeyCacheDir(targetPath);
201016
201302
  const projectRoot = findProjectRoot(targetPath);
201017
201303
  const cacheDir = existing ?? path24.join(projectRoot, NORN_CACHE_DIR);
201018
- if (!fs21.existsSync(cacheDir)) {
201019
- fs21.mkdirSync(cacheDir, { recursive: true });
201304
+ if (!fs22.existsSync(cacheDir)) {
201305
+ fs22.mkdirSync(cacheDir, { recursive: true });
201020
201306
  }
201021
201307
  ensureNornCacheGitignore(cacheDir);
201022
201308
  rememberSecretKeyCacheDir(targetPath, cacheDir);
@@ -201029,7 +201315,7 @@ function getReadCachePath(targetPath) {
201029
201315
  }
201030
201316
  const projectRoot = findProjectRoot(targetPath);
201031
201317
  const projectCacheDir = path24.join(projectRoot, NORN_CACHE_DIR);
201032
- if (fs21.existsSync(projectCacheDir) && fs21.statSync(projectCacheDir).isDirectory()) {
201318
+ if (fs22.existsSync(projectCacheDir) && fs22.statSync(projectCacheDir).isDirectory()) {
201033
201319
  return getCacheFilePath(projectCacheDir);
201034
201320
  }
201035
201321
  return void 0;
@@ -201039,11 +201325,11 @@ function getWriteCachePath(targetPath) {
201039
201325
  }
201040
201326
  function readCache(targetPath) {
201041
201327
  const cachePath = getReadCachePath(targetPath);
201042
- if (!cachePath || !fs21.existsSync(cachePath)) {
201328
+ if (!cachePath || !fs22.existsSync(cachePath)) {
201043
201329
  return { version: CACHE_VERSION2, keys: {} };
201044
201330
  }
201045
201331
  try {
201046
- const parsed = JSON.parse(fs21.readFileSync(cachePath, "utf8"));
201332
+ const parsed = JSON.parse(fs22.readFileSync(cachePath, "utf8"));
201047
201333
  if (parsed.version !== CACHE_VERSION2 || typeof parsed.keys !== "object" || parsed.keys === null) {
201048
201334
  return { version: CACHE_VERSION2, keys: {} };
201049
201335
  }
@@ -201054,9 +201340,9 @@ function readCache(targetPath) {
201054
201340
  }
201055
201341
  function writeCache(targetPath, cache) {
201056
201342
  const cachePath = getWriteCachePath(targetPath);
201057
- fs21.writeFileSync(cachePath, JSON.stringify(cache, null, 2), { encoding: "utf8", mode: 384 });
201343
+ fs22.writeFileSync(cachePath, JSON.stringify(cache, null, 2), { encoding: "utf8", mode: 384 });
201058
201344
  try {
201059
- fs21.chmodSync(cachePath, 384);
201345
+ fs22.chmodSync(cachePath, 384);
201060
201346
  } catch {
201061
201347
  }
201062
201348
  }
@@ -201263,7 +201549,7 @@ function parseEnvFile(content, sourceFilePath) {
201263
201549
  function getEnvSearchStartDirectory(targetPath) {
201264
201550
  const resolvedPath = path25.resolve(targetPath);
201265
201551
  try {
201266
- const stats = fs22.statSync(resolvedPath);
201552
+ const stats = fs23.statSync(resolvedPath);
201267
201553
  return stats.isDirectory() ? resolvedPath : path25.dirname(resolvedPath);
201268
201554
  } catch {
201269
201555
  return path25.dirname(resolvedPath);
@@ -201273,7 +201559,7 @@ function findEnvFileFromPath(filePath) {
201273
201559
  let dir = getEnvSearchStartDirectory(filePath);
201274
201560
  while (true) {
201275
201561
  const envPath = path25.join(dir, ENV_FILENAME);
201276
- if (fs22.existsSync(envPath)) {
201562
+ if (fs23.existsSync(envPath)) {
201277
201563
  return envPath;
201278
201564
  }
201279
201565
  const parentDir = path25.dirname(dir);
@@ -201307,7 +201593,7 @@ function resolveNornenvImports(config2, baseDir, entryFilePath, readFile4, impor
201307
201593
  }
201308
201594
  for (const imp of config2.imports) {
201309
201595
  const resolvedImportPath = resolveImportPath(imp.path, baseDir);
201310
- if (!resolvedImportPath || !fs22.existsSync(resolvedImportPath)) {
201596
+ if (!resolvedImportPath || !fs23.existsSync(resolvedImportPath)) {
201311
201597
  errors.push({
201312
201598
  message: `Imported file not found: '${imp.path}'`,
201313
201599
  filePath: entryFilePath,
@@ -201482,7 +201768,7 @@ function toDisplayPath(filePath, entryFilePath) {
201482
201768
  return relative12 && relative12 !== "" ? relative12 : path25.basename(filePath);
201483
201769
  }
201484
201770
  function loadAndResolveEnvFile(filePath) {
201485
- const content = fs22.readFileSync(filePath, "utf-8");
201771
+ const content = fs23.readFileSync(filePath, "utf-8");
201486
201772
  const config2 = parseEnvFile(content, filePath);
201487
201773
  if (config2.imports.length === 0) {
201488
201774
  const secretErrors = resolveEncryptedSecretValues(config2, filePath);
@@ -201492,7 +201778,7 @@ function loadAndResolveEnvFile(filePath) {
201492
201778
  config2,
201493
201779
  path25.dirname(filePath),
201494
201780
  filePath,
201495
- (p) => fs22.readFileSync(p, "utf-8")
201781
+ (p) => fs23.readFileSync(p, "utf-8")
201496
201782
  );
201497
201783
  result.secretErrors.push(...resolveEncryptedSecretValues(result.config, filePath));
201498
201784
  return result;
@@ -202023,7 +202309,7 @@ function chooseCollisionSafeRecordingPath(runsDirectory, recording) {
202023
202309
  while (true) {
202024
202310
  const suffix = index === 1 ? "" : `-${index}`;
202025
202311
  const candidate = path26.join(runsDirectory, `${base}${suffix}.json`);
202026
- if (!fs23.existsSync(candidate)) {
202312
+ if (!fs24.existsSync(candidate)) {
202027
202313
  return candidate;
202028
202314
  }
202029
202315
  index++;
@@ -202034,13 +202320,13 @@ function isGeneratedRecordingCandidate(filePath) {
202034
202320
  return void 0;
202035
202321
  }
202036
202322
  try {
202037
- const parsed = JSON.parse(fs23.readFileSync(filePath, "utf8"));
202323
+ const parsed = JSON.parse(fs24.readFileSync(filePath, "utf8"));
202038
202324
  if (!isObjectRecord2(parsed) || !Number.isSafeInteger(parsed.version) || typeof parsed.timestamp !== "string" || typeof parsed.sequenceName !== "string" || typeof parsed.sourcePath !== "string") {
202039
202325
  return void 0;
202040
202326
  }
202041
202327
  const parsedTimestamp = Date.parse(parsed.timestamp);
202042
202328
  return {
202043
- timestamp: Number.isFinite(parsedTimestamp) ? parsedTimestamp : fs23.statSync(filePath).mtimeMs,
202329
+ timestamp: Number.isFinite(parsedTimestamp) ? parsedTimestamp : fs24.statSync(filePath).mtimeMs,
202044
202330
  filePath
202045
202331
  };
202046
202332
  } catch {
@@ -202048,14 +202334,14 @@ function isGeneratedRecordingCandidate(filePath) {
202048
202334
  }
202049
202335
  }
202050
202336
  function pruneAgentRunRecordings(runsDirectory) {
202051
- if (!fs23.existsSync(runsDirectory)) {
202337
+ if (!fs24.existsSync(runsDirectory)) {
202052
202338
  return [];
202053
202339
  }
202054
- const candidates = fs23.readdirSync(runsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => isGeneratedRecordingCandidate(path26.join(runsDirectory, entry.name))).filter((entry) => Boolean(entry)).sort((left, right) => left.timestamp - right.timestamp || compareStrings(left.filePath, right.filePath));
202340
+ const candidates = fs24.readdirSync(runsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => isGeneratedRecordingCandidate(path26.join(runsDirectory, entry.name))).filter((entry) => Boolean(entry)).sort((left, right) => left.timestamp - right.timestamp || compareStrings(left.filePath, right.filePath));
202055
202341
  const deleted = [];
202056
202342
  for (const candidate of candidates.slice(0, Math.max(0, candidates.length - MAX_AGENT_RUN_RECORDINGS))) {
202057
202343
  try {
202058
- fs23.unlinkSync(candidate.filePath);
202344
+ fs24.unlinkSync(candidate.filePath);
202059
202345
  deleted.push(candidate.filePath);
202060
202346
  } catch {
202061
202347
  }
@@ -202097,14 +202383,14 @@ function writeAgentRunRecording(input2, options = {}) {
202097
202383
  let destinationPath;
202098
202384
  if (options.outputPath) {
202099
202385
  destinationPath = path26.resolve(options.outputPath);
202100
- fs23.mkdirSync(path26.dirname(destinationPath), { recursive: true });
202386
+ fs24.mkdirSync(path26.dirname(destinationPath), { recursive: true });
202101
202387
  } else {
202102
202388
  const cacheDirectory = ensureNornCacheDir(projectRoot);
202103
202389
  if (!cacheDirectory) {
202104
202390
  throw new Error(`Could not create Norn cache directory under '${projectRoot}'.`);
202105
202391
  }
202106
202392
  runsDirectory = path26.join(cacheDirectory, AGENT_RUN_RECORDINGS_DIRECTORY);
202107
- fs23.mkdirSync(runsDirectory, { recursive: true, mode: 448 });
202393
+ fs24.mkdirSync(runsDirectory, { recursive: true, mode: 448 });
202108
202394
  destinationPath = chooseCollisionSafeRecordingPath(runsDirectory, masked);
202109
202395
  }
202110
202396
  const temporaryPath = path26.join(
@@ -202112,12 +202398,12 @@ function writeAgentRunRecording(input2, options = {}) {
202112
202398
  `.${path26.basename(destinationPath)}.${process.pid}.${(0, import_crypto10.randomUUID)()}.tmp`
202113
202399
  );
202114
202400
  try {
202115
- fs23.writeFileSync(temporaryPath, serialized, { encoding: "utf8", flag: "wx", mode: 384 });
202116
- fs23.renameSync(temporaryPath, destinationPath);
202401
+ fs24.writeFileSync(temporaryPath, serialized, { encoding: "utf8", flag: "wx", mode: 384 });
202402
+ fs24.renameSync(temporaryPath, destinationPath);
202117
202403
  } catch (error2) {
202118
202404
  try {
202119
- if (fs23.existsSync(temporaryPath)) {
202120
- fs23.unlinkSync(temporaryPath);
202405
+ if (fs24.existsSync(temporaryPath)) {
202406
+ fs24.unlinkSync(temporaryPath);
202121
202407
  }
202122
202408
  } catch {
202123
202409
  }
@@ -202143,7 +202429,7 @@ function isSafeProjectRelativePath(value) {
202143
202429
  return isRelativePath(value) && !normalizePathSeparators(value).split("/").includes("..");
202144
202430
  }
202145
202431
  function isAgentToolCall(value) {
202146
- return isObjectRecord2(value) && typeof value.name === "string" && (value.kind === void 0 || value.kind === "mcp" || value.kind === "agent" || value.kind === "knowledge" || value.kind === "context" || value.kind === "journal") && isObjectRecord2(value.input) && isFiniteNonNegativeNumber(value.ms) && (value.childInvocationId === void 0 || typeof value.childInvocationId === "string");
202432
+ return isObjectRecord2(value) && typeof value.name === "string" && (value.kind === void 0 || value.kind === "mcp" || value.kind === "agent" || value.kind === "knowledge" || value.kind === "database" || value.kind === "context" || value.kind === "journal") && isObjectRecord2(value.input) && isFiniteNonNegativeNumber(value.ms) && (value.childInvocationId === void 0 || typeof value.childInvocationId === "string");
202147
202433
  }
202148
202434
  function isAgentKnowledgeTopicSnapshot(value) {
202149
202435
  return isObjectRecord2(value) && typeof value.topicHash === "string" && (value.heading === void 0 || typeof value.heading === "string") && isFiniteNonNegativeNumber(value.estimatedTokens) && isStringArray(value.itemPaths);
@@ -202159,7 +202445,7 @@ function isAgentRequestSnapshot(value) {
202159
202445
  (message) => isObjectRecord2(message) && (message.role === "user" || message.role === "assistant") && typeof message.content === "string"
202160
202446
  );
202161
202447
  const validTools = value.tools.every(
202162
- (tool) => isObjectRecord2(tool) && typeof tool.name === "string" && typeof tool.providerName === "string" && (tool.kind === void 0 || tool.kind === "mcp" || tool.kind === "agent" || tool.kind === "knowledge" || tool.kind === "context" || tool.kind === "journal") && (tool.description === void 0 || typeof tool.description === "string") && isObjectRecord2(tool.inputSchema)
202448
+ (tool) => isObjectRecord2(tool) && typeof tool.name === "string" && typeof tool.providerName === "string" && (tool.kind === void 0 || tool.kind === "mcp" || tool.kind === "agent" || tool.kind === "knowledge" || tool.kind === "database" || tool.kind === "context" || tool.kind === "journal") && (tool.description === void 0 || typeof tool.description === "string") && isObjectRecord2(tool.inputSchema)
202163
202449
  );
202164
202450
  const validKnowledge = value.knowledge === void 0 || isObjectRecord2(value.knowledge) && typeof value.knowledge.runId === "string" && typeof value.knowledge.snapshotId === "string" && isStringArray(value.knowledge.declarationIds) && ["exact_entity", "lexical_unique", "lexical_ambiguous", "no_match"].includes(
202165
202451
  String(value.knowledge.routingRule)
@@ -202220,7 +202506,7 @@ function isMaskedAgentRunRecordingEnvelope(value) {
202220
202506
  function readMaskedAgentRunRecording(filePath) {
202221
202507
  let content;
202222
202508
  try {
202223
- content = fs23.readFileSync(filePath, "utf8");
202509
+ content = fs24.readFileSync(filePath, "utf8");
202224
202510
  } catch (error2) {
202225
202511
  throw new AgentRunRecordingLoadError(
202226
202512
  "read",
@@ -202332,11 +202618,11 @@ var import_crypto11 = require("crypto");
202332
202618
  var path35 = __toESM(require("path"));
202333
202619
 
202334
202620
  // src/knowledge/knowledgeIndexBuilder.ts
202335
- var fs27 = __toESM(require("fs"));
202621
+ var fs28 = __toESM(require("fs"));
202336
202622
  var path31 = __toESM(require("path"));
202337
202623
 
202338
202624
  // src/knowledge/knowledgeBuilder.ts
202339
- var fs24 = __toESM(require("fs"));
202625
+ var fs25 = __toESM(require("fs"));
202340
202626
  var path28 = __toESM(require("path"));
202341
202627
  var crypto11 = __toESM(require("crypto"));
202342
202628
 
@@ -202713,7 +202999,7 @@ function knowledgeGlobMatches(pattern, itemPath) {
202713
202999
  return new RegExp(`^${source}$`).test(normalizeRelative(itemPath));
202714
203000
  }
202715
203001
  function walkFiles(directory) {
202716
- const entries = fs24.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
203002
+ const entries = fs25.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
202717
203003
  return entries.flatMap((entry) => {
202718
203004
  const entryPath = path28.join(directory, entry.name);
202719
203005
  if (entry.isDirectory()) {
@@ -202723,7 +203009,7 @@ function walkFiles(directory) {
202723
203009
  });
202724
203010
  }
202725
203011
  function sourceCandidates(sourcePath) {
202726
- const stats = fs24.statSync(sourcePath);
203012
+ const stats = fs25.statSync(sourcePath);
202727
203013
  return stats.isDirectory() ? walkFiles(sourcePath) : [sourcePath];
202728
203014
  }
202729
203015
  function knowledgeItemPathFor(sourcePath, sourceIsFile, absolutePath) {
@@ -202908,7 +203194,7 @@ function buildKnowledgeBase(declaration, options = {}) {
202908
203194
  const memberships = [];
202909
203195
  declaration.sources.forEach((source, sourceIndex) => {
202910
203196
  for (const absolutePath of sourceCandidates(source.resolvedPath)) {
202911
- const sourceIsFile = fs24.statSync(source.resolvedPath).isFile();
203197
+ const sourceIsFile = fs25.statSync(source.resolvedPath).isFile();
202912
203198
  const itemPath = knowledgeItemPathFor(source.resolvedPath, sourceIsFile, absolutePath);
202913
203199
  const glob2 = declaration.excludes.find((entry) => knowledgeGlobMatches(entry.pattern, itemPath));
202914
203200
  const extension2 = path28.extname(absolutePath).toLowerCase();
@@ -202917,7 +203203,7 @@ function buildKnowledgeBase(declaration, options = {}) {
202917
203203
  let reason = glob2 ? `excluded by config glob '${glob2.pattern}'` : topicProducing ? `declared source; topic-producing extension '${extension2}'` : `declared source; '${extension2 || "(none)"}' is not a topic-producing extension`;
202918
203204
  let topics = { topics: [], diagnostics: [], fileExcluded: false, metaBlocks: [] };
202919
203205
  if (topicProducing) {
202920
- const content = fs24.readFileSync(absolutePath, "utf8");
203206
+ const content = fs25.readFileSync(absolutePath, "utf8");
202921
203207
  const inputHash = crypto11.createHash("sha256").update(content).digest("hex");
202922
203208
  const analyzerInputsHash = crypto11.createHash("sha256").update(JSON.stringify({
202923
203209
  analyzer: "knowledge-markdown-topics",
@@ -203157,7 +203443,7 @@ function sha256(value) {
203157
203443
  }
203158
203444
 
203159
203445
  // src/knowledge/knowledgeEntityExtractors.ts
203160
- var fs25 = __toESM(require("fs"));
203446
+ var fs26 = __toESM(require("fs"));
203161
203447
  var path29 = __toESM(require("path"));
203162
203448
  var HTTP_METHODS = "GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS|TRACE|CONNECT";
203163
203449
  var PROJECT_EXTENSIONS = /* @__PURE__ */ new Set([".norn", ".nornapi"]);
@@ -203409,7 +203695,7 @@ function extractNornEvidence(content, projectPath) {
203409
203695
  function walkProjectFiles(projectRoot, directory = projectRoot) {
203410
203696
  let entries;
203411
203697
  try {
203412
- entries = fs25.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
203698
+ entries = fs26.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
203413
203699
  } catch {
203414
203700
  return [];
203415
203701
  }
@@ -203428,7 +203714,7 @@ function walkProjectFiles(projectRoot, directory = projectRoot) {
203428
203714
  function discoverProjectEntityFiles(projectRoot) {
203429
203715
  return walkProjectFiles(projectRoot);
203430
203716
  }
203431
- function extractProjectEntityInput(projectRoot, absolutePath, content = fs25.readFileSync(absolutePath, "utf8")) {
203717
+ function extractProjectEntityInput(projectRoot, absolutePath, content = fs26.readFileSync(absolutePath, "utf8")) {
203432
203718
  const projectPath = path29.relative(projectRoot, absolutePath).split(path29.sep).join("/");
203433
203719
  const extension2 = path29.extname(absolutePath).toLowerCase();
203434
203720
  const evidence = path29.basename(absolutePath) === ".nornenv" ? extractNornEnvEvidence(content, projectPath) : extension2 === ".nornapi" ? extractNornApiEvidence(content, projectPath) : extractNornEvidence(content, projectPath);
@@ -203436,7 +203722,7 @@ function extractProjectEntityInput(projectRoot, absolutePath, content = fs25.rea
203436
203722
  }
203437
203723
 
203438
203724
  // src/knowledge/knowledgeIndex.ts
203439
- var fs26 = __toESM(require("fs"));
203725
+ var fs27 = __toESM(require("fs"));
203440
203726
  var path30 = __toESM(require("path"));
203441
203727
  var import_node_sqlite = require("node:sqlite");
203442
203728
  var KNOWLEDGE_SCHEMA_VERSION = 3;
@@ -203672,13 +203958,13 @@ function defaultDatabasePath(projectRoot) {
203672
203958
  throw new Error(`Could not create the Norn cache directory below '${projectRoot}'.`);
203673
203959
  }
203674
203960
  const directory = path30.join(cache, "knowledge");
203675
- fs26.mkdirSync(directory, { recursive: true, mode: 448 });
203961
+ fs27.mkdirSync(directory, { recursive: true, mode: 448 });
203676
203962
  return path30.join(directory, "knowledge.sqlite");
203677
203963
  }
203678
203964
  function removeDatabaseFiles(databasePath) {
203679
203965
  for (const candidate of [databasePath, `${databasePath}-wal`, `${databasePath}-shm`]) {
203680
- if (fs26.existsSync(candidate)) {
203681
- fs26.unlinkSync(candidate);
203966
+ if (fs27.existsSync(candidate)) {
203967
+ fs27.unlinkSync(candidate);
203682
203968
  }
203683
203969
  }
203684
203970
  }
@@ -203691,7 +203977,7 @@ var KnowledgeIndex = class {
203691
203977
  database;
203692
203978
  constructor(projectRoot, options = {}) {
203693
203979
  this.databasePath = options.databasePath ?? defaultDatabasePath(projectRoot);
203694
- fs26.mkdirSync(path30.dirname(this.databasePath), { recursive: true, mode: 448 });
203980
+ fs27.mkdirSync(path30.dirname(this.databasePath), { recursive: true, mode: 448 });
203695
203981
  let database = new import_node_sqlite.DatabaseSync(this.databasePath);
203696
203982
  const version4 = currentSchemaVersion(database);
203697
203983
  if (version4 !== 0 && version4 !== 1 && version4 !== 2 && version4 !== KNOWLEDGE_SCHEMA_VERSION) {
@@ -203711,7 +203997,7 @@ var KnowledgeIndex = class {
203711
203997
  }
203712
203998
  this.database.exec(`PRAGMA user_version = ${KNOWLEDGE_SCHEMA_VERSION}`);
203713
203999
  try {
203714
- fs26.chmodSync(this.databasePath, 384);
204000
+ fs27.chmodSync(this.databasePath, 384);
203715
204001
  } catch {
203716
204002
  }
203717
204003
  }
@@ -203879,7 +204165,7 @@ function portablePath(projectRoot, targetPath) {
203879
204165
  function walkSidecars(directory) {
203880
204166
  let entries;
203881
204167
  try {
203882
- entries = fs27.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
204168
+ entries = fs28.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
203883
204169
  } catch {
203884
204170
  return [];
203885
204171
  }
@@ -203897,7 +204183,7 @@ function walkSidecars(directory) {
203897
204183
  function discoverKnowledgeDeclarations(projectRoot) {
203898
204184
  const declarations = [];
203899
204185
  for (const sidecarPath of walkSidecars(projectRoot)) {
203900
- const parsed = parseNornAgentFile(fs27.readFileSync(sidecarPath, "utf8"), sidecarPath);
204186
+ const parsed = parseNornAgentFile(fs28.readFileSync(sidecarPath, "utf8"), sidecarPath);
203901
204187
  const knowledgeErrors = parsed.errors.filter((error2) => error2.code.startsWith("agent-knowledge-"));
203902
204188
  if (knowledgeErrors.length > 0) {
203903
204189
  throw new Error(knowledgeErrors.map((error2) => `${portablePath(projectRoot, sidecarPath)}:${error2.lineNumber + 1}: ${error2.message}`).join("\n"));
@@ -203910,7 +204196,7 @@ function knowledgeDeclarationId(projectRoot, declaration) {
203910
204196
  return `declaration:${sha256(`${portablePath(projectRoot, declaration.sourcePath)}\0${declaration.alias}`).slice(0, 32)}`;
203911
204197
  }
203912
204198
  function knowledgeSourceId(projectRoot, declarationId, resolvedPath) {
203913
- const kind = fs27.statSync(resolvedPath).isDirectory() ? "directory" : "file";
204199
+ const kind = fs28.statSync(resolvedPath).isDirectory() ? "directory" : "file";
203914
204200
  const locator = portablePath(projectRoot, resolvedPath);
203915
204201
  return {
203916
204202
  sourceId: `source:${sha256(`${declarationId}\0${kind}\0${locator}`).slice(0, 32)}`,
@@ -204071,7 +204357,7 @@ function knowledgeEntities(index, pending, used, occurrence, topic, analyzerVers
204071
204357
  }
204072
204358
  function projectEntityInputs(index, projectRoot, pending, used, analyzerVersion, stats) {
204073
204359
  return discoverProjectEntityFiles(projectRoot).map((absolutePath) => {
204074
- const content = fs27.readFileSync(absolutePath, "utf8");
204360
+ const content = fs28.readFileSync(absolutePath, "utf8");
204075
204361
  const projectPath = portablePath(projectRoot, absolutePath);
204076
204362
  const inputHash = sha256(content);
204077
204363
  const inputsHash = sha256(canonicalJson({ projectPath }));
@@ -204147,7 +204433,7 @@ function commitSnapshot(index, projectRoot, snapshotId, manifestJson, builtAt, d
204147
204433
  `,
204148
204434
  descriptor.sourceId,
204149
204435
  member.itemPath,
204150
- sha256(fs27.readFileSync(member.absolutePath)),
204436
+ sha256(fs28.readFileSync(member.absolutePath)),
204151
204437
  member.included ? 1 : 0,
204152
204438
  member.topicProducing ? 1 : 0,
204153
204439
  member.extension,
@@ -204828,7 +205114,7 @@ function routeKnowledge(startPath, input2, projection, config2, agentName, optio
204828
205114
  }
204829
205115
 
204830
205116
  // src/knowledge/knowledgeEnvironment.ts
204831
- var fs28 = __toESM(require("fs"));
205117
+ var fs29 = __toESM(require("fs"));
204832
205118
  var path34 = __toESM(require("path"));
204833
205119
  var REFERENCE = /\{\{(?:\$env\.)?([A-Za-z_][A-Za-z0-9_]*)\}\}/g;
204834
205120
  var extensionSelection;
@@ -204845,7 +205131,7 @@ function resolveKnowledgeMarkdown(text, filePath, metadata, environmentName, opt
204845
205131
  if (!envFile) {
204846
205132
  return text;
204847
205133
  }
204848
- if (!fs28.existsSync(envFile)) {
205134
+ if (!fs29.existsSync(envFile)) {
204849
205135
  throw new Error(`Knowledge file '${filePath}' cannot read environment import '${envFile}'.`);
204850
205136
  }
204851
205137
  const loaded = loadAndResolveEnvFile(envFile);
@@ -204883,7 +205169,7 @@ function resolveKnowledgeProjectionVariables(projection, projectRoot, environmen
204883
205169
  const source = path34.resolve(projectRoot, domain2.sourcePath);
204884
205170
  let sourceIsFile;
204885
205171
  try {
204886
- sourceIsFile = fs28.statSync(source).isFile();
205172
+ sourceIsFile = fs29.statSync(source).isFile();
204887
205173
  } catch {
204888
205174
  sourceIsFile = path34.extname(source).toLowerCase() === ".md";
204889
205175
  }
@@ -206299,30 +206585,6 @@ function evaluateSqlArgumentExpression(expr, runtimeVariables) {
206299
206585
  }
206300
206586
  return evaluateValueExpression(trimmed, runtimeVariables);
206301
206587
  }
206302
- function getSqlConnectionValues(profile, runtimeVariables) {
206303
- const values = {};
206304
- const envScope = runtimeVariables.$env && typeof runtimeVariables.$env === "object" ? runtimeVariables.$env : void 0;
206305
- if (!envScope) {
206306
- return values;
206307
- }
206308
- const prefix = `${profile}_`;
206309
- for (const [key, value] of Object.entries(envScope)) {
206310
- if (!key.startsWith(prefix) || value === void 0 || value === null) {
206311
- continue;
206312
- }
206313
- const propertyName = key.slice(prefix.length);
206314
- if (!propertyName) {
206315
- continue;
206316
- }
206317
- const resolved = resolveEnvironmentTemplateValue(key, envScope);
206318
- if (resolved.errors.length > 0) {
206319
- const message = resolved.errors.map((error2) => error2.message).join("; ");
206320
- throw new Error(`Failed to resolve SQL connection value '${key}': ${message}`);
206321
- }
206322
- values[propertyName] = resolved.value;
206323
- }
206324
- return values;
206325
- }
206326
206588
  function getRuntimeEnvironmentVariables(runtimeVariables) {
206327
206589
  const envScope = runtimeVariables.$env;
206328
206590
  if (!envScope || typeof envScope !== "object" || Array.isArray(envScope)) {
@@ -207989,9 +208251,23 @@ ${describeUnmetExpectations(verdict).map((line2) => ` - ${line2}`).join("\n")}`
207989
208251
  }
207990
208252
  const adapterWorkingDir = workingDir || process.cwd();
207991
208253
  try {
207992
- const connection = resolveSqlConnection(executionContext?.filePath || adapterWorkingDir, operation.connectionName);
207993
- const adapterTarget = resolveSqlAdapterTarget(executionContext?.filePath || adapterWorkingDir, connection.adapter);
207994
- const connectionValues = getSqlConnectionValues(connection.profile, runtimeVariables);
208254
+ const connection = operation.database ? {
208255
+ alias: operation.database.alias,
208256
+ adapter: operation.database.adapter,
208257
+ profile: operation.database.alias,
208258
+ sourcePath: operation.database.sourcePath,
208259
+ connectionStringTemplate: operation.database.connectionStringTemplate
208260
+ } : resolveSqlConnection(executionContext?.filePath || adapterWorkingDir, operation.connectionName);
208261
+ const adapterTarget = resolveSqlAdapterTarget(
208262
+ connection.sourcePath || executionContext?.filePath || adapterWorkingDir,
208263
+ connection.adapter
208264
+ );
208265
+ const connectionString = resolveDatabaseConnectionTemplate(
208266
+ connection.alias,
208267
+ connection.connectionStringTemplate || "",
208268
+ runtimeVariables
208269
+ );
208270
+ const connectionValues = { connectionString };
207995
208271
  const adapterResponse = await runSqlAdapter(
207996
208272
  adapterTarget,
207997
208273
  {
@@ -210091,7 +210367,7 @@ function formatRunSummary(results, totalDuration, colors) {
210091
210367
  }
210092
210368
 
210093
210369
  // src/cli/reporters/junit.ts
210094
- var fs29 = __toESM(require("fs"));
210370
+ var fs30 = __toESM(require("fs"));
210095
210371
  function escapeXml(text) {
210096
210372
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
210097
210373
  }
@@ -210118,7 +210394,7 @@ function generateJUnitReport(results, options) {
210118
210394
  xml += generateTestSuite(result, redaction);
210119
210395
  }
210120
210396
  xml += "</testsuites>\n";
210121
- fs29.writeFileSync(outputPath, xml, "utf-8");
210397
+ fs30.writeFileSync(outputPath, xml, "utf-8");
210122
210398
  }
210123
210399
  function generateTestSuite(result, redaction) {
210124
210400
  const assertions = result.assertionResults || [];
@@ -210282,11 +210558,11 @@ Response: ${bodyStr}`;
210282
210558
  xml += " </testcase>\n";
210283
210559
  xml += " </testsuite>\n";
210284
210560
  xml += "</testsuites>\n";
210285
- fs29.writeFileSync(outputPath, xml, "utf-8");
210561
+ fs30.writeFileSync(outputPath, xml, "utf-8");
210286
210562
  }
210287
210563
 
210288
210564
  // src/cli/reporters/html.ts
210289
- var fs30 = __toESM(require("fs"));
210565
+ var fs31 = __toESM(require("fs"));
210290
210566
  function escapeHtml(text) {
210291
210567
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
210292
210568
  }
@@ -210400,7 +210676,7 @@ function generateHtmlReport(results, options) {
210400
210676
  </script>
210401
210677
  </body>
210402
210678
  </html>`;
210403
- fs30.writeFileSync(outputPath, html, "utf-8");
210679
+ fs31.writeFileSync(outputPath, html, "utf-8");
210404
210680
  }
210405
210681
  function generateSequenceHtml(result, index, redaction) {
210406
210682
  const statusClass = result.success ? "passed" : "failed";
@@ -210856,13 +211132,13 @@ function generateHtmlReportFromResponse(response, testName, options) {
210856
211132
  }
210857
211133
 
210858
211134
  // src/secrets/cliSecrets.ts
210859
- var fs32 = __toESM(require("fs"));
211135
+ var fs33 = __toESM(require("fs"));
210860
211136
  var path38 = __toESM(require("path"));
210861
211137
  var readline2 = __toESM(require("readline"));
210862
211138
  var import_process = require("process");
210863
211139
 
210864
211140
  // src/secrets/envFileSecrets.ts
210865
- var fs31 = __toESM(require("fs"));
211141
+ var fs32 = __toESM(require("fs"));
210866
211142
  var path37 = __toESM(require("path"));
210867
211143
  var envRegex = /^\s*\[env:([a-zA-Z_][a-zA-Z0-9_-]*)\]\s*$/;
210868
211144
  var secretConnectionStringRegex2 = /^(\s*secret\s+connectionString\s+)([a-zA-Z_][a-zA-Z0-9_]*)(\s*=\s*)(.+)$/;
@@ -210948,7 +211224,7 @@ function findSecretLine(content, variableName, envName) {
210948
211224
  return secretLines.find((secret) => secret.name === variableName);
210949
211225
  }
210950
211226
  function loadSecretLine(filePath, variableName, envName) {
210951
- const content = fs31.readFileSync(filePath, "utf8");
211227
+ const content = fs32.readFileSync(filePath, "utf8");
210952
211228
  const secret = findSecretLine(content, variableName, envName);
210953
211229
  if (!secret) {
210954
211230
  const envLabel = envName ? ` in [env:${envName}]` : "";
@@ -210957,20 +211233,20 @@ function loadSecretLine(filePath, variableName, envName) {
210957
211233
  return { content, secret };
210958
211234
  }
210959
211235
  function writeSecretLine(filePath, content) {
210960
- fs31.writeFileSync(filePath, content, "utf8");
211236
+ fs32.writeFileSync(filePath, content, "utf8");
210961
211237
  }
210962
211238
  function discoverNornenvFiles(targetPath) {
210963
211239
  const resolved = path37.resolve(targetPath);
210964
- if (!fs31.existsSync(resolved)) {
211240
+ if (!fs32.existsSync(resolved)) {
210965
211241
  return [];
210966
211242
  }
210967
- const stats = fs31.statSync(resolved);
211243
+ const stats = fs32.statSync(resolved);
210968
211244
  if (stats.isFile()) {
210969
211245
  return isNornenvFilePath(resolved) ? [resolved] : [];
210970
211246
  }
210971
211247
  const results = [];
210972
211248
  const walk2 = (dir) => {
210973
- const entries = fs31.readdirSync(dir, { withFileTypes: true });
211249
+ const entries = fs32.readdirSync(dir, { withFileTypes: true });
210974
211250
  for (const entry of entries) {
210975
211251
  const fullPath = path37.join(dir, entry.name);
210976
211252
  if (entry.isDirectory()) {
@@ -211201,7 +211477,7 @@ async function handleRekey(args) {
211201
211477
  let updatedFiles = 0;
211202
211478
  let updatedSecrets = 0;
211203
211479
  for (const filePath of files) {
211204
- const original = fs32.readFileSync(filePath, "utf8");
211480
+ const original = fs33.readFileSync(filePath, "utf8");
211205
211481
  const secretLines = extractSecretLines(original, filePath);
211206
211482
  if (secretLines.length === 0) {
211207
211483
  continue;
@@ -211252,7 +211528,7 @@ async function handleRekey(args) {
211252
211528
  updatedSecrets += 1;
211253
211529
  }
211254
211530
  if (updated !== original) {
211255
- fs32.writeFileSync(filePath, updated, "utf8");
211531
+ fs33.writeFileSync(filePath, updated, "utf8");
211256
211532
  updatedFiles += 1;
211257
211533
  }
211258
211534
  }
@@ -211269,7 +211545,7 @@ async function handleAudit(args) {
211269
211545
  }
211270
211546
  const issues = [];
211271
211547
  for (const filePath of files) {
211272
- const content = fs32.readFileSync(filePath, "utf8");
211548
+ const content = fs33.readFileSync(filePath, "utf8");
211273
211549
  const secrets = extractSecretLines(content, filePath);
211274
211550
  for (const secret of secrets) {
211275
211551
  if (!secret.encrypted) {
@@ -211355,7 +211631,7 @@ function printSecretResolutionErrors(errors, envFilePath) {
211355
211631
  }
211356
211632
 
211357
211633
  // src/contracts/cliContracts.ts
211358
- var fs33 = __toESM(require("fs"));
211634
+ var fs34 = __toESM(require("fs"));
211359
211635
  var path39 = __toESM(require("path"));
211360
211636
  function getFlagValue2(args, flag) {
211361
211637
  const index = args.indexOf(flag);
@@ -211368,11 +211644,11 @@ function resolveTarget(args) {
211368
211644
  return void 0;
211369
211645
  }
211370
211646
  const nornapiPath = path39.resolve(fileArg);
211371
- if (!fs33.existsSync(nornapiPath)) {
211647
+ if (!fs34.existsSync(nornapiPath)) {
211372
211648
  console.error(`Error: File not found: ${nornapiPath}`);
211373
211649
  return void 0;
211374
211650
  }
211375
- const content = fs33.readFileSync(nornapiPath, "utf-8");
211651
+ const content = fs34.readFileSync(nornapiPath, "utf-8");
211376
211652
  const specUrl = parseSwaggerDirective(content);
211377
211653
  if (!specUrl) {
211378
211654
  console.error(`Error: No swagger directive found in ${path39.basename(nornapiPath)}`);
@@ -211391,11 +211667,11 @@ function applyTlsFlag(args) {
211391
211667
  }
211392
211668
  function readManifest(contractsDir) {
211393
211669
  const manifestPath = path39.join(contractsDir, MANIFEST_FILENAME);
211394
- if (!fs33.existsSync(manifestPath)) {
211670
+ if (!fs34.existsSync(manifestPath)) {
211395
211671
  return void 0;
211396
211672
  }
211397
211673
  try {
211398
- const parsed = JSON.parse(fs33.readFileSync(manifestPath, "utf-8"));
211674
+ const parsed = JSON.parse(fs34.readFileSync(manifestPath, "utf-8"));
211399
211675
  if (typeof parsed?.specUrl === "string" && Array.isArray(parsed?.files)) {
211400
211676
  return { specUrl: parsed.specUrl, files: parsed.files.filter((f3) => typeof f3 === "string") };
211401
211677
  }
@@ -211463,25 +211739,25 @@ async function handleSync(args) {
211463
211739
  console.error("Error: No response schemas found in the spec - nothing to sync");
211464
211740
  return 1;
211465
211741
  }
211466
- fs33.mkdirSync(target.contractsDir, { recursive: true });
211742
+ fs34.mkdirSync(target.contractsDir, { recursive: true });
211467
211743
  const previousManifest = readManifest(target.contractsDir);
211468
211744
  const sortedFilenames = [...files.keys()].sort();
211469
211745
  for (const filename of sortedFilenames) {
211470
211746
  const filePath = path39.join(target.contractsDir, filename);
211471
- fs33.writeFileSync(filePath, JSON.stringify(files.get(filename), null, 2), "utf-8");
211747
+ fs34.writeFileSync(filePath, JSON.stringify(files.get(filename), null, 2), "utf-8");
211472
211748
  }
211473
211749
  let pruned = 0;
211474
211750
  for (const staleFile of previousManifest?.files ?? []) {
211475
211751
  if (!files.has(staleFile)) {
211476
211752
  const stalePath = path39.join(target.contractsDir, staleFile);
211477
- if (fs33.existsSync(stalePath)) {
211478
- fs33.unlinkSync(stalePath);
211753
+ if (fs34.existsSync(stalePath)) {
211754
+ fs34.unlinkSync(stalePath);
211479
211755
  pruned++;
211480
211756
  }
211481
211757
  }
211482
211758
  }
211483
211759
  const manifest = { specUrl: target.specUrl, files: sortedFilenames };
211484
- fs33.writeFileSync(path39.join(target.contractsDir, MANIFEST_FILENAME), JSON.stringify(manifest, null, 2), "utf-8");
211760
+ fs34.writeFileSync(path39.join(target.contractsDir, MANIFEST_FILENAME), JSON.stringify(manifest, null, 2), "utf-8");
211485
211761
  const componentCount = files.has(COMPONENTS_FILENAME2) ? Object.keys(files.get(COMPONENTS_FILENAME2).definitions ?? {}).length : 0;
211486
211762
  const relativeDir = path39.relative(process.cwd(), target.contractsDir) || ".";
211487
211763
  console.log(`Synced ${sortedFilenames.length} schema file(s) to ${relativeDir}/ (${componentCount} shared component(s)${pruned > 0 ? `, pruned ${pruned} stale` : ""})`);
@@ -211515,11 +211791,11 @@ async function handleCheck(args) {
211515
211791
  const committed = /* @__PURE__ */ new Map();
211516
211792
  for (const filename of manifest.files) {
211517
211793
  const filePath = path39.join(target.contractsDir, filename);
211518
- if (!fs33.existsSync(filePath)) {
211794
+ if (!fs34.existsSync(filePath)) {
211519
211795
  continue;
211520
211796
  }
211521
211797
  try {
211522
- committed.set(filename, JSON.parse(fs33.readFileSync(filePath, "utf-8")));
211798
+ committed.set(filename, JSON.parse(fs34.readFileSync(filePath, "utf-8")));
211523
211799
  } catch {
211524
211800
  console.error(`Warning: ${filename} is not valid JSON - treating as missing`);
211525
211801
  }
@@ -211585,7 +211861,7 @@ async function handleContractsCommand(args) {
211585
211861
  }
211586
211862
 
211587
211863
  // src/theoryCaseLoader.ts
211588
- var fs34 = __toESM(require("fs/promises"));
211864
+ var fs35 = __toESM(require("fs/promises"));
211589
211865
  var path40 = __toESM(require("path"));
211590
211866
  function formatTheoryCaseLabel(params, index) {
211591
211867
  const entries = Object.entries(params);
@@ -211611,7 +211887,7 @@ function normalizeTheoryCase(caseValue, sequenceParamNames) {
211611
211887
  }
211612
211888
  async function loadTheoryCasesFromSource(sourcePath, workingDir, sequenceParamNames) {
211613
211889
  const resolvedPath = path40.resolve(workingDir, sourcePath);
211614
- const content = await fs34.readFile(resolvedPath, "utf-8");
211890
+ const content = await fs35.readFile(resolvedPath, "utf-8");
211615
211891
  const parsed = JSON.parse(content);
211616
211892
  if (!Array.isArray(parsed)) {
211617
211893
  throw new Error(`Theory file "${sourcePath}" must contain a JSON array of test cases`);
@@ -213132,6 +213408,20 @@ var ReplayCoordinator = class {
213132
213408
  this.mcpExecutionCounts.set(executionKey, executionIndex + 1);
213133
213409
  return { output: structuredClone(call.output), ms: call.ms };
213134
213410
  }
213411
+ executeDatabaseToolOverride(hopPath, toolName2, input2) {
213412
+ if (this.isLiveInvocation(hopPath)) {
213413
+ return void 0;
213414
+ }
213415
+ const calls = this.getRecordedHop(hopPath)?.output.toolCalls.filter((call2) => call2.kind === "database" && call2.name === toolName2) ?? [];
213416
+ const key = `${pathKey(hopPath)}\0database\0${toolName2}`;
213417
+ const index = this.mcpExecutionCounts.get(key) ?? 0;
213418
+ const call = calls[index];
213419
+ if (!call || !(0, import_util8.isDeepStrictEqual)(input2, call.input)) {
213420
+ throw new Error(`Replay input drift at '${hopPath}' for database tool '${toolName2}' call ${index + 1}.`);
213421
+ }
213422
+ this.mcpExecutionCounts.set(key, index + 1);
213423
+ return { output: structuredClone(call.output), ms: call.ms };
213424
+ }
213135
213425
  async runRecordedProviderRequest(request) {
213136
213426
  const startsLive = this.isLiveInvocation(request.hopPath);
213137
213427
  const recorded = this.getRecordedHop(request.hopPath);
@@ -213395,6 +213685,7 @@ async function replayAgentRun(options) {
213395
213685
  ),
213396
213686
  executeMcpToolOverride: (hopPath, reference, input2) => coordinator.executeMcpToolOverride(hopPath, reference, input2),
213397
213687
  executeKnowledgeToolOverride: (hopPath, input2) => coordinator.executeKnowledgeToolOverride(hopPath, input2),
213688
+ executeDatabaseToolOverride: (hopPath, toolName2, input2) => coordinator.executeDatabaseToolOverride(hopPath, toolName2, input2),
213398
213689
  onInvocationProgress: (event) => {
213399
213690
  generatedEvents.push(event);
213400
213691
  if (targetHopPath) {
@@ -213522,7 +213813,7 @@ Pure replay never calls a model or re-fires an MCP tool. Recordings default to
213522
213813
  }
213523
213814
 
213524
213815
  // src/knowledge/cliKnowledge.ts
213525
- var fs35 = __toESM(require("fs"));
213816
+ var fs36 = __toESM(require("fs"));
213526
213817
  var path41 = __toESM(require("path"));
213527
213818
  var SKIPPED_DIRECTORIES3 = /* @__PURE__ */ new Set([".git", ".norn-cache", "coverage", "dist", "node_modules", "out"]);
213528
213819
  function knowledgeCliHelp() {
@@ -213565,7 +213856,7 @@ function parseKnowledgeCliArgs(args) {
213565
213856
  return options;
213566
213857
  }
213567
213858
  function discoverSidecars(directory) {
213568
- const entries = fs35.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
213859
+ const entries = fs36.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
213569
213860
  return entries.flatMap((entry) => {
213570
213861
  const entryPath = path41.join(directory, entry.name);
213571
213862
  if (entry.isDirectory()) {
@@ -213576,18 +213867,18 @@ function discoverSidecars(directory) {
213576
213867
  }
213577
213868
  function resolveSidecar(target) {
213578
213869
  const resolved = path41.resolve(target ?? process.cwd());
213579
- if (fs35.existsSync(resolved) && fs35.statSync(resolved).isFile()) {
213870
+ if (fs36.existsSync(resolved) && fs36.statSync(resolved).isFile()) {
213580
213871
  if (!isAgentSidecarPath(resolved)) {
213581
213872
  throw new Error(`Knowledge target '${target}' is not a .nornai or .nornagent sidecar.`);
213582
213873
  }
213583
213874
  return resolved;
213584
213875
  }
213585
- if (!fs35.existsSync(resolved) || !fs35.statSync(resolved).isDirectory()) {
213876
+ if (!fs36.existsSync(resolved) || !fs36.statSync(resolved).isDirectory()) {
213586
213877
  throw new Error(`Knowledge target '${target ?? resolved}' was not found.`);
213587
213878
  }
213588
213879
  const matches = discoverSidecars(resolved).filter((sidecarPath) => {
213589
213880
  try {
213590
- const content = fs35.readFileSync(sidecarPath, "utf8");
213881
+ const content = fs36.readFileSync(sidecarPath, "utf8");
213591
213882
  const parsed = parseNornAgentFile(content, sidecarPath);
213592
213883
  return parsed.knowledgeBases.size > 0 || parsed.errors.some((error2) => error2.code.startsWith("agent-knowledge-"));
213593
213884
  } catch {
@@ -213620,7 +213911,7 @@ async function handleKnowledgeCommand(args) {
213620
213911
  }
213621
213912
  try {
213622
213913
  const sidecarPath = resolveSidecar(options.target);
213623
- const parsed = parseNornAgentFile(fs35.readFileSync(sidecarPath, "utf8"), sidecarPath);
213914
+ const parsed = parseNornAgentFile(fs36.readFileSync(sidecarPath, "utf8"), sidecarPath);
213624
213915
  if (parsed.errors.length > 0) {
213625
213916
  for (const error2 of parsed.errors) {
213626
213917
  console.error(`${path41.basename(sidecarPath)}:${error2.lineNumber + 1}: ${error2.message}`);
@@ -213671,7 +213962,7 @@ async function handleKnowledgeCommand(args) {
213671
213962
  }
213672
213963
 
213673
213964
  // src/cli/sequenceParameters.ts
213674
- var fs36 = __toESM(require("fs"));
213965
+ var fs37 = __toESM(require("fs"));
213675
213966
  var path42 = __toESM(require("path"));
213676
213967
  var PARAMETER_NAME = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
213677
213968
  function parseCliSequenceParameterAssignment(authored2, source) {
@@ -213711,7 +214002,7 @@ function loadJsonParameter(assignment, cwd) {
213711
214002
  }
213712
214003
  let content;
213713
214004
  try {
213714
- content = fs36.readFileSync(filePath, "utf8");
214005
+ content = fs37.readFileSync(filePath, "utf8");
213715
214006
  } catch (error2) {
213716
214007
  throw new Error(
213717
214008
  `Could not read JSON parameter${parameterLabel} from '${filePath}': ${error2 instanceof Error ? error2.message : String(error2)}`
@@ -214273,7 +214564,7 @@ async function handleReplayCommand(args) {
214273
214564
  sequenceName = metadata.sequenceName;
214274
214565
  const projectRoot = resolveAgentRecordingProjectRoot(recordingPath);
214275
214566
  const sourcePath = resolveAgentRecordingSourcePath(recordingPath, metadata, projectRoot);
214276
- if (!fs37.existsSync(sourcePath) || !fs37.statSync(sourcePath).isFile()) {
214567
+ if (!fs38.existsSync(sourcePath) || !fs38.statSync(sourcePath).isFile()) {
214277
214568
  throw new Error(
214278
214569
  `Recorded source '${metadata.sourcePath}' was not found under project root '${projectRoot}'.`
214279
214570
  );
@@ -214310,7 +214601,7 @@ async function handleReplayCommand(args) {
214310
214601
  environment: restorationEnvironment(resolvedEnv),
214311
214602
  ...selectedEnvironment ? { environmentName: selectedEnvironment } : {}
214312
214603
  });
214313
- const fileContent = fs37.readFileSync(sourcePath, "utf8");
214604
+ const fileContent = fs38.readFileSync(sourcePath, "utf8");
214314
214605
  const workingDirectory = path43.dirname(sourcePath);
214315
214606
  const importResult = await resolveImports(
214316
214607
  fileContent,
@@ -214598,7 +214889,7 @@ function formatRegionPatternSummary(pattern) {
214598
214889
  return lines;
214599
214890
  }
214600
214891
  function runNornenvRegionRefactor(filePath, options) {
214601
- const content = fs37.readFileSync(filePath, "utf-8");
214892
+ const content = fs38.readFileSync(filePath, "utf-8");
214602
214893
  const config2 = parseEnvFile(content, filePath);
214603
214894
  const pattern = detectRegionPattern(config2, content);
214604
214895
  if (!pattern) {
@@ -214611,7 +214902,7 @@ function runNornenvRegionRefactor(filePath, options) {
214611
214902
  }
214612
214903
  const refactored = applyRegionRefactorToText(content, pattern);
214613
214904
  if (options.writeRefactor) {
214614
- fs37.writeFileSync(filePath, refactored, "utf-8");
214905
+ fs38.writeFileSync(filePath, refactored, "utf-8");
214615
214906
  }
214616
214907
  if (options.output === "json") {
214617
214908
  console.log(JSON.stringify({
@@ -214689,7 +214980,7 @@ async function runK8sCliFile(filePath, options, colors) {
214689
214980
  console.log(colors.info(`Using environment: ${options.env}`));
214690
214981
  }
214691
214982
  const redaction = createRedactionOptions(resolvedEnv.secretNames, resolvedEnv.secretValues, !options.noRedact);
214692
- const fileContent = fs37.readFileSync(filePath, "utf-8");
214983
+ const fileContent = fs38.readFileSync(filePath, "utf-8");
214693
214984
  const parsed = parseK8sDocument(fileContent);
214694
214985
  const variables = attachEnvironmentScope({ ...resolvedEnv.variables }, resolvedEnv.variables);
214695
214986
  const executionOptions = {
@@ -214768,7 +215059,7 @@ async function runSingleRequest(fileContent, variables, cookieJar, apiDefinition
214768
215059
  function discoverNornFiles(dirPath) {
214769
215060
  const files = [];
214770
215061
  function walkDir(currentPath) {
214771
- const entries = fs37.readdirSync(currentPath, { withFileTypes: true });
215062
+ const entries = fs38.readdirSync(currentPath, { withFileTypes: true });
214772
215063
  for (const entry of entries) {
214773
215064
  const fullPath = path43.join(currentPath, entry.name);
214774
215065
  if (entry.isDirectory()) {
@@ -214786,7 +215077,7 @@ function discoverNornFiles(dirPath) {
214786
215077
  function discoverNornK8sFiles(dirPath) {
214787
215078
  const files = [];
214788
215079
  function walkDir(currentPath) {
214789
- const entries = fs37.readdirSync(currentPath, { withFileTypes: true });
215080
+ const entries = fs38.readdirSync(currentPath, { withFileTypes: true });
214790
215081
  for (const entry of entries) {
214791
215082
  const fullPath = path43.join(currentPath, entry.name);
214792
215083
  if (entry.isDirectory()) {
@@ -214912,7 +215203,7 @@ async function main() {
214912
215203
  }
214913
215204
  const args = rawArgs[0] === "run" ? rawArgs.slice(1) : rawArgs;
214914
215205
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-V")) {
214915
- console.log(`Norn CLI ${"4.6.2"}`);
215206
+ console.log(`Norn CLI ${"5.0.0"}`);
214916
215207
  return;
214917
215208
  }
214918
215209
  if (args.length === 0) {
@@ -214945,11 +215236,11 @@ async function main() {
214945
215236
  console.error(colors.warning("Warning: TLS certificate verification is disabled (--insecure). Use this only for local development."));
214946
215237
  }
214947
215238
  const inputPath = path43.resolve(options.file);
214948
- if (!fs37.existsSync(inputPath)) {
215239
+ if (!fs38.existsSync(inputPath)) {
214949
215240
  console.error(`Error: Path not found: ${inputPath}`);
214950
215241
  process.exit(1);
214951
215242
  }
214952
- const isDirectory = fs37.statSync(inputPath).isDirectory();
215243
+ const isDirectory = fs38.statSync(inputPath).isDirectory();
214953
215244
  const hasHostedSequenceOptions = options.sequenceParameters.length > 0 || options.agentRecordingOutputPath !== void 0;
214954
215245
  if (hasHostedSequenceOptions && !options.sequence) {
214955
215246
  console.error("Error: --param, --param-json, and --recording require --sequence.");
@@ -215072,7 +215363,7 @@ async function main() {
215072
215363
  }
215073
215364
  mergeSecrets(combinedSecretNames, combinedSecretValues, resolvedEnv.secretNames, resolvedEnv.secretValues);
215074
215365
  const redaction2 = createRedactionOptions(combinedSecretNames, combinedSecretValues, !options.noRedact);
215075
- const fileContent = fs37.readFileSync(filePath, "utf-8");
215366
+ const fileContent = fs38.readFileSync(filePath, "utf-8");
215076
215367
  const fileVariables = extractFileLevelVariables(fileContent);
215077
215368
  const variables = attachEnvironmentScope({ ...resolvedEnv.variables, ...fileVariables }, resolvedEnv.variables);
215078
215369
  const cookieJar = createCookieJar();
@@ -215277,7 +215568,7 @@ ${fileContent}` : fileContent;
215277
215568
  let totalTestCount = 0;
215278
215569
  let filteredTestCount = 0;
215279
215570
  for (const filePath of filesToRun) {
215280
- const fileContent = fs37.readFileSync(filePath, "utf-8");
215571
+ const fileContent = fs38.readFileSync(filePath, "utf-8");
215281
215572
  const counts = countTestSequences(fileContent, tagFilterOptions);
215282
215573
  totalTestCount += counts.total;
215283
215574
  filteredTestCount += counts.filtered;
@@ -215328,7 +215619,7 @@ ${fileContent}` : fileContent;
215328
215619
  }
215329
215620
  mergeSecrets(combinedSecretNames, combinedSecretValues, resolvedEnv.secretNames, resolvedEnv.secretValues);
215330
215621
  const redaction2 = createRedactionOptions(combinedSecretNames, combinedSecretValues, !options.noRedact);
215331
- const fileContent = fs37.readFileSync(filePath, "utf-8");
215622
+ const fileContent = fs38.readFileSync(filePath, "utf-8");
215332
215623
  const fileVariables = extractFileLevelVariables(fileContent);
215333
215624
  const variables = attachEnvironmentScope({ ...resolvedEnv.variables, ...fileVariables }, resolvedEnv.variables);
215334
215625
  const cookieJar = createCookieJar();
@@ -215417,8 +215708,8 @@ ${fileContent}` : fileContent;
215417
215708
  if (!htmlOutputPath) {
215418
215709
  htmlOutputPath = generatedPaths.htmlPath;
215419
215710
  }
215420
- if (!fs37.existsSync(options.outputDir)) {
215421
- fs37.mkdirSync(options.outputDir, { recursive: true });
215711
+ if (!fs38.existsSync(options.outputDir)) {
215712
+ fs38.mkdirSync(options.outputDir, { recursive: true });
215422
215713
  }
215423
215714
  }
215424
215715
  if (junitOutputPath) {