@intentic/claude-plugin 1.330.0 → 1.332.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.
@@ -8,6 +8,16 @@ import { join as join3 } from "node:path";
8
8
  import { readdirSync, readFileSync } from "node:fs";
9
9
  import { basename, dirname, join } from "node:path";
10
10
 
11
+ // ../../_tools/base/src/errors.ts
12
+ var errnoCode = (error) => {
13
+ const code = typeof error === `object` && error !== null ? error.code : void 0;
14
+ return typeof code === `string` ? code : void 0;
15
+ };
16
+ var isMissing = (error) => {
17
+ const code = errnoCode(error);
18
+ return code === `ENOENT` || code === `ENOTDIR`;
19
+ };
20
+
11
21
  // ../../_search/iq/src/recall/transcript/lines.ts
12
22
  var asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
13
23
  var asString = (value) => typeof value === "string" ? value : void 0;
@@ -198,10 +208,6 @@ var parse = (raw) => {
198
208
  return void 0;
199
209
  }
200
210
  };
201
- var isMissing = (error) => {
202
- const code = typeof error === "object" && error !== null ? error.code : void 0;
203
- return code === "ENOENT" || code === "ENOTDIR";
204
- };
205
211
  var promptOf2 = (line) => {
206
212
  const prompt = promptOf(line);
207
213
  return prompt?.kind === "typed" || prompt?.kind === "command" ? prompt.text : void 0;
@@ -570,7 +576,42 @@ var SECRET_NAME = String.raw`[A-Za-z0-9_]*(?:TOKEN|SECRET|PASSWORD|PASSWD|API[_-
570
576
  var ASSIGN = String.raw`["']?\s*[:=](?![=>])\s*`;
571
577
  var QUOTED_VALUE = String.raw`(["'\x60])([^"'\x60\n]{6,})\2`;
572
578
  var BARE_VALUE = String.raw`[\w+/=~-]{6,}(?![\w+/=~(-])`;
573
- var ISSUER_PREFIX = /^(?:sk-|pk-|rk-|ghp_|gho_|ghu_|ghs_|ghr_|github_pat_|xox[abposr]-|AKIA|ASIA|eyJ|AIza|ya29\.|glpat-|dop_v1_|shpat_|SG\.|npm_)/;
579
+ var CREDENTIAL_ISSUERS = [
580
+ { prefix: "npm_", body: "[A-Za-z0-9]{30,}" },
581
+ { prefix: "ghp_", body: "[A-Za-z0-9]{20,}" },
582
+ { prefix: "gho_", body: "[A-Za-z0-9]{20,}" },
583
+ { prefix: "ghu_", body: "[A-Za-z0-9]{20,}" },
584
+ { prefix: "ghs_", body: "[A-Za-z0-9]{20,}" },
585
+ { prefix: "ghr_", body: "[A-Za-z0-9]{20,}" },
586
+ { prefix: "github_pat_", body: "[A-Za-z0-9_]{50,}" },
587
+ { prefix: "glpat-", body: "[A-Za-z0-9_-]{16,}" },
588
+ { prefix: "xoxa-", body: "[A-Za-z0-9-]{10,}" },
589
+ { prefix: "xoxb-", body: "[A-Za-z0-9-]{10,}" },
590
+ { prefix: "xoxo-", body: "[A-Za-z0-9-]{10,}" },
591
+ { prefix: "xoxp-", body: "[A-Za-z0-9-]{10,}" },
592
+ { prefix: "xoxr-", body: "[A-Za-z0-9-]{10,}" },
593
+ { prefix: "xoxs-", body: "[A-Za-z0-9-]{10,}" },
594
+ { prefix: "sk-", body: "[A-Za-z0-9_-]{20,}" },
595
+ { prefix: "pk-", body: "[A-Za-z0-9_-]{20,}" },
596
+ { prefix: "rk-", body: "[A-Za-z0-9_-]{20,}" },
597
+ { prefix: "sk_live_", body: "[A-Za-z0-9]{16,}" },
598
+ { prefix: "rk_live_", body: "[A-Za-z0-9]{16,}" },
599
+ { prefix: "AKIA", body: String.raw`[0-9A-Z]{16}\b` },
600
+ { prefix: "ASIA", body: String.raw`[0-9A-Z]{16}\b` },
601
+ { prefix: "AIza", body: String.raw`[0-9A-Za-z_-]{35}\b` },
602
+ { prefix: "ya29.", body: "[0-9A-Za-z_-]{20,}" },
603
+ { prefix: "hf_", body: "[A-Za-z0-9]{30,}" },
604
+ { prefix: "dop_v1_", body: "[a-f0-9]{60,}" },
605
+ { prefix: "shpat_", body: "[a-fA-F0-9]{32,}" },
606
+ // SendGrid: a key id and its secret, dot-separated.
607
+ { prefix: "SG.", body: String.raw`[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}` },
608
+ // A JWT: three base64url segments, the first two of which decode from `{"` and so always begin `eyJ` and `ey`.
609
+ { prefix: "eyJ", body: String.raw`[A-Za-z0-9_-]{9,}\.ey[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]*` }
610
+ ];
611
+ var CREDENTIAL_ISSUER_PREFIXES = CREDENTIAL_ISSUERS.map(({ prefix }) => prefix);
612
+ var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
613
+ var ISSUER_PREFIX = new RegExp(`^(?:${CREDENTIAL_ISSUER_PREFIXES.map(escapeRegExp).join("|")})`);
614
+ var ISSUED_TOKENS = CREDENTIAL_ISSUERS.map(({ prefix, body }) => new RegExp(String.raw`(?<![\w-])${escapeRegExp(prefix)}${body}`, "g"));
574
615
  var NUMERIC_VALUE = /^[\d_,.]+$/;
575
616
  var STRUCTURAL_VALUE = /[\s/\\${}]/;
576
617
  var ENV_NAME_VALUE = /^[A-Z0-9_]+$/;
@@ -583,13 +624,38 @@ var SECRET_PATTERNS = [
583
624
  // Quoted and bare arrive in different groups because only the quoted one has a quote to put back.
584
625
  (match, assignment, quote, quoted, bare) => looksLikeCredential(quoted ?? bare) ? `${assignment}${quote ?? ""}***${quote ?? ""}` : match
585
626
  ],
586
- [/\bAKIA[0-9A-Z]{16}\b/g, "***"],
627
+ ...ISSUED_TOKENS.map((token) => [token, "***"]),
587
628
  // Same rule for a bearer value: prose about tokens carries no digit, every real bearer token does.
588
629
  [/\b(Bearer\s+)(?=[\w.-]*\d)[\w.-]{8,}/gi, "$1***"],
589
- [/\b(https?:\/\/[^:@\s/]+:)[^@\s]+@/gi, "$1***@"]
630
+ // scheme://user:password@host for any scheme (a postgres DSN as much as an https remote). Any length, unlike the
631
+ // contract's three-character floor: output reaching a model is not a file someone meant to publish. A `/` ends the
632
+ // password, so `http://host:3000/@scope/pkg` is a port and a path, and a reference already standing in is kept.
633
+ [/\b([a-z][a-z0-9+.-]*:\/\/[^:@\s/]+:)(?!\{\{secret:)[^@\s/]+@/gi, "$1***@"]
590
634
  ];
591
- var redactText = (text, values = []) => text.split("\n").map((line) => redactLine(line, values)).join("\n");
592
- var redactLine = (line, values = []) => {
635
+ var MASKED_NEXT = String.raw`(?!(?:\s|\\[nr])*\*\*\*)`;
636
+ var ARMOR_LINES = String.raw`(?:(?:\s|\\[nr])+(?:[A-Za-z-]+:[^\n\\]*|[A-Za-z0-9+/=]+(?=[ \t]*(?:[\r\n"'\x60<>,;})\]]|\\[nr]|$))))*`;
637
+ var PRIVATE_KEY_BLOCK = new RegExp(
638
+ String.raw`(-----BEGIN ((?:[A-Z0-9]+ )*)PRIVATE KEY( BLOCK)?-----)${MASKED_NEXT}(?:[\s\S]*?(-----END \2PRIVATE KEY\3-----)|${ARMOR_LINES})`,
639
+ "g"
640
+ );
641
+ var PUTTY_KEY = new RegExp(String.raw`(PuTTY-User-Key-File-\d:)${MASKED_NEXT}[^\n\\]*${ARMOR_LINES}`, "g");
642
+ var maskKeyBlocks = (text) => (
643
+ // The cheap test first: almost no output holds a key, and the block patterns scan the whole body.
644
+ text.includes("PRIVATE KEY") || text.includes("PuTTY-User-Key-File-") ? text.replace(
645
+ PRIVATE_KEY_BLOCK,
646
+ (_block, header, _label, _kind, footer) => footer === void 0 ? `${header}
647
+ ***` : `${header}
648
+ ***
649
+ ${footer}`
650
+ ).replace(PUTTY_KEY, "$1 ***") : text
651
+ );
652
+ var redactLines = (lines, values = []) => {
653
+ const joined = lines.join("\n");
654
+ const keyed = maskKeyBlocks(joined);
655
+ return (keyed === joined ? lines : keyed.split("\n")).map((line) => redactLine(line, values));
656
+ };
657
+ var redactText = (text, values = []) => redactLines(text.split("\n"), values).join("\n");
658
+ var redactLine = (line, values) => {
593
659
  let masked = line;
594
660
  for (const { target, replacement } of values) {
595
661
  if (masked.includes(target)) {
@@ -637,12 +703,6 @@ import { join as join2 } from "node:path";
637
703
  var fieldNotesFile = (project) => join2(project, ".claude", "intentic", "field-notes.toon");
638
704
  var transcriptDir = (project, env = process.env) => join2(env["CLAUDE_CONFIG_DIR"] ?? join2(homedir(), ".claude"), "projects", project.replace(/[^a-zA-Z0-9]/g, "-"));
639
705
 
640
- // src/runtime.ts
641
- var isMissing2 = (error) => {
642
- const code = typeof error === "object" && error !== null ? error.code : void 0;
643
- return code === "ENOENT" || code === "ENOTDIR";
644
- };
645
-
646
706
  // src/notes-evidence.ts
647
707
  var MAX_SESSIONS = 200;
648
708
  var BUDGET_CHARS = 12e3;
@@ -768,7 +828,7 @@ var sessionFiles = (dir) => {
768
828
  try {
769
829
  names = readdirSync2(dir).filter((name) => name.endsWith(".jsonl"));
770
830
  } catch (error) {
771
- if (isMissing2(error)) {
831
+ if (isMissing(error)) {
772
832
  return [];
773
833
  }
774
834
  throw error;
@@ -7,6 +7,7 @@ import { join as join4 } from "node:path";
7
7
  import { createHash } from "node:crypto";
8
8
  import { closeSync, fstatSync, mkdirSync, openSync, readFileSync, writeFileSync } from "node:fs";
9
9
  import { dirname, join } from "node:path";
10
+ import * as util from "node:util";
10
11
  var ANSI = /\x1b(?:\[[0-9;?]*[ -/]*[@-~]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-Z\\-_])/g;
11
12
  var collapseCr = (line) => {
12
13
  const frames = line.split("\r");
@@ -270,27 +271,90 @@ var SECRET_NAME = String.raw`[A-Za-z0-9_]*(?:TOKEN|SECRET|PASSWORD|PASSWD|API[_-
270
271
  var ASSIGN = String.raw`["']?\s*[:=](?![=>])\s*`;
271
272
  var QUOTED_VALUE = String.raw`(["'\x60])([^"'\x60\n]{6,})\2`;
272
273
  var BARE_VALUE = String.raw`[\w+/=~-]{6,}(?![\w+/=~(-])`;
273
- var ISSUER_PREFIX = /^(?:sk-|pk-|rk-|ghp_|gho_|ghu_|ghs_|ghr_|github_pat_|xox[abposr]-|AKIA|ASIA|eyJ|AIza|ya29\.|glpat-|dop_v1_|shpat_|SG\.|npm_)/;
274
+ var CREDENTIAL_ISSUERS = [
275
+ { prefix: "npm_", body: "[A-Za-z0-9]{30,}" },
276
+ { prefix: "ghp_", body: "[A-Za-z0-9]{20,}" },
277
+ { prefix: "gho_", body: "[A-Za-z0-9]{20,}" },
278
+ { prefix: "ghu_", body: "[A-Za-z0-9]{20,}" },
279
+ { prefix: "ghs_", body: "[A-Za-z0-9]{20,}" },
280
+ { prefix: "ghr_", body: "[A-Za-z0-9]{20,}" },
281
+ { prefix: "github_pat_", body: "[A-Za-z0-9_]{50,}" },
282
+ { prefix: "glpat-", body: "[A-Za-z0-9_-]{16,}" },
283
+ { prefix: "xoxa-", body: "[A-Za-z0-9-]{10,}" },
284
+ { prefix: "xoxb-", body: "[A-Za-z0-9-]{10,}" },
285
+ { prefix: "xoxo-", body: "[A-Za-z0-9-]{10,}" },
286
+ { prefix: "xoxp-", body: "[A-Za-z0-9-]{10,}" },
287
+ { prefix: "xoxr-", body: "[A-Za-z0-9-]{10,}" },
288
+ { prefix: "xoxs-", body: "[A-Za-z0-9-]{10,}" },
289
+ { prefix: "sk-", body: "[A-Za-z0-9_-]{20,}" },
290
+ { prefix: "pk-", body: "[A-Za-z0-9_-]{20,}" },
291
+ { prefix: "rk-", body: "[A-Za-z0-9_-]{20,}" },
292
+ { prefix: "sk_live_", body: "[A-Za-z0-9]{16,}" },
293
+ { prefix: "rk_live_", body: "[A-Za-z0-9]{16,}" },
294
+ { prefix: "AKIA", body: String.raw`[0-9A-Z]{16}\b` },
295
+ { prefix: "ASIA", body: String.raw`[0-9A-Z]{16}\b` },
296
+ { prefix: "AIza", body: String.raw`[0-9A-Za-z_-]{35}\b` },
297
+ { prefix: "ya29.", body: "[0-9A-Za-z_-]{20,}" },
298
+ { prefix: "hf_", body: "[A-Za-z0-9]{30,}" },
299
+ { prefix: "dop_v1_", body: "[a-f0-9]{60,}" },
300
+ { prefix: "shpat_", body: "[a-fA-F0-9]{32,}" },
301
+ // SendGrid: a key id and its secret, dot-separated.
302
+ { prefix: "SG.", body: String.raw`[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}` },
303
+ // A JWT: three base64url segments, the first two of which decode from `{"` and so always begin `eyJ` and `ey`.
304
+ { prefix: "eyJ", body: String.raw`[A-Za-z0-9_-]{9,}\.ey[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]*` }
305
+ ];
306
+ var CREDENTIAL_ISSUER_PREFIXES = CREDENTIAL_ISSUERS.map(({ prefix }) => prefix);
307
+ var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
308
+ var ISSUER_PREFIX = new RegExp(`^(?:${CREDENTIAL_ISSUER_PREFIXES.map(escapeRegExp).join("|")})`);
309
+ var ISSUED_TOKENS = CREDENTIAL_ISSUERS.map(({ prefix, body }) => new RegExp(String.raw`(?<![\w-])${escapeRegExp(prefix)}${body}`, "g"));
274
310
  var NUMERIC_VALUE = /^[\d_,.]+$/;
275
311
  var STRUCTURAL_VALUE = /[\s/\\${}]/;
276
312
  var ENV_NAME_VALUE = /^[A-Z0-9_]+$/;
277
313
  var ENTROPIC_VALUE = /^(?=[^\n]*\d)(?=[^\n]*[A-Za-z])/;
278
314
  var HANDWRITTEN_MAX = 12;
279
315
  var looksLikeCredential = (value) => ISSUER_PREFIX.test(value) || value.length > HANDWRITTEN_MAX && ENTROPIC_VALUE.test(value) && !NUMERIC_VALUE.test(value) && !STRUCTURAL_VALUE.test(value) && !ENV_NAME_VALUE.test(value);
316
+ var secretReference = (name) => `{{secret:${name}}}`;
280
317
  var SECRET_PATTERNS = [
281
318
  [
282
319
  new RegExp(`\\b(${SECRET_NAME}${ASSIGN})(?:${QUOTED_VALUE}|(${BARE_VALUE}))`, "gi"),
283
320
  // Quoted and bare arrive in different groups because only the quoted one has a quote to put back.
284
321
  (match, assignment, quote, quoted, bare) => looksLikeCredential(quoted ?? bare) ? `${assignment}${quote ?? ""}***${quote ?? ""}` : match
285
322
  ],
286
- [/\bAKIA[0-9A-Z]{16}\b/g, "***"],
323
+ ...ISSUED_TOKENS.map((token) => [token, "***"]),
287
324
  // Same rule for a bearer value: prose about tokens carries no digit, every real bearer token does.
288
325
  [/\b(Bearer\s+)(?=[\w.-]*\d)[\w.-]{8,}/gi, "$1***"],
289
- [/\b(https?:\/\/[^:@\s/]+:)[^@\s]+@/gi, "$1***@"]
326
+ // scheme://user:password@host for any scheme (a postgres DSN as much as an https remote). Any length, unlike the
327
+ // contract's three-character floor: output reaching a model is not a file someone meant to publish. A `/` ends the
328
+ // password, so `http://host:3000/@scope/pkg` is a port and a path, and a reference already standing in is kept.
329
+ [/\b([a-z][a-z0-9+.-]*:\/\/[^:@\s/]+:)(?!\{\{secret:)[^@\s/]+@/gi, "$1***@"]
290
330
  ];
331
+ var MASKED_NEXT = String.raw`(?!(?:\s|\\[nr])*\*\*\*)`;
332
+ var ARMOR_LINES = String.raw`(?:(?:\s|\\[nr])+(?:[A-Za-z-]+:[^\n\\]*|[A-Za-z0-9+/=]+(?=[ \t]*(?:[\r\n"'\x60<>,;})\]]|\\[nr]|$))))*`;
333
+ var PRIVATE_KEY_BLOCK = new RegExp(
334
+ String.raw`(-----BEGIN ((?:[A-Z0-9]+ )*)PRIVATE KEY( BLOCK)?-----)${MASKED_NEXT}(?:[\s\S]*?(-----END \2PRIVATE KEY\3-----)|${ARMOR_LINES})`,
335
+ "g"
336
+ );
337
+ var PUTTY_KEY = new RegExp(String.raw`(PuTTY-User-Key-File-\d:)${MASKED_NEXT}[^\n\\]*${ARMOR_LINES}`, "g");
338
+ var maskKeyBlocks = (text) => (
339
+ // The cheap test first: almost no output holds a key, and the block patterns scan the whole body.
340
+ text.includes("PRIVATE KEY") || text.includes("PuTTY-User-Key-File-") ? text.replace(
341
+ PRIVATE_KEY_BLOCK,
342
+ (_block, header, _label, _kind, footer) => footer === void 0 ? `${header}
343
+ ***` : `${header}
344
+ ***
345
+ ${footer}`
346
+ ).replace(PUTTY_KEY, "$1 ***") : text
347
+ );
291
348
  var SECRET_VALUE_MIN = 12;
349
+ var SECRET_STORES = [
350
+ { root: "desiredState", path: ".env", layout: "env", source: "env" },
351
+ // Pasted on a need's card or the Secrets view (src/secrets/sandbox-secrets.ts).
352
+ { root: "auth", path: "sandbox-secrets.json", layout: "flat", source: "sandbox" },
353
+ { root: "desiredState", path: ".secrets.json", layout: "flat", source: "generated" },
354
+ { root: "auth", path: "capability-secrets.json", layout: "vault", source: "capability" }
355
+ ];
292
356
  var secretValueCache = /* @__PURE__ */ new Map();
293
- var readIfChanged = (path, name) => {
357
+ var readIfChanged = (path, layout) => {
294
358
  try {
295
359
  const descriptor = openSync(path, "r");
296
360
  try {
@@ -300,7 +364,7 @@ var readIfChanged = (path, name) => {
300
364
  if (cached?.stamp === stamp) {
301
365
  return cached.values;
302
366
  }
303
- const values = harvest(readFileSync(descriptor, "utf8"), path, name);
367
+ const values = harvest(readFileSync(descriptor, "utf8"), layout);
304
368
  secretValueCache.set(path, { stamp, values });
305
369
  return values;
306
370
  } finally {
@@ -325,33 +389,19 @@ var surfaceForms = (value) => {
325
389
  }
326
390
  return forms;
327
391
  };
328
- var harvest = (text, path, name) => {
329
- const named = [];
330
- if (path.endsWith("capability-secrets.json")) {
331
- for (const [id, entry] of Object.entries(JSON.parse(text))) {
332
- if (entry === null || typeof entry !== "object") {
333
- continue;
334
- }
335
- for (const [field, value] of Object.entries(entry)) {
336
- if (typeof value === "string") {
337
- named.push([name(id, field), value]);
338
- }
339
- }
340
- }
341
- } else if (path.endsWith(".json")) {
342
- for (const [key, value] of Object.entries(JSON.parse(text))) {
343
- if (typeof value === "string") {
344
- named.push([name(key), value]);
345
- }
346
- }
347
- } else {
348
- for (const line of text.split("\n")) {
349
- const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(line);
350
- if (match !== null) {
351
- named.push([name(match[1]), (match[2] ?? "").trim().replace(/^(["'])([\s\S]*)\1$/, "$2")]);
352
- }
353
- }
392
+ var namedValues = (text, layout) => {
393
+ if (layout === "env") {
394
+ return Object.entries(util.parseEnv(text));
354
395
  }
396
+ const parsed = JSON.parse(text);
397
+ if (layout === "flat") {
398
+ return Object.entries(parsed).filter(([, value]) => typeof value === "string");
399
+ }
400
+ return Object.entries(parsed).flatMap(
401
+ ([id, entry]) => entry === null || typeof entry !== "object" ? [] : Object.entries(entry).flatMap(([field, value]) => typeof value === "string" ? [[`${id}/${field}`, value]] : [])
402
+ );
403
+ };
404
+ var harvest = (text, layout) => {
355
405
  const byTarget = /* @__PURE__ */ new Map();
356
406
  const add = (target, replacement) => {
357
407
  const trimmed = target.trim();
@@ -359,9 +409,9 @@ var harvest = (text, path, name) => {
359
409
  byTarget.set(trimmed, { target: trimmed, replacement });
360
410
  }
361
411
  };
362
- for (const [reference, value] of named) {
412
+ for (const [name, value] of namedValues(text, layout)) {
363
413
  for (const form of surfaceForms(value.trim())) {
364
- add(form, `{{secret:${reference}}}`);
414
+ add(form, secretReference(name));
365
415
  }
366
416
  if (value.includes("\n")) {
367
417
  for (const line of value.split("\n")) {
@@ -372,16 +422,21 @@ var harvest = (text, path, name) => {
372
422
  return [...byTarget.values()].toSorted((a, b) => b.target.length - a.target.length);
373
423
  };
374
424
  var secretValues = (env = process.env) => {
375
- const authRoot = env.AGENT_AUTH_DIR !== void 0 && env.AGENT_AUTH_DIR !== "" ? env.AGENT_AUTH_DIR : join(env.WORKSPACE_ROOT ?? "/work", ".intentic/secrets/auth");
376
- const repo = join(env.WORKSPACE_ROOT ?? "/work", "desired-state");
377
- return [
378
- ...readIfChanged(join(authRoot, "capability-secrets.json"), (id, field) => `${id}/${field}`),
379
- ...readIfChanged(join(repo, ".env"), (key) => key),
380
- ...readIfChanged(join(repo, ".secrets.json"), (key) => key)
381
- ].toSorted((a, b) => b.target.length - a.target.length);
382
- };
383
- var redactText = (text, values = []) => text.split("\n").map((line) => redactLine(line, values)).join("\n");
384
- var redactLine = (line, values = []) => {
425
+ const roots = {
426
+ auth: env.AGENT_AUTH_DIR !== void 0 && env.AGENT_AUTH_DIR !== "" ? env.AGENT_AUTH_DIR : join(env.WORKSPACE_ROOT ?? "/work", ".intentic/secrets/auth"),
427
+ desiredState: join(env.WORKSPACE_ROOT ?? "/work", "desired-state")
428
+ };
429
+ return SECRET_STORES.flatMap(({ root, path, layout }) => readIfChanged(join(roots[root], path), layout)).toSorted(
430
+ (a, b) => b.target.length - a.target.length
431
+ );
432
+ };
433
+ var redactLines = (lines, values = []) => {
434
+ const joined = lines.join("\n");
435
+ const keyed = maskKeyBlocks(joined);
436
+ return (keyed === joined ? lines : keyed.split("\n")).map((line) => redactLine(line, values));
437
+ };
438
+ var redactText = (text, values = []) => redactLines(text.split("\n"), values).join("\n");
439
+ var redactLine = (line, values) => {
385
440
  let masked = line;
386
441
  for (const { target, replacement } of values) {
387
442
  if (masked.includes(target)) {
@@ -492,7 +547,7 @@ var cleanLines = (lines, { command, exitCode, enabled, values = [] }) => {
492
547
  if (enabled.has("redact")) {
493
548
  out = ran(
494
549
  "redact",
495
- out.map((line) => redactLine(line, values))
550
+ redactLines(out, values)
496
551
  );
497
552
  }
498
553
  return { lines: out, stages };
@@ -747,6 +802,9 @@ if (process.argv[1]?.endsWith("agent-output-filter") || process.argv[1]?.endsWit
747
802
  await main();
748
803
  }
749
804
 
805
+ // ../../_tools/base/src/errors.ts
806
+ var errorMessage = (error) => error instanceof Error ? error.message : String(error);
807
+
750
808
  // src/features.ts
751
809
  var OPTIONS = {
752
810
  output_cleaners: {
@@ -865,7 +923,7 @@ var runHook = async (handle) => {
865
923
  `);
866
924
  }
867
925
  } catch (error) {
868
- process.stderr.write(`intentic: ${error instanceof Error ? error.message : String(error)}
926
+ process.stderr.write(`intentic: ${errorMessage(error)}
869
927
  `);
870
928
  }
871
929
  };
@@ -6,6 +6,11 @@ import { spawnSync } from "node:child_process";
6
6
  // src/runtime.ts
7
7
  import { accessSync, closeSync, constants, mkdirSync, openSync, readFileSync, statSync, writeFileSync } from "node:fs";
8
8
  import { delimiter, dirname, join } from "node:path";
9
+
10
+ // ../../_tools/base/src/errors.ts
11
+ var errorMessage = (error) => error instanceof Error ? error.message : String(error);
12
+
13
+ // src/runtime.ts
9
14
  var onPath = (name, env = process.env) => {
10
15
  const extensions = process.platform === "win32" ? (env["PATHEXT"] ?? ".EXE;.CMD;.BAT").split(";") : [""];
11
16
  for (const dir of (env["PATH"] ?? "").split(delimiter)) {
@@ -136,7 +141,7 @@ var runHook = async (handle) => {
136
141
  `);
137
142
  }
138
143
  } catch (error) {
139
- process.stderr.write(`intentic: ${error instanceof Error ? error.message : String(error)}
144
+ process.stderr.write(`intentic: ${errorMessage(error)}
140
145
  `);
141
146
  }
142
147
  };