terminal-pilot 0.0.20 → 0.0.22

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.
Files changed (58) hide show
  1. package/dist/cli.js +1011 -452
  2. package/dist/cli.js.map +4 -4
  3. package/dist/commands/close-session.js +6 -4
  4. package/dist/commands/close-session.js.map +3 -3
  5. package/dist/commands/create-session.js +6 -4
  6. package/dist/commands/create-session.js.map +3 -3
  7. package/dist/commands/fill.js +6 -4
  8. package/dist/commands/fill.js.map +3 -3
  9. package/dist/commands/get-session.js +6 -4
  10. package/dist/commands/get-session.js.map +3 -3
  11. package/dist/commands/index.js +299 -159
  12. package/dist/commands/index.js.map +4 -4
  13. package/dist/commands/install.js +251 -113
  14. package/dist/commands/install.js.map +4 -4
  15. package/dist/commands/installer.js +190 -62
  16. package/dist/commands/installer.js.map +4 -4
  17. package/dist/commands/list-sessions.js +6 -4
  18. package/dist/commands/list-sessions.js.map +3 -3
  19. package/dist/commands/press-key.js +6 -4
  20. package/dist/commands/press-key.js.map +3 -3
  21. package/dist/commands/read-history.js +6 -4
  22. package/dist/commands/read-history.js.map +3 -3
  23. package/dist/commands/read-screen.js +6 -4
  24. package/dist/commands/read-screen.js.map +3 -3
  25. package/dist/commands/resize.js +6 -4
  26. package/dist/commands/resize.js.map +3 -3
  27. package/dist/commands/runtime.js +6 -4
  28. package/dist/commands/runtime.js.map +3 -3
  29. package/dist/commands/screenshot.js +17 -8
  30. package/dist/commands/screenshot.js.map +3 -3
  31. package/dist/commands/send-signal.js +6 -4
  32. package/dist/commands/send-signal.js.map +3 -3
  33. package/dist/commands/type.js +6 -4
  34. package/dist/commands/type.js.map +3 -3
  35. package/dist/commands/uninstall.js +226 -98
  36. package/dist/commands/uninstall.js.map +4 -4
  37. package/dist/commands/wait-for-exit.js +6 -4
  38. package/dist/commands/wait-for-exit.js.map +3 -3
  39. package/dist/commands/wait-for.js +6 -4
  40. package/dist/commands/wait-for.js.map +3 -3
  41. package/dist/errors.d.ts +1 -0
  42. package/dist/errors.js +8 -0
  43. package/dist/errors.js.map +7 -0
  44. package/dist/index.js +8 -4
  45. package/dist/index.js.map +3 -3
  46. package/dist/terminal-pilot.js +6 -4
  47. package/dist/terminal-pilot.js.map +3 -3
  48. package/dist/terminal-session.js +6 -4
  49. package/dist/terminal-session.js.map +3 -3
  50. package/dist/testing/cli-repl.js +1011 -452
  51. package/dist/testing/cli-repl.js.map +4 -4
  52. package/dist/testing/qa-cli.js +1011 -452
  53. package/dist/testing/qa-cli.js.map +4 -4
  54. package/node_modules/@poe-code/agent-skill-config/dist/apply.js +4 -1
  55. package/node_modules/@poe-code/agent-skill-config/dist/bridge-active-skills.js +1 -1
  56. package/node_modules/@poe-code/agent-skill-config/dist/git-exclude.js +17 -9
  57. package/node_modules/@poe-code/agent-skill-config/dist/templates.js +4 -1
  58. package/package.json +2 -1
@@ -78,12 +78,12 @@ function consumeTerminatedString(input, index, allowBellTerminator) {
78
78
  }
79
79
 
80
80
  // src/cli.ts
81
- import { realpath as realpath2 } from "node:fs/promises";
81
+ import { realpath as realpath3 } from "node:fs/promises";
82
82
  import path23 from "node:path";
83
83
  import { fileURLToPath as fileURLToPath5 } from "node:url";
84
84
 
85
85
  // ../toolcraft/src/cli.ts
86
- import { access as access2, lstat as lstat3, readFile as readFile4, rename as rename3, unlink as unlink2, writeFile as writeFile5 } from "node:fs/promises";
86
+ import { access as access2, lstat as lstat3, readFile as readFile4, rename as rename3, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
87
87
  import path14 from "node:path";
88
88
  import {
89
89
  Command as CommanderCommand,
@@ -92,7 +92,7 @@ import {
92
92
  Option
93
93
  } from "commander";
94
94
 
95
- // ../design-system/src/internal/color-support.ts
95
+ // ../toolcraft-design/src/internal/color-support.ts
96
96
  function supportsColor(env = process.env, stream = process.stdout) {
97
97
  if (env.FORCE_COLOR !== void 0 && env.FORCE_COLOR !== "0") {
98
98
  return true;
@@ -106,7 +106,7 @@ function supportsColor(env = process.env, stream = process.stdout) {
106
106
  return typeof env.TERM === "string" && env.TERM.length > 0 && env.TERM !== "dumb";
107
107
  }
108
108
 
109
- // ../design-system/src/components/color.ts
109
+ // ../toolcraft-design/src/components/color.ts
110
110
  var reset = "\x1B[0m";
111
111
  var ansiStyles = {
112
112
  reset: { open: reset },
@@ -208,41 +208,135 @@ function createColor(styles = []) {
208
208
  }
209
209
  var color = createColor();
210
210
 
211
- // ../design-system/src/tokens/colors.ts
212
- var dark = {
213
- header: (text5) => color.magentaBright.bold(text5),
214
- divider: (text5) => color.dim(text5),
215
- prompt: (text5) => color.cyan(text5),
216
- number: (text5) => color.cyanBright(text5),
217
- intro: (text5) => color.bgMagenta.white(` Poe - ${text5} `),
218
- resolvedSymbol: color.magenta("\u25C7"),
219
- errorSymbol: color.red("\u25A0"),
220
- accent: (text5) => color.cyan(text5),
221
- muted: (text5) => color.dim(text5),
222
- success: (text5) => color.green(text5),
223
- warning: (text5) => color.yellow(text5),
224
- error: (text5) => color.red(text5),
225
- info: (text5) => color.magenta(text5),
226
- badge: (text5) => color.bgYellow.black(` ${text5} `)
211
+ // ../toolcraft-design/src/tokens/brand.ts
212
+ var brands = {
213
+ purple: { name: "purple", primary: "#a200ff" },
214
+ blue: { name: "blue", primary: "#2f6fed" },
215
+ green: { name: "green", primary: "#1f9d57" }
227
216
  };
228
- var light = {
229
- header: (text5) => color.hex("#a200ff").bold(text5),
230
- divider: (text5) => color.hex("#666666")(text5),
231
- prompt: (text5) => color.hex("#006699").bold(text5),
232
- number: (text5) => color.hex("#0077cc").bold(text5),
233
- intro: (text5) => color.bgHex("#a200ff").white(` Poe - ${text5} `),
234
- resolvedSymbol: color.hex("#a200ff")("\u25C7"),
235
- errorSymbol: color.hex("#cc0000")("\u25A0"),
236
- accent: (text5) => color.hex("#006699").bold(text5),
237
- muted: (text5) => color.hex("#666666")(text5),
238
- success: (text5) => color.hex("#008800")(text5),
239
- warning: (text5) => color.hex("#cc6600")(text5),
240
- error: (text5) => color.hex("#cc0000")(text5),
241
- info: (text5) => color.hex("#a200ff")(text5),
242
- badge: (text5) => color.bgHex("#cc6600").white(` ${text5} `)
217
+
218
+ // ../toolcraft-design/src/internal/theme-state.ts
219
+ var defaults = {
220
+ brand: "purple",
221
+ label: "Poe"
243
222
  };
223
+ var config = { ...defaults };
224
+ var revision = 0;
225
+ var brandConfigured = false;
226
+ function configureTheme(patch) {
227
+ if (patch.brand !== void 0 && !Object.hasOwn(brands, patch.brand)) {
228
+ throw new Error(`Unknown brand: ${patch.brand}`);
229
+ }
230
+ config = {
231
+ brand: patch.brand ?? config.brand,
232
+ label: patch.label ?? config.label
233
+ };
234
+ if (patch.brand !== void 0) {
235
+ brandConfigured = true;
236
+ }
237
+ revision += 1;
238
+ }
239
+ function getThemeConfig() {
240
+ return { ...config };
241
+ }
242
+ function getThemeRevision() {
243
+ return revision;
244
+ }
245
+ function isThemeBrandConfigured() {
246
+ return brandConfigured;
247
+ }
248
+
249
+ // ../toolcraft-design/src/tokens/colors.ts
250
+ var brand = brands.purple.primary;
251
+ function withStyles(palette, styles) {
252
+ return Object.defineProperty(palette, "styles", {
253
+ value: styles,
254
+ enumerable: false
255
+ });
256
+ }
257
+ function brandColor(activeBrand, purple) {
258
+ return activeBrand.name === "purple" ? purple : color.hex(activeBrand.primary);
259
+ }
260
+ function brandBackground(activeBrand, purple) {
261
+ return activeBrand.name === "purple" ? purple : color.bgHex(activeBrand.primary);
262
+ }
263
+ function createPalette(activeBrand, mode) {
264
+ const isPurple = activeBrand.name === "purple";
265
+ if (mode === "light") {
266
+ const active2 = color.hex(activeBrand.primary);
267
+ const prompt2 = isPurple ? color.hex("#006699") : active2;
268
+ const number2 = isPurple ? color.hex("#0077cc") : active2;
269
+ return withStyles(
270
+ {
271
+ header: (text5) => active2.bold(text5),
272
+ divider: (text5) => color.hex("#666666")(text5),
273
+ prompt: (text5) => prompt2.bold(text5),
274
+ number: (text5) => number2.bold(text5),
275
+ intro: (text5) => color.bgHex(activeBrand.primary).white(` ${getThemeConfig().label} - ${text5} `),
276
+ get resolvedSymbol() {
277
+ return active2("\u25C7");
278
+ },
279
+ get errorSymbol() {
280
+ return color.hex("#cc0000")("\u25A0");
281
+ },
282
+ accent: (text5) => prompt2.bold(text5),
283
+ muted: (text5) => color.hex("#666666")(text5),
284
+ success: (text5) => color.hex("#008800")(text5),
285
+ warning: (text5) => color.hex("#cc6600")(text5),
286
+ error: (text5) => color.hex("#cc0000")(text5),
287
+ info: (text5) => active2(text5),
288
+ badge: (text5) => color.bgHex("#cc6600").white(` ${text5} `)
289
+ },
290
+ {
291
+ accent: { fg: isPurple ? "#006699" : activeBrand.primary, bold: true },
292
+ muted: { fg: "#666666" },
293
+ success: { fg: "#008800" },
294
+ warning: { fg: "#cc6600" },
295
+ error: { fg: "#cc0000" },
296
+ info: { fg: activeBrand.primary }
297
+ }
298
+ );
299
+ }
300
+ const active = brandColor(activeBrand, color.magenta);
301
+ const activeBright = brandColor(activeBrand, color.magentaBright);
302
+ const activeBackground = brandBackground(activeBrand, color.bgMagenta);
303
+ const prompt = isPurple ? color.cyan : active;
304
+ const number = isPurple ? color.cyanBright : active;
305
+ return withStyles(
306
+ {
307
+ header: (text5) => activeBright.bold(text5),
308
+ divider: (text5) => color.dim(text5),
309
+ prompt: (text5) => prompt(text5),
310
+ number: (text5) => number(text5),
311
+ intro: (text5) => activeBackground.white(` ${getThemeConfig().label} - ${text5} `),
312
+ get resolvedSymbol() {
313
+ return active("\u25C7");
314
+ },
315
+ get errorSymbol() {
316
+ return color.red("\u25A0");
317
+ },
318
+ accent: (text5) => prompt(text5),
319
+ muted: (text5) => color.dim(text5),
320
+ success: (text5) => color.green(text5),
321
+ warning: (text5) => color.yellow(text5),
322
+ error: (text5) => color.red(text5),
323
+ info: (text5) => active(text5),
324
+ badge: (text5) => color.bgYellow.black(` ${text5} `)
325
+ },
326
+ {
327
+ accent: { fg: isPurple ? "cyan" : activeBrand.primary, bold: true },
328
+ muted: { dim: true },
329
+ success: { fg: "green" },
330
+ warning: { fg: "yellow" },
331
+ error: { fg: "red" },
332
+ info: { fg: isPurple ? "magenta" : activeBrand.primary }
333
+ }
334
+ );
335
+ }
336
+ var dark = createPalette(brands.purple, "dark");
337
+ var light = createPalette(brands.purple, "light");
244
338
 
245
- // ../design-system/src/tokens/typography.ts
339
+ // ../toolcraft-design/src/tokens/typography.ts
246
340
  var typography = {
247
341
  bold: (text5) => color.bold(text5),
248
342
  dim: (text5) => color.dim(text5),
@@ -251,14 +345,14 @@ var typography = {
251
345
  strikethrough: (text5) => color.strikethrough(text5)
252
346
  };
253
347
 
254
- // ../design-system/src/tokens/widths.ts
348
+ // ../toolcraft-design/src/tokens/widths.ts
255
349
  var widths = {
256
350
  header: 60,
257
351
  helpColumn: 24,
258
352
  maxLine: 80
259
353
  };
260
354
 
261
- // ../design-system/src/internal/output-format.ts
355
+ // ../toolcraft-design/src/internal/output-format.ts
262
356
  import { AsyncLocalStorage } from "node:async_hooks";
263
357
  var VALID_FORMATS = /* @__PURE__ */ new Set(["terminal", "markdown", "json"]);
264
358
  var formatStorage = new AsyncLocalStorage();
@@ -279,7 +373,7 @@ function resetOutputFormatCache() {
279
373
  cached = void 0;
280
374
  }
281
375
 
282
- // ../design-system/src/internal/theme-detect.ts
376
+ // ../toolcraft-design/src/internal/theme-detect.ts
283
377
  function detectThemeFromEnv(env) {
284
378
  const apple = env.APPLE_INTERFACE_STYLE;
285
379
  if (typeof apple === "string") {
@@ -316,17 +410,30 @@ function resolveThemeName(env = process.env) {
316
410
  }
317
411
  return "dark";
318
412
  }
319
- var cachedTheme;
413
+ var themeCache = /* @__PURE__ */ new Map();
414
+ var cachedRevision = -1;
320
415
  function getTheme(env) {
416
+ const themeName = resolveThemeName(env);
417
+ const config2 = getThemeConfig();
418
+ const requestedBrand = env?.POE_BRAND?.toLowerCase();
419
+ const activeBrandName = !isThemeBrandConfigured() && requestedBrand && Object.hasOwn(brands, requestedBrand) ? requestedBrand : config2.brand;
420
+ const revision2 = getThemeRevision();
421
+ if (revision2 !== cachedRevision) {
422
+ themeCache.clear();
423
+ cachedRevision = revision2;
424
+ }
425
+ const cacheKey = `${activeBrandName}:${themeName}`;
426
+ const cachedTheme = themeCache.get(cacheKey);
321
427
  if (cachedTheme) {
322
428
  return cachedTheme;
323
429
  }
324
- const themeName = resolveThemeName(env);
325
- cachedTheme = themeName === "light" ? light : dark;
326
- return cachedTheme;
430
+ const activeBrand = brands[activeBrandName];
431
+ const theme = activeBrandName === "purple" ? themeName === "light" ? light : dark : createPalette(activeBrand, themeName);
432
+ themeCache.set(cacheKey, theme);
433
+ return theme;
327
434
  }
328
435
 
329
- // ../design-system/src/components/text.ts
436
+ // ../toolcraft-design/src/components/text.ts
330
437
  function renderMarkdownInline(content) {
331
438
  return content.replaceAll("\r\n", " ").replaceAll("\n", " ").replaceAll("\r", " ");
332
439
  }
@@ -442,7 +549,7 @@ var text = {
442
549
  }
443
550
  };
444
551
 
445
- // ../design-system/src/components/symbols.ts
552
+ // ../toolcraft-design/src/components/symbols.ts
446
553
  var symbols = {
447
554
  get info() {
448
555
  const format = resolveOutputFormat();
@@ -496,12 +603,12 @@ var symbols = {
496
603
  }
497
604
  };
498
605
 
499
- // ../design-system/src/internal/strip-ansi.ts
606
+ // ../toolcraft-design/src/internal/strip-ansi.ts
500
607
  function stripAnsi2(value) {
501
608
  return value.replace(/\u001b\[[0-9;]*m/g, "");
502
609
  }
503
610
 
504
- // ../design-system/src/prompts/primitives/log.ts
611
+ // ../toolcraft-design/src/prompts/primitives/log.ts
505
612
  function renderMarkdownInline2(value) {
506
613
  return stripAnsi2(value).replaceAll("\r\n", " ").replaceAll("\n", " ").replaceAll("\r", " ");
507
614
  }
@@ -628,7 +735,7 @@ var log = {
628
735
  error
629
736
  };
630
737
 
631
- // ../design-system/src/components/logger.ts
738
+ // ../toolcraft-design/src/components/logger.ts
632
739
  function createLogger(emitter) {
633
740
  const emit = (level, message2) => {
634
741
  if (emitter) {
@@ -689,7 +796,7 @@ function createLogger(emitter) {
689
796
  }
690
797
  var logger = createLogger();
691
798
 
692
- // ../design-system/src/components/help-formatter.ts
799
+ // ../toolcraft-design/src/components/help-formatter.ts
693
800
  var graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
694
801
  function normalizeInline(value) {
695
802
  return value.replaceAll("\r\n", " ").replaceAll("\n", " ").replaceAll("\r", " ");
@@ -865,7 +972,7 @@ function formatOptionList(options) {
865
972
  });
866
973
  }
867
974
 
868
- // ../design-system/src/components/help-formatter-plain.ts
975
+ // ../toolcraft-design/src/components/help-formatter-plain.ts
869
976
  var help_formatter_plain_exports = {};
870
977
  __export(help_formatter_plain_exports, {
871
978
  formatColumns: () => formatColumns2,
@@ -1002,7 +1109,7 @@ function formatOptionList2(options) {
1002
1109
  });
1003
1110
  }
1004
1111
 
1005
- // ../design-system/src/components/table.ts
1112
+ // ../toolcraft-design/src/components/table.ts
1006
1113
  var reset2 = "\x1B[0m";
1007
1114
  var ellipsis = "\u2026";
1008
1115
  var graphemeSegmenter2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
@@ -1286,7 +1393,7 @@ function renderTable(options) {
1286
1393
  }
1287
1394
  }
1288
1395
 
1289
- // ../design-system/src/components/detail-card.ts
1396
+ // ../toolcraft-design/src/components/detail-card.ts
1290
1397
  function wrap(value, width) {
1291
1398
  const lines = [];
1292
1399
  for (const paragraph of value.split("\n")) {
@@ -1349,7 +1456,7 @@ ${options.theme.muted(options.badges.map((badge) => badge[0] + badge.slice(1).to
1349
1456
  return blocks.join("\n\n");
1350
1457
  }
1351
1458
 
1352
- // ../design-system/src/components/template.ts
1459
+ // ../toolcraft-design/src/components/template.ts
1353
1460
  var MAX_PARTIAL_DEPTH = 100;
1354
1461
  var HTML_ESCAPE = {
1355
1462
  "&": "&",
@@ -1761,22 +1868,22 @@ function hasProperty(value, key2) {
1761
1868
  return Object.prototype.hasOwnProperty.call(value, key2);
1762
1869
  }
1763
1870
 
1764
- // ../design-system/src/components/browser.ts
1871
+ // ../toolcraft-design/src/components/browser.ts
1765
1872
  import { spawn } from "node:child_process";
1766
1873
  import process2 from "node:process";
1767
1874
 
1768
- // ../design-system/src/acp/writer.ts
1875
+ // ../toolcraft-design/src/acp/writer.ts
1769
1876
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
1770
1877
  var storage = new AsyncLocalStorage2();
1771
1878
 
1772
- // ../design-system/src/dashboard/terminal-width.ts
1879
+ // ../toolcraft-design/src/dashboard/terminal-width.ts
1773
1880
  var graphemeSegmenter3 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1774
1881
 
1775
- // ../design-system/src/dashboard/terminal.ts
1882
+ // ../toolcraft-design/src/dashboard/terminal.ts
1776
1883
  import readline from "node:readline";
1777
1884
  import { PassThrough } from "node:stream";
1778
1885
 
1779
- // ../design-system/src/explorer/state.ts
1886
+ // ../toolcraft-design/src/explorer/state.ts
1780
1887
  var REGION_HEADER = 1 << 0;
1781
1888
  var REGION_LIST = 1 << 1;
1782
1889
  var REGION_DETAIL = 1 << 2;
@@ -1785,10 +1892,10 @@ var REGION_MODAL = 1 << 4;
1785
1892
  var REGION_TOAST = 1 << 5;
1786
1893
  var REGION_ALL = REGION_HEADER | REGION_LIST | REGION_DETAIL | REGION_FOOTER | REGION_MODAL | REGION_TOAST;
1787
1894
 
1788
- // ../design-system/src/prompts/index.ts
1895
+ // ../toolcraft-design/src/prompts/index.ts
1789
1896
  import * as clack from "@clack/prompts";
1790
1897
 
1791
- // ../design-system/src/prompts/primitives/cancel.ts
1898
+ // ../toolcraft-design/src/prompts/primitives/cancel.ts
1792
1899
  import { isCancel } from "@clack/prompts";
1793
1900
  function cancel(msg = "") {
1794
1901
  if (resolveOutputFormat() !== "terminal") {
@@ -1799,7 +1906,7 @@ function cancel(msg = "") {
1799
1906
  `);
1800
1907
  }
1801
1908
 
1802
- // ../design-system/src/prompts/primitives/note.ts
1909
+ // ../toolcraft-design/src/prompts/primitives/note.ts
1803
1910
  function getVisibleWidth(value) {
1804
1911
  return stripAnsi2(value).length;
1805
1912
  }
@@ -1848,10 +1955,10 @@ function note(message2, title) {
1848
1955
  `);
1849
1956
  }
1850
1957
 
1851
- // ../design-system/src/static/spinner.ts
1958
+ // ../toolcraft-design/src/static/spinner.ts
1852
1959
  var SPINNER_FRAMES = Object.freeze(["\u25D2", "\u25D0", "\u25D3", "\u25D1"]);
1853
1960
 
1854
- // ../design-system/src/prompts/index.ts
1961
+ // ../toolcraft-design/src/prompts/index.ts
1855
1962
  async function select2(opts) {
1856
1963
  return clack.select(opts);
1857
1964
  }
@@ -1894,19 +2001,19 @@ var ApprovalDeclinedError = class extends UserError {
1894
2001
  };
1895
2002
 
1896
2003
  // ../toolcraft/src/human-in-loop/config.ts
1897
- function validateHumanInLoopOnDefine(config) {
1898
- const label = Array.isArray(config.children) ? "group" : "command";
1899
- if (config.confirm === true && config.humanInLoop !== void 0 && config.humanInLoop !== null) {
1900
- throw new Error(`${label} '${config.name}': use either confirm or humanInLoop, not both`);
2004
+ function validateHumanInLoopOnDefine(config2) {
2005
+ const label = Array.isArray(config2.children) ? "group" : "command";
2006
+ if (config2.confirm === true && config2.humanInLoop !== void 0 && config2.humanInLoop !== null) {
2007
+ throw new Error(`${label} '${config2.name}': use either confirm or humanInLoop, not both`);
1901
2008
  }
1902
- if (config.humanInLoop === void 0 || config.humanInLoop === null) {
2009
+ if (config2.humanInLoop === void 0 || config2.humanInLoop === null) {
1903
2010
  return;
1904
2011
  }
1905
- if (config.humanInLoop.mode !== "sync" && config.humanInLoop.mode !== "async") {
1906
- throw new Error(`${label} '${config.name}': humanInLoop.mode must be "sync" or "async"`);
2012
+ if (config2.humanInLoop.mode !== "sync" && config2.humanInLoop.mode !== "async") {
2013
+ throw new Error(`${label} '${config2.name}': humanInLoop.mode must be "sync" or "async"`);
1907
2014
  }
1908
- if (typeof config.humanInLoop.message !== "function") {
1909
- throw new Error(`${label} '${config.name}': humanInLoop.message must be a function`);
2015
+ if (typeof config2.humanInLoop.message !== "function") {
2016
+ throw new Error(`${label} '${config2.name}': humanInLoop.message must be a function`);
1910
2017
  }
1911
2018
  }
1912
2019
  function mergeHumanInLoopFromGroup(groupHumanInLoop, childHumanInLoop) {
@@ -1982,12 +2089,12 @@ function assertValidBranches(branches, discriminator) {
1982
2089
  }
1983
2090
  }
1984
2091
  }
1985
- function OneOf(config) {
1986
- assertValidBranches(config.branches, config.discriminator);
2092
+ function OneOf(config2) {
2093
+ assertValidBranches(config2.branches, config2.discriminator);
1987
2094
  return {
1988
2095
  kind: "oneOf",
1989
- discriminator: config.discriminator,
1990
- branches: config.branches
2096
+ discriminator: config2.discriminator,
2097
+ branches: config2.branches
1991
2098
  };
1992
2099
  }
1993
2100
 
@@ -2237,22 +2344,22 @@ function cloneStringArray(values) {
2237
2344
  function cloneStringRecord(values) {
2238
2345
  return values === void 0 ? void 0 : { ...values };
2239
2346
  }
2240
- function cloneMcpServerConfig(config) {
2241
- if (config === void 0) {
2347
+ function cloneMcpServerConfig(config2) {
2348
+ if (config2 === void 0) {
2242
2349
  return void 0;
2243
2350
  }
2244
- if (config.transport === "stdio") {
2351
+ if (config2.transport === "stdio") {
2245
2352
  return {
2246
2353
  transport: "stdio",
2247
- command: config.command,
2248
- args: cloneStringArray(config.args),
2249
- env: cloneStringRecord(config.env)
2354
+ command: config2.command,
2355
+ args: cloneStringArray(config2.args),
2356
+ env: cloneStringRecord(config2.env)
2250
2357
  };
2251
2358
  }
2252
2359
  return {
2253
2360
  transport: "http",
2254
- url: config.url,
2255
- headers: cloneStringRecord(config.headers)
2361
+ url: config2.url,
2362
+ headers: cloneStringRecord(config2.headers)
2256
2363
  };
2257
2364
  }
2258
2365
  function cloneRenameMap(rename5) {
@@ -2493,57 +2600,57 @@ function resolveCommandScope(ownScope, inheritedScope) {
2493
2600
  function resolveGroupScope(ownScope, inheritedScope) {
2494
2601
  return cloneScope(ownScope ?? inheritedScope);
2495
2602
  }
2496
- function createBaseCommand(config) {
2603
+ function createBaseCommand(config2) {
2497
2604
  const command = {
2498
2605
  kind: "command",
2499
- name: config.name,
2500
- description: config.description,
2501
- aliases: [...config.aliases ?? []],
2502
- positional: [...config.positional ?? []],
2503
- params: config.params,
2504
- secrets: cloneSecrets(config.secrets),
2505
- scope: resolveCommandScope(config.scope, void 0),
2506
- confirm: config.confirm ?? false,
2507
- humanInLoop: config.humanInLoop,
2508
- requires: cloneRequires(config.requires),
2509
- handler: config.handler,
2510
- render: config.render
2606
+ name: config2.name,
2607
+ description: config2.description,
2608
+ aliases: [...config2.aliases ?? []],
2609
+ positional: [...config2.positional ?? []],
2610
+ params: config2.params,
2611
+ secrets: cloneSecrets(config2.secrets),
2612
+ scope: resolveCommandScope(config2.scope, void 0),
2613
+ confirm: config2.confirm ?? false,
2614
+ humanInLoop: config2.humanInLoop,
2615
+ requires: cloneRequires(config2.requires),
2616
+ handler: config2.handler,
2617
+ render: config2.render
2511
2618
  };
2512
2619
  Object.defineProperty(command, commandConfigSymbol, {
2513
2620
  value: {
2514
- scope: cloneScope(config.scope),
2515
- humanInLoop: config.humanInLoop,
2516
- secrets: cloneSecrets(config.secrets),
2517
- requires: cloneRequires(config.requires),
2621
+ scope: cloneScope(config2.scope),
2622
+ humanInLoop: config2.humanInLoop,
2623
+ secrets: cloneSecrets(config2.secrets),
2624
+ requires: cloneRequires(config2.requires),
2518
2625
  sourcePath: inferCommandSourcePath()
2519
2626
  }
2520
2627
  });
2521
2628
  return command;
2522
2629
  }
2523
- function createBaseGroup(config) {
2630
+ function createBaseGroup(config2) {
2524
2631
  const group = {
2525
2632
  kind: "group",
2526
- name: config.name,
2527
- description: config.description,
2528
- aliases: [...config.aliases ?? []],
2529
- scope: resolveGroupScope(config.scope, void 0),
2530
- humanInLoop: config.humanInLoop,
2531
- secrets: cloneSecrets(config.secrets),
2532
- requires: cloneRequires(config.requires),
2633
+ name: config2.name,
2634
+ description: config2.description,
2635
+ aliases: [...config2.aliases ?? []],
2636
+ scope: resolveGroupScope(config2.scope, void 0),
2637
+ humanInLoop: config2.humanInLoop,
2638
+ secrets: cloneSecrets(config2.secrets),
2639
+ requires: cloneRequires(config2.requires),
2533
2640
  children: [],
2534
2641
  default: void 0
2535
2642
  };
2536
2643
  Object.defineProperty(group, groupConfigSymbol, {
2537
2644
  value: {
2538
- mcp: cloneMcpServerConfig(config.mcp),
2539
- scope: cloneScope(config.scope),
2540
- humanInLoop: config.humanInLoop,
2541
- secrets: cloneSecrets(config.secrets),
2542
- tools: cloneStringArray(config.tools),
2543
- rename: cloneRenameMap(config.rename),
2544
- requires: cloneRequires(config.requires),
2545
- children: [...config.children],
2546
- default: config.default
2645
+ mcp: cloneMcpServerConfig(config2.mcp),
2646
+ scope: cloneScope(config2.scope),
2647
+ humanInLoop: config2.humanInLoop,
2648
+ secrets: cloneSecrets(config2.secrets),
2649
+ tools: cloneStringArray(config2.tools),
2650
+ rename: cloneRenameMap(config2.rename),
2651
+ requires: cloneRequires(config2.requires),
2652
+ children: [...config2.children],
2653
+ default: config2.default
2547
2654
  }
2548
2655
  });
2549
2656
  return group;
@@ -2646,10 +2753,10 @@ function materializeNode(node, inherited) {
2646
2753
  }
2647
2754
  return materializeGroup(node, inherited);
2648
2755
  }
2649
- function defineCommand(config) {
2650
- validateHumanInLoopOnDefine(config);
2756
+ function defineCommand(config2) {
2757
+ validateHumanInLoopOnDefine(config2);
2651
2758
  return materializeCommand(
2652
- createBaseCommand(config),
2759
+ createBaseCommand(config2),
2653
2760
  {
2654
2761
  scope: void 0,
2655
2762
  humanInLoop: void 0,
@@ -2658,10 +2765,10 @@ function defineCommand(config) {
2658
2765
  }
2659
2766
  );
2660
2767
  }
2661
- function defineGroup(config) {
2662
- validateRenameMap(config.rename);
2663
- validateHumanInLoopOnDefine(config);
2664
- return materializeGroup(createBaseGroup(config), {
2768
+ function defineGroup(config2) {
2769
+ validateRenameMap(config2.rename);
2770
+ validateHumanInLoopOnDefine(config2);
2771
+ return materializeGroup(createBaseGroup(config2), {
2665
2772
  scope: void 0,
2666
2773
  humanInLoop: void 0,
2667
2774
  secrets: {},
@@ -2692,27 +2799,27 @@ function validateMachine(machine) {
2692
2799
  if (!isRecord(machine)) {
2693
2800
  throw new TypeError("State machine must be an object.");
2694
2801
  }
2695
- if (!isStateList(machine.states)) {
2802
+ if (!hasOwnRecordField(machine, "states") || !isStateList(machine.states)) {
2696
2803
  throw new TypeError("State machine states must be a string array.");
2697
2804
  }
2698
2805
  const states = new Set(machine.states);
2699
- if (typeof machine.initial !== "string") {
2806
+ if (!hasOwnRecordField(machine, "initial") || typeof machine.initial !== "string") {
2700
2807
  throw new TypeError("State machine initial must be a string.");
2701
2808
  }
2702
2809
  if (!states.has(machine.initial)) {
2703
2810
  throw new Error(`Initial state "${machine.initial}" is not declared.`);
2704
2811
  }
2705
- if (!isRecord(machine.events)) {
2812
+ if (!hasOwnRecordField(machine, "events") || !isRecord(machine.events)) {
2706
2813
  throw new TypeError("State machine events must be an object.");
2707
2814
  }
2708
2815
  for (const [eventName, event] of Object.entries(machine.events)) {
2709
2816
  if (!isRecord(event)) {
2710
2817
  throw new TypeError(`Event "${eventName}" must be an object.`);
2711
2818
  }
2712
- if (event.from !== "*" && !isStateList(event.from)) {
2819
+ if (!hasOwnRecordField(event, "from") || event.from !== "*" && !isStateList(event.from)) {
2713
2820
  throw new TypeError(`Event "${eventName}" has an invalid "from" definition.`);
2714
2821
  }
2715
- if (typeof event.to !== "string") {
2822
+ if (!hasOwnRecordField(event, "to") || typeof event.to !== "string") {
2716
2823
  throw new TypeError(`Event "${eventName}" target state must be a string.`);
2717
2824
  }
2718
2825
  if (!states.has(event.to)) {
@@ -2727,6 +2834,9 @@ function validateMachine(machine) {
2727
2834
  }
2728
2835
  }
2729
2836
  }
2837
+ function hasOwnRecordField(record, key2) {
2838
+ return Object.prototype.hasOwnProperty.call(record, key2);
2839
+ }
2730
2840
  function eventsFromState(machine, fromState) {
2731
2841
  const events = [];
2732
2842
  for (const [eventName, event] of Object.entries(machine.events)) {
@@ -2830,7 +2940,7 @@ import path3 from "node:path";
2830
2940
  // ../process-runner/src/docker/docker-execution-env.ts
2831
2941
  import { createHash as createHash2, randomBytes as randomBytes2 } from "node:crypto";
2832
2942
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "node:fs";
2833
- import { readdir, readFile, writeFile } from "node:fs/promises";
2943
+ import { readdir, readFile, realpath, writeFile } from "node:fs/promises";
2834
2944
  import { tmpdir as tmpdir2 } from "node:os";
2835
2945
  import path5 from "node:path";
2836
2946
 
@@ -2998,6 +3108,7 @@ function resolveEndpoint(options = {}) {
2998
3108
  }
2999
3109
 
3000
3110
  // ../task-list/src/backends/utils.ts
3111
+ import { randomUUID as randomUUID2 } from "node:crypto";
3001
3112
  import path6 from "node:path";
3002
3113
  function compareCreated(left, right) {
3003
3114
  const leftCreated = typeof left.raw.created === "string" ? left.raw.created : "";
@@ -3018,9 +3129,8 @@ function applyOrder(entries, order) {
3018
3129
  }
3019
3130
  return entries.map((entry) => entry.task);
3020
3131
  }
3021
- var tmpFileCounter = 0;
3022
3132
  function hasErrorCode(error3, code) {
3023
- return !!error3 && typeof error3 === "object" && "code" in error3 && error3.code === code;
3133
+ return !!error3 && typeof error3 === "object" && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === code;
3024
3134
  }
3025
3135
  function isRecord2(value) {
3026
3136
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -3067,18 +3177,22 @@ async function rejectSymbolicLinkComponents(fs4, filePath) {
3067
3177
  }
3068
3178
  }
3069
3179
  async function writeAtomically(fs4, filePath, content) {
3070
- const tempPath = `${filePath}.tmp-${process.pid}-${tmpFileCounter}`;
3071
- tmpFileCounter += 1;
3180
+ const tempPath = `${filePath}.${process.pid}.${randomUUID2()}.tmp`;
3181
+ let tempCreated = false;
3072
3182
  await fs4.mkdir(path6.dirname(filePath), { recursive: true });
3073
3183
  try {
3074
3184
  await fs4.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
3185
+ tempCreated = true;
3075
3186
  await fs4.rename(tempPath, filePath);
3187
+ tempCreated = false;
3076
3188
  } catch (error3) {
3077
- try {
3078
- await fs4.unlink(tempPath);
3079
- } catch (unlinkError) {
3080
- if (!hasErrorCode(unlinkError, "ENOENT")) {
3081
- throw unlinkError;
3189
+ if (tempCreated || !hasErrorCode(error3, "EEXIST")) {
3190
+ try {
3191
+ await fs4.unlink(tempPath);
3192
+ } catch (unlinkError) {
3193
+ if (!hasErrorCode(unlinkError, "ENOENT")) {
3194
+ throw unlinkError;
3195
+ }
3082
3196
  }
3083
3197
  }
3084
3198
  throw error3;
@@ -3092,6 +3206,7 @@ async function withFileLock(fs4, lockPath, operation) {
3092
3206
  break;
3093
3207
  } catch (error3) {
3094
3208
  if (!hasErrorCode(error3, "EEXIST")) {
3209
+ await fs4.unlink(lockPath).catch(() => void 0);
3095
3210
  throw error3;
3096
3211
  }
3097
3212
  if (await removeAbandonedLock(fs4, lockPath)) {
@@ -4375,27 +4490,30 @@ function readFrontmatter(frontmatterContent, filePath) {
4375
4490
  return parsed;
4376
4491
  }
4377
4492
  function assertValidTaskRecord(frontmatter, filePath, validStates) {
4378
- if ("$schema" in frontmatter && frontmatter.$schema !== TASK_SCHEMA_ID) {
4493
+ if (hasOwnTaskField(frontmatter, "$schema") && frontmatter.$schema !== TASK_SCHEMA_ID) {
4379
4494
  throw malformedTask(filePath, "$schema");
4380
4495
  }
4381
- if ("kind" in frontmatter && frontmatter.kind !== TASK_KIND) {
4496
+ if (hasOwnTaskField(frontmatter, "kind") && frontmatter.kind !== TASK_KIND) {
4382
4497
  throw malformedTask(filePath, "kind");
4383
4498
  }
4384
- if ("version" in frontmatter) {
4499
+ if (hasOwnTaskField(frontmatter, "version")) {
4385
4500
  if (typeof frontmatter.version !== "number" || !Number.isInteger(frontmatter.version) || frontmatter.version !== TASK_VERSION) {
4386
4501
  throw malformedTask(filePath, "version");
4387
4502
  }
4388
4503
  }
4389
- if (typeof frontmatter.name !== "string" || frontmatter.name.length === 0) {
4504
+ if (!hasOwnTaskField(frontmatter, "name") || typeof frontmatter.name !== "string" || frontmatter.name.length === 0) {
4390
4505
  throw malformedTask(filePath, "name");
4391
4506
  }
4392
- if (typeof frontmatter.state !== "string" || !validStates.has(frontmatter.state)) {
4507
+ if (!hasOwnTaskField(frontmatter, "state") || typeof frontmatter.state !== "string" || !validStates.has(frontmatter.state)) {
4393
4508
  throw malformedTask(filePath, "state");
4394
4509
  }
4395
- if ("description" in frontmatter && typeof frontmatter.description !== "string") {
4510
+ if (hasOwnTaskField(frontmatter, "description") && typeof frontmatter.description !== "string") {
4396
4511
  throw malformedTask(filePath, "description");
4397
4512
  }
4398
4513
  }
4514
+ function hasOwnTaskField(frontmatter, key2) {
4515
+ return Object.prototype.hasOwnProperty.call(frontmatter, key2);
4516
+ }
4399
4517
  function reservedFrontmatterKeys(mode) {
4400
4518
  return mode === "passthrough" ? PASSTHROUGH_RESERVED_FRONTMATTER_KEYS : RESERVED_FRONTMATTER_KEYS;
4401
4519
  }
@@ -4518,7 +4636,7 @@ async function readTaskAtLocation(fs4, rootPath, layout, list, id, validStates,
4518
4636
  }
4519
4637
  return readTaskFile(fs4, list, id, location.path, validStates, initialState, mode);
4520
4638
  }
4521
- function createdFrontmatter(defaults, input, initialState, mode) {
4639
+ function createdFrontmatter(defaults2, input, initialState, mode) {
4522
4640
  const frontmatter = mode !== "passthrough" ? {
4523
4641
  $schema: TASK_SCHEMA_ID,
4524
4642
  kind: TASK_KIND,
@@ -4530,7 +4648,7 @@ function createdFrontmatter(defaults, input, initialState, mode) {
4530
4648
  state: initialState
4531
4649
  };
4532
4650
  const reservedKeys = reservedFrontmatterKeys(mode);
4533
- for (const [key2, value] of Object.entries(defaults.metadata)) {
4651
+ for (const [key2, value] of Object.entries(defaults2.metadata)) {
4534
4652
  if (!reservedKeys.has(key2)) {
4535
4653
  setOwnValue(frontmatter, key2, value);
4536
4654
  }
@@ -5244,7 +5362,8 @@ function parseQualifiedId3(qualifiedId) {
5244
5362
  };
5245
5363
  }
5246
5364
  function descriptionFromTaskRecord(taskRecord) {
5247
- return typeof taskRecord.description === "string" ? taskRecord.description : "";
5365
+ const description = getOwnEntry(taskRecord, "description");
5366
+ return typeof description === "string" ? description : "";
5248
5367
  }
5249
5368
  function metadataFromTaskRecord(taskRecord) {
5250
5369
  const metadata = /* @__PURE__ */ Object.create(null);
@@ -5260,8 +5379,8 @@ function createTask2(list, id, taskRecord, sourcePath) {
5260
5379
  list,
5261
5380
  id,
5262
5381
  qualifiedId: `${list}/${id}`,
5263
- name: taskRecord.name,
5264
- state: taskRecord.state,
5382
+ name: getOwnEntry(taskRecord, "name"),
5383
+ state: getOwnEntry(taskRecord, "state"),
5265
5384
  description: descriptionFromTaskRecord(taskRecord),
5266
5385
  metadata: metadataFromTaskRecord(taskRecord),
5267
5386
  ...sourcePath !== void 0 && { sourcePath: path8.resolve(sourcePath) }
@@ -5276,13 +5395,13 @@ function matchesFilter(task, filter) {
5276
5395
  }
5277
5396
  return true;
5278
5397
  }
5279
- function createTaskRecord(defaults, input, initialState) {
5398
+ function createTaskRecord(defaults2, input, initialState) {
5280
5399
  const taskRecord = Object.assign(/* @__PURE__ */ Object.create(null), {
5281
5400
  name: input.name,
5282
5401
  state: initialState,
5283
5402
  description: input.description ?? ""
5284
5403
  });
5285
- for (const [key2, value] of Object.entries(defaults.metadata)) {
5404
+ for (const [key2, value] of Object.entries(defaults2.metadata)) {
5286
5405
  if (!RESERVED_TASK_KEYS.has(key2)) {
5287
5406
  taskRecord[key2] = value;
5288
5407
  }
@@ -5358,16 +5477,17 @@ function assertValidStoreRecord(store, filePath) {
5358
5477
  if (!isRecord2(store)) {
5359
5478
  throw malformedStore(filePath, "store");
5360
5479
  }
5361
- if (store.$schema !== STORE_SCHEMA_ID) {
5480
+ if (getOwnEntry(store, "$schema") !== STORE_SCHEMA_ID) {
5362
5481
  throw malformedStore(filePath, "$schema");
5363
5482
  }
5364
- if (store.kind !== STORE_KIND) {
5483
+ if (getOwnEntry(store, "kind") !== STORE_KIND) {
5365
5484
  throw malformedStore(filePath, "kind");
5366
5485
  }
5367
- if (typeof store.version !== "number" || !Number.isInteger(store.version) || store.version !== STORE_VERSION) {
5486
+ const version = getOwnEntry(store, "version");
5487
+ if (typeof version !== "number" || !Number.isInteger(version) || version !== STORE_VERSION) {
5368
5488
  throw malformedStore(filePath, "version");
5369
5489
  }
5370
- if (!isRecord2(store.lists)) {
5490
+ if (!isRecord2(getOwnEntry(store, "lists"))) {
5371
5491
  throw malformedStore(filePath, "lists");
5372
5492
  }
5373
5493
  }
@@ -5375,29 +5495,38 @@ function assertValidTaskRecord2(taskRecord, list, id, validStates) {
5375
5495
  if (!isRecord2(taskRecord)) {
5376
5496
  throw malformedTask2(list, id, "task");
5377
5497
  }
5378
- if ("$schema" in taskRecord && taskRecord.$schema !== TASK_SCHEMA_ID2) {
5498
+ if (hasOwnTaskField2(taskRecord, "$schema") && getOwnEntry(taskRecord, "$schema") !== TASK_SCHEMA_ID2) {
5379
5499
  throw malformedTask2(list, id, "$schema");
5380
5500
  }
5381
- if ("kind" in taskRecord && taskRecord.kind !== TASK_KIND2) {
5501
+ if (hasOwnTaskField2(taskRecord, "kind") && getOwnEntry(taskRecord, "kind") !== TASK_KIND2) {
5382
5502
  throw malformedTask2(list, id, "kind");
5383
5503
  }
5384
- if ("version" in taskRecord) {
5385
- if (typeof taskRecord.version !== "number" || !Number.isInteger(taskRecord.version) || taskRecord.version !== TASK_VERSION2) {
5504
+ if (hasOwnTaskField2(taskRecord, "version")) {
5505
+ const version = getOwnEntry(taskRecord, "version");
5506
+ if (typeof version !== "number" || !Number.isInteger(version) || version !== TASK_VERSION2) {
5386
5507
  throw malformedTask2(list, id, "version");
5387
5508
  }
5388
5509
  }
5389
- if (typeof taskRecord.name !== "string" || taskRecord.name.length === 0) {
5510
+ const name = getOwnEntry(taskRecord, "name");
5511
+ if (!hasOwnTaskField2(taskRecord, "name") || typeof name !== "string" || name.length === 0) {
5390
5512
  throw malformedTask2(list, id, "name");
5391
5513
  }
5392
- if (typeof taskRecord.state !== "string" || !validStates.has(taskRecord.state)) {
5514
+ const state = getOwnEntry(taskRecord, "state");
5515
+ if (!hasOwnTaskField2(taskRecord, "state") || typeof state !== "string" || !validStates.has(state)) {
5393
5516
  throw malformedTask2(list, id, "state");
5394
5517
  }
5395
- if ("description" in taskRecord && typeof taskRecord.description !== "string") {
5518
+ if (hasOwnTaskField2(taskRecord, "description") && typeof getOwnEntry(taskRecord, "description") !== "string") {
5396
5519
  throw malformedTask2(list, id, "description");
5397
5520
  }
5398
5521
  }
5522
+ function hasOwnTaskField2(taskRecord, key2) {
5523
+ return Object.prototype.hasOwnProperty.call(taskRecord, key2);
5524
+ }
5525
+ function getOwnEntry(record, key2) {
5526
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
5527
+ }
5399
5528
  function validateStoreEntries(store, filePath, validStates) {
5400
- const lists = store.lists;
5529
+ const lists = getOwnEntry(store, "lists");
5401
5530
  if (!isRecord2(lists)) {
5402
5531
  throw malformedStore(filePath, "lists");
5403
5532
  }
@@ -5437,10 +5566,11 @@ async function readStore(fs4, filePath, validStates) {
5437
5566
  };
5438
5567
  }
5439
5568
  function getListsRecord(store) {
5440
- return store.lists;
5569
+ const lists = getOwnEntry(store, "lists");
5570
+ return isRecord2(lists) ? lists : {};
5441
5571
  }
5442
5572
  function getListRecord(store, list) {
5443
- const listRecord = getListsRecord(store)[list];
5573
+ const listRecord = getOwnEntry(getListsRecord(store), list);
5444
5574
  return isRecord2(listRecord) ? listRecord : void 0;
5445
5575
  }
5446
5576
  function getTaskRecord(store, list, id) {
@@ -5733,7 +5863,7 @@ async function yamlFileBackend(deps) {
5733
5863
  const result = [];
5734
5864
  const listNames = sortStrings(Object.keys(getListsRecord(store)));
5735
5865
  for (const listName of listNames) {
5736
- const listRecord = getListsRecord(store)[listName];
5866
+ const listRecord = getOwnEntry(getListsRecord(store), listName);
5737
5867
  if (!isRecord2(listRecord)) continue;
5738
5868
  const entries = Object.entries(listRecord).map(([id, taskRecord]) => ({
5739
5869
  task: createTask2(listName, id, taskRecord, deps.path),
@@ -6367,8 +6497,8 @@ function createHandlerContext(command, params17) {
6367
6497
  function createFs() {
6368
6498
  return {
6369
6499
  readFile: async (path24, encoding = "utf8") => readFile2(path24, { encoding }),
6370
- writeFile: async (path24, contents) => {
6371
- await writeFile2(path24, contents);
6500
+ writeFile: async (path24, contents, options) => {
6501
+ await writeFile2(path24, contents, options);
6372
6502
  },
6373
6503
  exists: async (path24) => {
6374
6504
  try {
@@ -6656,17 +6786,17 @@ function isMissingStateError(error3) {
6656
6786
  }
6657
6787
 
6658
6788
  // ../toolcraft/src/error-report.ts
6659
- import { mkdir as mkdir2, realpath, writeFile as writeFile4 } from "node:fs/promises";
6660
- import { randomUUID as randomUUID3 } from "node:crypto";
6789
+ import { mkdir as mkdir2, realpath as realpath2, writeFile as writeFile4 } from "node:fs/promises";
6790
+ import { randomUUID as randomUUID5 } from "node:crypto";
6661
6791
  import os from "node:os";
6662
6792
  import path13 from "node:path";
6663
6793
  import { CommanderError } from "commander";
6664
6794
 
6665
6795
  // ../toolcraft/src/mcp-proxy.ts
6666
6796
  import { existsSync as existsSync2 } from "node:fs";
6667
- import { lstat as lstat2, mkdir, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "node:fs/promises";
6797
+ import { lstat as lstat2, mkdir, readFile as readFile3, rename as rename2, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
6668
6798
  import path12 from "node:path";
6669
- import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
6799
+ import { createHash as createHash3, randomUUID as randomUUID4 } from "node:crypto";
6670
6800
 
6671
6801
  // ../tiny-mcp-client/src/internal.ts
6672
6802
  import { spawn as spawn5 } from "node:child_process";
@@ -6677,7 +6807,7 @@ import crypto from "node:crypto";
6677
6807
  import path11 from "node:path";
6678
6808
 
6679
6809
  // ../auth-store/src/encrypted-file-store.ts
6680
- import { createCipheriv, createDecipheriv, randomBytes as randomBytes4, scrypt } from "node:crypto";
6810
+ import { createCipheriv, createDecipheriv, randomBytes as randomBytes4, randomUUID as randomUUID3, scrypt } from "node:crypto";
6681
6811
  import { promises as fs } from "node:fs";
6682
6812
  import { homedir, hostname, userInfo } from "node:os";
6683
6813
  import path10 from "node:path";
@@ -6688,7 +6818,6 @@ var ENCRYPTION_KEY_BYTES = 32;
6688
6818
  var ENCRYPTION_IV_BYTES = 12;
6689
6819
  var ENCRYPTION_AUTH_TAG_BYTES = 16;
6690
6820
  var ENCRYPTION_FILE_MODE = 384;
6691
- var temporaryFileSequence = 0;
6692
6821
  var EncryptedFileStore = class {
6693
6822
  fs;
6694
6823
  filePath;
@@ -6720,7 +6849,7 @@ var EncryptedFileStore = class {
6720
6849
  this.getRandomBytes = input.getRandomBytes ?? randomBytes4;
6721
6850
  }
6722
6851
  async get() {
6723
- await this.assertRegularCredentialPath();
6852
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
6724
6853
  let rawDocument;
6725
6854
  try {
6726
6855
  rawDocument = await this.fs.readFile(this.filePath, "utf8");
@@ -6751,7 +6880,7 @@ var EncryptedFileStore = class {
6751
6880
  }
6752
6881
  }
6753
6882
  async set(value) {
6754
- await this.assertRegularCredentialPath();
6883
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
6755
6884
  const key2 = await this.getEncryptionKey();
6756
6885
  const iv = this.getRandomBytes(ENCRYPTION_IV_BYTES);
6757
6886
  const cipher = createCipheriv(ENCRYPTION_ALGORITHM, key2, iv);
@@ -6767,25 +6896,28 @@ var EncryptedFileStore = class {
6767
6896
  ciphertext: ciphertext.toString("base64")
6768
6897
  };
6769
6898
  await this.fs.mkdir(path10.dirname(this.filePath), { recursive: true });
6770
- await this.assertRegularCredentialPath();
6771
- const temporaryPath = `${this.filePath}.${process.pid}.${temporaryFileSequence++}.tmp`;
6899
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
6900
+ const temporaryPath = `${this.filePath}.${process.pid}.${randomUUID3()}.tmp`;
6901
+ let temporaryCreated = false;
6772
6902
  try {
6903
+ await this.assertCredentialPathHasNoSymbolicLinks(temporaryPath);
6773
6904
  await this.fs.writeFile(temporaryPath, JSON.stringify(document), {
6774
6905
  encoding: "utf8",
6775
6906
  flag: "wx",
6776
6907
  mode: ENCRYPTION_FILE_MODE
6777
6908
  });
6909
+ temporaryCreated = true;
6778
6910
  await this.fs.chmod(temporaryPath, ENCRYPTION_FILE_MODE);
6779
6911
  await this.fs.rename(temporaryPath, this.filePath);
6780
6912
  } catch (error3) {
6781
- if (!isAlreadyExistsError(error3)) {
6913
+ if (temporaryCreated || !isAlreadyExistsError(error3)) {
6782
6914
  await removeIfPresent(this.fs, temporaryPath).catch(() => void 0);
6783
6915
  }
6784
6916
  throw error3;
6785
6917
  }
6786
6918
  }
6787
6919
  async delete() {
6788
- await this.assertRegularCredentialPath();
6920
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
6789
6921
  try {
6790
6922
  await this.fs.unlink(this.filePath);
6791
6923
  } catch (error3) {
@@ -6794,8 +6926,8 @@ var EncryptedFileStore = class {
6794
6926
  }
6795
6927
  }
6796
6928
  }
6797
- async assertRegularCredentialPath() {
6798
- const resolvedPath = path10.resolve(this.filePath);
6929
+ async assertCredentialPathHasNoSymbolicLinks(targetPath) {
6930
+ const resolvedPath = path10.resolve(targetPath);
6799
6931
  const protectedPaths = getProtectedCredentialPaths(
6800
6932
  resolvedPath,
6801
6933
  this.symbolicLinkCheckStartPath
@@ -6860,9 +6992,6 @@ async function removeIfPresent(fileSystem, filePath) {
6860
6992
  }
6861
6993
  }
6862
6994
  }
6863
- function isAlreadyExistsError(error3) {
6864
- return typeof error3 === "object" && error3 !== null && "code" in error3 && error3.code === "EEXIST";
6865
- }
6866
6995
  function defaultMachineIdentity() {
6867
6996
  return {
6868
6997
  hostname: hostname(),
@@ -6900,17 +7029,21 @@ function parseEncryptedDocument(raw) {
6900
7029
  if (!isRecord4(parsed)) {
6901
7030
  return null;
6902
7031
  }
6903
- if (parsed.version !== ENCRYPTION_VERSION) {
7032
+ const version = getOwnEntry2(parsed, "version");
7033
+ const iv = getOwnEntry2(parsed, "iv");
7034
+ const authTag = getOwnEntry2(parsed, "authTag");
7035
+ const ciphertext = getOwnEntry2(parsed, "ciphertext");
7036
+ if (version !== ENCRYPTION_VERSION) {
6904
7037
  return null;
6905
7038
  }
6906
- if (typeof parsed.iv !== "string" || typeof parsed.authTag !== "string" || typeof parsed.ciphertext !== "string") {
7039
+ if (typeof iv !== "string" || typeof authTag !== "string" || typeof ciphertext !== "string") {
6907
7040
  return null;
6908
7041
  }
6909
7042
  return {
6910
- version: parsed.version,
6911
- iv: parsed.iv,
6912
- authTag: parsed.authTag,
6913
- ciphertext: parsed.ciphertext
7043
+ version,
7044
+ iv,
7045
+ authTag,
7046
+ ciphertext
6914
7047
  };
6915
7048
  } catch {
6916
7049
  return null;
@@ -6919,9 +7052,17 @@ function parseEncryptedDocument(raw) {
6919
7052
  function isRecord4(value) {
6920
7053
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
6921
7054
  }
7055
+ function getOwnEntry2(record, key2) {
7056
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7057
+ }
6922
7058
  function isNotFoundError(error3) {
6923
7059
  return Boolean(
6924
- error3 && typeof error3 === "object" && "code" in error3 && error3.code === "ENOENT"
7060
+ error3 && typeof error3 === "object" && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "ENOENT"
7061
+ );
7062
+ }
7063
+ function isAlreadyExistsError(error3) {
7064
+ return Boolean(
7065
+ error3 && typeof error3 === "object" && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "EEXIST"
6925
7066
  );
6926
7067
  }
6927
7068
 
@@ -6943,8 +7084,8 @@ var KeychainStore = class {
6943
7084
  ["find-generic-password", "-s", this.service, "-a", this.account, "-w"],
6944
7085
  "read secret from macOS Keychain"
6945
7086
  );
6946
- if (result.exitCode === 0) {
6947
- return stripTrailingLineBreak(result.stdout);
7087
+ if (getCommandExitCode(result) === 0) {
7088
+ return stripTrailingLineBreak(getCommandOutput(result, "stdout"));
6948
7089
  }
6949
7090
  if (isKeychainEntryNotFound(result)) {
6950
7091
  return null;
@@ -6968,7 +7109,7 @@ var KeychainStore = class {
6968
7109
  "store secret in macOS Keychain",
6969
7110
  { stdin: value }
6970
7111
  );
6971
- if (result.exitCode !== 0) {
7112
+ if (getCommandExitCode(result) !== 0) {
6972
7113
  throw createSecurityCliFailure("store secret in macOS Keychain", result);
6973
7114
  }
6974
7115
  }
@@ -6977,7 +7118,7 @@ var KeychainStore = class {
6977
7118
  ["delete-generic-password", "-s", this.service, "-a", this.account],
6978
7119
  "delete secret from macOS Keychain"
6979
7120
  );
6980
- if (result.exitCode === 0 || isKeychainEntryNotFound(result)) {
7121
+ if (getCommandExitCode(result) === 0 || isKeychainEntryNotFound(result)) {
6981
7122
  return;
6982
7123
  }
6983
7124
  throw createSecurityCliFailure("delete secret from macOS Keychain", result);
@@ -7056,16 +7197,28 @@ function stripTrailingLineBreak(value) {
7056
7197
  return value;
7057
7198
  }
7058
7199
  function isKeychainEntryNotFound(result) {
7059
- return result.exitCode === KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE;
7200
+ return getCommandExitCode(result) === KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE;
7060
7201
  }
7061
7202
  function createSecurityCliFailure(operation, result) {
7062
- const details = result.stderr.trim() || result.stdout.trim();
7203
+ const exitCode = getCommandExitCode(result);
7204
+ const details = getCommandOutput(result, "stderr").trim() || getCommandOutput(result, "stdout").trim();
7063
7205
  if (details) {
7064
7206
  return new Error(
7065
- `Failed to ${operation}: security exited with code ${result.exitCode}: ${details}`
7207
+ `Failed to ${operation}: security exited with code ${exitCode}: ${details}`
7066
7208
  );
7067
7209
  }
7068
- return new Error(`Failed to ${operation}: security exited with code ${result.exitCode}`);
7210
+ return new Error(`Failed to ${operation}: security exited with code ${exitCode}`);
7211
+ }
7212
+ function getCommandExitCode(result) {
7213
+ const value = getOwnEntry3(result, "exitCode");
7214
+ return typeof value === "number" && Number.isInteger(value) ? value : 1;
7215
+ }
7216
+ function getCommandOutput(result, key2) {
7217
+ const value = getOwnEntry3(result, key2);
7218
+ return typeof value === "string" ? value : "";
7219
+ }
7220
+ function getOwnEntry3(record, key2) {
7221
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7069
7222
  }
7070
7223
 
7071
7224
  // ../auth-store/src/create-secret-store.ts
@@ -7098,7 +7251,7 @@ function createSecretStore(input) {
7098
7251
  }
7099
7252
  function resolveBackend(input) {
7100
7253
  const envVar = input.backendEnvVar ?? DEFAULT_BACKEND_ENV_VAR;
7101
- const configuredBackend = input.backend ?? input.env?.[envVar] ?? process.env[envVar];
7254
+ const configuredBackend = input.backend ?? getOwnEnvValue(input.env, envVar) ?? getOwnEnvValue(process.env, envVar);
7102
7255
  if (configuredBackend === "keychain") {
7103
7256
  return "keychain";
7104
7257
  }
@@ -7107,6 +7260,9 @@ function resolveBackend(input) {
7107
7260
  }
7108
7261
  throw new Error(`Unsupported auth store backend: ${configuredBackend}`);
7109
7262
  }
7263
+ function getOwnEnvValue(env, key2) {
7264
+ return env !== void 0 && Object.prototype.hasOwnProperty.call(env, key2) ? env[key2] : void 0;
7265
+ }
7110
7266
 
7111
7267
  // ../mcp-oauth/src/resource-indicator.ts
7112
7268
  function canonicalizeResourceIndicator(value) {
@@ -7160,8 +7316,13 @@ function createAuthStoreClientStore(options) {
7160
7316
  return null;
7161
7317
  }
7162
7318
  const parsed = JSON.parse(value);
7163
- if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && typeof parsed.clientId === "string") {
7164
- return parsed;
7319
+ const clientId = isObjectRecord(parsed) ? getOwnString(parsed, "clientId") : void 0;
7320
+ if (clientId !== void 0) {
7321
+ const client = { clientId };
7322
+ if (isObjectRecord(parsed) && Object.prototype.hasOwnProperty.call(parsed, "clientSecret")) {
7323
+ client.clientSecret = getOwnEntry4(parsed, "clientSecret");
7324
+ }
7325
+ return client;
7165
7326
  }
7166
7327
  throw new Error("Stored OAuth client must be a JSON object with clientId");
7167
7328
  },
@@ -7175,19 +7336,24 @@ function createAuthStoreClientStore(options) {
7175
7336
  }
7176
7337
  };
7177
7338
  }
7178
- function createNamedSecretStore(key2, options, defaults) {
7339
+ function createNamedSecretStore(key2, options, defaults2) {
7179
7340
  const hash = crypto.createHash("sha256").update(key2).digest("hex");
7180
- const parsedFilePath = options.fileStore?.filePath === void 0 ? null : path11.parse(options.fileStore.filePath);
7341
+ const configuredFilePath = options.fileStore?.filePath;
7342
+ const parsedFilePath = configuredFilePath === void 0 ? null : path11.parse(configuredFilePath);
7181
7343
  const fileStore = {
7182
7344
  ...options.fileStore,
7183
- salt: options.fileStore?.salt ?? defaults.salt,
7184
- defaultDirectory: parsedFilePath?.dir || options.fileStore?.defaultDirectory || defaults.directory,
7345
+ filePath: parsedFilePath === null ? void 0 : path11.join(
7346
+ parsedFilePath.dir,
7347
+ `${parsedFilePath.name}-${hash}${parsedFilePath.ext || ".enc"}`
7348
+ ),
7349
+ salt: options.fileStore?.salt ?? defaults2.salt,
7350
+ defaultDirectory: options.fileStore?.defaultDirectory || defaults2.directory,
7185
7351
  defaultFileName: parsedFilePath === null ? `${hash}.enc` : `${parsedFilePath.name}-${hash}${parsedFilePath.ext || ".enc"}`
7186
7352
  };
7187
7353
  const keychainStore = {
7188
7354
  ...options.keychainStore,
7189
- service: options.keychainStore?.service ?? defaults.service,
7190
- account: `${options.keychainStore?.account ?? defaults.accountPrefix}:${hash}`
7355
+ service: options.keychainStore?.service ?? defaults2.service,
7356
+ account: `${options.keychainStore?.account ?? defaults2.accountPrefix}:${hash}`
7191
7357
  };
7192
7358
  return createSecretStore({ ...options, fileStore, keychainStore }).store;
7193
7359
  }
@@ -7215,6 +7381,16 @@ function createIssuerSecretStore(issuer, options) {
7215
7381
  }
7216
7382
  );
7217
7383
  }
7384
+ function isObjectRecord(value) {
7385
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7386
+ }
7387
+ function getOwnEntry4(record, key2) {
7388
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7389
+ }
7390
+ function getOwnString(record, key2) {
7391
+ const value = getOwnEntry4(record, key2);
7392
+ return typeof value === "string" ? value : void 0;
7393
+ }
7218
7394
 
7219
7395
  // ../mcp-oauth/src/client/default-oauth-client-provider.ts
7220
7396
  import { URL as URL2 } from "node:url";
@@ -7240,17 +7416,30 @@ function parseAuthorizationState(value) {
7240
7416
  try {
7241
7417
  const decoded = Buffer.from(value, "base64url").toString("utf8");
7242
7418
  const parsed = JSON.parse(decoded);
7243
- if (parsed.v !== 1 || typeof parsed.n !== "string" || parsed.n.length === 0 || typeof parsed.i !== "string" || parsed.i.length === 0 || typeof parsed.r !== "boolean") {
7419
+ if (!isObjectRecord2(parsed)) {
7420
+ return null;
7421
+ }
7422
+ const version = getOwnEntry5(parsed, "v");
7423
+ const nonce = getOwnEntry5(parsed, "n");
7424
+ const issuer = getOwnEntry5(parsed, "i");
7425
+ const requireIssuer = getOwnEntry5(parsed, "r");
7426
+ if (version !== 1 || typeof nonce !== "string" || nonce.length === 0 || typeof issuer !== "string" || issuer.length === 0 || typeof requireIssuer !== "boolean") {
7244
7427
  return null;
7245
7428
  }
7246
7429
  return {
7247
- issuer: parsed.i,
7248
- requireIssuer: parsed.r
7430
+ issuer,
7431
+ requireIssuer
7249
7432
  };
7250
7433
  } catch {
7251
7434
  return null;
7252
7435
  }
7253
7436
  }
7437
+ function isObjectRecord2(value) {
7438
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7439
+ }
7440
+ function getOwnEntry5(record, key2) {
7441
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7442
+ }
7254
7443
 
7255
7444
  // ../mcp-oauth/src/client/loopback-authorization.ts
7256
7445
  async function createLoopbackAuthorizationSession(options = {}) {
@@ -7527,22 +7716,26 @@ async function requestTokens(input) {
7527
7716
  body: body.toString()
7528
7717
  });
7529
7718
  const payload = await readOAuthJsonObjectResponse(response);
7530
- if (typeof payload.access_token !== "string" || payload.access_token.trim().length === 0) {
7719
+ const accessToken = getOwnEntry6(payload, "access_token");
7720
+ if (typeof accessToken !== "string" || accessToken.trim().length === 0) {
7531
7721
  throw new Error("OAuth token response missing access_token");
7532
7722
  }
7533
- const tokenType = normalizeBearerTokenType(payload.token_type);
7723
+ const tokenType = normalizeBearerTokenType(getOwnEntry6(payload, "token_type"));
7534
7724
  if (tokenType === null) {
7535
7725
  throw new Error("OAuth token response missing token_type=Bearer");
7536
7726
  }
7537
- if (typeof payload.expires_in === "number" && Number.isFinite(payload.expires_in) && payload.expires_in < 0) {
7727
+ const expiresIn = getOwnEntry6(payload, "expires_in");
7728
+ if (typeof expiresIn === "number" && Number.isFinite(expiresIn) && expiresIn < 0) {
7538
7729
  throw new Error("OAuth token response has invalid expires_in");
7539
7730
  }
7731
+ const refreshToken = getOwnEntry6(payload, "refresh_token");
7732
+ const scope = getOwnEntry6(payload, "scope");
7540
7733
  return {
7541
- accessToken: payload.access_token,
7542
- refreshToken: typeof payload.refresh_token === "string" && payload.refresh_token.length > 0 ? payload.refresh_token : void 0,
7734
+ accessToken,
7735
+ refreshToken: typeof refreshToken === "string" && refreshToken.length > 0 ? refreshToken : void 0,
7543
7736
  tokenType,
7544
- expiresAt: typeof payload.expires_in === "number" && Number.isFinite(payload.expires_in) ? input.now() + payload.expires_in * 1e3 : null,
7545
- scope: typeof payload.scope === "string" && payload.scope.length > 0 ? payload.scope : void 0
7737
+ expiresAt: typeof expiresIn === "number" && Number.isFinite(expiresIn) ? input.now() + expiresIn * 1e3 : null,
7738
+ scope: typeof scope === "string" && scope.length > 0 ? scope : void 0
7546
7739
  };
7547
7740
  }
7548
7741
  async function readOAuthJsonObjectResponse(response) {
@@ -7569,12 +7762,18 @@ async function readOAuthJsonObjectResponse(response) {
7569
7762
  return record;
7570
7763
  }
7571
7764
  function readOAuthError(payload, fallbackError = "server_error") {
7765
+ const error3 = getOwnEntry6(payload, "error");
7766
+ const errorDescription = getOwnEntry6(payload, "error_description");
7767
+ const errorUri = getOwnEntry6(payload, "error_uri");
7572
7768
  return {
7573
- error: typeof payload.error === "string" ? payload.error : fallbackError,
7574
- error_description: typeof payload.error_description === "string" ? payload.error_description : void 0,
7575
- error_uri: typeof payload.error_uri === "string" ? payload.error_uri : void 0
7769
+ error: typeof error3 === "string" ? error3 : fallbackError,
7770
+ error_description: typeof errorDescription === "string" ? errorDescription : void 0,
7771
+ error_uri: typeof errorUri === "string" ? errorUri : void 0
7576
7772
  };
7577
7773
  }
7774
+ function getOwnEntry6(record, key2) {
7775
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7776
+ }
7578
7777
  function createFallbackOAuthError(status) {
7579
7778
  const error3 = status === 503 ? "temporarily_unavailable" : "server_error";
7580
7779
  return new OAuthError({ error: error3 }, status);
@@ -7679,7 +7878,11 @@ function createDefaultOAuthClientProvider(options) {
7679
7878
  while (true) {
7680
7879
  try {
7681
7880
  refreshedTokens = await refreshAccessToken({
7682
- tokenEndpoint: discovery.authorizationServerMetadata.token_endpoint,
7881
+ tokenEndpoint: requireOwnString(
7882
+ discovery.authorizationServerMetadata,
7883
+ "token_endpoint",
7884
+ "Authorization server metadata"
7885
+ ),
7683
7886
  clientId: session.client.clientId,
7684
7887
  clientSecret: session.client.clientSecret,
7685
7888
  refreshToken: session.tokens.refreshToken,
@@ -7767,7 +7970,11 @@ function createDefaultOAuthClientProvider(options) {
7767
7970
  });
7768
7971
  const code = await loopback.waitForCode(authorizationUrl);
7769
7972
  const tokens = await exchangeAuthorizationCode({
7770
- tokenEndpoint: discovery.authorizationServerMetadata.token_endpoint,
7973
+ tokenEndpoint: requireOwnString(
7974
+ discovery.authorizationServerMetadata,
7975
+ "token_endpoint",
7976
+ "Authorization server metadata"
7977
+ ),
7771
7978
  clientId: resolvedClient.client.clientId,
7772
7979
  clientSecret: resolvedClient.client.clientSecret,
7773
7980
  code,
@@ -7820,7 +8027,10 @@ function createDefaultOAuthClientProvider(options) {
7820
8027
  }
7821
8028
  };
7822
8029
  }
7823
- const registrationEndpoint = discovery.authorizationServerMetadata.registration_endpoint;
8030
+ const registrationEndpoint = getOwnString2(
8031
+ discovery.authorizationServerMetadata,
8032
+ "registration_endpoint"
8033
+ );
7824
8034
  if (registrationEndpoint === void 0 && options.client.clientId !== void 0) {
7825
8035
  return {
7826
8036
  kind: "static",
@@ -7872,12 +8082,14 @@ function createDefaultOAuthClientProvider(options) {
7872
8082
  body: JSON.stringify(registrationBody)
7873
8083
  });
7874
8084
  const payload = await readOAuthJsonObjectResponse(response);
7875
- if (typeof payload.client_id !== "string" || payload.client_id.trim().length === 0) {
8085
+ const clientId = getOwnString2(payload, "client_id");
8086
+ if (clientId === void 0 || clientId.trim().length === 0) {
7876
8087
  throw new Error("OAuth client registration response missing client_id");
7877
8088
  }
8089
+ const clientSecret = getOwnString2(payload, "client_secret");
7878
8090
  const registeredClient = {
7879
- clientId: payload.client_id,
7880
- clientSecret: typeof payload.client_secret === "string" && payload.client_secret.length > 0 ? payload.client_secret : void 0
8091
+ clientId,
8092
+ clientSecret: clientSecret !== void 0 && clientSecret.length > 0 ? clientSecret : void 0
7881
8093
  };
7882
8094
  await saveRegisteredClient(discovery.authorizationServer, registeredClient);
7883
8095
  return {
@@ -7903,12 +8115,13 @@ function createDefaultOAuthClientProvider(options) {
7903
8115
  return null;
7904
8116
  }
7905
8117
  const client = await clientStore.load(issuer);
7906
- if (client !== null && !isUsableClient(client)) {
8118
+ const normalizedClient = client === null ? null : normalizeStoredClient(client);
8119
+ if (client !== null && normalizedClient === null) {
7907
8120
  await clientStore.clear(issuer);
7908
8121
  return null;
7909
8122
  }
7910
- registeredClients.set(issuer, client);
7911
- return client;
8123
+ registeredClients.set(issuer, normalizedClient);
8124
+ return normalizedClient;
7912
8125
  }
7913
8126
  async function saveRegisteredClient(issuer, client) {
7914
8127
  registeredClients.set(issuer, client);
@@ -7924,7 +8137,7 @@ function createDefaultOAuthClientProvider(options) {
7924
8137
  }
7925
8138
  }
7926
8139
  function isProviderOptions(options) {
7927
- return "provider" in options;
8140
+ return Object.prototype.hasOwnProperty.call(options, "provider");
7928
8141
  }
7929
8142
  function isExpired(tokens, now) {
7930
8143
  return tokens.expiresAt !== null && tokens.expiresAt <= now();
@@ -7940,7 +8153,14 @@ function resolveDiscovery(discovery, session) {
7940
8153
  return void 0;
7941
8154
  }
7942
8155
  const metadata = session.discovery.authorizationServerMetadata;
7943
- if (typeof metadata.issuer !== "string" || typeof metadata.authorization_endpoint !== "string" || typeof metadata.token_endpoint !== "string" || !Array.isArray(metadata.code_challenge_methods_supported) || !metadata.code_challenge_methods_supported.includes("S256")) {
8156
+ const issuer = getOwnString2(metadata, "issuer");
8157
+ const authorizationEndpoint = getOwnString2(metadata, "authorization_endpoint");
8158
+ const tokenEndpoint = getOwnString2(metadata, "token_endpoint");
8159
+ const codeChallengeMethodsSupported = getOwnStringArray(
8160
+ metadata,
8161
+ "code_challenge_methods_supported"
8162
+ );
8163
+ if (issuer === void 0 || authorizationEndpoint === void 0 || tokenEndpoint === void 0 || codeChallengeMethodsSupported === void 0 || !codeChallengeMethodsSupported.includes("S256")) {
7944
8164
  return void 0;
7945
8165
  }
7946
8166
  return {
@@ -7964,29 +8184,94 @@ function normalizeLoadedSession(session) {
7964
8184
  if (session === null) {
7965
8185
  return null;
7966
8186
  }
7967
- if (!isUsableClient(session.client)) {
8187
+ const client = normalizeStoredClient(getOwnEntry7(session, "client"));
8188
+ if (client === null) {
7968
8189
  return { ...session, client: { clientId: "" }, tokens: void 0 };
7969
8190
  }
7970
- return isUsableTokens(session.tokens) ? session : { ...session, tokens: void 0 };
8191
+ return {
8192
+ ...session,
8193
+ client,
8194
+ tokens: normalizeStoredTokens(getOwnEntry7(session, "tokens"))
8195
+ };
7971
8196
  }
7972
- function isUsableClient(client) {
7973
- return typeof client.clientId === "string" && client.clientId.trim().length > 0 && (client.clientSecret === void 0 || typeof client.clientSecret === "string" && client.clientSecret.trim().length > 0);
8197
+ function normalizeStoredClient(value) {
8198
+ if (!isObjectRecord3(value)) {
8199
+ return null;
8200
+ }
8201
+ const clientId = getOwnString2(value, "clientId");
8202
+ if (clientId === void 0 || clientId.trim().length === 0) {
8203
+ return null;
8204
+ }
8205
+ const clientSecret = getOwnEntry7(value, "clientSecret");
8206
+ if (clientSecret === void 0) {
8207
+ return { clientId };
8208
+ }
8209
+ if (typeof clientSecret !== "string" || clientSecret.trim().length === 0) {
8210
+ return null;
8211
+ }
8212
+ return { clientId, clientSecret };
7974
8213
  }
7975
- function isUsableTokens(tokens) {
7976
- if (tokens === void 0) {
7977
- return true;
8214
+ function normalizeStoredTokens(value) {
8215
+ if (value === void 0 || !isObjectRecord3(value)) {
8216
+ return void 0;
7978
8217
  }
7979
- return typeof tokens.accessToken === "string" && tokens.accessToken.trim().length > 0 && tokens.tokenType === "Bearer" && (tokens.expiresAt === null || typeof tokens.expiresAt === "number" && Number.isFinite(tokens.expiresAt)) && (tokens.refreshToken === void 0 || typeof tokens.refreshToken === "string" && tokens.refreshToken.trim().length > 0);
8218
+ const accessToken = getOwnString2(value, "accessToken");
8219
+ const tokenType = getOwnString2(value, "tokenType");
8220
+ const expiresAt = getOwnEntry7(value, "expiresAt");
8221
+ const refreshToken = getOwnEntry7(value, "refreshToken");
8222
+ const scope = getOwnString2(value, "scope");
8223
+ const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken : void 0;
8224
+ if (accessToken === void 0 || accessToken.trim().length === 0 || tokenType !== "Bearer" || !(expiresAt === null || typeof expiresAt === "number" && Number.isFinite(expiresAt)) || refreshToken !== void 0 && (typeof refreshToken !== "string" || refreshToken.trim().length === 0)) {
8225
+ return void 0;
8226
+ }
8227
+ return {
8228
+ accessToken,
8229
+ tokenType,
8230
+ expiresAt,
8231
+ ...normalizedRefreshToken === void 0 ? {} : { refreshToken: normalizedRefreshToken },
8232
+ ...scope === void 0 || scope.length === 0 ? {} : { scope }
8233
+ };
7980
8234
  }
7981
8235
  function getClientMetadata(client) {
7982
8236
  return client.metadata;
7983
8237
  }
8238
+ function getOwnEntry7(record, key2) {
8239
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
8240
+ }
8241
+ function isObjectRecord3(value) {
8242
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8243
+ }
8244
+ function getOwnString2(record, key2) {
8245
+ const value = getOwnEntry7(record, key2);
8246
+ return typeof value === "string" ? value : void 0;
8247
+ }
8248
+ function requireOwnString(record, key2, label) {
8249
+ const value = getOwnString2(record, key2);
8250
+ if (value === void 0) {
8251
+ throw new Error(`${label} is missing ${key2}`);
8252
+ }
8253
+ return value;
8254
+ }
8255
+ function getOwnStringArray(record, key2) {
8256
+ const value = getOwnEntry7(record, key2);
8257
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : void 0;
8258
+ }
7984
8259
  function buildAuthorizationUrl(input) {
7985
- const url = new URL2(input.metadata.authorization_endpoint);
8260
+ const authorizationEndpoint = requireOwnString(
8261
+ input.metadata,
8262
+ "authorization_endpoint",
8263
+ "Authorization server metadata"
8264
+ );
8265
+ const issuer = requireOwnString(
8266
+ input.metadata,
8267
+ "issuer",
8268
+ "Authorization server metadata"
8269
+ );
8270
+ const url = new URL2(authorizationEndpoint);
7986
8271
  const resource = canonicalizeResourceIndicator(input.resource);
7987
8272
  const state = createAuthorizationState({
7988
- issuer: input.metadata.issuer,
7989
- requireIssuer: input.metadata.authorization_response_iss_parameter_supported === true
8273
+ issuer,
8274
+ requireIssuer: getOwnEntry7(input.metadata, "authorization_response_iss_parameter_supported") === true
7990
8275
  });
7991
8276
  url.searchParams.set("response_type", "code");
7992
8277
  url.searchParams.set("client_id", input.clientId);
@@ -8001,7 +8286,7 @@ function buildAuthorizationUrl(input) {
8001
8286
  return url.toString();
8002
8287
  }
8003
8288
  function assertS256PkceSupport(metadata) {
8004
- if (!metadata.code_challenge_methods_supported.includes("S256")) {
8289
+ if (!getOwnStringArray(metadata, "code_challenge_methods_supported")?.includes("S256")) {
8005
8290
  throw new Error(
8006
8291
  "Authorization server metadata must advertise code_challenge_methods_supported including S256"
8007
8292
  );
@@ -8025,13 +8310,24 @@ function assertSecureUrl(value, label) {
8025
8310
  throw new Error(`${label} must use https unless it targets a loopback host`);
8026
8311
  }
8027
8312
  function assertSecureOAuthFlowEndpoints(metadata) {
8028
- assertNoAccessTokenInUrl(metadata.authorization_endpoint, "Authorization endpoint");
8029
- assertNoAccessTokenInUrl(metadata.token_endpoint, "Token endpoint");
8030
- assertSecureUrl(metadata.authorization_endpoint, "Authorization endpoint");
8031
- assertSecureUrl(metadata.token_endpoint, "Token endpoint");
8032
- if (metadata.registration_endpoint !== void 0) {
8033
- assertNoAccessTokenInUrl(metadata.registration_endpoint, "Registration endpoint");
8034
- assertSecureUrl(metadata.registration_endpoint, "Registration endpoint");
8313
+ const authorizationEndpoint = requireOwnString(
8314
+ metadata,
8315
+ "authorization_endpoint",
8316
+ "Authorization server metadata"
8317
+ );
8318
+ const tokenEndpoint = requireOwnString(
8319
+ metadata,
8320
+ "token_endpoint",
8321
+ "Authorization server metadata"
8322
+ );
8323
+ const registrationEndpoint = getOwnString2(metadata, "registration_endpoint");
8324
+ assertNoAccessTokenInUrl(authorizationEndpoint, "Authorization endpoint");
8325
+ assertNoAccessTokenInUrl(tokenEndpoint, "Token endpoint");
8326
+ assertSecureUrl(authorizationEndpoint, "Authorization endpoint");
8327
+ assertSecureUrl(tokenEndpoint, "Token endpoint");
8328
+ if (registrationEndpoint !== void 0) {
8329
+ assertNoAccessTokenInUrl(registrationEndpoint, "Registration endpoint");
8330
+ assertSecureUrl(registrationEndpoint, "Registration endpoint");
8035
8331
  }
8036
8332
  }
8037
8333
  function assertNoAccessTokenInUrl(value, label) {
@@ -8054,17 +8350,21 @@ function buildClientRegistrationBody(metadata, redirectUri) {
8054
8350
  response_types: ["code"],
8055
8351
  token_endpoint_auth_method: "none"
8056
8352
  };
8057
- if (metadata?.clientName !== void 0 && metadata.clientName.length > 0) {
8058
- body.client_name = metadata.clientName;
8353
+ const clientName = metadata === void 0 ? void 0 : getOwnString2(metadata, "clientName");
8354
+ const scope = metadata === void 0 ? void 0 : getOwnString2(metadata, "scope");
8355
+ const softwareId = metadata === void 0 ? void 0 : getOwnString2(metadata, "softwareId");
8356
+ const softwareVersion = metadata === void 0 ? void 0 : getOwnString2(metadata, "softwareVersion");
8357
+ if (clientName !== void 0 && clientName.length > 0) {
8358
+ body.client_name = clientName;
8059
8359
  }
8060
- if (metadata?.scope !== void 0 && metadata.scope.length > 0) {
8061
- body.scope = metadata.scope;
8360
+ if (scope !== void 0 && scope.length > 0) {
8361
+ body.scope = scope;
8062
8362
  }
8063
- if (metadata?.softwareId !== void 0 && metadata.softwareId.length > 0) {
8064
- body.software_id = metadata.softwareId;
8363
+ if (softwareId !== void 0 && softwareId.length > 0) {
8364
+ body.software_id = softwareId;
8065
8365
  }
8066
- if (metadata?.softwareVersion !== void 0 && metadata.softwareVersion.length > 0) {
8067
- body.software_version = metadata.softwareVersion;
8366
+ if (softwareVersion !== void 0 && softwareVersion.length > 0) {
8367
+ body.software_version = softwareVersion;
8068
8368
  }
8069
8369
  return body;
8070
8370
  }
@@ -8100,7 +8400,7 @@ import {
8100
8400
  function defaultOAuthMetadataFetch(input, init) {
8101
8401
  return fetch(input, init);
8102
8402
  }
8103
- function isObjectRecord(value) {
8403
+ function isObjectRecord4(value) {
8104
8404
  return typeof value === "object" && value !== null && !Array.isArray(value);
8105
8405
  }
8106
8406
  function isStringArray(value) {
@@ -8123,7 +8423,7 @@ function assertSecureUrl2(url, label) {
8123
8423
  throw new Error(`${label} must use https unless it targets a loopback host`);
8124
8424
  }
8125
8425
  function validateProtectedResourceMetadata(value, resourceUrl) {
8126
- if (!isObjectRecord(value)) {
8426
+ if (!isObjectRecord4(value)) {
8127
8427
  throw new Error("Protected resource metadata must be a JSON object");
8128
8428
  }
8129
8429
  if (typeof value.resource !== "string" || value.resource.length === 0) {
@@ -8146,7 +8446,7 @@ function validateProtectedResourceMetadata(value, resourceUrl) {
8146
8446
  };
8147
8447
  }
8148
8448
  function validateAuthorizationServerMetadata(value, issuer) {
8149
- if (!isObjectRecord(value)) {
8449
+ if (!isObjectRecord4(value)) {
8150
8450
  throw new Error("Authorization server metadata must be a JSON object");
8151
8451
  }
8152
8452
  if (typeof value.issuer !== "string" || value.issuer.length === 0) {
@@ -8599,7 +8899,7 @@ var McpClient = class {
8599
8899
  await onPromptsChanged();
8600
8900
  });
8601
8901
  messageLayer.onNotification("notifications/message", async (params17) => {
8602
- if (onLog === void 0 || !isObjectRecord2(params17) || !isLogLevel(params17.level)) {
8902
+ if (onLog === void 0 || !isObjectRecord5(params17) || !isLogLevel(params17.level)) {
8603
8903
  return;
8604
8904
  }
8605
8905
  if (!hasOwn(params17, "data")) {
@@ -8618,7 +8918,7 @@ var McpClient = class {
8618
8918
  await onLog(message2);
8619
8919
  });
8620
8920
  messageLayer.onNotification("notifications/progress", async (params17) => {
8621
- if (onProgress === void 0 || !isObjectRecord2(params17)) {
8921
+ if (onProgress === void 0 || !isObjectRecord5(params17)) {
8622
8922
  return;
8623
8923
  }
8624
8924
  const { progressToken, progress } = params17;
@@ -8787,6 +9087,9 @@ var McpClient = class {
8787
9087
  const abortPromise = new Promise((_, reject) => {
8788
9088
  const rejectWithAbortReason = () => {
8789
9089
  sendCancellationNotification();
9090
+ if (requestId !== void 0) {
9091
+ messageLayer.cancelRequest(requestId, signal.reason);
9092
+ }
8790
9093
  reject(signal.reason);
8791
9094
  };
8792
9095
  abortListener = rejectWithAbortReason;
@@ -8961,11 +9264,13 @@ var StdioTransport = class _StdioTransport {
8961
9264
  const child = this.child;
8962
9265
  this.readable = child.stdout;
8963
9266
  this.writable = child.stdin;
9267
+ const stderrDecoder = new TextDecoder();
8964
9268
  child.stderr.on("data", (chunk) => {
8965
- this.stderrOutput += chunkToString(chunk);
8966
- if (this.stderrOutput.length > _StdioTransport.STDERR_MAX_LENGTH) {
8967
- this.stderrOutput = this.stderrOutput.slice(-_StdioTransport.STDERR_MAX_LENGTH);
8968
- }
9269
+ const decoded = chunk instanceof Uint8Array ? stderrDecoder.decode(chunk, { stream: true }) : `${stderrDecoder.decode()}${String(chunk)}`;
9270
+ this.appendStderrOutput(decoded);
9271
+ });
9272
+ child.stderr.once("end", () => {
9273
+ this.appendStderrOutput(stderrDecoder.decode());
8969
9274
  });
8970
9275
  this.closed = new Promise((resolve) => {
8971
9276
  let settled = false;
@@ -9005,6 +9310,15 @@ var StdioTransport = class _StdioTransport {
9005
9310
  getStderrOutput() {
9006
9311
  return this.stderrOutput;
9007
9312
  }
9313
+ appendStderrOutput(chunk) {
9314
+ if (chunk.length === 0) {
9315
+ return;
9316
+ }
9317
+ this.stderrOutput += chunk;
9318
+ if (this.stderrOutput.length > _StdioTransport.STDERR_MAX_LENGTH) {
9319
+ this.stderrOutput = this.stderrOutput.slice(-_StdioTransport.STDERR_MAX_LENGTH);
9320
+ }
9321
+ }
9008
9322
  dispose(reason = new Error("Stdio transport disposed")) {
9009
9323
  void reason;
9010
9324
  if (this.disposed) {
@@ -9412,15 +9726,6 @@ function serializeJsonRpcMessage(message2) {
9412
9726
  return `${JSON.stringify(message2)}
9413
9727
  `;
9414
9728
  }
9415
- function chunkToString(chunk) {
9416
- if (typeof chunk === "string") {
9417
- return chunk;
9418
- }
9419
- if (chunk instanceof Uint8Array) {
9420
- return Buffer.from(chunk).toString("utf8");
9421
- }
9422
- return String(chunk);
9423
- }
9424
9729
  function normalizeLine(line) {
9425
9730
  return line.endsWith("\r") ? line.slice(0, -1) : line;
9426
9731
  }
@@ -9610,6 +9915,16 @@ var JsonRpcMessageLayer = class {
9610
9915
  }
9611
9916
  });
9612
9917
  }
9918
+ cancelRequest(requestId, reason) {
9919
+ const pending = this.pendingRequests.get(requestId);
9920
+ if (pending === void 0) {
9921
+ return false;
9922
+ }
9923
+ this.pendingRequests.delete(requestId);
9924
+ clearTimeout(pending.timeout);
9925
+ pending.reject(reason);
9926
+ return true;
9927
+ }
9613
9928
  dispose(reason = new Error("JSON-RPC message layer disposed")) {
9614
9929
  if (this.disposedError !== void 0) {
9615
9930
  return;
@@ -9804,7 +10119,7 @@ var JsonRpcMessageLayer = class {
9804
10119
  })();
9805
10120
  }
9806
10121
  handleCancellationNotification(params17) {
9807
- if (!isObjectRecord2(params17)) {
10122
+ if (!isObjectRecord5(params17)) {
9808
10123
  return;
9809
10124
  }
9810
10125
  const requestId = params17.requestId;
@@ -9819,34 +10134,34 @@ var JsonRpcMessageLayer = class {
9819
10134
  this.activeIncomingRequests.delete(requestId);
9820
10135
  }
9821
10136
  };
9822
- function isObjectRecord2(value) {
10137
+ function isObjectRecord5(value) {
9823
10138
  return typeof value === "object" && value !== null && !Array.isArray(value);
9824
10139
  }
9825
10140
  function isInitializeResult(value) {
9826
- if (!isObjectRecord2(value) || typeof value.protocolVersion !== "string") {
10141
+ if (!isObjectRecord5(value) || typeof value.protocolVersion !== "string") {
9827
10142
  return false;
9828
10143
  }
9829
10144
  if (!isServerCapabilities(value.capabilities)) {
9830
10145
  return false;
9831
10146
  }
9832
- if (!isObjectRecord2(value.serverInfo) || typeof value.serverInfo.name !== "string" || value.serverInfo.name.length === 0 || typeof value.serverInfo.version !== "string" || value.serverInfo.version.length === 0) {
10147
+ if (!isObjectRecord5(value.serverInfo) || typeof value.serverInfo.name !== "string" || value.serverInfo.name.length === 0 || typeof value.serverInfo.version !== "string" || value.serverInfo.version.length === 0) {
9833
10148
  return false;
9834
10149
  }
9835
10150
  return value.instructions === void 0 || typeof value.instructions === "string";
9836
10151
  }
9837
10152
  function isServerCapabilities(value) {
9838
- if (!isObjectRecord2(value)) {
10153
+ if (!isObjectRecord5(value)) {
9839
10154
  return false;
9840
10155
  }
9841
10156
  for (const capability of ["prompts", "resources", "tools", "logging", "completions", "experimental"]) {
9842
- if (value[capability] !== void 0 && !isObjectRecord2(value[capability])) {
10157
+ if (value[capability] !== void 0 && !isObjectRecord5(value[capability])) {
9843
10158
  return false;
9844
10159
  }
9845
10160
  }
9846
10161
  return true;
9847
10162
  }
9848
10163
  function isCallToolResult(value) {
9849
- if (!isObjectRecord2(value) || !Array.isArray(value.content)) {
10164
+ if (!isObjectRecord5(value) || !Array.isArray(value.content)) {
9850
10165
  return false;
9851
10166
  }
9852
10167
  if (value.isError !== void 0 && typeof value.isError !== "boolean") {
@@ -9855,10 +10170,10 @@ function isCallToolResult(value) {
9855
10170
  return value.content.every(isContentItem);
9856
10171
  }
9857
10172
  function isToolsListResult(value) {
9858
- return isObjectRecord2(value) && Array.isArray(value.tools) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
10173
+ return isObjectRecord5(value) && Array.isArray(value.tools) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
9859
10174
  }
9860
10175
  function isContentItem(value) {
9861
- if (!isObjectRecord2(value)) {
10176
+ if (!isObjectRecord5(value)) {
9862
10177
  return false;
9863
10178
  }
9864
10179
  if (value.type === "text") {
@@ -9867,7 +10182,7 @@ function isContentItem(value) {
9867
10182
  if (value.type === "image" || value.type === "audio") {
9868
10183
  return typeof value.data === "string" && typeof value.mimeType === "string";
9869
10184
  }
9870
- if (value.type !== "resource" || !isObjectRecord2(value.resource)) {
10185
+ if (value.type !== "resource" || !isObjectRecord5(value.resource)) {
9871
10186
  return false;
9872
10187
  }
9873
10188
  return typeof value.resource.uri === "string" && (value.resource.mimeType === void 0 || typeof value.resource.mimeType === "string") && (typeof value.resource.text === "string" || typeof value.resource.blob === "string");
@@ -9891,7 +10206,7 @@ function invalidRequest() {
9891
10206
  return new McpError(ERROR_INVALID_REQUEST, "Invalid Request");
9892
10207
  }
9893
10208
  function isJsonRpcErrorObject(value) {
9894
- if (!isObjectRecord2(value)) {
10209
+ if (!isObjectRecord5(value)) {
9895
10210
  return false;
9896
10211
  }
9897
10212
  if (typeof value.code !== "number" || typeof value.message !== "string") {
@@ -9900,7 +10215,7 @@ function isJsonRpcErrorObject(value) {
9900
10215
  return value.data === void 0 || hasOwn(value, "data");
9901
10216
  }
9902
10217
  function parseJsonRpcPayload(parsed) {
9903
- if (!isObjectRecord2(parsed)) {
10218
+ if (!isObjectRecord5(parsed)) {
9904
10219
  return {
9905
10220
  type: "invalid",
9906
10221
  id: null,
@@ -10227,7 +10542,11 @@ function convertObjectSchema(schema, root, options) {
10227
10542
  "properties",
10228
10543
  key2
10229
10544
  ]);
10230
- shape[key2] = requiredKeys.has(key2) ? convertedProperty : S.Optional(convertedProperty);
10545
+ setOwnShapeProperty(
10546
+ shape,
10547
+ key2,
10548
+ requiredKeys.has(key2) ? convertedProperty : S.Optional(convertedProperty)
10549
+ );
10231
10550
  }
10232
10551
  return applyMetadata(
10233
10552
  S.Object(shape, {
@@ -10239,6 +10558,14 @@ function convertObjectSchema(schema, root, options) {
10239
10558
  }
10240
10559
  );
10241
10560
  }
10561
+ function setOwnShapeProperty(shape, key2, value) {
10562
+ Object.defineProperty(shape, key2, {
10563
+ configurable: true,
10564
+ enumerable: true,
10565
+ writable: true,
10566
+ value
10567
+ });
10568
+ }
10242
10569
  function createCommonOptions(schema, nullable, defaultValue) {
10243
10570
  return {
10244
10571
  ...schema.description === void 0 ? {} : { description: schema.description },
@@ -10489,6 +10816,9 @@ function resolveLocalRef(root, ref) {
10489
10816
  if (!isPlainObject(current)) {
10490
10817
  return void 0;
10491
10818
  }
10819
+ if (!Object.prototype.hasOwnProperty.call(current, segment)) {
10820
+ return void 0;
10821
+ }
10492
10822
  current = current[segment];
10493
10823
  }
10494
10824
  return isPlainObject(current) ? current : void 0;
@@ -10678,10 +11008,10 @@ function validateRenameMap2(name, tools, rename5) {
10678
11008
  }
10679
11009
  }
10680
11010
  }
10681
- function createConnection(name, config) {
11011
+ function createConnection(name, config2) {
10682
11012
  const connection = {
10683
11013
  name,
10684
- config,
11014
+ config: config2,
10685
11015
  async dispose() {
10686
11016
  shutdownDisposers.delete(connection.dispose);
10687
11017
  connection.connecting = void 0;
@@ -10737,24 +11067,42 @@ async function readCache(cachePath) {
10737
11067
  }
10738
11068
  async function writeCache(cachePath, cache) {
10739
11069
  const directory = path12.dirname(cachePath);
10740
- const tempPath = `${cachePath}.tmp-${randomUUID2()}`;
11070
+ const tempPath = `${cachePath}.tmp-${randomUUID4()}`;
11071
+ let tempCreated = false;
10741
11072
  await assertCachePathHasNoSymlinks(cachePath);
10742
11073
  await assertCachePathHasNoSymlinks(tempPath);
10743
11074
  await mkdir(directory, { recursive: true });
10744
11075
  await assertCachePathHasNoSymlinks(directory);
10745
- await writeFile3(tempPath, `${JSON.stringify(cache, null, 2)}
10746
- `);
10747
- await assertCachePathHasNoSymlinks(tempPath);
10748
- await assertCachePathHasNoSymlinks(cachePath);
10749
- await rename2(tempPath, cachePath);
11076
+ try {
11077
+ await writeFile3(tempPath, `${JSON.stringify(cache, null, 2)}
11078
+ `, {
11079
+ encoding: "utf8",
11080
+ flag: "wx"
11081
+ });
11082
+ tempCreated = true;
11083
+ await assertCachePathHasNoSymlinks(tempPath);
11084
+ await assertCachePathHasNoSymlinks(cachePath);
11085
+ await rename2(tempPath, cachePath);
11086
+ tempCreated = false;
11087
+ } catch (error3) {
11088
+ if (tempCreated || !isAlreadyExistsError2(error3)) {
11089
+ await unlink2(tempPath).catch(() => void 0);
11090
+ }
11091
+ throw error3;
11092
+ }
10750
11093
  }
10751
- async function fetchCache(name, config) {
11094
+ function isAlreadyExistsError2(error3) {
11095
+ return Boolean(
11096
+ error3 && typeof error3 === "object" && error3.code === "EEXIST"
11097
+ );
11098
+ }
11099
+ async function fetchCache(name, config2) {
10752
11100
  const logger2 = createLogger((message2) => {
10753
11101
  process.stderr.write(`${message2}
10754
11102
  `);
10755
11103
  });
10756
11104
  logger2.info(`MCP ${name}: connecting`);
10757
- const client = await dialUpstream(name, config);
11105
+ const client = await dialUpstream(name, config2);
10758
11106
  try {
10759
11107
  logger2.info(`MCP ${name}: listing tools`);
10760
11108
  const tools = [];
@@ -10773,7 +11121,7 @@ async function fetchCache(name, config) {
10773
11121
  $schema: MCP_PROXY_SCHEMA_URL,
10774
11122
  version: 1,
10775
11123
  upstream,
10776
- configFingerprint: fingerprintMcpServerConfig(config),
11124
+ configFingerprint: fingerprintMcpServerConfig(config2),
10777
11125
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
10778
11126
  tools
10779
11127
  };
@@ -10843,8 +11191,8 @@ function isRefreshRequested(name, refresh) {
10843
11191
  }
10844
11192
  async function resolveSingleProxy(group, options) {
10845
11193
  const internal = getInternalGroupConfig2(group);
10846
- const config = internal.mcp;
10847
- if (config === void 0) {
11194
+ const config2 = internal.mcp;
11195
+ if (config2 === void 0) {
10848
11196
  return;
10849
11197
  }
10850
11198
  const name = group.name;
@@ -10854,21 +11202,21 @@ async function resolveSingleProxy(group, options) {
10854
11202
  let cache;
10855
11203
  let shouldWriteCache = false;
10856
11204
  if (isRefreshRequested(name, refresh)) {
10857
- cache = await fetchCache(name, config);
11205
+ cache = await fetchCache(name, config2);
10858
11206
  shouldWriteCache = true;
10859
11207
  } else {
10860
11208
  const storedCache = await readCache(cachePath);
10861
- if (storedCache && cacheMatchesConfig(storedCache, config)) {
11209
+ if (storedCache && cacheMatchesConfig(storedCache, config2)) {
10862
11210
  cache = storedCache;
10863
11211
  } else {
10864
- cache = await fetchCache(name, config);
11212
+ cache = await fetchCache(name, config2);
10865
11213
  shouldWriteCache = true;
10866
11214
  }
10867
11215
  }
10868
11216
  const tools = filterAllowlistedTools(cache.tools, internal.tools);
10869
11217
  validateRenameMap2(name, tools, internal.rename);
10870
11218
  const previousConnection = getProxyConnection(group);
10871
- const nextConnection = createConnection(name, config);
11219
+ const nextConnection = createConnection(name, config2);
10872
11220
  try {
10873
11221
  replaceProxyChildrenSafely(group, tools, internal.rename, nextConnection);
10874
11222
  if (shouldWriteCache) {
@@ -10893,11 +11241,11 @@ async function resolveSingleProxy(group, options) {
10893
11241
  );
10894
11242
  }
10895
11243
  }
10896
- function cacheMatchesConfig(cache, config) {
10897
- return cache.configFingerprint === fingerprintMcpServerConfig(config);
11244
+ function cacheMatchesConfig(cache, config2) {
11245
+ return cache.configFingerprint === fingerprintMcpServerConfig(config2);
10898
11246
  }
10899
- function fingerprintMcpServerConfig(config) {
10900
- return createHash3("sha256").update(JSON.stringify(config)).digest("hex");
11247
+ function fingerprintMcpServerConfig(config2) {
11248
+ return createHash3("sha256").update(JSON.stringify(config2)).digest("hex");
10901
11249
  }
10902
11250
  function collectProxyGroups(root) {
10903
11251
  const groups = [];
@@ -10975,20 +11323,20 @@ function parseRefreshEnv(value) {
10975
11323
  const names = trimmed.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
10976
11324
  return names.length === 0 ? void 0 : new Set(names);
10977
11325
  }
10978
- async function dialUpstream(name, config) {
11326
+ async function dialUpstream(name, config2) {
10979
11327
  const client = new McpClient({
10980
11328
  clientInfo: {
10981
11329
  name: `${DEFAULT_CLIENT_INFO.name}-${name}`,
10982
11330
  version: DEFAULT_CLIENT_INFO.version
10983
11331
  }
10984
11332
  });
10985
- const transport = config.transport === "stdio" ? new StdioTransport({
10986
- command: config.command,
10987
- ...config.args === void 0 ? {} : { args: config.args },
10988
- ...config.env === void 0 ? {} : { env: config.env }
11333
+ const transport = config2.transport === "stdio" ? new StdioTransport({
11334
+ command: config2.command,
11335
+ ...config2.args === void 0 ? {} : { args: config2.args },
11336
+ ...config2.env === void 0 ? {} : { env: config2.env }
10989
11337
  }) : new HttpTransport({
10990
- url: config.url,
10991
- ...config.headers === void 0 ? {} : { headers: config.headers }
11338
+ url: config2.url,
11339
+ ...config2.headers === void 0 ? {} : { headers: config2.headers }
10992
11340
  });
10993
11341
  await client.connect(transport);
10994
11342
  return client;
@@ -10998,10 +11346,82 @@ async function resolveMcpProxies(root, options = {}) {
10998
11346
  await Promise.all(groups.map((group) => resolveSingleProxy(group, options)));
10999
11347
  }
11000
11348
 
11349
+ // ../toolcraft/src/redaction.ts
11350
+ var REDACTED_VALUE = "<redacted>";
11351
+ var SENSITIVE_NAME_PARTS = ["password", "token", "apikey", "secret"];
11352
+ var AUTHORIZATION_HEADER_NAMES = /* @__PURE__ */ new Set(["authorization", "proxyauthorization"]);
11353
+ var SECRET_HEADER_NAMES = /* @__PURE__ */ new Set(["cookie", "setcookie"]);
11354
+ function isPlainObject2(value) {
11355
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11356
+ }
11357
+ function normalizeName(name) {
11358
+ return name.toLowerCase().replace(/[^a-z0-9]/g, "");
11359
+ }
11360
+ function isSensitiveName(name) {
11361
+ const normalized = normalizeName(name);
11362
+ return SENSITIVE_NAME_PARTS.some((candidate) => normalized.includes(candidate));
11363
+ }
11364
+ function redactSecretLikeFieldsValue(value, name, seen) {
11365
+ if (name.length > 0 && isSensitiveName(name)) {
11366
+ return REDACTED_VALUE;
11367
+ }
11368
+ if (Array.isArray(value)) {
11369
+ if (seen.has(value)) {
11370
+ return "[Circular]";
11371
+ }
11372
+ seen.add(value);
11373
+ return value.map((entry) => redactSecretLikeFieldsValue(entry, name, seen));
11374
+ }
11375
+ if (isPlainObject2(value)) {
11376
+ if (seen.has(value)) {
11377
+ return "[Circular]";
11378
+ }
11379
+ seen.add(value);
11380
+ return Object.fromEntries(
11381
+ Object.entries(value).map(([key2, entry]) => [
11382
+ key2,
11383
+ redactSecretLikeFieldsValue(entry, key2, seen)
11384
+ ])
11385
+ );
11386
+ }
11387
+ return value;
11388
+ }
11389
+ function redactSecretLikeFields(value, name = "") {
11390
+ return redactSecretLikeFieldsValue(value, name, /* @__PURE__ */ new WeakSet());
11391
+ }
11392
+ function parseJsonObjectOrArray(value) {
11393
+ const trimmed = value.trim();
11394
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
11395
+ return void 0;
11396
+ }
11397
+ try {
11398
+ const parsed = JSON.parse(trimmed);
11399
+ return isPlainObject2(parsed) || Array.isArray(parsed) ? parsed : void 0;
11400
+ } catch {
11401
+ return void 0;
11402
+ }
11403
+ }
11404
+ function redactHttpBody(body) {
11405
+ if (typeof body === "string") {
11406
+ const parsed = parseJsonObjectOrArray(body);
11407
+ return parsed === void 0 ? body : redactSecretLikeFields(parsed);
11408
+ }
11409
+ return redactSecretLikeFields(body);
11410
+ }
11411
+ function redactHttpHeaderValue(name, value) {
11412
+ const normalized = normalizeName(name);
11413
+ if (AUTHORIZATION_HEADER_NAMES.has(normalized)) {
11414
+ return "Bearer ****";
11415
+ }
11416
+ if (SECRET_HEADER_NAMES.has(normalized) || isSensitiveName(name)) {
11417
+ return REDACTED_VALUE;
11418
+ }
11419
+ return value;
11420
+ }
11421
+
11001
11422
  // ../toolcraft/src/error-report.ts
11002
11423
  var ERROR_REPORTS_ENV = "TOOLCRAFT_ERROR_REPORTS";
11003
- var DEFAULT_SENSITIVE_NAMES = ["password", "token", "apikey", "secret"];
11004
- function isPlainObject2(value) {
11424
+ function isPlainObject3(value) {
11005
11425
  return typeof value === "object" && value !== null && !Array.isArray(value);
11006
11426
  }
11007
11427
  function unwrapOptional(schema) {
@@ -11011,7 +11431,7 @@ function unwrapOptional(schema) {
11011
11431
  return schema;
11012
11432
  }
11013
11433
  function hasHttpContext(error3) {
11014
- return error3 instanceof Error && error3.name === "HttpError" && isPlainObject2(error3.request) && isPlainObject2(error3.response);
11434
+ return error3 instanceof Error && error3.name === "HttpError" && isPlainObject3(error3.request) && isPlainObject3(error3.response);
11015
11435
  }
11016
11436
  function isSkippedError(error3) {
11017
11437
  if (error3 instanceof ApprovalDeclinedError) {
@@ -11048,8 +11468,8 @@ async function assertReportDirWithinProject(projectRoot, reportDir) {
11048
11468
  throw new Error("Error report directory resolves outside project root.");
11049
11469
  }
11050
11470
  const [canonicalProjectRoot, canonicalReportDir] = await Promise.all([
11051
- realpath(projectRoot),
11052
- realpath(reportDir)
11471
+ realpath2(projectRoot),
11472
+ realpath2(reportDir)
11053
11473
  ]);
11054
11474
  if (!isWithinDirectory(canonicalProjectRoot, canonicalReportDir)) {
11055
11475
  throw new Error("Error report directory resolves outside project root.");
@@ -11104,9 +11524,24 @@ function redactValue(value) {
11104
11524
  }
11105
11525
  return `<set, ${value.length} chars>`;
11106
11526
  }
11107
- function isSensitiveName(name) {
11108
- const normalized = name.toLowerCase();
11109
- return DEFAULT_SENSITIVE_NAMES.some((candidate) => normalized.includes(candidate));
11527
+ function collectStringLeaves(value, output) {
11528
+ if (typeof value === "string") {
11529
+ if (value.length > 0) {
11530
+ output.add(value);
11531
+ }
11532
+ return;
11533
+ }
11534
+ if (Array.isArray(value)) {
11535
+ for (const entry of value) {
11536
+ collectStringLeaves(entry, output);
11537
+ }
11538
+ return;
11539
+ }
11540
+ if (isPlainObject3(value)) {
11541
+ for (const entry of Object.values(value)) {
11542
+ collectStringLeaves(entry, output);
11543
+ }
11544
+ }
11110
11545
  }
11111
11546
  function schemaSecretValue(schema) {
11112
11547
  const unwrapped = unwrapOptional(schema);
@@ -11127,7 +11562,7 @@ function redactParamsValue(value, schema, name) {
11127
11562
  return "<redacted>";
11128
11563
  }
11129
11564
  const unwrapped = unwrapOptional(schema);
11130
- if (unwrapped.kind === "object" && isPlainObject2(value)) {
11565
+ if (unwrapped.kind === "object" && isPlainObject3(value)) {
11131
11566
  return Object.fromEntries(
11132
11567
  Object.entries(value).map(([key2, childValue]) => {
11133
11568
  const childSchema = unwrapped.shape[key2];
@@ -11149,6 +11584,52 @@ function redactParams(params17, command) {
11149
11584
  }
11150
11585
  return redactParamsValue(params17, command.params, "");
11151
11586
  }
11587
+ function collectSensitiveParamValues(value, schema, name, output) {
11588
+ if (shouldRedactParam(name, schema)) {
11589
+ collectStringLeaves(value, output);
11590
+ return;
11591
+ }
11592
+ const unwrapped = unwrapOptional(schema);
11593
+ if (unwrapped.kind === "object" && isPlainObject3(value)) {
11594
+ for (const [key2, childValue] of Object.entries(value)) {
11595
+ const childSchema = unwrapped.shape[key2];
11596
+ if (childSchema !== void 0) {
11597
+ collectSensitiveParamValues(childValue, childSchema, key2, output);
11598
+ }
11599
+ }
11600
+ return;
11601
+ }
11602
+ if (unwrapped.kind === "array" && Array.isArray(value)) {
11603
+ for (const entry of value) {
11604
+ collectSensitiveParamValues(entry, unwrapped.item, name, output);
11605
+ }
11606
+ }
11607
+ }
11608
+ function createReportStringRedactor(context, env) {
11609
+ const values = /* @__PURE__ */ new Set();
11610
+ for (const value of Object.values(context.secrets ?? {})) {
11611
+ if (value !== void 0 && value.length > 0) {
11612
+ values.add(value);
11613
+ }
11614
+ }
11615
+ for (const [name, secret] of Object.entries(context.command?.secrets ?? {})) {
11616
+ const value = context.secrets?.[name] ?? env[secret.env];
11617
+ if (value !== void 0 && value.length > 0) {
11618
+ values.add(value);
11619
+ }
11620
+ }
11621
+ if (context.command !== void 0) {
11622
+ collectSensitiveParamValues(context.params, context.command.params, "", values);
11623
+ }
11624
+ const orderedValues = [...values].sort((left, right) => right.length - left.length);
11625
+ return (value) => {
11626
+ let redacted = value;
11627
+ for (const secretValue of orderedValues) {
11628
+ redacted = redacted.split(secretValue).join("<redacted>");
11629
+ }
11630
+ return redacted;
11631
+ };
11632
+ }
11152
11633
  function commandSecretEnvNames(secrets) {
11153
11634
  if (secrets === void 0) {
11154
11635
  return [];
@@ -11202,28 +11683,42 @@ function redactArgv(argv, options) {
11202
11683
  function stableJson(value) {
11203
11684
  return JSON.stringify(value, null, 2) ?? "undefined";
11204
11685
  }
11205
- function redactStructuredErrorField(name, value) {
11206
- if (typeof value === "string" && name.toLowerCase() === "authorization") {
11207
- return "Bearer ****";
11686
+ function redactStructuredErrorField(name, value, redactString) {
11687
+ if (typeof value === "string") {
11688
+ const redactedHeaderValue = redactHttpHeaderValue(name, value);
11689
+ if (redactedHeaderValue !== value) {
11690
+ return redactedHeaderValue;
11691
+ }
11692
+ if (isSensitiveName(name)) {
11693
+ return "<redacted>";
11694
+ }
11695
+ return redactString(value);
11208
11696
  }
11209
11697
  if (Array.isArray(value)) {
11210
- return value.map((entry) => redactStructuredErrorField(name, entry));
11698
+ return value.map((entry) => redactStructuredErrorField(name, entry, redactString));
11211
11699
  }
11212
- if (isPlainObject2(value)) {
11700
+ if (isPlainObject3(value)) {
11213
11701
  return Object.fromEntries(
11214
- Object.entries(value).map(([key2, entry]) => [key2, redactStructuredErrorField(key2, entry)])
11702
+ Object.entries(value).map(([key2, entry]) => [
11703
+ key2,
11704
+ redactStructuredErrorField(key2, entry, redactString)
11705
+ ])
11215
11706
  );
11216
11707
  }
11217
11708
  return value;
11218
11709
  }
11219
- function ownStructuredFields(error3) {
11710
+ function ownStructuredFields(error3, redactString) {
11220
11711
  const fields = {};
11221
11712
  for (const key2 of Object.keys(error3)) {
11222
11713
  if (key2 === "name" || key2 === "message" || key2 === "stack" || key2 === "cause") {
11223
11714
  continue;
11224
11715
  }
11225
11716
  Object.defineProperty(fields, key2, {
11226
- value: redactStructuredErrorField(key2, error3[key2]),
11717
+ value: redactStructuredErrorField(
11718
+ key2,
11719
+ error3[key2],
11720
+ redactString
11721
+ ),
11227
11722
  enumerable: true,
11228
11723
  configurable: true,
11229
11724
  writable: true
@@ -11231,43 +11726,44 @@ function ownStructuredFields(error3) {
11231
11726
  }
11232
11727
  return fields;
11233
11728
  }
11234
- function formatStackChain(error3) {
11729
+ function formatStackChain(error3, redactString) {
11235
11730
  const lines = [];
11236
11731
  let current = error3;
11237
11732
  let index = 0;
11238
11733
  while (current !== void 0) {
11239
11734
  if (current instanceof Error) {
11240
- lines.push(
11241
- index === 0 ? current.stack ?? String(current) : `Caused by: ${current.stack ?? String(current)}`
11242
- );
11735
+ const stack = current.stack ?? String(current);
11736
+ lines.push(redactString(index === 0 ? stack : `Caused by: ${stack}`));
11243
11737
  current = current.cause;
11244
11738
  } else {
11245
- lines.push(index === 0 ? String(current) : `Caused by: ${String(current)}`);
11739
+ const message2 = String(current);
11740
+ lines.push(redactString(index === 0 ? message2 : `Caused by: ${message2}`));
11246
11741
  current = void 0;
11247
11742
  }
11248
11743
  index += 1;
11249
11744
  }
11250
11745
  return lines.join("\n");
11251
11746
  }
11252
- function formatHeaderValue(name, value) {
11253
- return name.toLowerCase() === "authorization" ? "Bearer ****" : value;
11747
+ function formatHeaderValue(name, value, redactString) {
11748
+ return redactString(redactHttpHeaderValue(name, value));
11254
11749
  }
11255
- function formatHeaders(headers) {
11256
- return Object.entries(headers).map(([name, value]) => `${name}: ${formatHeaderValue(name, value)}`).join("\n");
11750
+ function formatHeaders(headers, redactString) {
11751
+ return Object.entries(headers).map(([name, value]) => `${name}: ${formatHeaderValue(name, value, redactString)}`).join("\n");
11257
11752
  }
11258
- function formatBody(body) {
11259
- if (typeof body === "string") {
11260
- return body;
11753
+ function formatBody(body, redactString) {
11754
+ const redactedBody = redactHttpBody(body);
11755
+ if (typeof redactedBody === "string") {
11756
+ return redactString(redactedBody);
11261
11757
  }
11262
- return stableJson(body);
11758
+ return redactString(stableJson(redactedBody));
11263
11759
  }
11264
- function formatHttpTranscript(error3) {
11760
+ function formatHttpTranscript(error3, redactString) {
11265
11761
  const requestLines = [
11266
11762
  `${error3.request.method} ${error3.request.url}`,
11267
- formatHeaders(error3.request.headers)
11763
+ formatHeaders(error3.request.headers, redactString)
11268
11764
  ].filter((line) => line.length > 0);
11269
11765
  if (error3.request.body !== void 0) {
11270
- requestLines.push("", formatBody(error3.request.body));
11766
+ requestLines.push("", formatBody(error3.request.body, redactString));
11271
11767
  }
11272
11768
  return [
11273
11769
  "Request:",
@@ -11275,9 +11771,9 @@ function formatHttpTranscript(error3) {
11275
11771
  "",
11276
11772
  "Response:",
11277
11773
  `${error3.response.status} ${error3.response.statusText}`,
11278
- formatHeaders(error3.response.headers),
11774
+ formatHeaders(error3.response.headers, redactString),
11279
11775
  "",
11280
- formatBody(error3.response.body)
11776
+ formatBody(error3.response.body, redactString)
11281
11777
  ].join("\n");
11282
11778
  }
11283
11779
  function resolveToolcraftVersion(version) {
@@ -11286,9 +11782,10 @@ function resolveToolcraftVersion(version) {
11286
11782
  function buildReport(context) {
11287
11783
  const env = context.env ?? process.env;
11288
11784
  const error3 = context.error;
11785
+ const redactString = createReportStringRedactor(context, env);
11289
11786
  const errorName = error3 instanceof Error ? error3.name : typeof error3;
11290
- const errorMessage = error3 instanceof Error ? error3.message : String(error3);
11291
- const structuredFields = error3 instanceof Error ? ownStructuredFields(error3) : {};
11787
+ const errorMessage = redactString(error3 instanceof Error ? error3.message : String(error3));
11788
+ const structuredFields = error3 instanceof Error ? ownStructuredFields(error3, redactString) : {};
11292
11789
  const secretLines = Object.entries(context.command?.secrets ?? {}).map(([name, secret]) => {
11293
11790
  const value = context.secrets?.[name] ?? env[secret.env];
11294
11791
  return `${secret.env}=${redactValue(value)}`;
@@ -11302,7 +11799,9 @@ function buildReport(context) {
11302
11799
  `platform: ${process.platform} ${process.arch}`,
11303
11800
  "",
11304
11801
  "Argv",
11305
- stableJson(redactArgv(context.argv, { command: context.command, secrets: context.secrets })),
11802
+ redactString(
11803
+ stableJson(redactArgv(context.argv, { command: context.command, secrets: context.secrets }))
11804
+ ),
11306
11805
  "",
11307
11806
  "Resolved Secrets",
11308
11807
  ...secretLines.length === 0 ? ["<none>"] : secretLines,
@@ -11311,19 +11810,19 @@ function buildReport(context) {
11311
11810
  context.commandPath === void 0 || context.commandPath.length === 0 ? "root" : context.commandPath,
11312
11811
  "",
11313
11812
  "Parsed Params",
11314
- stableJson(redactParams(context.params, context.command)),
11813
+ redactString(stableJson(redactParams(context.params, context.command))),
11315
11814
  "",
11316
11815
  "Error",
11317
11816
  `name: ${errorName}`,
11318
11817
  `message: ${errorMessage}`,
11319
11818
  "structured fields:",
11320
- stableJson(structuredFields),
11819
+ redactString(stableJson(structuredFields)),
11321
11820
  "",
11322
11821
  "Stack",
11323
- formatStackChain(error3)
11822
+ formatStackChain(error3, redactString)
11324
11823
  ];
11325
11824
  if (hasHttpContext(error3)) {
11326
- lines.push("", "HTTP Transcript", formatHttpTranscript(error3));
11825
+ lines.push("", "HTTP Transcript", formatHttpTranscript(error3, redactString));
11327
11826
  }
11328
11827
  return `${lines.join("\n")}
11329
11828
  `;
@@ -11335,7 +11834,7 @@ async function writeErrorReport(context) {
11335
11834
  }
11336
11835
  const projectRoot = resolveProjectRoot(context.projectRoot);
11337
11836
  const reportDir = resolveReportDir(context.errorReports, projectRoot);
11338
- const fileName = `${formatTimestamp(/* @__PURE__ */ new Date())}-${slugifyCommandPath(context.commandPath)}-${randomUUID3()}.log`;
11837
+ const fileName = `${formatTimestamp(/* @__PURE__ */ new Date())}-${slugifyCommandPath(context.commandPath)}-${randomUUID5()}.log`;
11339
11838
  const absolutePath = path13.join(reportDir, fileName);
11340
11839
  await mkdir2(reportDir, { recursive: true });
11341
11840
  if (reportDirMustStayWithinProject(context.errorReports)) {
@@ -11783,6 +12282,7 @@ ${rendered.join("\n")}`);
11783
12282
  }
11784
12283
 
11785
12284
  // ../toolcraft/src/cli.ts
12285
+ configureTheme({ brand: "blue", label: "Toolcraft" });
11786
12286
  var RESERVED_SERVICE_NAMES = /* @__PURE__ */ new Set([
11787
12287
  "params",
11788
12288
  "secrets",
@@ -12813,10 +13313,10 @@ function renderHelpSections(sections) {
12813
13313
  return sections.filter((section) => section.length > 0).join("\n\n");
12814
13314
  }
12815
13315
  function formatHelpCommandList(rows) {
12816
- return process.stdout.isTTY === false ? help_formatter_plain_exports.formatCommandList(rows) : formatCommandList(rows);
13316
+ return process.stdout.isTTY !== true ? help_formatter_plain_exports.formatCommandList(rows) : formatCommandList(rows);
12817
13317
  }
12818
13318
  function formatHelpOptionList(rows) {
12819
- return process.stdout.isTTY === false ? help_formatter_plain_exports.formatOptionList(rows) : formatOptionList(rows);
13319
+ return process.stdout.isTTY !== true ? help_formatter_plain_exports.formatOptionList(rows) : formatOptionList(rows);
12820
13320
  }
12821
13321
  function buildUsageLine(breadcrumb, rootUsageName, suffix) {
12822
13322
  const visibleBreadcrumb = breadcrumb.filter((segment) => segment.length > 0);
@@ -13104,11 +13604,18 @@ function formatResolvedValue(value) {
13104
13604
  function fieldPromptLabel(field) {
13105
13605
  return field.positionalIndex === void 0 ? field.optionFlag : `<${field.displayPath}>`;
13106
13606
  }
13607
+ function enumOptionLabel(schema, value) {
13608
+ const key2 = String(value);
13609
+ if (schema.labels === void 0 || !Object.prototype.hasOwnProperty.call(schema.labels, key2)) {
13610
+ return key2;
13611
+ }
13612
+ return schema.labels[key2] ?? key2;
13613
+ }
13107
13614
  async function promptForField(field) {
13108
13615
  const schema = field.schema;
13109
13616
  if (schema.kind === "enum") {
13110
13617
  const options = schema.loadOptions ? await schema.loadOptions() : schema.values.map((value) => ({
13111
- label: schema.labels?.[String(value)] ?? String(value),
13618
+ label: enumOptionLabel(schema, value),
13112
13619
  value
13113
13620
  }));
13114
13621
  const selected = await select2({
@@ -13193,8 +13700,8 @@ async function withOutputFormat2(output, fn) {
13193
13700
  function createFs2() {
13194
13701
  return {
13195
13702
  readFile: async (path24, encoding = "utf8") => readFile4(path24, { encoding }),
13196
- writeFile: async (path24, contents) => {
13197
- await writeFile5(path24, contents);
13703
+ writeFile: async (path24, contents, options) => {
13704
+ await writeFile5(path24, contents, options);
13198
13705
  },
13199
13706
  exists: async (path24) => {
13200
13707
  try {
@@ -13206,7 +13713,7 @@ function createFs2() {
13206
13713
  },
13207
13714
  lstat: async (path24) => lstat3(path24),
13208
13715
  rename: async (fromPath, toPath) => rename3(fromPath, toPath),
13209
- unlink: async (path24) => unlink2(path24)
13716
+ unlink: async (path24) => unlink3(path24)
13210
13717
  };
13211
13718
  }
13212
13719
  function createEnv2(values = process.env) {
@@ -13216,7 +13723,7 @@ function createEnv2(values = process.env) {
13216
13723
  }
13217
13724
  };
13218
13725
  }
13219
- function isPlainObject3(value) {
13726
+ function isPlainObject4(value) {
13220
13727
  return typeof value === "object" && value !== null && !Array.isArray(value);
13221
13728
  }
13222
13729
  function hasFieldValue(value) {
@@ -13325,7 +13832,7 @@ async function loadPresetValues(fields, presetPath) {
13325
13832
  { cause: error3 }
13326
13833
  );
13327
13834
  }
13328
- if (!isPlainObject3(parsedPreset)) {
13835
+ if (!isPlainObject4(parsedPreset)) {
13329
13836
  throw new UserError(`Preset file "${presetPath}" must contain a JSON object.`);
13330
13837
  }
13331
13838
  const fieldByPath = new Map(fields.map((field) => [field.displayPath, field]));
@@ -13344,7 +13851,7 @@ async function loadPresetValues(fields, presetPath) {
13344
13851
  `Preset file "${presetPath}" contains unknown parameter "${displayPath}".`
13345
13852
  );
13346
13853
  }
13347
- if (!isPlainObject3(value)) {
13854
+ if (!isPlainObject4(value)) {
13348
13855
  throw new UserError(
13349
13856
  `Preset file "${presetPath}" has an invalid value for "${displayPath}". Expected an object, got ${describeReceived(value)}.`
13350
13857
  );
@@ -13387,8 +13894,8 @@ function matchesFixtureValue(expected, actual) {
13387
13894
  }
13388
13895
  return expected.every((item, index) => matchesFixtureValue(item, actual[index]));
13389
13896
  }
13390
- if (isPlainObject3(expected)) {
13391
- if (!isPlainObject3(actual)) {
13897
+ if (isPlainObject4(expected)) {
13898
+ if (!isPlainObject4(actual)) {
13392
13899
  return false;
13393
13900
  }
13394
13901
  return Object.entries(expected).every(
@@ -13451,9 +13958,9 @@ function createFixtureFetch(entries) {
13451
13958
  };
13452
13959
  }
13453
13960
  function createFixtureFs(definition) {
13454
- const fsDefinition = isPlainObject3(definition) ? definition : {};
13455
- const readFileEntries = isPlainObject3(fsDefinition.readFile) ? fsDefinition.readFile : {};
13456
- const existsEntries = isPlainObject3(fsDefinition.exists) ? fsDefinition.exists : {};
13961
+ const fsDefinition = isPlainObject4(definition) ? definition : {};
13962
+ const readFileEntries = isPlainObject4(fsDefinition.readFile) ? fsDefinition.readFile : {};
13963
+ const existsEntries = isPlainObject4(fsDefinition.exists) ? fsDefinition.exists : {};
13457
13964
  return {
13458
13965
  readFile: async (filePath) => {
13459
13966
  if (Object.prototype.hasOwnProperty.call(readFileEntries, filePath)) {
@@ -13476,10 +13983,10 @@ function createFixtureFs(definition) {
13476
13983
  function resolveFixtureMethodResult(methodName, definition, args) {
13477
13984
  if (Array.isArray(definition)) {
13478
13985
  for (const entry of definition) {
13479
- if (!isPlainObject3(entry)) {
13986
+ if (!isPlainObject4(entry)) {
13480
13987
  continue;
13481
13988
  }
13482
- const explicitMatcher = isPlainObject3(entry.request) ? entry.request : void 0;
13989
+ const explicitMatcher = isPlainObject4(entry.request) ? entry.request : void 0;
13483
13990
  const matcher = explicitMatcher ?? Object.fromEntries(
13484
13991
  Object.entries(entry).filter(
13485
13992
  ([key2]) => key2 !== "result" && key2 !== "response" && key2 !== "error"
@@ -13491,7 +13998,7 @@ function resolveFixtureMethodResult(methodName, definition, args) {
13491
13998
  matched = matchesFixtureValue(matcher.args, args);
13492
13999
  } else if (Object.keys(matcher).length === 0) {
13493
14000
  matched = true;
13494
- } else if (isPlainObject3(firstArg)) {
14001
+ } else if (isPlainObject4(firstArg)) {
13495
14002
  matched = matchesFixtureValue(matcher, firstArg);
13496
14003
  } else if (args.length === 1 && Object.keys(matcher).length === 1) {
13497
14004
  const [[, expectedValue]] = Object.entries(matcher);
@@ -13512,7 +14019,7 @@ function resolveFixtureMethodResult(methodName, definition, args) {
13512
14019
  return Promise.resolve(null);
13513
14020
  }
13514
14021
  }
13515
- if (isPlainObject3(definition)) {
14022
+ if (isPlainObject4(definition)) {
13516
14023
  const firstArg = args[0];
13517
14024
  if (typeof firstArg === "string" && Object.prototype.hasOwnProperty.call(definition, firstArg)) {
13518
14025
  return Promise.resolve(definition[firstArg]);
@@ -13524,7 +14031,7 @@ function resolveFixtureMethodResult(methodName, definition, args) {
13524
14031
  return Promise.resolve(null);
13525
14032
  }
13526
14033
  function createFixtureService(definition) {
13527
- const methods = isPlainObject3(definition) ? definition : {};
14034
+ const methods = isPlainObject4(definition) ? definition : {};
13528
14035
  return new Proxy(
13529
14036
  {},
13530
14037
  {
@@ -13622,7 +14129,7 @@ async function resolveFixtureRuntime(command, services, requirementOptions) {
13622
14129
  };
13623
14130
  }
13624
14131
  const scenario = await loadFixtureScenario(command, selector);
13625
- const scenarioServices = isPlainObject3(scenario.services) ? scenario.services : {};
14132
+ const scenarioServices = isPlainObject4(scenario.services) ? scenario.services : {};
13626
14133
  const customServiceNames = /* @__PURE__ */ new Set([
13627
14134
  ...Object.keys(services),
13628
14135
  ...Object.keys(scenarioServices).filter((name) => !RESERVED_SERVICE_NAMES.has(name))
@@ -13904,7 +14411,7 @@ function finalizeDynamicValue(schema, value, displayPath, errors2) {
13904
14411
  if (itemSchema.kind !== "object") {
13905
14412
  return value;
13906
14413
  }
13907
- if (!isPlainObject3(value)) {
14414
+ if (!isPlainObject4(value)) {
13908
14415
  errors2.push({
13909
14416
  path: displayPath,
13910
14417
  message: `Invalid value for "${displayPath}". Expected indexed object entries, got ${describeReceived(value)}.`
@@ -13939,7 +14446,7 @@ function finalizeDynamicValue(schema, value, displayPath, errors2) {
13939
14446
  );
13940
14447
  }
13941
14448
  case "object": {
13942
- if (!isPlainObject3(value)) {
14449
+ if (!isPlainObject4(value)) {
13943
14450
  errors2.push({
13944
14451
  path: displayPath,
13945
14452
  message: `Invalid value for "${displayPath}". Expected an object, got ${describeReceived(value)}.`
@@ -13970,7 +14477,7 @@ function finalizeDynamicValue(schema, value, displayPath, errors2) {
13970
14477
  return result;
13971
14478
  }
13972
14479
  case "record": {
13973
- if (!isPlainObject3(value)) {
14480
+ if (!isPlainObject4(value)) {
13974
14481
  errors2.push({
13975
14482
  path: displayPath,
13976
14483
  message: `Invalid value for "${displayPath}". Expected an object, got ${describeReceived(value)}.`
@@ -14396,10 +14903,10 @@ async function executeCommand(state, services, requirementOptions, runtimeOption
14396
14903
  }
14397
14904
  }
14398
14905
  function isStringRecord(value) {
14399
- return isPlainObject3(value) && Object.values(value).every((entry) => typeof entry === "string");
14906
+ return isPlainObject4(value) && Object.values(value).every((entry) => typeof entry === "string");
14400
14907
  }
14401
14908
  function isHttpErrorLike(error3) {
14402
- if (!isPlainObject3(error3)) {
14909
+ if (!isPlainObject4(error3)) {
14403
14910
  return false;
14404
14911
  }
14405
14912
  if (error3.name !== "HttpError" || typeof error3.message !== "string") {
@@ -14407,7 +14914,7 @@ function isHttpErrorLike(error3) {
14407
14914
  }
14408
14915
  const request = error3.request;
14409
14916
  const response = error3.response;
14410
- return isPlainObject3(request) && typeof request.method === "string" && typeof request.url === "string" && isStringRecord(request.headers) && isPlainObject3(response) && typeof response.status === "number" && typeof response.statusText === "string" && isStringRecord(response.headers) && "body" in response;
14917
+ return isPlainObject4(request) && typeof request.method === "string" && typeof request.url === "string" && isStringRecord(request.headers) && isPlainObject4(response) && typeof response.status === "number" && typeof response.statusText === "string" && isStringRecord(response.headers) && "body" in response;
14411
14918
  }
14412
14919
  function hasTypedOptionalField(value, field, type2) {
14413
14920
  return !(field in value) || typeof value[field] === type2;
@@ -14416,7 +14923,7 @@ function isNonEmptyString(value) {
14416
14923
  return typeof value === "string" && value.trim().length > 0;
14417
14924
  }
14418
14925
  function isProblemDetailsLike(body) {
14419
- if (!isPlainObject3(body)) {
14926
+ if (!isPlainObject4(body)) {
14420
14927
  return false;
14421
14928
  }
14422
14929
  if (!hasTypedOptionalField(body, "type", "string")) {
@@ -14437,11 +14944,11 @@ function isProblemDetailsLike(body) {
14437
14944
  return isNonEmptyString(body.title) || isNonEmptyString(body.detail);
14438
14945
  }
14439
14946
  function isGraphQLErrorEnvelopeLike(body) {
14440
- if (!isPlainObject3(body) || !Array.isArray(body.errors) || body.errors.length === 0) {
14947
+ if (!isPlainObject4(body) || !Array.isArray(body.errors) || body.errors.length === 0) {
14441
14948
  return false;
14442
14949
  }
14443
14950
  return body.errors.every((error3) => {
14444
- if (!isPlainObject3(error3) || typeof error3.message !== "string") {
14951
+ if (!isPlainObject4(error3) || typeof error3.message !== "string") {
14445
14952
  return false;
14446
14953
  }
14447
14954
  if ("path" in error3) {
@@ -14451,7 +14958,7 @@ function isGraphQLErrorEnvelopeLike(body) {
14451
14958
  }
14452
14959
  }
14453
14960
  if ("extensions" in error3) {
14454
- if (!isPlainObject3(error3.extensions)) {
14961
+ if (!isPlainObject4(error3.extensions)) {
14455
14962
  return false;
14456
14963
  }
14457
14964
  if ("code" in error3.extensions && typeof error3.extensions.code !== "string") {
@@ -14462,7 +14969,7 @@ function isGraphQLErrorEnvelopeLike(body) {
14462
14969
  });
14463
14970
  }
14464
14971
  function styleHttpErrorLine(value, style) {
14465
- return process.stdout.isTTY === false ? value : style(value);
14972
+ return process.stdout.isTTY !== true ? value : style(value);
14466
14973
  }
14467
14974
  function formatHttpErrorStatus(value) {
14468
14975
  return styleHttpErrorLine(value, text.error);
@@ -14499,23 +15006,24 @@ function formatGraphQLErrorEnvelopeBody(body) {
14499
15006
  }).join("\n\n");
14500
15007
  }
14501
15008
  function formatHttpErrorBody(body) {
14502
- if (typeof body === "string") {
14503
- return body;
15009
+ const redactedBody = redactHttpBody(body);
15010
+ if (typeof redactedBody === "string") {
15011
+ return redactedBody;
14504
15012
  }
14505
- if (isProblemDetailsLike(body)) {
14506
- return formatProblemDetailsBody(body);
15013
+ if (isProblemDetailsLike(redactedBody)) {
15014
+ return formatProblemDetailsBody(redactedBody);
14507
15015
  }
14508
- if (isGraphQLErrorEnvelopeLike(body)) {
14509
- return formatGraphQLErrorEnvelopeBody(body);
15016
+ if (isGraphQLErrorEnvelopeLike(redactedBody)) {
15017
+ return formatGraphQLErrorEnvelopeBody(redactedBody);
14510
15018
  }
14511
- const serialized = JSON.stringify(body, null, 2);
14512
- return serialized === void 0 ? String(body) : serialized;
15019
+ const serialized = JSON.stringify(redactedBody, null, 2);
15020
+ return serialized === void 0 ? String(redactedBody) : serialized;
14513
15021
  }
14514
15022
  function indentHttpErrorBlock(value) {
14515
15023
  return value.split("\n").map((line) => ` ${line}`).join("\n");
14516
15024
  }
14517
15025
  function formatHttpHeaderValue(name, value) {
14518
- return name.toLowerCase() === "authorization" ? "Bearer ****" : value;
15026
+ return redactHttpHeaderValue(name, value);
14519
15027
  }
14520
15028
  function formatHttpErrorHeaders(headers) {
14521
15029
  return Object.entries(headers).map(
@@ -14533,7 +15041,11 @@ function renderHttpError(error3, options) {
14533
15041
  if (detailed) {
14534
15042
  lines.push("", "Request headers:", ...formatHttpErrorHeaders(error3.request.headers), "");
14535
15043
  if (error3.request.body !== void 0) {
14536
- lines.push("Request body:", indentHttpErrorBlock(formatHttpErrorBody(error3.request.body)), "");
15044
+ lines.push(
15045
+ "Request body:",
15046
+ indentHttpErrorBlock(formatHttpErrorBody(error3.request.body)),
15047
+ ""
15048
+ );
14537
15049
  }
14538
15050
  }
14539
15051
  lines.push(
@@ -14939,7 +15451,7 @@ async function runCLI(roots, options = {}) {
14939
15451
  }
14940
15452
 
14941
15453
  // src/terminal-pilot.ts
14942
- import { randomUUID as randomUUID4 } from "node:crypto";
15454
+ import { randomUUID as randomUUID6 } from "node:crypto";
14943
15455
 
14944
15456
  // src/terminal-session.ts
14945
15457
  import { EventEmitter } from "node:events";
@@ -14948,6 +15460,11 @@ import { createRequire } from "node:module";
14948
15460
  import { dirname, join } from "node:path";
14949
15461
  import * as nodePty from "node-pty";
14950
15462
 
15463
+ // src/errors.ts
15464
+ function hasOwnErrorCode(error3, code) {
15465
+ return error3 instanceof Error && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === code;
15466
+ }
15467
+
14951
15468
  // src/terminal-buffer.ts
14952
15469
  var RESET_SGR = "\x1B[0m";
14953
15470
  var DEC_SPECIAL_GRAPHICS = {
@@ -16047,10 +16564,7 @@ function ensureSpawnHelperExecutable() {
16047
16564
  }
16048
16565
  }
16049
16566
  function isMissingFileError(error3) {
16050
- if (!(error3 instanceof Error)) {
16051
- return false;
16052
- }
16053
- return "code" in error3 && error3.code === "ENOENT";
16567
+ return hasOwnErrorCode(error3, "ENOENT");
16054
16568
  }
16055
16569
  function matchPattern(buffer, pattern) {
16056
16570
  const clean = normalizeHistoryBuffer(stripAnsi(buffer));
@@ -16141,7 +16655,7 @@ var TerminalPilot = class _TerminalPilot {
16141
16655
  }
16142
16656
  async newSession(opts) {
16143
16657
  const session = new TerminalSession({
16144
- id: randomUUID4(),
16658
+ id: randomUUID6(),
16145
16659
  command: opts.command,
16146
16660
  args: opts.args,
16147
16661
  cwd: opts.cwd,
@@ -16427,6 +16941,11 @@ var claudeCodeAgent = {
16427
16941
  aliases: ["claude"],
16428
16942
  binaryName: "claude",
16429
16943
  apiShapes: ["anthropic-messages"],
16944
+ otelCapture: {
16945
+ env: {
16946
+ CLAUDE_CODE_ENABLE_TELEMETRY: "1"
16947
+ }
16948
+ },
16430
16949
  configPath: "~/.claude/settings.json",
16431
16950
  branding: {
16432
16951
  colors: {
@@ -16459,6 +16978,16 @@ var codexAgent = {
16459
16978
  summary: "Configure Codex to use Poe as the model provider.",
16460
16979
  binaryName: "codex",
16461
16980
  apiShapes: ["openai-responses"],
16981
+ otelCapture: {
16982
+ args: (endpoint, content) => [
16983
+ "-c",
16984
+ `otel.trace_exporter={"otlp-http"={endpoint=${JSON.stringify(`${endpoint}/v1/traces`)},protocol="json"}}`,
16985
+ "-c",
16986
+ `otel.exporter={"otlp-http"={endpoint=${JSON.stringify(`${endpoint}/v1/logs`)},protocol="json"}}`,
16987
+ "-c",
16988
+ `otel.log_user_prompt=${content}`
16989
+ ]
16990
+ },
16462
16991
  configPath: "~/.codex/config.toml",
16463
16992
  branding: {
16464
16993
  colors: {
@@ -16494,6 +17023,11 @@ var openCodeAgent = {
16494
17023
  summary: "Configure OpenCode CLI to use the Poe API.",
16495
17024
  binaryName: "opencode",
16496
17025
  apiShapes: ["openai-chat-completions"],
17026
+ otelCapture: {
17027
+ env: {
17028
+ OPENCODE_CONFIG_CONTENT: '{"experimental":{"openTelemetry":true}}'
17029
+ }
17030
+ },
16497
17031
  configPath: "~/.config/opencode/config.json",
16498
17032
  branding: {
16499
17033
  colors: {
@@ -16529,6 +17063,7 @@ var gooseAgent = {
16529
17063
  summary: "Block's open-source AI agent with ACP support.",
16530
17064
  binaryName: "goose",
16531
17065
  apiShapes: ["openai-chat-completions"],
17066
+ otelCapture: {},
16532
17067
  configPath: "~/.config/goose/config.yaml",
16533
17068
  branding: {
16534
17069
  colors: {
@@ -16562,6 +17097,12 @@ function freezeAgent(agent) {
16562
17097
  if (agent.apiShapes !== void 0) {
16563
17098
  Object.freeze(agent.apiShapes);
16564
17099
  }
17100
+ if (agent.otelCapture?.env !== void 0) {
17101
+ Object.freeze(agent.otelCapture.env);
17102
+ }
17103
+ if (agent.otelCapture !== void 0) {
17104
+ Object.freeze(agent.otelCapture);
17105
+ }
16565
17106
  Object.freeze(agent.branding.colors);
16566
17107
  Object.freeze(agent.branding);
16567
17108
  return Object.freeze(agent);
@@ -16622,11 +17163,11 @@ function resolveAgentSupport(input, registry = agentSkillConfigs) {
16622
17163
  if (!resolvedId) {
16623
17164
  return { status: "unknown", input };
16624
17165
  }
16625
- const config = registry[resolvedId];
16626
- if (!config) {
17166
+ const config2 = registry[resolvedId];
17167
+ if (!config2) {
16627
17168
  return { status: "unsupported", input, id: resolvedId };
16628
17169
  }
16629
- return { status: "supported", input, id: resolvedId, config: { ...config } };
17170
+ return { status: "supported", input, id: resolvedId, config: { ...config2 } };
16630
17171
  }
16631
17172
  function getAgentConfig(agentId) {
16632
17173
  const support = resolveAgentSupport(agentId);
@@ -16725,6 +17266,7 @@ var templateMutation = {
16725
17266
  };
16726
17267
 
16727
17268
  // ../config-mutations/src/execution/apply-mutation.ts
17269
+ import { randomUUID as randomUUID7 } from "node:crypto";
16728
17270
  import path17 from "node:path";
16729
17271
 
16730
17272
  // ../config-mutations/src/formats/json.ts
@@ -16800,7 +17342,7 @@ function merge(base, patch) {
16800
17342
  if (value === void 0) {
16801
17343
  continue;
16802
17344
  }
16803
- const existing = result[key2];
17345
+ const existing = hasConfigEntry(result, key2) ? result[key2] : void 0;
16804
17346
  if (isConfigObject(existing) && isConfigObject(value)) {
16805
17347
  setConfigEntry(result, key2, merge(existing, value));
16806
17348
  continue;
@@ -16928,7 +17470,7 @@ function merge2(base, patch) {
16928
17470
  if (value === void 0) {
16929
17471
  continue;
16930
17472
  }
16931
- const existing = result[key2];
17473
+ const existing = hasConfigEntry(result, key2) ? result[key2] : void 0;
16932
17474
  if (isConfigObject2(existing) && isConfigObject2(value)) {
16933
17475
  setConfigEntry(result, key2, merge2(existing, value));
16934
17476
  continue;
@@ -17008,7 +17550,7 @@ function merge3(base, patch) {
17008
17550
  if (value === void 0) {
17009
17551
  continue;
17010
17552
  }
17011
- const existing = result[key2];
17553
+ const existing = hasConfigEntry(result, key2) ? result[key2] : void 0;
17012
17554
  if (isConfigObject3(existing) && isConfigObject3(value)) {
17013
17555
  setConfigEntry(result, key2, merge3(existing, value));
17014
17556
  continue;
@@ -17145,7 +17687,7 @@ function resolvePath(rawPath, homeDir, pathMapper) {
17145
17687
 
17146
17688
  // ../config-mutations/src/fs-utils.ts
17147
17689
  function isNotFound(error3) {
17148
- return typeof error3 === "object" && error3 !== null && "code" in error3 && error3.code === "ENOENT";
17690
+ return typeof error3 === "object" && error3 !== null && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "ENOENT";
17149
17691
  }
17150
17692
  async function readFileIfExists(fs4, target) {
17151
17693
  try {
@@ -17194,6 +17736,7 @@ async function backupInvalidDocument(context, targetPath, content) {
17194
17736
  return;
17195
17737
  } catch (error3) {
17196
17738
  if (!isAlreadyExists(error3)) {
17739
+ await context.fs.unlink(backupPath).catch(() => void 0);
17197
17740
  throw error3;
17198
17741
  }
17199
17742
  attempt += 1;
@@ -17201,7 +17744,7 @@ async function backupInvalidDocument(context, targetPath, content) {
17201
17744
  }
17202
17745
  }
17203
17746
  function isAlreadyExists(error3) {
17204
- return Boolean(error3 && typeof error3 === "object" && "code" in error3 && error3.code === "EEXIST");
17747
+ return typeof error3 === "object" && error3 !== null && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "EEXIST";
17205
17748
  }
17206
17749
  async function assertRegularWriteTarget(context, targetPath) {
17207
17750
  const boundary = path17.dirname(path17.resolve(context.homeDir));
@@ -17225,28 +17768,34 @@ async function assertRegularWriteTarget(context, targetPath) {
17225
17768
  }
17226
17769
  async function writeAtomically2(context, targetPath, content) {
17227
17770
  await assertRegularWriteTarget(context, targetPath);
17228
- let attempt = 0;
17229
- while (true) {
17230
- const tempPath = `${targetPath}.mutation-tmp-${attempt}`;
17771
+ for (let attempt = 0; attempt < 10; attempt += 1) {
17772
+ const tempPath = `${targetPath}.mutation-tmp-${process.pid}-${randomUUID7()}`;
17773
+ let tempCreated = false;
17231
17774
  try {
17775
+ await assertRegularWriteTarget(context, tempPath);
17232
17776
  await context.fs.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
17777
+ tempCreated = true;
17233
17778
  await context.fs.rename(tempPath, targetPath);
17779
+ tempCreated = false;
17234
17780
  return;
17235
17781
  } catch (error3) {
17236
- if (isAlreadyExists(error3)) {
17237
- attempt += 1;
17238
- continue;
17239
- }
17240
- try {
17241
- await context.fs.unlink(tempPath);
17242
- } catch (cleanupError) {
17243
- if (!isNotFound(cleanupError)) {
17244
- void cleanupError;
17782
+ const alreadyExists = isAlreadyExists(error3);
17783
+ if (tempCreated || !alreadyExists) {
17784
+ try {
17785
+ await context.fs.unlink(tempPath);
17786
+ } catch (cleanupError) {
17787
+ if (!isNotFound(cleanupError)) {
17788
+ void cleanupError;
17789
+ }
17245
17790
  }
17246
17791
  }
17792
+ if (alreadyExists) {
17793
+ continue;
17794
+ }
17247
17795
  throw error3;
17248
17796
  }
17249
17797
  }
17798
+ throw new Error(`Unable to create temporary mutation file for ${targetPath}.`);
17250
17799
  }
17251
17800
  function describeMutation(kind, targetPath) {
17252
17801
  const displayPath = targetPath ?? "target";
@@ -17538,6 +18087,7 @@ async function applyBackup(mutation, context, options) {
17538
18087
  break;
17539
18088
  } catch (error3) {
17540
18089
  if (!isAlreadyExists(error3)) {
18090
+ await context.fs.unlink(backupPath).catch(() => void 0);
17541
18091
  throw error3;
17542
18092
  }
17543
18093
  attempt += 1;
@@ -17945,7 +18495,7 @@ async function pathExists2(fs4, targetPath) {
17945
18495
  await fs4.stat(targetPath);
17946
18496
  return true;
17947
18497
  } catch (error3) {
17948
- if (error3 && typeof error3 === "object" && "code" in error3 && error3.code === "ENOENT") {
18498
+ if (typeof error3 === "object" && error3 !== null && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "ENOENT") {
17949
18499
  return false;
17950
18500
  }
17951
18501
  throw error3;
@@ -17958,14 +18508,14 @@ async function installSkill(agentId, skill, options) {
17958
18508
  throw new UnsupportedAgentError(agentId);
17959
18509
  }
17960
18510
  const scope = options.scope ?? "local";
17961
- const config = support.config;
18511
+ const config2 = support.config;
17962
18512
  if (skill.name.length === 0 || skill.name === "." || skill.name === ".." || skill.name.includes("/") || skill.name.includes("\\") || skill.name.includes("\n") || skill.name.includes("\r")) {
17963
18513
  throw new Error(`Invalid skill name: ${skill.name}`);
17964
18514
  }
17965
- const skillDir = scope === "global" ? config.globalSkillDir : toHomeRelative(config.localSkillDir);
18515
+ const skillDir = scope === "global" ? config2.globalSkillDir : toHomeRelative(config2.localSkillDir);
17966
18516
  const skillFolderPath = `${skillDir}/${skill.name}`;
17967
18517
  const skillFilePath = `${skillFolderPath}/SKILL.md`;
17968
- const displayPath = `${scope === "global" ? config.globalSkillDir : config.localSkillDir}/${skill.name}/SKILL.md`;
18518
+ const displayPath = `${scope === "global" ? config2.globalSkillDir : config2.localSkillDir}/${skill.name}/SKILL.md`;
17969
18519
  const absoluteSkillPath = `${scope === "global" ? options.homeDir : options.cwd}/${skillFilePath.slice(2)}`;
17970
18520
  if (await pathExists2(options.fs, absoluteSkillPath)) {
17971
18521
  throw new Error(`Skill already exists: ${displayPath}`);
@@ -18004,12 +18554,13 @@ import path19 from "node:path";
18004
18554
 
18005
18555
  // ../agent-skill-config/src/git-exclude.ts
18006
18556
  import { execFileSync } from "node:child_process";
18557
+ import { randomUUID as randomUUID8 } from "node:crypto";
18007
18558
  import * as fs2 from "node:fs";
18008
18559
  import path20 from "node:path";
18009
18560
 
18010
18561
  // ../agent-skill-config/src/bridge-active-skills.ts
18011
18562
  import * as fs3 from "node:fs";
18012
- import { createHash as createHash4, randomUUID as randomUUID5 } from "node:crypto";
18563
+ import { createHash as createHash4, randomUUID as randomUUID9 } from "node:crypto";
18013
18564
  import path21 from "node:path";
18014
18565
 
18015
18566
  // src/commands/installer.ts
@@ -18022,7 +18573,7 @@ var DEFAULT_INSTALL_SCOPE = "local";
18022
18573
  var TERMINAL_PILOT_SKILL_NAME = "terminal-pilot";
18023
18574
  var installableAgents = supportedAgents;
18024
18575
  function isNotFoundError2(error3) {
18025
- return typeof error3 === "object" && error3 !== null && "code" in error3 && error3.code === "ENOENT";
18576
+ return hasOwnErrorCode(error3, "ENOENT");
18026
18577
  }
18027
18578
  function resolveInstallerServices(installer) {
18028
18579
  return {
@@ -18086,17 +18637,17 @@ function resolveHomeRelativePath(targetPath, homeDir) {
18086
18637
  return targetPath;
18087
18638
  }
18088
18639
  function getSkillFolderWithHome(agent, scope, cwd, homeDir) {
18089
- const config = getAgentConfig(agent);
18090
- if (!config) {
18640
+ const config2 = getAgentConfig(agent);
18641
+ if (!config2) {
18091
18642
  throwUnsupportedAgent(agent);
18092
18643
  }
18093
18644
  return {
18094
18645
  displayPath: path22.join(
18095
- scope === "global" ? config.globalSkillDir : config.localSkillDir,
18646
+ scope === "global" ? config2.globalSkillDir : config2.localSkillDir,
18096
18647
  TERMINAL_PILOT_SKILL_NAME
18097
18648
  ),
18098
18649
  fullPath: path22.join(
18099
- scope === "global" ? resolveHomeRelativePath(config.globalSkillDir, homeDir) : path22.resolve(cwd, config.localSkillDir),
18650
+ scope === "global" ? resolveHomeRelativePath(config2.globalSkillDir, homeDir) : path22.resolve(cwd, config2.localSkillDir),
18100
18651
  TERMINAL_PILOT_SKILL_NAME
18101
18652
  )
18102
18653
  };
@@ -18253,7 +18804,7 @@ var resize = defineCommand({
18253
18804
  });
18254
18805
 
18255
18806
  // ../terminal-png/src/index.ts
18256
- import { randomUUID as randomUUID6 } from "node:crypto";
18807
+ import { randomUUID as randomUUID10 } from "node:crypto";
18257
18808
  import { rename as rename4, rm, writeFile as writeFile6 } from "node:fs/promises";
18258
18809
 
18259
18810
  // ../terminal-png/src/ansi-parser.ts
@@ -19193,21 +19744,28 @@ async function renderTerminalPng(ansiText, options = {}) {
19193
19744
  });
19194
19745
  const png = renderPng(svg);
19195
19746
  if (options.output) {
19196
- const temporaryPath = `${options.output}.${randomUUID6()}.tmp`;
19747
+ const temporaryPath = `${options.output}.${randomUUID10()}.tmp`;
19748
+ let temporaryCreated = false;
19197
19749
  try {
19198
19750
  await writeFile6(temporaryPath, png, { flag: "wx" });
19751
+ temporaryCreated = true;
19199
19752
  await rename4(temporaryPath, options.output);
19200
19753
  } catch (error3) {
19201
- try {
19202
- await rm(temporaryPath, { force: true });
19203
- } catch (cleanupError) {
19204
- void cleanupError;
19754
+ if (temporaryCreated || !isAlreadyExistsError3(error3)) {
19755
+ try {
19756
+ await rm(temporaryPath, { force: true });
19757
+ } catch (cleanupError) {
19758
+ void cleanupError;
19759
+ }
19205
19760
  }
19206
19761
  throw error3;
19207
19762
  }
19208
19763
  }
19209
19764
  return png;
19210
19765
  }
19766
+ function isAlreadyExistsError3(error3) {
19767
+ return error3 instanceof Error && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "EEXIST";
19768
+ }
19211
19769
 
19212
19770
  // src/commands/screenshot.ts
19213
19771
  var params11 = S.Object({
@@ -19270,7 +19828,7 @@ var type = defineCommand({
19270
19828
  });
19271
19829
 
19272
19830
  // src/commands/uninstall.ts
19273
- import { randomUUID as randomUUID7 } from "node:crypto";
19831
+ import { randomUUID as randomUUID11 } from "node:crypto";
19274
19832
  var params14 = S.Object({
19275
19833
  agent: S.Enum(installableAgents, {
19276
19834
  description: "Agent to uninstall terminal-pilot from",
@@ -19306,7 +19864,7 @@ var uninstall = defineCommand({
19306
19864
  if (!await folderExists(services.fs, skill.fullPath)) {
19307
19865
  continue;
19308
19866
  }
19309
- const stagingPath = `${skill.fullPath}.removing-${randomUUID7()}`;
19867
+ const stagingPath = `${skill.fullPath}.removing-${randomUUID11()}`;
19310
19868
  await services.fs.rename(skill.fullPath, stagingPath);
19311
19869
  staged.push({ ...skill, stagingPath });
19312
19870
  }
@@ -19332,7 +19890,7 @@ async function folderExists(fs4, folderPath) {
19332
19890
  await fs4.stat(folderPath);
19333
19891
  return true;
19334
19892
  } catch (error3) {
19335
- if (typeof error3 === "object" && error3 !== null && "code" in error3 && error3.code === "ENOENT") {
19893
+ if (hasOwnErrorCode(error3, "ENOENT")) {
19336
19894
  return false;
19337
19895
  }
19338
19896
  throw error3;
@@ -19413,6 +19971,7 @@ function createTerminalPilotGroup() {
19413
19971
  var terminalPilotGroup = Object.freeze(createTerminalPilotGroup());
19414
19972
 
19415
19973
  // src/cli.ts
19974
+ configureTheme({ brand: "green", label: "Terminal Pilot" });
19416
19975
  function normalizeArgv(argv) {
19417
19976
  if (argv.includes("--json") && !argv.some((argument) => argument === "--output" || argument.startsWith("--output="))) {
19418
19977
  return argv.flatMap((argument) => argument === "--json" ? ["--output", "json"] : [argument]);
@@ -19436,8 +19995,8 @@ async function isDirectExecution(argv) {
19436
19995
  try {
19437
19996
  const modulePath = fileURLToPath5(import.meta.url);
19438
19997
  const [resolvedEntryPoint, resolvedModulePath] = await Promise.all([
19439
- realpath2(path23.resolve(entryPoint)),
19440
- realpath2(modulePath)
19998
+ realpath3(path23.resolve(entryPoint)),
19999
+ realpath3(modulePath)
19441
20000
  ]);
19442
20001
  return resolvedEntryPoint === resolvedModulePath;
19443
20002
  } catch {