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
@@ -85,12 +85,12 @@ function consumeTerminatedString(input, index, allowBellTerminator) {
85
85
  }
86
86
 
87
87
  // src/cli.ts
88
- import { realpath as realpath2 } from "node:fs/promises";
88
+ import { realpath as realpath3 } from "node:fs/promises";
89
89
  import path23 from "node:path";
90
90
  import { fileURLToPath as fileURLToPath5 } from "node:url";
91
91
 
92
92
  // ../toolcraft/src/cli.ts
93
- import { access as access2, lstat as lstat3, readFile as readFile4, rename as rename3, unlink as unlink2, writeFile as writeFile5 } from "node:fs/promises";
93
+ import { access as access2, lstat as lstat3, readFile as readFile4, rename as rename3, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
94
94
  import path14 from "node:path";
95
95
  import {
96
96
  Command as CommanderCommand,
@@ -99,7 +99,7 @@ import {
99
99
  Option
100
100
  } from "commander";
101
101
 
102
- // ../design-system/src/internal/color-support.ts
102
+ // ../toolcraft-design/src/internal/color-support.ts
103
103
  function supportsColor(env = process.env, stream = process.stdout) {
104
104
  if (env.FORCE_COLOR !== void 0 && env.FORCE_COLOR !== "0") {
105
105
  return true;
@@ -113,7 +113,7 @@ function supportsColor(env = process.env, stream = process.stdout) {
113
113
  return typeof env.TERM === "string" && env.TERM.length > 0 && env.TERM !== "dumb";
114
114
  }
115
115
 
116
- // ../design-system/src/components/color.ts
116
+ // ../toolcraft-design/src/components/color.ts
117
117
  var reset = "\x1B[0m";
118
118
  var ansiStyles = {
119
119
  reset: { open: reset },
@@ -215,41 +215,135 @@ function createColor(styles = []) {
215
215
  }
216
216
  var color = createColor();
217
217
 
218
- // ../design-system/src/tokens/colors.ts
219
- var dark = {
220
- header: (text5) => color.magentaBright.bold(text5),
221
- divider: (text5) => color.dim(text5),
222
- prompt: (text5) => color.cyan(text5),
223
- number: (text5) => color.cyanBright(text5),
224
- intro: (text5) => color.bgMagenta.white(` Poe - ${text5} `),
225
- resolvedSymbol: color.magenta("\u25C7"),
226
- errorSymbol: color.red("\u25A0"),
227
- accent: (text5) => color.cyan(text5),
228
- muted: (text5) => color.dim(text5),
229
- success: (text5) => color.green(text5),
230
- warning: (text5) => color.yellow(text5),
231
- error: (text5) => color.red(text5),
232
- info: (text5) => color.magenta(text5),
233
- badge: (text5) => color.bgYellow.black(` ${text5} `)
218
+ // ../toolcraft-design/src/tokens/brand.ts
219
+ var brands = {
220
+ purple: { name: "purple", primary: "#a200ff" },
221
+ blue: { name: "blue", primary: "#2f6fed" },
222
+ green: { name: "green", primary: "#1f9d57" }
234
223
  };
235
- var light = {
236
- header: (text5) => color.hex("#a200ff").bold(text5),
237
- divider: (text5) => color.hex("#666666")(text5),
238
- prompt: (text5) => color.hex("#006699").bold(text5),
239
- number: (text5) => color.hex("#0077cc").bold(text5),
240
- intro: (text5) => color.bgHex("#a200ff").white(` Poe - ${text5} `),
241
- resolvedSymbol: color.hex("#a200ff")("\u25C7"),
242
- errorSymbol: color.hex("#cc0000")("\u25A0"),
243
- accent: (text5) => color.hex("#006699").bold(text5),
244
- muted: (text5) => color.hex("#666666")(text5),
245
- success: (text5) => color.hex("#008800")(text5),
246
- warning: (text5) => color.hex("#cc6600")(text5),
247
- error: (text5) => color.hex("#cc0000")(text5),
248
- info: (text5) => color.hex("#a200ff")(text5),
249
- badge: (text5) => color.bgHex("#cc6600").white(` ${text5} `)
224
+
225
+ // ../toolcraft-design/src/internal/theme-state.ts
226
+ var defaults = {
227
+ brand: "purple",
228
+ label: "Poe"
250
229
  };
230
+ var config = { ...defaults };
231
+ var revision = 0;
232
+ var brandConfigured = false;
233
+ function configureTheme(patch) {
234
+ if (patch.brand !== void 0 && !Object.hasOwn(brands, patch.brand)) {
235
+ throw new Error(`Unknown brand: ${patch.brand}`);
236
+ }
237
+ config = {
238
+ brand: patch.brand ?? config.brand,
239
+ label: patch.label ?? config.label
240
+ };
241
+ if (patch.brand !== void 0) {
242
+ brandConfigured = true;
243
+ }
244
+ revision += 1;
245
+ }
246
+ function getThemeConfig() {
247
+ return { ...config };
248
+ }
249
+ function getThemeRevision() {
250
+ return revision;
251
+ }
252
+ function isThemeBrandConfigured() {
253
+ return brandConfigured;
254
+ }
251
255
 
252
- // ../design-system/src/tokens/typography.ts
256
+ // ../toolcraft-design/src/tokens/colors.ts
257
+ var brand = brands.purple.primary;
258
+ function withStyles(palette, styles) {
259
+ return Object.defineProperty(palette, "styles", {
260
+ value: styles,
261
+ enumerable: false
262
+ });
263
+ }
264
+ function brandColor(activeBrand, purple) {
265
+ return activeBrand.name === "purple" ? purple : color.hex(activeBrand.primary);
266
+ }
267
+ function brandBackground(activeBrand, purple) {
268
+ return activeBrand.name === "purple" ? purple : color.bgHex(activeBrand.primary);
269
+ }
270
+ function createPalette(activeBrand, mode) {
271
+ const isPurple = activeBrand.name === "purple";
272
+ if (mode === "light") {
273
+ const active2 = color.hex(activeBrand.primary);
274
+ const prompt2 = isPurple ? color.hex("#006699") : active2;
275
+ const number2 = isPurple ? color.hex("#0077cc") : active2;
276
+ return withStyles(
277
+ {
278
+ header: (text5) => active2.bold(text5),
279
+ divider: (text5) => color.hex("#666666")(text5),
280
+ prompt: (text5) => prompt2.bold(text5),
281
+ number: (text5) => number2.bold(text5),
282
+ intro: (text5) => color.bgHex(activeBrand.primary).white(` ${getThemeConfig().label} - ${text5} `),
283
+ get resolvedSymbol() {
284
+ return active2("\u25C7");
285
+ },
286
+ get errorSymbol() {
287
+ return color.hex("#cc0000")("\u25A0");
288
+ },
289
+ accent: (text5) => prompt2.bold(text5),
290
+ muted: (text5) => color.hex("#666666")(text5),
291
+ success: (text5) => color.hex("#008800")(text5),
292
+ warning: (text5) => color.hex("#cc6600")(text5),
293
+ error: (text5) => color.hex("#cc0000")(text5),
294
+ info: (text5) => active2(text5),
295
+ badge: (text5) => color.bgHex("#cc6600").white(` ${text5} `)
296
+ },
297
+ {
298
+ accent: { fg: isPurple ? "#006699" : activeBrand.primary, bold: true },
299
+ muted: { fg: "#666666" },
300
+ success: { fg: "#008800" },
301
+ warning: { fg: "#cc6600" },
302
+ error: { fg: "#cc0000" },
303
+ info: { fg: activeBrand.primary }
304
+ }
305
+ );
306
+ }
307
+ const active = brandColor(activeBrand, color.magenta);
308
+ const activeBright = brandColor(activeBrand, color.magentaBright);
309
+ const activeBackground = brandBackground(activeBrand, color.bgMagenta);
310
+ const prompt = isPurple ? color.cyan : active;
311
+ const number = isPurple ? color.cyanBright : active;
312
+ return withStyles(
313
+ {
314
+ header: (text5) => activeBright.bold(text5),
315
+ divider: (text5) => color.dim(text5),
316
+ prompt: (text5) => prompt(text5),
317
+ number: (text5) => number(text5),
318
+ intro: (text5) => activeBackground.white(` ${getThemeConfig().label} - ${text5} `),
319
+ get resolvedSymbol() {
320
+ return active("\u25C7");
321
+ },
322
+ get errorSymbol() {
323
+ return color.red("\u25A0");
324
+ },
325
+ accent: (text5) => prompt(text5),
326
+ muted: (text5) => color.dim(text5),
327
+ success: (text5) => color.green(text5),
328
+ warning: (text5) => color.yellow(text5),
329
+ error: (text5) => color.red(text5),
330
+ info: (text5) => active(text5),
331
+ badge: (text5) => color.bgYellow.black(` ${text5} `)
332
+ },
333
+ {
334
+ accent: { fg: isPurple ? "cyan" : activeBrand.primary, bold: true },
335
+ muted: { dim: true },
336
+ success: { fg: "green" },
337
+ warning: { fg: "yellow" },
338
+ error: { fg: "red" },
339
+ info: { fg: isPurple ? "magenta" : activeBrand.primary }
340
+ }
341
+ );
342
+ }
343
+ var dark = createPalette(brands.purple, "dark");
344
+ var light = createPalette(brands.purple, "light");
345
+
346
+ // ../toolcraft-design/src/tokens/typography.ts
253
347
  var typography = {
254
348
  bold: (text5) => color.bold(text5),
255
349
  dim: (text5) => color.dim(text5),
@@ -258,14 +352,14 @@ var typography = {
258
352
  strikethrough: (text5) => color.strikethrough(text5)
259
353
  };
260
354
 
261
- // ../design-system/src/tokens/widths.ts
355
+ // ../toolcraft-design/src/tokens/widths.ts
262
356
  var widths = {
263
357
  header: 60,
264
358
  helpColumn: 24,
265
359
  maxLine: 80
266
360
  };
267
361
 
268
- // ../design-system/src/internal/output-format.ts
362
+ // ../toolcraft-design/src/internal/output-format.ts
269
363
  import { AsyncLocalStorage } from "node:async_hooks";
270
364
  var VALID_FORMATS = /* @__PURE__ */ new Set(["terminal", "markdown", "json"]);
271
365
  var formatStorage = new AsyncLocalStorage();
@@ -286,7 +380,7 @@ function resetOutputFormatCache() {
286
380
  cached = void 0;
287
381
  }
288
382
 
289
- // ../design-system/src/internal/theme-detect.ts
383
+ // ../toolcraft-design/src/internal/theme-detect.ts
290
384
  function detectThemeFromEnv(env) {
291
385
  const apple = env.APPLE_INTERFACE_STYLE;
292
386
  if (typeof apple === "string") {
@@ -323,17 +417,30 @@ function resolveThemeName(env = process.env) {
323
417
  }
324
418
  return "dark";
325
419
  }
326
- var cachedTheme;
420
+ var themeCache = /* @__PURE__ */ new Map();
421
+ var cachedRevision = -1;
327
422
  function getTheme(env) {
423
+ const themeName = resolveThemeName(env);
424
+ const config2 = getThemeConfig();
425
+ const requestedBrand = env?.POE_BRAND?.toLowerCase();
426
+ const activeBrandName = !isThemeBrandConfigured() && requestedBrand && Object.hasOwn(brands, requestedBrand) ? requestedBrand : config2.brand;
427
+ const revision2 = getThemeRevision();
428
+ if (revision2 !== cachedRevision) {
429
+ themeCache.clear();
430
+ cachedRevision = revision2;
431
+ }
432
+ const cacheKey = `${activeBrandName}:${themeName}`;
433
+ const cachedTheme = themeCache.get(cacheKey);
328
434
  if (cachedTheme) {
329
435
  return cachedTheme;
330
436
  }
331
- const themeName = resolveThemeName(env);
332
- cachedTheme = themeName === "light" ? light : dark;
333
- return cachedTheme;
437
+ const activeBrand = brands[activeBrandName];
438
+ const theme = activeBrandName === "purple" ? themeName === "light" ? light : dark : createPalette(activeBrand, themeName);
439
+ themeCache.set(cacheKey, theme);
440
+ return theme;
334
441
  }
335
442
 
336
- // ../design-system/src/components/text.ts
443
+ // ../toolcraft-design/src/components/text.ts
337
444
  function renderMarkdownInline(content) {
338
445
  return content.replaceAll("\r\n", " ").replaceAll("\n", " ").replaceAll("\r", " ");
339
446
  }
@@ -449,7 +556,7 @@ var text = {
449
556
  }
450
557
  };
451
558
 
452
- // ../design-system/src/components/symbols.ts
559
+ // ../toolcraft-design/src/components/symbols.ts
453
560
  var symbols = {
454
561
  get info() {
455
562
  const format = resolveOutputFormat();
@@ -503,12 +610,12 @@ var symbols = {
503
610
  }
504
611
  };
505
612
 
506
- // ../design-system/src/internal/strip-ansi.ts
613
+ // ../toolcraft-design/src/internal/strip-ansi.ts
507
614
  function stripAnsi2(value) {
508
615
  return value.replace(/\u001b\[[0-9;]*m/g, "");
509
616
  }
510
617
 
511
- // ../design-system/src/prompts/primitives/log.ts
618
+ // ../toolcraft-design/src/prompts/primitives/log.ts
512
619
  function renderMarkdownInline2(value) {
513
620
  return stripAnsi2(value).replaceAll("\r\n", " ").replaceAll("\n", " ").replaceAll("\r", " ");
514
621
  }
@@ -635,7 +742,7 @@ var log = {
635
742
  error
636
743
  };
637
744
 
638
- // ../design-system/src/components/logger.ts
745
+ // ../toolcraft-design/src/components/logger.ts
639
746
  function createLogger(emitter) {
640
747
  const emit = (level, message2) => {
641
748
  if (emitter) {
@@ -696,7 +803,7 @@ function createLogger(emitter) {
696
803
  }
697
804
  var logger = createLogger();
698
805
 
699
- // ../design-system/src/components/help-formatter.ts
806
+ // ../toolcraft-design/src/components/help-formatter.ts
700
807
  var graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
701
808
  function normalizeInline(value) {
702
809
  return value.replaceAll("\r\n", " ").replaceAll("\n", " ").replaceAll("\r", " ");
@@ -872,7 +979,7 @@ function formatOptionList(options) {
872
979
  });
873
980
  }
874
981
 
875
- // ../design-system/src/components/help-formatter-plain.ts
982
+ // ../toolcraft-design/src/components/help-formatter-plain.ts
876
983
  var help_formatter_plain_exports = {};
877
984
  __export(help_formatter_plain_exports, {
878
985
  formatColumns: () => formatColumns2,
@@ -1009,7 +1116,7 @@ function formatOptionList2(options) {
1009
1116
  });
1010
1117
  }
1011
1118
 
1012
- // ../design-system/src/components/table.ts
1119
+ // ../toolcraft-design/src/components/table.ts
1013
1120
  var reset2 = "\x1B[0m";
1014
1121
  var ellipsis = "\u2026";
1015
1122
  var graphemeSegmenter2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
@@ -1293,7 +1400,7 @@ function renderTable(options) {
1293
1400
  }
1294
1401
  }
1295
1402
 
1296
- // ../design-system/src/components/detail-card.ts
1403
+ // ../toolcraft-design/src/components/detail-card.ts
1297
1404
  function wrap(value, width) {
1298
1405
  const lines = [];
1299
1406
  for (const paragraph of value.split("\n")) {
@@ -1356,7 +1463,7 @@ ${options.theme.muted(options.badges.map((badge) => badge[0] + badge.slice(1).to
1356
1463
  return blocks.join("\n\n");
1357
1464
  }
1358
1465
 
1359
- // ../design-system/src/components/template.ts
1466
+ // ../toolcraft-design/src/components/template.ts
1360
1467
  var MAX_PARTIAL_DEPTH = 100;
1361
1468
  var HTML_ESCAPE = {
1362
1469
  "&": "&",
@@ -1768,22 +1875,22 @@ function hasProperty(value, key2) {
1768
1875
  return Object.prototype.hasOwnProperty.call(value, key2);
1769
1876
  }
1770
1877
 
1771
- // ../design-system/src/components/browser.ts
1878
+ // ../toolcraft-design/src/components/browser.ts
1772
1879
  import { spawn } from "node:child_process";
1773
1880
  import process2 from "node:process";
1774
1881
 
1775
- // ../design-system/src/acp/writer.ts
1882
+ // ../toolcraft-design/src/acp/writer.ts
1776
1883
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
1777
1884
  var storage = new AsyncLocalStorage2();
1778
1885
 
1779
- // ../design-system/src/dashboard/terminal-width.ts
1886
+ // ../toolcraft-design/src/dashboard/terminal-width.ts
1780
1887
  var graphemeSegmenter3 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1781
1888
 
1782
- // ../design-system/src/dashboard/terminal.ts
1889
+ // ../toolcraft-design/src/dashboard/terminal.ts
1783
1890
  import readline from "node:readline";
1784
1891
  import { PassThrough } from "node:stream";
1785
1892
 
1786
- // ../design-system/src/explorer/state.ts
1893
+ // ../toolcraft-design/src/explorer/state.ts
1787
1894
  var REGION_HEADER = 1 << 0;
1788
1895
  var REGION_LIST = 1 << 1;
1789
1896
  var REGION_DETAIL = 1 << 2;
@@ -1792,10 +1899,10 @@ var REGION_MODAL = 1 << 4;
1792
1899
  var REGION_TOAST = 1 << 5;
1793
1900
  var REGION_ALL = REGION_HEADER | REGION_LIST | REGION_DETAIL | REGION_FOOTER | REGION_MODAL | REGION_TOAST;
1794
1901
 
1795
- // ../design-system/src/prompts/index.ts
1902
+ // ../toolcraft-design/src/prompts/index.ts
1796
1903
  import * as clack from "@clack/prompts";
1797
1904
 
1798
- // ../design-system/src/prompts/primitives/cancel.ts
1905
+ // ../toolcraft-design/src/prompts/primitives/cancel.ts
1799
1906
  import { isCancel } from "@clack/prompts";
1800
1907
  function cancel(msg = "") {
1801
1908
  if (resolveOutputFormat() !== "terminal") {
@@ -1806,7 +1913,7 @@ function cancel(msg = "") {
1806
1913
  `);
1807
1914
  }
1808
1915
 
1809
- // ../design-system/src/prompts/primitives/note.ts
1916
+ // ../toolcraft-design/src/prompts/primitives/note.ts
1810
1917
  function getVisibleWidth(value) {
1811
1918
  return stripAnsi2(value).length;
1812
1919
  }
@@ -1855,10 +1962,10 @@ function note(message2, title) {
1855
1962
  `);
1856
1963
  }
1857
1964
 
1858
- // ../design-system/src/static/spinner.ts
1965
+ // ../toolcraft-design/src/static/spinner.ts
1859
1966
  var SPINNER_FRAMES = Object.freeze(["\u25D2", "\u25D0", "\u25D3", "\u25D1"]);
1860
1967
 
1861
- // ../design-system/src/prompts/index.ts
1968
+ // ../toolcraft-design/src/prompts/index.ts
1862
1969
  async function select2(opts) {
1863
1970
  return clack.select(opts);
1864
1971
  }
@@ -1901,19 +2008,19 @@ var ApprovalDeclinedError = class extends UserError {
1901
2008
  };
1902
2009
 
1903
2010
  // ../toolcraft/src/human-in-loop/config.ts
1904
- function validateHumanInLoopOnDefine(config) {
1905
- const label = Array.isArray(config.children) ? "group" : "command";
1906
- if (config.confirm === true && config.humanInLoop !== void 0 && config.humanInLoop !== null) {
1907
- throw new Error(`${label} '${config.name}': use either confirm or humanInLoop, not both`);
2011
+ function validateHumanInLoopOnDefine(config2) {
2012
+ const label = Array.isArray(config2.children) ? "group" : "command";
2013
+ if (config2.confirm === true && config2.humanInLoop !== void 0 && config2.humanInLoop !== null) {
2014
+ throw new Error(`${label} '${config2.name}': use either confirm or humanInLoop, not both`);
1908
2015
  }
1909
- if (config.humanInLoop === void 0 || config.humanInLoop === null) {
2016
+ if (config2.humanInLoop === void 0 || config2.humanInLoop === null) {
1910
2017
  return;
1911
2018
  }
1912
- if (config.humanInLoop.mode !== "sync" && config.humanInLoop.mode !== "async") {
1913
- throw new Error(`${label} '${config.name}': humanInLoop.mode must be "sync" or "async"`);
2019
+ if (config2.humanInLoop.mode !== "sync" && config2.humanInLoop.mode !== "async") {
2020
+ throw new Error(`${label} '${config2.name}': humanInLoop.mode must be "sync" or "async"`);
1914
2021
  }
1915
- if (typeof config.humanInLoop.message !== "function") {
1916
- throw new Error(`${label} '${config.name}': humanInLoop.message must be a function`);
2022
+ if (typeof config2.humanInLoop.message !== "function") {
2023
+ throw new Error(`${label} '${config2.name}': humanInLoop.message must be a function`);
1917
2024
  }
1918
2025
  }
1919
2026
  function mergeHumanInLoopFromGroup(groupHumanInLoop, childHumanInLoop) {
@@ -1989,12 +2096,12 @@ function assertValidBranches(branches, discriminator) {
1989
2096
  }
1990
2097
  }
1991
2098
  }
1992
- function OneOf(config) {
1993
- assertValidBranches(config.branches, config.discriminator);
2099
+ function OneOf(config2) {
2100
+ assertValidBranches(config2.branches, config2.discriminator);
1994
2101
  return {
1995
2102
  kind: "oneOf",
1996
- discriminator: config.discriminator,
1997
- branches: config.branches
2103
+ discriminator: config2.discriminator,
2104
+ branches: config2.branches
1998
2105
  };
1999
2106
  }
2000
2107
 
@@ -2244,22 +2351,22 @@ function cloneStringArray(values) {
2244
2351
  function cloneStringRecord(values) {
2245
2352
  return values === void 0 ? void 0 : { ...values };
2246
2353
  }
2247
- function cloneMcpServerConfig(config) {
2248
- if (config === void 0) {
2354
+ function cloneMcpServerConfig(config2) {
2355
+ if (config2 === void 0) {
2249
2356
  return void 0;
2250
2357
  }
2251
- if (config.transport === "stdio") {
2358
+ if (config2.transport === "stdio") {
2252
2359
  return {
2253
2360
  transport: "stdio",
2254
- command: config.command,
2255
- args: cloneStringArray(config.args),
2256
- env: cloneStringRecord(config.env)
2361
+ command: config2.command,
2362
+ args: cloneStringArray(config2.args),
2363
+ env: cloneStringRecord(config2.env)
2257
2364
  };
2258
2365
  }
2259
2366
  return {
2260
2367
  transport: "http",
2261
- url: config.url,
2262
- headers: cloneStringRecord(config.headers)
2368
+ url: config2.url,
2369
+ headers: cloneStringRecord(config2.headers)
2263
2370
  };
2264
2371
  }
2265
2372
  function cloneRenameMap(rename5) {
@@ -2500,57 +2607,57 @@ function resolveCommandScope(ownScope, inheritedScope) {
2500
2607
  function resolveGroupScope(ownScope, inheritedScope) {
2501
2608
  return cloneScope(ownScope ?? inheritedScope);
2502
2609
  }
2503
- function createBaseCommand(config) {
2610
+ function createBaseCommand(config2) {
2504
2611
  const command = {
2505
2612
  kind: "command",
2506
- name: config.name,
2507
- description: config.description,
2508
- aliases: [...config.aliases ?? []],
2509
- positional: [...config.positional ?? []],
2510
- params: config.params,
2511
- secrets: cloneSecrets(config.secrets),
2512
- scope: resolveCommandScope(config.scope, void 0),
2513
- confirm: config.confirm ?? false,
2514
- humanInLoop: config.humanInLoop,
2515
- requires: cloneRequires(config.requires),
2516
- handler: config.handler,
2517
- render: config.render
2613
+ name: config2.name,
2614
+ description: config2.description,
2615
+ aliases: [...config2.aliases ?? []],
2616
+ positional: [...config2.positional ?? []],
2617
+ params: config2.params,
2618
+ secrets: cloneSecrets(config2.secrets),
2619
+ scope: resolveCommandScope(config2.scope, void 0),
2620
+ confirm: config2.confirm ?? false,
2621
+ humanInLoop: config2.humanInLoop,
2622
+ requires: cloneRequires(config2.requires),
2623
+ handler: config2.handler,
2624
+ render: config2.render
2518
2625
  };
2519
2626
  Object.defineProperty(command, commandConfigSymbol, {
2520
2627
  value: {
2521
- scope: cloneScope(config.scope),
2522
- humanInLoop: config.humanInLoop,
2523
- secrets: cloneSecrets(config.secrets),
2524
- requires: cloneRequires(config.requires),
2628
+ scope: cloneScope(config2.scope),
2629
+ humanInLoop: config2.humanInLoop,
2630
+ secrets: cloneSecrets(config2.secrets),
2631
+ requires: cloneRequires(config2.requires),
2525
2632
  sourcePath: inferCommandSourcePath()
2526
2633
  }
2527
2634
  });
2528
2635
  return command;
2529
2636
  }
2530
- function createBaseGroup(config) {
2637
+ function createBaseGroup(config2) {
2531
2638
  const group = {
2532
2639
  kind: "group",
2533
- name: config.name,
2534
- description: config.description,
2535
- aliases: [...config.aliases ?? []],
2536
- scope: resolveGroupScope(config.scope, void 0),
2537
- humanInLoop: config.humanInLoop,
2538
- secrets: cloneSecrets(config.secrets),
2539
- requires: cloneRequires(config.requires),
2640
+ name: config2.name,
2641
+ description: config2.description,
2642
+ aliases: [...config2.aliases ?? []],
2643
+ scope: resolveGroupScope(config2.scope, void 0),
2644
+ humanInLoop: config2.humanInLoop,
2645
+ secrets: cloneSecrets(config2.secrets),
2646
+ requires: cloneRequires(config2.requires),
2540
2647
  children: [],
2541
2648
  default: void 0
2542
2649
  };
2543
2650
  Object.defineProperty(group, groupConfigSymbol, {
2544
2651
  value: {
2545
- mcp: cloneMcpServerConfig(config.mcp),
2546
- scope: cloneScope(config.scope),
2547
- humanInLoop: config.humanInLoop,
2548
- secrets: cloneSecrets(config.secrets),
2549
- tools: cloneStringArray(config.tools),
2550
- rename: cloneRenameMap(config.rename),
2551
- requires: cloneRequires(config.requires),
2552
- children: [...config.children],
2553
- default: config.default
2652
+ mcp: cloneMcpServerConfig(config2.mcp),
2653
+ scope: cloneScope(config2.scope),
2654
+ humanInLoop: config2.humanInLoop,
2655
+ secrets: cloneSecrets(config2.secrets),
2656
+ tools: cloneStringArray(config2.tools),
2657
+ rename: cloneRenameMap(config2.rename),
2658
+ requires: cloneRequires(config2.requires),
2659
+ children: [...config2.children],
2660
+ default: config2.default
2554
2661
  }
2555
2662
  });
2556
2663
  return group;
@@ -2653,10 +2760,10 @@ function materializeNode(node, inherited) {
2653
2760
  }
2654
2761
  return materializeGroup(node, inherited);
2655
2762
  }
2656
- function defineCommand(config) {
2657
- validateHumanInLoopOnDefine(config);
2763
+ function defineCommand(config2) {
2764
+ validateHumanInLoopOnDefine(config2);
2658
2765
  return materializeCommand(
2659
- createBaseCommand(config),
2766
+ createBaseCommand(config2),
2660
2767
  {
2661
2768
  scope: void 0,
2662
2769
  humanInLoop: void 0,
@@ -2665,10 +2772,10 @@ function defineCommand(config) {
2665
2772
  }
2666
2773
  );
2667
2774
  }
2668
- function defineGroup(config) {
2669
- validateRenameMap(config.rename);
2670
- validateHumanInLoopOnDefine(config);
2671
- return materializeGroup(createBaseGroup(config), {
2775
+ function defineGroup(config2) {
2776
+ validateRenameMap(config2.rename);
2777
+ validateHumanInLoopOnDefine(config2);
2778
+ return materializeGroup(createBaseGroup(config2), {
2672
2779
  scope: void 0,
2673
2780
  humanInLoop: void 0,
2674
2781
  secrets: {},
@@ -2699,27 +2806,27 @@ function validateMachine(machine) {
2699
2806
  if (!isRecord(machine)) {
2700
2807
  throw new TypeError("State machine must be an object.");
2701
2808
  }
2702
- if (!isStateList(machine.states)) {
2809
+ if (!hasOwnRecordField(machine, "states") || !isStateList(machine.states)) {
2703
2810
  throw new TypeError("State machine states must be a string array.");
2704
2811
  }
2705
2812
  const states = new Set(machine.states);
2706
- if (typeof machine.initial !== "string") {
2813
+ if (!hasOwnRecordField(machine, "initial") || typeof machine.initial !== "string") {
2707
2814
  throw new TypeError("State machine initial must be a string.");
2708
2815
  }
2709
2816
  if (!states.has(machine.initial)) {
2710
2817
  throw new Error(`Initial state "${machine.initial}" is not declared.`);
2711
2818
  }
2712
- if (!isRecord(machine.events)) {
2819
+ if (!hasOwnRecordField(machine, "events") || !isRecord(machine.events)) {
2713
2820
  throw new TypeError("State machine events must be an object.");
2714
2821
  }
2715
2822
  for (const [eventName, event] of Object.entries(machine.events)) {
2716
2823
  if (!isRecord(event)) {
2717
2824
  throw new TypeError(`Event "${eventName}" must be an object.`);
2718
2825
  }
2719
- if (event.from !== "*" && !isStateList(event.from)) {
2826
+ if (!hasOwnRecordField(event, "from") || event.from !== "*" && !isStateList(event.from)) {
2720
2827
  throw new TypeError(`Event "${eventName}" has an invalid "from" definition.`);
2721
2828
  }
2722
- if (typeof event.to !== "string") {
2829
+ if (!hasOwnRecordField(event, "to") || typeof event.to !== "string") {
2723
2830
  throw new TypeError(`Event "${eventName}" target state must be a string.`);
2724
2831
  }
2725
2832
  if (!states.has(event.to)) {
@@ -2734,6 +2841,9 @@ function validateMachine(machine) {
2734
2841
  }
2735
2842
  }
2736
2843
  }
2844
+ function hasOwnRecordField(record, key2) {
2845
+ return Object.prototype.hasOwnProperty.call(record, key2);
2846
+ }
2737
2847
  function eventsFromState(machine, fromState) {
2738
2848
  const events = [];
2739
2849
  for (const [eventName, event] of Object.entries(machine.events)) {
@@ -2837,7 +2947,7 @@ import path3 from "node:path";
2837
2947
  // ../process-runner/src/docker/docker-execution-env.ts
2838
2948
  import { createHash as createHash2, randomBytes as randomBytes2 } from "node:crypto";
2839
2949
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "node:fs";
2840
- import { readdir, readFile, writeFile } from "node:fs/promises";
2950
+ import { readdir, readFile, realpath, writeFile } from "node:fs/promises";
2841
2951
  import { tmpdir as tmpdir2 } from "node:os";
2842
2952
  import path5 from "node:path";
2843
2953
 
@@ -3005,6 +3115,7 @@ function resolveEndpoint(options = {}) {
3005
3115
  }
3006
3116
 
3007
3117
  // ../task-list/src/backends/utils.ts
3118
+ import { randomUUID as randomUUID2 } from "node:crypto";
3008
3119
  import path6 from "node:path";
3009
3120
  function compareCreated(left, right) {
3010
3121
  const leftCreated = typeof left.raw.created === "string" ? left.raw.created : "";
@@ -3025,9 +3136,8 @@ function applyOrder(entries, order) {
3025
3136
  }
3026
3137
  return entries.map((entry) => entry.task);
3027
3138
  }
3028
- var tmpFileCounter = 0;
3029
3139
  function hasErrorCode(error3, code) {
3030
- return !!error3 && typeof error3 === "object" && "code" in error3 && error3.code === code;
3140
+ return !!error3 && typeof error3 === "object" && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === code;
3031
3141
  }
3032
3142
  function isRecord2(value) {
3033
3143
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -3074,18 +3184,22 @@ async function rejectSymbolicLinkComponents(fs4, filePath) {
3074
3184
  }
3075
3185
  }
3076
3186
  async function writeAtomically(fs4, filePath, content) {
3077
- const tempPath = `${filePath}.tmp-${process.pid}-${tmpFileCounter}`;
3078
- tmpFileCounter += 1;
3187
+ const tempPath = `${filePath}.${process.pid}.${randomUUID2()}.tmp`;
3188
+ let tempCreated = false;
3079
3189
  await fs4.mkdir(path6.dirname(filePath), { recursive: true });
3080
3190
  try {
3081
3191
  await fs4.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
3192
+ tempCreated = true;
3082
3193
  await fs4.rename(tempPath, filePath);
3194
+ tempCreated = false;
3083
3195
  } catch (error3) {
3084
- try {
3085
- await fs4.unlink(tempPath);
3086
- } catch (unlinkError) {
3087
- if (!hasErrorCode(unlinkError, "ENOENT")) {
3088
- throw unlinkError;
3196
+ if (tempCreated || !hasErrorCode(error3, "EEXIST")) {
3197
+ try {
3198
+ await fs4.unlink(tempPath);
3199
+ } catch (unlinkError) {
3200
+ if (!hasErrorCode(unlinkError, "ENOENT")) {
3201
+ throw unlinkError;
3202
+ }
3089
3203
  }
3090
3204
  }
3091
3205
  throw error3;
@@ -3099,6 +3213,7 @@ async function withFileLock(fs4, lockPath, operation) {
3099
3213
  break;
3100
3214
  } catch (error3) {
3101
3215
  if (!hasErrorCode(error3, "EEXIST")) {
3216
+ await fs4.unlink(lockPath).catch(() => void 0);
3102
3217
  throw error3;
3103
3218
  }
3104
3219
  if (await removeAbandonedLock(fs4, lockPath)) {
@@ -4382,27 +4497,30 @@ function readFrontmatter(frontmatterContent, filePath) {
4382
4497
  return parsed;
4383
4498
  }
4384
4499
  function assertValidTaskRecord(frontmatter, filePath, validStates) {
4385
- if ("$schema" in frontmatter && frontmatter.$schema !== TASK_SCHEMA_ID) {
4500
+ if (hasOwnTaskField(frontmatter, "$schema") && frontmatter.$schema !== TASK_SCHEMA_ID) {
4386
4501
  throw malformedTask(filePath, "$schema");
4387
4502
  }
4388
- if ("kind" in frontmatter && frontmatter.kind !== TASK_KIND) {
4503
+ if (hasOwnTaskField(frontmatter, "kind") && frontmatter.kind !== TASK_KIND) {
4389
4504
  throw malformedTask(filePath, "kind");
4390
4505
  }
4391
- if ("version" in frontmatter) {
4506
+ if (hasOwnTaskField(frontmatter, "version")) {
4392
4507
  if (typeof frontmatter.version !== "number" || !Number.isInteger(frontmatter.version) || frontmatter.version !== TASK_VERSION) {
4393
4508
  throw malformedTask(filePath, "version");
4394
4509
  }
4395
4510
  }
4396
- if (typeof frontmatter.name !== "string" || frontmatter.name.length === 0) {
4511
+ if (!hasOwnTaskField(frontmatter, "name") || typeof frontmatter.name !== "string" || frontmatter.name.length === 0) {
4397
4512
  throw malformedTask(filePath, "name");
4398
4513
  }
4399
- if (typeof frontmatter.state !== "string" || !validStates.has(frontmatter.state)) {
4514
+ if (!hasOwnTaskField(frontmatter, "state") || typeof frontmatter.state !== "string" || !validStates.has(frontmatter.state)) {
4400
4515
  throw malformedTask(filePath, "state");
4401
4516
  }
4402
- if ("description" in frontmatter && typeof frontmatter.description !== "string") {
4517
+ if (hasOwnTaskField(frontmatter, "description") && typeof frontmatter.description !== "string") {
4403
4518
  throw malformedTask(filePath, "description");
4404
4519
  }
4405
4520
  }
4521
+ function hasOwnTaskField(frontmatter, key2) {
4522
+ return Object.prototype.hasOwnProperty.call(frontmatter, key2);
4523
+ }
4406
4524
  function reservedFrontmatterKeys(mode) {
4407
4525
  return mode === "passthrough" ? PASSTHROUGH_RESERVED_FRONTMATTER_KEYS : RESERVED_FRONTMATTER_KEYS;
4408
4526
  }
@@ -4525,7 +4643,7 @@ async function readTaskAtLocation(fs4, rootPath, layout, list, id, validStates,
4525
4643
  }
4526
4644
  return readTaskFile(fs4, list, id, location.path, validStates, initialState, mode);
4527
4645
  }
4528
- function createdFrontmatter(defaults, input, initialState, mode) {
4646
+ function createdFrontmatter(defaults2, input, initialState, mode) {
4529
4647
  const frontmatter = mode !== "passthrough" ? {
4530
4648
  $schema: TASK_SCHEMA_ID,
4531
4649
  kind: TASK_KIND,
@@ -4537,7 +4655,7 @@ function createdFrontmatter(defaults, input, initialState, mode) {
4537
4655
  state: initialState
4538
4656
  };
4539
4657
  const reservedKeys = reservedFrontmatterKeys(mode);
4540
- for (const [key2, value] of Object.entries(defaults.metadata)) {
4658
+ for (const [key2, value] of Object.entries(defaults2.metadata)) {
4541
4659
  if (!reservedKeys.has(key2)) {
4542
4660
  setOwnValue(frontmatter, key2, value);
4543
4661
  }
@@ -5251,7 +5369,8 @@ function parseQualifiedId3(qualifiedId) {
5251
5369
  };
5252
5370
  }
5253
5371
  function descriptionFromTaskRecord(taskRecord) {
5254
- return typeof taskRecord.description === "string" ? taskRecord.description : "";
5372
+ const description = getOwnEntry(taskRecord, "description");
5373
+ return typeof description === "string" ? description : "";
5255
5374
  }
5256
5375
  function metadataFromTaskRecord(taskRecord) {
5257
5376
  const metadata = /* @__PURE__ */ Object.create(null);
@@ -5267,8 +5386,8 @@ function createTask2(list, id, taskRecord, sourcePath) {
5267
5386
  list,
5268
5387
  id,
5269
5388
  qualifiedId: `${list}/${id}`,
5270
- name: taskRecord.name,
5271
- state: taskRecord.state,
5389
+ name: getOwnEntry(taskRecord, "name"),
5390
+ state: getOwnEntry(taskRecord, "state"),
5272
5391
  description: descriptionFromTaskRecord(taskRecord),
5273
5392
  metadata: metadataFromTaskRecord(taskRecord),
5274
5393
  ...sourcePath !== void 0 && { sourcePath: path8.resolve(sourcePath) }
@@ -5283,13 +5402,13 @@ function matchesFilter(task, filter) {
5283
5402
  }
5284
5403
  return true;
5285
5404
  }
5286
- function createTaskRecord(defaults, input, initialState) {
5405
+ function createTaskRecord(defaults2, input, initialState) {
5287
5406
  const taskRecord = Object.assign(/* @__PURE__ */ Object.create(null), {
5288
5407
  name: input.name,
5289
5408
  state: initialState,
5290
5409
  description: input.description ?? ""
5291
5410
  });
5292
- for (const [key2, value] of Object.entries(defaults.metadata)) {
5411
+ for (const [key2, value] of Object.entries(defaults2.metadata)) {
5293
5412
  if (!RESERVED_TASK_KEYS.has(key2)) {
5294
5413
  taskRecord[key2] = value;
5295
5414
  }
@@ -5365,16 +5484,17 @@ function assertValidStoreRecord(store, filePath) {
5365
5484
  if (!isRecord2(store)) {
5366
5485
  throw malformedStore(filePath, "store");
5367
5486
  }
5368
- if (store.$schema !== STORE_SCHEMA_ID) {
5487
+ if (getOwnEntry(store, "$schema") !== STORE_SCHEMA_ID) {
5369
5488
  throw malformedStore(filePath, "$schema");
5370
5489
  }
5371
- if (store.kind !== STORE_KIND) {
5490
+ if (getOwnEntry(store, "kind") !== STORE_KIND) {
5372
5491
  throw malformedStore(filePath, "kind");
5373
5492
  }
5374
- if (typeof store.version !== "number" || !Number.isInteger(store.version) || store.version !== STORE_VERSION) {
5493
+ const version = getOwnEntry(store, "version");
5494
+ if (typeof version !== "number" || !Number.isInteger(version) || version !== STORE_VERSION) {
5375
5495
  throw malformedStore(filePath, "version");
5376
5496
  }
5377
- if (!isRecord2(store.lists)) {
5497
+ if (!isRecord2(getOwnEntry(store, "lists"))) {
5378
5498
  throw malformedStore(filePath, "lists");
5379
5499
  }
5380
5500
  }
@@ -5382,29 +5502,38 @@ function assertValidTaskRecord2(taskRecord, list, id, validStates) {
5382
5502
  if (!isRecord2(taskRecord)) {
5383
5503
  throw malformedTask2(list, id, "task");
5384
5504
  }
5385
- if ("$schema" in taskRecord && taskRecord.$schema !== TASK_SCHEMA_ID2) {
5505
+ if (hasOwnTaskField2(taskRecord, "$schema") && getOwnEntry(taskRecord, "$schema") !== TASK_SCHEMA_ID2) {
5386
5506
  throw malformedTask2(list, id, "$schema");
5387
5507
  }
5388
- if ("kind" in taskRecord && taskRecord.kind !== TASK_KIND2) {
5508
+ if (hasOwnTaskField2(taskRecord, "kind") && getOwnEntry(taskRecord, "kind") !== TASK_KIND2) {
5389
5509
  throw malformedTask2(list, id, "kind");
5390
5510
  }
5391
- if ("version" in taskRecord) {
5392
- if (typeof taskRecord.version !== "number" || !Number.isInteger(taskRecord.version) || taskRecord.version !== TASK_VERSION2) {
5511
+ if (hasOwnTaskField2(taskRecord, "version")) {
5512
+ const version = getOwnEntry(taskRecord, "version");
5513
+ if (typeof version !== "number" || !Number.isInteger(version) || version !== TASK_VERSION2) {
5393
5514
  throw malformedTask2(list, id, "version");
5394
5515
  }
5395
5516
  }
5396
- if (typeof taskRecord.name !== "string" || taskRecord.name.length === 0) {
5517
+ const name = getOwnEntry(taskRecord, "name");
5518
+ if (!hasOwnTaskField2(taskRecord, "name") || typeof name !== "string" || name.length === 0) {
5397
5519
  throw malformedTask2(list, id, "name");
5398
5520
  }
5399
- if (typeof taskRecord.state !== "string" || !validStates.has(taskRecord.state)) {
5521
+ const state = getOwnEntry(taskRecord, "state");
5522
+ if (!hasOwnTaskField2(taskRecord, "state") || typeof state !== "string" || !validStates.has(state)) {
5400
5523
  throw malformedTask2(list, id, "state");
5401
5524
  }
5402
- if ("description" in taskRecord && typeof taskRecord.description !== "string") {
5525
+ if (hasOwnTaskField2(taskRecord, "description") && typeof getOwnEntry(taskRecord, "description") !== "string") {
5403
5526
  throw malformedTask2(list, id, "description");
5404
5527
  }
5405
5528
  }
5529
+ function hasOwnTaskField2(taskRecord, key2) {
5530
+ return Object.prototype.hasOwnProperty.call(taskRecord, key2);
5531
+ }
5532
+ function getOwnEntry(record, key2) {
5533
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
5534
+ }
5406
5535
  function validateStoreEntries(store, filePath, validStates) {
5407
- const lists = store.lists;
5536
+ const lists = getOwnEntry(store, "lists");
5408
5537
  if (!isRecord2(lists)) {
5409
5538
  throw malformedStore(filePath, "lists");
5410
5539
  }
@@ -5444,10 +5573,11 @@ async function readStore(fs4, filePath, validStates) {
5444
5573
  };
5445
5574
  }
5446
5575
  function getListsRecord(store) {
5447
- return store.lists;
5576
+ const lists = getOwnEntry(store, "lists");
5577
+ return isRecord2(lists) ? lists : {};
5448
5578
  }
5449
5579
  function getListRecord(store, list) {
5450
- const listRecord = getListsRecord(store)[list];
5580
+ const listRecord = getOwnEntry(getListsRecord(store), list);
5451
5581
  return isRecord2(listRecord) ? listRecord : void 0;
5452
5582
  }
5453
5583
  function getTaskRecord(store, list, id) {
@@ -5740,7 +5870,7 @@ async function yamlFileBackend(deps) {
5740
5870
  const result = [];
5741
5871
  const listNames = sortStrings(Object.keys(getListsRecord(store)));
5742
5872
  for (const listName of listNames) {
5743
- const listRecord = getListsRecord(store)[listName];
5873
+ const listRecord = getOwnEntry(getListsRecord(store), listName);
5744
5874
  if (!isRecord2(listRecord)) continue;
5745
5875
  const entries = Object.entries(listRecord).map(([id, taskRecord]) => ({
5746
5876
  task: createTask2(listName, id, taskRecord, deps.path),
@@ -6374,8 +6504,8 @@ function createHandlerContext(command, params17) {
6374
6504
  function createFs() {
6375
6505
  return {
6376
6506
  readFile: async (path25, encoding = "utf8") => readFile2(path25, { encoding }),
6377
- writeFile: async (path25, contents) => {
6378
- await writeFile2(path25, contents);
6507
+ writeFile: async (path25, contents, options) => {
6508
+ await writeFile2(path25, contents, options);
6379
6509
  },
6380
6510
  exists: async (path25) => {
6381
6511
  try {
@@ -6663,17 +6793,17 @@ function isMissingStateError(error3) {
6663
6793
  }
6664
6794
 
6665
6795
  // ../toolcraft/src/error-report.ts
6666
- import { mkdir as mkdir2, realpath, writeFile as writeFile4 } from "node:fs/promises";
6667
- import { randomUUID as randomUUID3 } from "node:crypto";
6796
+ import { mkdir as mkdir2, realpath as realpath2, writeFile as writeFile4 } from "node:fs/promises";
6797
+ import { randomUUID as randomUUID5 } from "node:crypto";
6668
6798
  import os from "node:os";
6669
6799
  import path13 from "node:path";
6670
6800
  import { CommanderError } from "commander";
6671
6801
 
6672
6802
  // ../toolcraft/src/mcp-proxy.ts
6673
6803
  import { existsSync as existsSync2 } from "node:fs";
6674
- import { lstat as lstat2, mkdir, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "node:fs/promises";
6804
+ import { lstat as lstat2, mkdir, readFile as readFile3, rename as rename2, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
6675
6805
  import path12 from "node:path";
6676
- import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
6806
+ import { createHash as createHash3, randomUUID as randomUUID4 } from "node:crypto";
6677
6807
 
6678
6808
  // ../tiny-mcp-client/src/internal.ts
6679
6809
  import { spawn as spawn5 } from "node:child_process";
@@ -6684,7 +6814,7 @@ import crypto from "node:crypto";
6684
6814
  import path11 from "node:path";
6685
6815
 
6686
6816
  // ../auth-store/src/encrypted-file-store.ts
6687
- import { createCipheriv, createDecipheriv, randomBytes as randomBytes4, scrypt } from "node:crypto";
6817
+ import { createCipheriv, createDecipheriv, randomBytes as randomBytes4, randomUUID as randomUUID3, scrypt } from "node:crypto";
6688
6818
  import { promises as fs } from "node:fs";
6689
6819
  import { homedir, hostname, userInfo } from "node:os";
6690
6820
  import path10 from "node:path";
@@ -6695,7 +6825,6 @@ var ENCRYPTION_KEY_BYTES = 32;
6695
6825
  var ENCRYPTION_IV_BYTES = 12;
6696
6826
  var ENCRYPTION_AUTH_TAG_BYTES = 16;
6697
6827
  var ENCRYPTION_FILE_MODE = 384;
6698
- var temporaryFileSequence = 0;
6699
6828
  var EncryptedFileStore = class {
6700
6829
  fs;
6701
6830
  filePath;
@@ -6727,7 +6856,7 @@ var EncryptedFileStore = class {
6727
6856
  this.getRandomBytes = input.getRandomBytes ?? randomBytes4;
6728
6857
  }
6729
6858
  async get() {
6730
- await this.assertRegularCredentialPath();
6859
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
6731
6860
  let rawDocument;
6732
6861
  try {
6733
6862
  rawDocument = await this.fs.readFile(this.filePath, "utf8");
@@ -6758,7 +6887,7 @@ var EncryptedFileStore = class {
6758
6887
  }
6759
6888
  }
6760
6889
  async set(value) {
6761
- await this.assertRegularCredentialPath();
6890
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
6762
6891
  const key2 = await this.getEncryptionKey();
6763
6892
  const iv = this.getRandomBytes(ENCRYPTION_IV_BYTES);
6764
6893
  const cipher = createCipheriv(ENCRYPTION_ALGORITHM, key2, iv);
@@ -6774,25 +6903,28 @@ var EncryptedFileStore = class {
6774
6903
  ciphertext: ciphertext.toString("base64")
6775
6904
  };
6776
6905
  await this.fs.mkdir(path10.dirname(this.filePath), { recursive: true });
6777
- await this.assertRegularCredentialPath();
6778
- const temporaryPath = `${this.filePath}.${process.pid}.${temporaryFileSequence++}.tmp`;
6906
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
6907
+ const temporaryPath = `${this.filePath}.${process.pid}.${randomUUID3()}.tmp`;
6908
+ let temporaryCreated = false;
6779
6909
  try {
6910
+ await this.assertCredentialPathHasNoSymbolicLinks(temporaryPath);
6780
6911
  await this.fs.writeFile(temporaryPath, JSON.stringify(document), {
6781
6912
  encoding: "utf8",
6782
6913
  flag: "wx",
6783
6914
  mode: ENCRYPTION_FILE_MODE
6784
6915
  });
6916
+ temporaryCreated = true;
6785
6917
  await this.fs.chmod(temporaryPath, ENCRYPTION_FILE_MODE);
6786
6918
  await this.fs.rename(temporaryPath, this.filePath);
6787
6919
  } catch (error3) {
6788
- if (!isAlreadyExistsError(error3)) {
6920
+ if (temporaryCreated || !isAlreadyExistsError(error3)) {
6789
6921
  await removeIfPresent(this.fs, temporaryPath).catch(() => void 0);
6790
6922
  }
6791
6923
  throw error3;
6792
6924
  }
6793
6925
  }
6794
6926
  async delete() {
6795
- await this.assertRegularCredentialPath();
6927
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
6796
6928
  try {
6797
6929
  await this.fs.unlink(this.filePath);
6798
6930
  } catch (error3) {
@@ -6801,8 +6933,8 @@ var EncryptedFileStore = class {
6801
6933
  }
6802
6934
  }
6803
6935
  }
6804
- async assertRegularCredentialPath() {
6805
- const resolvedPath = path10.resolve(this.filePath);
6936
+ async assertCredentialPathHasNoSymbolicLinks(targetPath) {
6937
+ const resolvedPath = path10.resolve(targetPath);
6806
6938
  const protectedPaths = getProtectedCredentialPaths(
6807
6939
  resolvedPath,
6808
6940
  this.symbolicLinkCheckStartPath
@@ -6867,9 +6999,6 @@ async function removeIfPresent(fileSystem, filePath) {
6867
6999
  }
6868
7000
  }
6869
7001
  }
6870
- function isAlreadyExistsError(error3) {
6871
- return typeof error3 === "object" && error3 !== null && "code" in error3 && error3.code === "EEXIST";
6872
- }
6873
7002
  function defaultMachineIdentity() {
6874
7003
  return {
6875
7004
  hostname: hostname(),
@@ -6907,17 +7036,21 @@ function parseEncryptedDocument(raw) {
6907
7036
  if (!isRecord4(parsed)) {
6908
7037
  return null;
6909
7038
  }
6910
- if (parsed.version !== ENCRYPTION_VERSION) {
7039
+ const version = getOwnEntry2(parsed, "version");
7040
+ const iv = getOwnEntry2(parsed, "iv");
7041
+ const authTag = getOwnEntry2(parsed, "authTag");
7042
+ const ciphertext = getOwnEntry2(parsed, "ciphertext");
7043
+ if (version !== ENCRYPTION_VERSION) {
6911
7044
  return null;
6912
7045
  }
6913
- if (typeof parsed.iv !== "string" || typeof parsed.authTag !== "string" || typeof parsed.ciphertext !== "string") {
7046
+ if (typeof iv !== "string" || typeof authTag !== "string" || typeof ciphertext !== "string") {
6914
7047
  return null;
6915
7048
  }
6916
7049
  return {
6917
- version: parsed.version,
6918
- iv: parsed.iv,
6919
- authTag: parsed.authTag,
6920
- ciphertext: parsed.ciphertext
7050
+ version,
7051
+ iv,
7052
+ authTag,
7053
+ ciphertext
6921
7054
  };
6922
7055
  } catch {
6923
7056
  return null;
@@ -6926,9 +7059,17 @@ function parseEncryptedDocument(raw) {
6926
7059
  function isRecord4(value) {
6927
7060
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
6928
7061
  }
7062
+ function getOwnEntry2(record, key2) {
7063
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7064
+ }
6929
7065
  function isNotFoundError(error3) {
6930
7066
  return Boolean(
6931
- error3 && typeof error3 === "object" && "code" in error3 && error3.code === "ENOENT"
7067
+ error3 && typeof error3 === "object" && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "ENOENT"
7068
+ );
7069
+ }
7070
+ function isAlreadyExistsError(error3) {
7071
+ return Boolean(
7072
+ error3 && typeof error3 === "object" && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "EEXIST"
6932
7073
  );
6933
7074
  }
6934
7075
 
@@ -6950,8 +7091,8 @@ var KeychainStore = class {
6950
7091
  ["find-generic-password", "-s", this.service, "-a", this.account, "-w"],
6951
7092
  "read secret from macOS Keychain"
6952
7093
  );
6953
- if (result.exitCode === 0) {
6954
- return stripTrailingLineBreak(result.stdout);
7094
+ if (getCommandExitCode(result) === 0) {
7095
+ return stripTrailingLineBreak(getCommandOutput(result, "stdout"));
6955
7096
  }
6956
7097
  if (isKeychainEntryNotFound(result)) {
6957
7098
  return null;
@@ -6975,7 +7116,7 @@ var KeychainStore = class {
6975
7116
  "store secret in macOS Keychain",
6976
7117
  { stdin: value }
6977
7118
  );
6978
- if (result.exitCode !== 0) {
7119
+ if (getCommandExitCode(result) !== 0) {
6979
7120
  throw createSecurityCliFailure("store secret in macOS Keychain", result);
6980
7121
  }
6981
7122
  }
@@ -6984,7 +7125,7 @@ var KeychainStore = class {
6984
7125
  ["delete-generic-password", "-s", this.service, "-a", this.account],
6985
7126
  "delete secret from macOS Keychain"
6986
7127
  );
6987
- if (result.exitCode === 0 || isKeychainEntryNotFound(result)) {
7128
+ if (getCommandExitCode(result) === 0 || isKeychainEntryNotFound(result)) {
6988
7129
  return;
6989
7130
  }
6990
7131
  throw createSecurityCliFailure("delete secret from macOS Keychain", result);
@@ -7063,16 +7204,28 @@ function stripTrailingLineBreak(value) {
7063
7204
  return value;
7064
7205
  }
7065
7206
  function isKeychainEntryNotFound(result) {
7066
- return result.exitCode === KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE;
7207
+ return getCommandExitCode(result) === KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE;
7067
7208
  }
7068
7209
  function createSecurityCliFailure(operation, result) {
7069
- const details = result.stderr.trim() || result.stdout.trim();
7210
+ const exitCode = getCommandExitCode(result);
7211
+ const details = getCommandOutput(result, "stderr").trim() || getCommandOutput(result, "stdout").trim();
7070
7212
  if (details) {
7071
7213
  return new Error(
7072
- `Failed to ${operation}: security exited with code ${result.exitCode}: ${details}`
7214
+ `Failed to ${operation}: security exited with code ${exitCode}: ${details}`
7073
7215
  );
7074
7216
  }
7075
- return new Error(`Failed to ${operation}: security exited with code ${result.exitCode}`);
7217
+ return new Error(`Failed to ${operation}: security exited with code ${exitCode}`);
7218
+ }
7219
+ function getCommandExitCode(result) {
7220
+ const value = getOwnEntry3(result, "exitCode");
7221
+ return typeof value === "number" && Number.isInteger(value) ? value : 1;
7222
+ }
7223
+ function getCommandOutput(result, key2) {
7224
+ const value = getOwnEntry3(result, key2);
7225
+ return typeof value === "string" ? value : "";
7226
+ }
7227
+ function getOwnEntry3(record, key2) {
7228
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7076
7229
  }
7077
7230
 
7078
7231
  // ../auth-store/src/create-secret-store.ts
@@ -7105,7 +7258,7 @@ function createSecretStore(input) {
7105
7258
  }
7106
7259
  function resolveBackend(input) {
7107
7260
  const envVar = input.backendEnvVar ?? DEFAULT_BACKEND_ENV_VAR;
7108
- const configuredBackend = input.backend ?? input.env?.[envVar] ?? process.env[envVar];
7261
+ const configuredBackend = input.backend ?? getOwnEnvValue(input.env, envVar) ?? getOwnEnvValue(process.env, envVar);
7109
7262
  if (configuredBackend === "keychain") {
7110
7263
  return "keychain";
7111
7264
  }
@@ -7114,6 +7267,9 @@ function resolveBackend(input) {
7114
7267
  }
7115
7268
  throw new Error(`Unsupported auth store backend: ${configuredBackend}`);
7116
7269
  }
7270
+ function getOwnEnvValue(env, key2) {
7271
+ return env !== void 0 && Object.prototype.hasOwnProperty.call(env, key2) ? env[key2] : void 0;
7272
+ }
7117
7273
 
7118
7274
  // ../mcp-oauth/src/resource-indicator.ts
7119
7275
  function canonicalizeResourceIndicator(value) {
@@ -7167,8 +7323,13 @@ function createAuthStoreClientStore(options) {
7167
7323
  return null;
7168
7324
  }
7169
7325
  const parsed = JSON.parse(value);
7170
- if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && typeof parsed.clientId === "string") {
7171
- return parsed;
7326
+ const clientId = isObjectRecord(parsed) ? getOwnString(parsed, "clientId") : void 0;
7327
+ if (clientId !== void 0) {
7328
+ const client = { clientId };
7329
+ if (isObjectRecord(parsed) && Object.prototype.hasOwnProperty.call(parsed, "clientSecret")) {
7330
+ client.clientSecret = getOwnEntry4(parsed, "clientSecret");
7331
+ }
7332
+ return client;
7172
7333
  }
7173
7334
  throw new Error("Stored OAuth client must be a JSON object with clientId");
7174
7335
  },
@@ -7182,19 +7343,24 @@ function createAuthStoreClientStore(options) {
7182
7343
  }
7183
7344
  };
7184
7345
  }
7185
- function createNamedSecretStore(key2, options, defaults) {
7346
+ function createNamedSecretStore(key2, options, defaults2) {
7186
7347
  const hash = crypto.createHash("sha256").update(key2).digest("hex");
7187
- const parsedFilePath = options.fileStore?.filePath === void 0 ? null : path11.parse(options.fileStore.filePath);
7348
+ const configuredFilePath = options.fileStore?.filePath;
7349
+ const parsedFilePath = configuredFilePath === void 0 ? null : path11.parse(configuredFilePath);
7188
7350
  const fileStore = {
7189
7351
  ...options.fileStore,
7190
- salt: options.fileStore?.salt ?? defaults.salt,
7191
- defaultDirectory: parsedFilePath?.dir || options.fileStore?.defaultDirectory || defaults.directory,
7352
+ filePath: parsedFilePath === null ? void 0 : path11.join(
7353
+ parsedFilePath.dir,
7354
+ `${parsedFilePath.name}-${hash}${parsedFilePath.ext || ".enc"}`
7355
+ ),
7356
+ salt: options.fileStore?.salt ?? defaults2.salt,
7357
+ defaultDirectory: options.fileStore?.defaultDirectory || defaults2.directory,
7192
7358
  defaultFileName: parsedFilePath === null ? `${hash}.enc` : `${parsedFilePath.name}-${hash}${parsedFilePath.ext || ".enc"}`
7193
7359
  };
7194
7360
  const keychainStore = {
7195
7361
  ...options.keychainStore,
7196
- service: options.keychainStore?.service ?? defaults.service,
7197
- account: `${options.keychainStore?.account ?? defaults.accountPrefix}:${hash}`
7362
+ service: options.keychainStore?.service ?? defaults2.service,
7363
+ account: `${options.keychainStore?.account ?? defaults2.accountPrefix}:${hash}`
7198
7364
  };
7199
7365
  return createSecretStore({ ...options, fileStore, keychainStore }).store;
7200
7366
  }
@@ -7222,6 +7388,16 @@ function createIssuerSecretStore(issuer, options) {
7222
7388
  }
7223
7389
  );
7224
7390
  }
7391
+ function isObjectRecord(value) {
7392
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7393
+ }
7394
+ function getOwnEntry4(record, key2) {
7395
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7396
+ }
7397
+ function getOwnString(record, key2) {
7398
+ const value = getOwnEntry4(record, key2);
7399
+ return typeof value === "string" ? value : void 0;
7400
+ }
7225
7401
 
7226
7402
  // ../mcp-oauth/src/client/default-oauth-client-provider.ts
7227
7403
  import { URL as URL2 } from "node:url";
@@ -7247,17 +7423,30 @@ function parseAuthorizationState(value) {
7247
7423
  try {
7248
7424
  const decoded = Buffer.from(value, "base64url").toString("utf8");
7249
7425
  const parsed = JSON.parse(decoded);
7250
- if (parsed.v !== 1 || typeof parsed.n !== "string" || parsed.n.length === 0 || typeof parsed.i !== "string" || parsed.i.length === 0 || typeof parsed.r !== "boolean") {
7426
+ if (!isObjectRecord2(parsed)) {
7427
+ return null;
7428
+ }
7429
+ const version = getOwnEntry5(parsed, "v");
7430
+ const nonce = getOwnEntry5(parsed, "n");
7431
+ const issuer = getOwnEntry5(parsed, "i");
7432
+ const requireIssuer = getOwnEntry5(parsed, "r");
7433
+ if (version !== 1 || typeof nonce !== "string" || nonce.length === 0 || typeof issuer !== "string" || issuer.length === 0 || typeof requireIssuer !== "boolean") {
7251
7434
  return null;
7252
7435
  }
7253
7436
  return {
7254
- issuer: parsed.i,
7255
- requireIssuer: parsed.r
7437
+ issuer,
7438
+ requireIssuer
7256
7439
  };
7257
7440
  } catch {
7258
7441
  return null;
7259
7442
  }
7260
7443
  }
7444
+ function isObjectRecord2(value) {
7445
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7446
+ }
7447
+ function getOwnEntry5(record, key2) {
7448
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7449
+ }
7261
7450
 
7262
7451
  // ../mcp-oauth/src/client/loopback-authorization.ts
7263
7452
  async function createLoopbackAuthorizationSession(options = {}) {
@@ -7534,22 +7723,26 @@ async function requestTokens(input) {
7534
7723
  body: body.toString()
7535
7724
  });
7536
7725
  const payload = await readOAuthJsonObjectResponse(response);
7537
- if (typeof payload.access_token !== "string" || payload.access_token.trim().length === 0) {
7726
+ const accessToken = getOwnEntry6(payload, "access_token");
7727
+ if (typeof accessToken !== "string" || accessToken.trim().length === 0) {
7538
7728
  throw new Error("OAuth token response missing access_token");
7539
7729
  }
7540
- const tokenType = normalizeBearerTokenType(payload.token_type);
7730
+ const tokenType = normalizeBearerTokenType(getOwnEntry6(payload, "token_type"));
7541
7731
  if (tokenType === null) {
7542
7732
  throw new Error("OAuth token response missing token_type=Bearer");
7543
7733
  }
7544
- if (typeof payload.expires_in === "number" && Number.isFinite(payload.expires_in) && payload.expires_in < 0) {
7734
+ const expiresIn = getOwnEntry6(payload, "expires_in");
7735
+ if (typeof expiresIn === "number" && Number.isFinite(expiresIn) && expiresIn < 0) {
7545
7736
  throw new Error("OAuth token response has invalid expires_in");
7546
7737
  }
7738
+ const refreshToken = getOwnEntry6(payload, "refresh_token");
7739
+ const scope = getOwnEntry6(payload, "scope");
7547
7740
  return {
7548
- accessToken: payload.access_token,
7549
- refreshToken: typeof payload.refresh_token === "string" && payload.refresh_token.length > 0 ? payload.refresh_token : void 0,
7741
+ accessToken,
7742
+ refreshToken: typeof refreshToken === "string" && refreshToken.length > 0 ? refreshToken : void 0,
7550
7743
  tokenType,
7551
- expiresAt: typeof payload.expires_in === "number" && Number.isFinite(payload.expires_in) ? input.now() + payload.expires_in * 1e3 : null,
7552
- scope: typeof payload.scope === "string" && payload.scope.length > 0 ? payload.scope : void 0
7744
+ expiresAt: typeof expiresIn === "number" && Number.isFinite(expiresIn) ? input.now() + expiresIn * 1e3 : null,
7745
+ scope: typeof scope === "string" && scope.length > 0 ? scope : void 0
7553
7746
  };
7554
7747
  }
7555
7748
  async function readOAuthJsonObjectResponse(response) {
@@ -7576,12 +7769,18 @@ async function readOAuthJsonObjectResponse(response) {
7576
7769
  return record;
7577
7770
  }
7578
7771
  function readOAuthError(payload, fallbackError = "server_error") {
7772
+ const error3 = getOwnEntry6(payload, "error");
7773
+ const errorDescription = getOwnEntry6(payload, "error_description");
7774
+ const errorUri = getOwnEntry6(payload, "error_uri");
7579
7775
  return {
7580
- error: typeof payload.error === "string" ? payload.error : fallbackError,
7581
- error_description: typeof payload.error_description === "string" ? payload.error_description : void 0,
7582
- error_uri: typeof payload.error_uri === "string" ? payload.error_uri : void 0
7776
+ error: typeof error3 === "string" ? error3 : fallbackError,
7777
+ error_description: typeof errorDescription === "string" ? errorDescription : void 0,
7778
+ error_uri: typeof errorUri === "string" ? errorUri : void 0
7583
7779
  };
7584
7780
  }
7781
+ function getOwnEntry6(record, key2) {
7782
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
7783
+ }
7585
7784
  function createFallbackOAuthError(status) {
7586
7785
  const error3 = status === 503 ? "temporarily_unavailable" : "server_error";
7587
7786
  return new OAuthError({ error: error3 }, status);
@@ -7686,7 +7885,11 @@ function createDefaultOAuthClientProvider(options) {
7686
7885
  while (true) {
7687
7886
  try {
7688
7887
  refreshedTokens = await refreshAccessToken({
7689
- tokenEndpoint: discovery.authorizationServerMetadata.token_endpoint,
7888
+ tokenEndpoint: requireOwnString(
7889
+ discovery.authorizationServerMetadata,
7890
+ "token_endpoint",
7891
+ "Authorization server metadata"
7892
+ ),
7690
7893
  clientId: session.client.clientId,
7691
7894
  clientSecret: session.client.clientSecret,
7692
7895
  refreshToken: session.tokens.refreshToken,
@@ -7774,7 +7977,11 @@ function createDefaultOAuthClientProvider(options) {
7774
7977
  });
7775
7978
  const code = await loopback.waitForCode(authorizationUrl);
7776
7979
  const tokens = await exchangeAuthorizationCode({
7777
- tokenEndpoint: discovery.authorizationServerMetadata.token_endpoint,
7980
+ tokenEndpoint: requireOwnString(
7981
+ discovery.authorizationServerMetadata,
7982
+ "token_endpoint",
7983
+ "Authorization server metadata"
7984
+ ),
7778
7985
  clientId: resolvedClient.client.clientId,
7779
7986
  clientSecret: resolvedClient.client.clientSecret,
7780
7987
  code,
@@ -7827,7 +8034,10 @@ function createDefaultOAuthClientProvider(options) {
7827
8034
  }
7828
8035
  };
7829
8036
  }
7830
- const registrationEndpoint = discovery.authorizationServerMetadata.registration_endpoint;
8037
+ const registrationEndpoint = getOwnString2(
8038
+ discovery.authorizationServerMetadata,
8039
+ "registration_endpoint"
8040
+ );
7831
8041
  if (registrationEndpoint === void 0 && options.client.clientId !== void 0) {
7832
8042
  return {
7833
8043
  kind: "static",
@@ -7879,12 +8089,14 @@ function createDefaultOAuthClientProvider(options) {
7879
8089
  body: JSON.stringify(registrationBody)
7880
8090
  });
7881
8091
  const payload = await readOAuthJsonObjectResponse(response);
7882
- if (typeof payload.client_id !== "string" || payload.client_id.trim().length === 0) {
8092
+ const clientId = getOwnString2(payload, "client_id");
8093
+ if (clientId === void 0 || clientId.trim().length === 0) {
7883
8094
  throw new Error("OAuth client registration response missing client_id");
7884
8095
  }
8096
+ const clientSecret = getOwnString2(payload, "client_secret");
7885
8097
  const registeredClient = {
7886
- clientId: payload.client_id,
7887
- clientSecret: typeof payload.client_secret === "string" && payload.client_secret.length > 0 ? payload.client_secret : void 0
8098
+ clientId,
8099
+ clientSecret: clientSecret !== void 0 && clientSecret.length > 0 ? clientSecret : void 0
7888
8100
  };
7889
8101
  await saveRegisteredClient(discovery.authorizationServer, registeredClient);
7890
8102
  return {
@@ -7910,12 +8122,13 @@ function createDefaultOAuthClientProvider(options) {
7910
8122
  return null;
7911
8123
  }
7912
8124
  const client = await clientStore.load(issuer);
7913
- if (client !== null && !isUsableClient(client)) {
8125
+ const normalizedClient = client === null ? null : normalizeStoredClient(client);
8126
+ if (client !== null && normalizedClient === null) {
7914
8127
  await clientStore.clear(issuer);
7915
8128
  return null;
7916
8129
  }
7917
- registeredClients.set(issuer, client);
7918
- return client;
8130
+ registeredClients.set(issuer, normalizedClient);
8131
+ return normalizedClient;
7919
8132
  }
7920
8133
  async function saveRegisteredClient(issuer, client) {
7921
8134
  registeredClients.set(issuer, client);
@@ -7931,7 +8144,7 @@ function createDefaultOAuthClientProvider(options) {
7931
8144
  }
7932
8145
  }
7933
8146
  function isProviderOptions(options) {
7934
- return "provider" in options;
8147
+ return Object.prototype.hasOwnProperty.call(options, "provider");
7935
8148
  }
7936
8149
  function isExpired(tokens, now) {
7937
8150
  return tokens.expiresAt !== null && tokens.expiresAt <= now();
@@ -7947,7 +8160,14 @@ function resolveDiscovery(discovery, session) {
7947
8160
  return void 0;
7948
8161
  }
7949
8162
  const metadata = session.discovery.authorizationServerMetadata;
7950
- 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")) {
8163
+ const issuer = getOwnString2(metadata, "issuer");
8164
+ const authorizationEndpoint = getOwnString2(metadata, "authorization_endpoint");
8165
+ const tokenEndpoint = getOwnString2(metadata, "token_endpoint");
8166
+ const codeChallengeMethodsSupported = getOwnStringArray(
8167
+ metadata,
8168
+ "code_challenge_methods_supported"
8169
+ );
8170
+ if (issuer === void 0 || authorizationEndpoint === void 0 || tokenEndpoint === void 0 || codeChallengeMethodsSupported === void 0 || !codeChallengeMethodsSupported.includes("S256")) {
7951
8171
  return void 0;
7952
8172
  }
7953
8173
  return {
@@ -7971,29 +8191,94 @@ function normalizeLoadedSession(session) {
7971
8191
  if (session === null) {
7972
8192
  return null;
7973
8193
  }
7974
- if (!isUsableClient(session.client)) {
8194
+ const client = normalizeStoredClient(getOwnEntry7(session, "client"));
8195
+ if (client === null) {
7975
8196
  return { ...session, client: { clientId: "" }, tokens: void 0 };
7976
8197
  }
7977
- return isUsableTokens(session.tokens) ? session : { ...session, tokens: void 0 };
8198
+ return {
8199
+ ...session,
8200
+ client,
8201
+ tokens: normalizeStoredTokens(getOwnEntry7(session, "tokens"))
8202
+ };
7978
8203
  }
7979
- function isUsableClient(client) {
7980
- return typeof client.clientId === "string" && client.clientId.trim().length > 0 && (client.clientSecret === void 0 || typeof client.clientSecret === "string" && client.clientSecret.trim().length > 0);
8204
+ function normalizeStoredClient(value) {
8205
+ if (!isObjectRecord3(value)) {
8206
+ return null;
8207
+ }
8208
+ const clientId = getOwnString2(value, "clientId");
8209
+ if (clientId === void 0 || clientId.trim().length === 0) {
8210
+ return null;
8211
+ }
8212
+ const clientSecret = getOwnEntry7(value, "clientSecret");
8213
+ if (clientSecret === void 0) {
8214
+ return { clientId };
8215
+ }
8216
+ if (typeof clientSecret !== "string" || clientSecret.trim().length === 0) {
8217
+ return null;
8218
+ }
8219
+ return { clientId, clientSecret };
7981
8220
  }
7982
- function isUsableTokens(tokens) {
7983
- if (tokens === void 0) {
7984
- return true;
8221
+ function normalizeStoredTokens(value) {
8222
+ if (value === void 0 || !isObjectRecord3(value)) {
8223
+ return void 0;
8224
+ }
8225
+ const accessToken = getOwnString2(value, "accessToken");
8226
+ const tokenType = getOwnString2(value, "tokenType");
8227
+ const expiresAt = getOwnEntry7(value, "expiresAt");
8228
+ const refreshToken = getOwnEntry7(value, "refreshToken");
8229
+ const scope = getOwnString2(value, "scope");
8230
+ const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken : void 0;
8231
+ 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)) {
8232
+ return void 0;
7985
8233
  }
7986
- 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);
8234
+ return {
8235
+ accessToken,
8236
+ tokenType,
8237
+ expiresAt,
8238
+ ...normalizedRefreshToken === void 0 ? {} : { refreshToken: normalizedRefreshToken },
8239
+ ...scope === void 0 || scope.length === 0 ? {} : { scope }
8240
+ };
7987
8241
  }
7988
8242
  function getClientMetadata(client) {
7989
8243
  return client.metadata;
7990
8244
  }
8245
+ function getOwnEntry7(record, key2) {
8246
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
8247
+ }
8248
+ function isObjectRecord3(value) {
8249
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8250
+ }
8251
+ function getOwnString2(record, key2) {
8252
+ const value = getOwnEntry7(record, key2);
8253
+ return typeof value === "string" ? value : void 0;
8254
+ }
8255
+ function requireOwnString(record, key2, label) {
8256
+ const value = getOwnString2(record, key2);
8257
+ if (value === void 0) {
8258
+ throw new Error(`${label} is missing ${key2}`);
8259
+ }
8260
+ return value;
8261
+ }
8262
+ function getOwnStringArray(record, key2) {
8263
+ const value = getOwnEntry7(record, key2);
8264
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : void 0;
8265
+ }
7991
8266
  function buildAuthorizationUrl(input) {
7992
- const url = new URL2(input.metadata.authorization_endpoint);
8267
+ const authorizationEndpoint = requireOwnString(
8268
+ input.metadata,
8269
+ "authorization_endpoint",
8270
+ "Authorization server metadata"
8271
+ );
8272
+ const issuer = requireOwnString(
8273
+ input.metadata,
8274
+ "issuer",
8275
+ "Authorization server metadata"
8276
+ );
8277
+ const url = new URL2(authorizationEndpoint);
7993
8278
  const resource = canonicalizeResourceIndicator(input.resource);
7994
8279
  const state = createAuthorizationState({
7995
- issuer: input.metadata.issuer,
7996
- requireIssuer: input.metadata.authorization_response_iss_parameter_supported === true
8280
+ issuer,
8281
+ requireIssuer: getOwnEntry7(input.metadata, "authorization_response_iss_parameter_supported") === true
7997
8282
  });
7998
8283
  url.searchParams.set("response_type", "code");
7999
8284
  url.searchParams.set("client_id", input.clientId);
@@ -8008,7 +8293,7 @@ function buildAuthorizationUrl(input) {
8008
8293
  return url.toString();
8009
8294
  }
8010
8295
  function assertS256PkceSupport(metadata) {
8011
- if (!metadata.code_challenge_methods_supported.includes("S256")) {
8296
+ if (!getOwnStringArray(metadata, "code_challenge_methods_supported")?.includes("S256")) {
8012
8297
  throw new Error(
8013
8298
  "Authorization server metadata must advertise code_challenge_methods_supported including S256"
8014
8299
  );
@@ -8032,13 +8317,24 @@ function assertSecureUrl(value, label) {
8032
8317
  throw new Error(`${label} must use https unless it targets a loopback host`);
8033
8318
  }
8034
8319
  function assertSecureOAuthFlowEndpoints(metadata) {
8035
- assertNoAccessTokenInUrl(metadata.authorization_endpoint, "Authorization endpoint");
8036
- assertNoAccessTokenInUrl(metadata.token_endpoint, "Token endpoint");
8037
- assertSecureUrl(metadata.authorization_endpoint, "Authorization endpoint");
8038
- assertSecureUrl(metadata.token_endpoint, "Token endpoint");
8039
- if (metadata.registration_endpoint !== void 0) {
8040
- assertNoAccessTokenInUrl(metadata.registration_endpoint, "Registration endpoint");
8041
- assertSecureUrl(metadata.registration_endpoint, "Registration endpoint");
8320
+ const authorizationEndpoint = requireOwnString(
8321
+ metadata,
8322
+ "authorization_endpoint",
8323
+ "Authorization server metadata"
8324
+ );
8325
+ const tokenEndpoint = requireOwnString(
8326
+ metadata,
8327
+ "token_endpoint",
8328
+ "Authorization server metadata"
8329
+ );
8330
+ const registrationEndpoint = getOwnString2(metadata, "registration_endpoint");
8331
+ assertNoAccessTokenInUrl(authorizationEndpoint, "Authorization endpoint");
8332
+ assertNoAccessTokenInUrl(tokenEndpoint, "Token endpoint");
8333
+ assertSecureUrl(authorizationEndpoint, "Authorization endpoint");
8334
+ assertSecureUrl(tokenEndpoint, "Token endpoint");
8335
+ if (registrationEndpoint !== void 0) {
8336
+ assertNoAccessTokenInUrl(registrationEndpoint, "Registration endpoint");
8337
+ assertSecureUrl(registrationEndpoint, "Registration endpoint");
8042
8338
  }
8043
8339
  }
8044
8340
  function assertNoAccessTokenInUrl(value, label) {
@@ -8061,17 +8357,21 @@ function buildClientRegistrationBody(metadata, redirectUri) {
8061
8357
  response_types: ["code"],
8062
8358
  token_endpoint_auth_method: "none"
8063
8359
  };
8064
- if (metadata?.clientName !== void 0 && metadata.clientName.length > 0) {
8065
- body.client_name = metadata.clientName;
8360
+ const clientName = metadata === void 0 ? void 0 : getOwnString2(metadata, "clientName");
8361
+ const scope = metadata === void 0 ? void 0 : getOwnString2(metadata, "scope");
8362
+ const softwareId = metadata === void 0 ? void 0 : getOwnString2(metadata, "softwareId");
8363
+ const softwareVersion = metadata === void 0 ? void 0 : getOwnString2(metadata, "softwareVersion");
8364
+ if (clientName !== void 0 && clientName.length > 0) {
8365
+ body.client_name = clientName;
8066
8366
  }
8067
- if (metadata?.scope !== void 0 && metadata.scope.length > 0) {
8068
- body.scope = metadata.scope;
8367
+ if (scope !== void 0 && scope.length > 0) {
8368
+ body.scope = scope;
8069
8369
  }
8070
- if (metadata?.softwareId !== void 0 && metadata.softwareId.length > 0) {
8071
- body.software_id = metadata.softwareId;
8370
+ if (softwareId !== void 0 && softwareId.length > 0) {
8371
+ body.software_id = softwareId;
8072
8372
  }
8073
- if (metadata?.softwareVersion !== void 0 && metadata.softwareVersion.length > 0) {
8074
- body.software_version = metadata.softwareVersion;
8373
+ if (softwareVersion !== void 0 && softwareVersion.length > 0) {
8374
+ body.software_version = softwareVersion;
8075
8375
  }
8076
8376
  return body;
8077
8377
  }
@@ -8107,7 +8407,7 @@ import {
8107
8407
  function defaultOAuthMetadataFetch(input, init) {
8108
8408
  return fetch(input, init);
8109
8409
  }
8110
- function isObjectRecord(value) {
8410
+ function isObjectRecord4(value) {
8111
8411
  return typeof value === "object" && value !== null && !Array.isArray(value);
8112
8412
  }
8113
8413
  function isStringArray(value) {
@@ -8130,7 +8430,7 @@ function assertSecureUrl2(url, label) {
8130
8430
  throw new Error(`${label} must use https unless it targets a loopback host`);
8131
8431
  }
8132
8432
  function validateProtectedResourceMetadata(value, resourceUrl) {
8133
- if (!isObjectRecord(value)) {
8433
+ if (!isObjectRecord4(value)) {
8134
8434
  throw new Error("Protected resource metadata must be a JSON object");
8135
8435
  }
8136
8436
  if (typeof value.resource !== "string" || value.resource.length === 0) {
@@ -8153,7 +8453,7 @@ function validateProtectedResourceMetadata(value, resourceUrl) {
8153
8453
  };
8154
8454
  }
8155
8455
  function validateAuthorizationServerMetadata(value, issuer) {
8156
- if (!isObjectRecord(value)) {
8456
+ if (!isObjectRecord4(value)) {
8157
8457
  throw new Error("Authorization server metadata must be a JSON object");
8158
8458
  }
8159
8459
  if (typeof value.issuer !== "string" || value.issuer.length === 0) {
@@ -8606,7 +8906,7 @@ var McpClient = class {
8606
8906
  await onPromptsChanged();
8607
8907
  });
8608
8908
  messageLayer.onNotification("notifications/message", async (params17) => {
8609
- if (onLog === void 0 || !isObjectRecord2(params17) || !isLogLevel(params17.level)) {
8909
+ if (onLog === void 0 || !isObjectRecord5(params17) || !isLogLevel(params17.level)) {
8610
8910
  return;
8611
8911
  }
8612
8912
  if (!hasOwn(params17, "data")) {
@@ -8625,7 +8925,7 @@ var McpClient = class {
8625
8925
  await onLog(message2);
8626
8926
  });
8627
8927
  messageLayer.onNotification("notifications/progress", async (params17) => {
8628
- if (onProgress === void 0 || !isObjectRecord2(params17)) {
8928
+ if (onProgress === void 0 || !isObjectRecord5(params17)) {
8629
8929
  return;
8630
8930
  }
8631
8931
  const { progressToken, progress } = params17;
@@ -8794,6 +9094,9 @@ var McpClient = class {
8794
9094
  const abortPromise = new Promise((_, reject) => {
8795
9095
  const rejectWithAbortReason = () => {
8796
9096
  sendCancellationNotification();
9097
+ if (requestId !== void 0) {
9098
+ messageLayer.cancelRequest(requestId, signal.reason);
9099
+ }
8797
9100
  reject(signal.reason);
8798
9101
  };
8799
9102
  abortListener = rejectWithAbortReason;
@@ -8968,11 +9271,13 @@ var StdioTransport = class _StdioTransport {
8968
9271
  const child = this.child;
8969
9272
  this.readable = child.stdout;
8970
9273
  this.writable = child.stdin;
9274
+ const stderrDecoder = new TextDecoder();
8971
9275
  child.stderr.on("data", (chunk) => {
8972
- this.stderrOutput += chunkToString(chunk);
8973
- if (this.stderrOutput.length > _StdioTransport.STDERR_MAX_LENGTH) {
8974
- this.stderrOutput = this.stderrOutput.slice(-_StdioTransport.STDERR_MAX_LENGTH);
8975
- }
9276
+ const decoded = chunk instanceof Uint8Array ? stderrDecoder.decode(chunk, { stream: true }) : `${stderrDecoder.decode()}${String(chunk)}`;
9277
+ this.appendStderrOutput(decoded);
9278
+ });
9279
+ child.stderr.once("end", () => {
9280
+ this.appendStderrOutput(stderrDecoder.decode());
8976
9281
  });
8977
9282
  this.closed = new Promise((resolve) => {
8978
9283
  let settled = false;
@@ -9012,6 +9317,15 @@ var StdioTransport = class _StdioTransport {
9012
9317
  getStderrOutput() {
9013
9318
  return this.stderrOutput;
9014
9319
  }
9320
+ appendStderrOutput(chunk) {
9321
+ if (chunk.length === 0) {
9322
+ return;
9323
+ }
9324
+ this.stderrOutput += chunk;
9325
+ if (this.stderrOutput.length > _StdioTransport.STDERR_MAX_LENGTH) {
9326
+ this.stderrOutput = this.stderrOutput.slice(-_StdioTransport.STDERR_MAX_LENGTH);
9327
+ }
9328
+ }
9015
9329
  dispose(reason = new Error("Stdio transport disposed")) {
9016
9330
  void reason;
9017
9331
  if (this.disposed) {
@@ -9419,15 +9733,6 @@ function serializeJsonRpcMessage(message2) {
9419
9733
  return `${JSON.stringify(message2)}
9420
9734
  `;
9421
9735
  }
9422
- function chunkToString(chunk) {
9423
- if (typeof chunk === "string") {
9424
- return chunk;
9425
- }
9426
- if (chunk instanceof Uint8Array) {
9427
- return Buffer.from(chunk).toString("utf8");
9428
- }
9429
- return String(chunk);
9430
- }
9431
9736
  function normalizeLine(line) {
9432
9737
  return line.endsWith("\r") ? line.slice(0, -1) : line;
9433
9738
  }
@@ -9617,6 +9922,16 @@ var JsonRpcMessageLayer = class {
9617
9922
  }
9618
9923
  });
9619
9924
  }
9925
+ cancelRequest(requestId, reason) {
9926
+ const pending = this.pendingRequests.get(requestId);
9927
+ if (pending === void 0) {
9928
+ return false;
9929
+ }
9930
+ this.pendingRequests.delete(requestId);
9931
+ clearTimeout(pending.timeout);
9932
+ pending.reject(reason);
9933
+ return true;
9934
+ }
9620
9935
  dispose(reason = new Error("JSON-RPC message layer disposed")) {
9621
9936
  if (this.disposedError !== void 0) {
9622
9937
  return;
@@ -9811,7 +10126,7 @@ var JsonRpcMessageLayer = class {
9811
10126
  })();
9812
10127
  }
9813
10128
  handleCancellationNotification(params17) {
9814
- if (!isObjectRecord2(params17)) {
10129
+ if (!isObjectRecord5(params17)) {
9815
10130
  return;
9816
10131
  }
9817
10132
  const requestId = params17.requestId;
@@ -9826,34 +10141,34 @@ var JsonRpcMessageLayer = class {
9826
10141
  this.activeIncomingRequests.delete(requestId);
9827
10142
  }
9828
10143
  };
9829
- function isObjectRecord2(value) {
10144
+ function isObjectRecord5(value) {
9830
10145
  return typeof value === "object" && value !== null && !Array.isArray(value);
9831
10146
  }
9832
10147
  function isInitializeResult(value) {
9833
- if (!isObjectRecord2(value) || typeof value.protocolVersion !== "string") {
10148
+ if (!isObjectRecord5(value) || typeof value.protocolVersion !== "string") {
9834
10149
  return false;
9835
10150
  }
9836
10151
  if (!isServerCapabilities(value.capabilities)) {
9837
10152
  return false;
9838
10153
  }
9839
- if (!isObjectRecord2(value.serverInfo) || typeof value.serverInfo.name !== "string" || value.serverInfo.name.length === 0 || typeof value.serverInfo.version !== "string" || value.serverInfo.version.length === 0) {
10154
+ if (!isObjectRecord5(value.serverInfo) || typeof value.serverInfo.name !== "string" || value.serverInfo.name.length === 0 || typeof value.serverInfo.version !== "string" || value.serverInfo.version.length === 0) {
9840
10155
  return false;
9841
10156
  }
9842
10157
  return value.instructions === void 0 || typeof value.instructions === "string";
9843
10158
  }
9844
10159
  function isServerCapabilities(value) {
9845
- if (!isObjectRecord2(value)) {
10160
+ if (!isObjectRecord5(value)) {
9846
10161
  return false;
9847
10162
  }
9848
10163
  for (const capability of ["prompts", "resources", "tools", "logging", "completions", "experimental"]) {
9849
- if (value[capability] !== void 0 && !isObjectRecord2(value[capability])) {
10164
+ if (value[capability] !== void 0 && !isObjectRecord5(value[capability])) {
9850
10165
  return false;
9851
10166
  }
9852
10167
  }
9853
10168
  return true;
9854
10169
  }
9855
10170
  function isCallToolResult(value) {
9856
- if (!isObjectRecord2(value) || !Array.isArray(value.content)) {
10171
+ if (!isObjectRecord5(value) || !Array.isArray(value.content)) {
9857
10172
  return false;
9858
10173
  }
9859
10174
  if (value.isError !== void 0 && typeof value.isError !== "boolean") {
@@ -9862,10 +10177,10 @@ function isCallToolResult(value) {
9862
10177
  return value.content.every(isContentItem);
9863
10178
  }
9864
10179
  function isToolsListResult(value) {
9865
- return isObjectRecord2(value) && Array.isArray(value.tools) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
10180
+ return isObjectRecord5(value) && Array.isArray(value.tools) && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
9866
10181
  }
9867
10182
  function isContentItem(value) {
9868
- if (!isObjectRecord2(value)) {
10183
+ if (!isObjectRecord5(value)) {
9869
10184
  return false;
9870
10185
  }
9871
10186
  if (value.type === "text") {
@@ -9874,7 +10189,7 @@ function isContentItem(value) {
9874
10189
  if (value.type === "image" || value.type === "audio") {
9875
10190
  return typeof value.data === "string" && typeof value.mimeType === "string";
9876
10191
  }
9877
- if (value.type !== "resource" || !isObjectRecord2(value.resource)) {
10192
+ if (value.type !== "resource" || !isObjectRecord5(value.resource)) {
9878
10193
  return false;
9879
10194
  }
9880
10195
  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");
@@ -9898,7 +10213,7 @@ function invalidRequest() {
9898
10213
  return new McpError(ERROR_INVALID_REQUEST, "Invalid Request");
9899
10214
  }
9900
10215
  function isJsonRpcErrorObject(value) {
9901
- if (!isObjectRecord2(value)) {
10216
+ if (!isObjectRecord5(value)) {
9902
10217
  return false;
9903
10218
  }
9904
10219
  if (typeof value.code !== "number" || typeof value.message !== "string") {
@@ -9907,7 +10222,7 @@ function isJsonRpcErrorObject(value) {
9907
10222
  return value.data === void 0 || hasOwn(value, "data");
9908
10223
  }
9909
10224
  function parseJsonRpcPayload(parsed) {
9910
- if (!isObjectRecord2(parsed)) {
10225
+ if (!isObjectRecord5(parsed)) {
9911
10226
  return {
9912
10227
  type: "invalid",
9913
10228
  id: null,
@@ -10234,7 +10549,11 @@ function convertObjectSchema(schema, root, options) {
10234
10549
  "properties",
10235
10550
  key2
10236
10551
  ]);
10237
- shape[key2] = requiredKeys.has(key2) ? convertedProperty : S.Optional(convertedProperty);
10552
+ setOwnShapeProperty(
10553
+ shape,
10554
+ key2,
10555
+ requiredKeys.has(key2) ? convertedProperty : S.Optional(convertedProperty)
10556
+ );
10238
10557
  }
10239
10558
  return applyMetadata(
10240
10559
  S.Object(shape, {
@@ -10246,6 +10565,14 @@ function convertObjectSchema(schema, root, options) {
10246
10565
  }
10247
10566
  );
10248
10567
  }
10568
+ function setOwnShapeProperty(shape, key2, value) {
10569
+ Object.defineProperty(shape, key2, {
10570
+ configurable: true,
10571
+ enumerable: true,
10572
+ writable: true,
10573
+ value
10574
+ });
10575
+ }
10249
10576
  function createCommonOptions(schema, nullable, defaultValue) {
10250
10577
  return {
10251
10578
  ...schema.description === void 0 ? {} : { description: schema.description },
@@ -10496,6 +10823,9 @@ function resolveLocalRef(root, ref) {
10496
10823
  if (!isPlainObject(current)) {
10497
10824
  return void 0;
10498
10825
  }
10826
+ if (!Object.prototype.hasOwnProperty.call(current, segment)) {
10827
+ return void 0;
10828
+ }
10499
10829
  current = current[segment];
10500
10830
  }
10501
10831
  return isPlainObject(current) ? current : void 0;
@@ -10685,10 +11015,10 @@ function validateRenameMap2(name, tools, rename5) {
10685
11015
  }
10686
11016
  }
10687
11017
  }
10688
- function createConnection(name, config) {
11018
+ function createConnection(name, config2) {
10689
11019
  const connection = {
10690
11020
  name,
10691
- config,
11021
+ config: config2,
10692
11022
  async dispose() {
10693
11023
  shutdownDisposers.delete(connection.dispose);
10694
11024
  connection.connecting = void 0;
@@ -10744,24 +11074,42 @@ async function readCache(cachePath) {
10744
11074
  }
10745
11075
  async function writeCache(cachePath, cache) {
10746
11076
  const directory = path12.dirname(cachePath);
10747
- const tempPath = `${cachePath}.tmp-${randomUUID2()}`;
11077
+ const tempPath = `${cachePath}.tmp-${randomUUID4()}`;
11078
+ let tempCreated = false;
10748
11079
  await assertCachePathHasNoSymlinks(cachePath);
10749
11080
  await assertCachePathHasNoSymlinks(tempPath);
10750
11081
  await mkdir(directory, { recursive: true });
10751
11082
  await assertCachePathHasNoSymlinks(directory);
10752
- await writeFile3(tempPath, `${JSON.stringify(cache, null, 2)}
10753
- `);
10754
- await assertCachePathHasNoSymlinks(tempPath);
10755
- await assertCachePathHasNoSymlinks(cachePath);
10756
- await rename2(tempPath, cachePath);
11083
+ try {
11084
+ await writeFile3(tempPath, `${JSON.stringify(cache, null, 2)}
11085
+ `, {
11086
+ encoding: "utf8",
11087
+ flag: "wx"
11088
+ });
11089
+ tempCreated = true;
11090
+ await assertCachePathHasNoSymlinks(tempPath);
11091
+ await assertCachePathHasNoSymlinks(cachePath);
11092
+ await rename2(tempPath, cachePath);
11093
+ tempCreated = false;
11094
+ } catch (error3) {
11095
+ if (tempCreated || !isAlreadyExistsError2(error3)) {
11096
+ await unlink2(tempPath).catch(() => void 0);
11097
+ }
11098
+ throw error3;
11099
+ }
11100
+ }
11101
+ function isAlreadyExistsError2(error3) {
11102
+ return Boolean(
11103
+ error3 && typeof error3 === "object" && error3.code === "EEXIST"
11104
+ );
10757
11105
  }
10758
- async function fetchCache(name, config) {
11106
+ async function fetchCache(name, config2) {
10759
11107
  const logger2 = createLogger((message2) => {
10760
11108
  process.stderr.write(`${message2}
10761
11109
  `);
10762
11110
  });
10763
11111
  logger2.info(`MCP ${name}: connecting`);
10764
- const client = await dialUpstream(name, config);
11112
+ const client = await dialUpstream(name, config2);
10765
11113
  try {
10766
11114
  logger2.info(`MCP ${name}: listing tools`);
10767
11115
  const tools = [];
@@ -10780,7 +11128,7 @@ async function fetchCache(name, config) {
10780
11128
  $schema: MCP_PROXY_SCHEMA_URL,
10781
11129
  version: 1,
10782
11130
  upstream,
10783
- configFingerprint: fingerprintMcpServerConfig(config),
11131
+ configFingerprint: fingerprintMcpServerConfig(config2),
10784
11132
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
10785
11133
  tools
10786
11134
  };
@@ -10850,8 +11198,8 @@ function isRefreshRequested(name, refresh) {
10850
11198
  }
10851
11199
  async function resolveSingleProxy(group, options) {
10852
11200
  const internal = getInternalGroupConfig2(group);
10853
- const config = internal.mcp;
10854
- if (config === void 0) {
11201
+ const config2 = internal.mcp;
11202
+ if (config2 === void 0) {
10855
11203
  return;
10856
11204
  }
10857
11205
  const name = group.name;
@@ -10861,21 +11209,21 @@ async function resolveSingleProxy(group, options) {
10861
11209
  let cache;
10862
11210
  let shouldWriteCache = false;
10863
11211
  if (isRefreshRequested(name, refresh)) {
10864
- cache = await fetchCache(name, config);
11212
+ cache = await fetchCache(name, config2);
10865
11213
  shouldWriteCache = true;
10866
11214
  } else {
10867
11215
  const storedCache = await readCache(cachePath);
10868
- if (storedCache && cacheMatchesConfig(storedCache, config)) {
11216
+ if (storedCache && cacheMatchesConfig(storedCache, config2)) {
10869
11217
  cache = storedCache;
10870
11218
  } else {
10871
- cache = await fetchCache(name, config);
11219
+ cache = await fetchCache(name, config2);
10872
11220
  shouldWriteCache = true;
10873
11221
  }
10874
11222
  }
10875
11223
  const tools = filterAllowlistedTools(cache.tools, internal.tools);
10876
11224
  validateRenameMap2(name, tools, internal.rename);
10877
11225
  const previousConnection = getProxyConnection(group);
10878
- const nextConnection = createConnection(name, config);
11226
+ const nextConnection = createConnection(name, config2);
10879
11227
  try {
10880
11228
  replaceProxyChildrenSafely(group, tools, internal.rename, nextConnection);
10881
11229
  if (shouldWriteCache) {
@@ -10900,11 +11248,11 @@ async function resolveSingleProxy(group, options) {
10900
11248
  );
10901
11249
  }
10902
11250
  }
10903
- function cacheMatchesConfig(cache, config) {
10904
- return cache.configFingerprint === fingerprintMcpServerConfig(config);
11251
+ function cacheMatchesConfig(cache, config2) {
11252
+ return cache.configFingerprint === fingerprintMcpServerConfig(config2);
10905
11253
  }
10906
- function fingerprintMcpServerConfig(config) {
10907
- return createHash3("sha256").update(JSON.stringify(config)).digest("hex");
11254
+ function fingerprintMcpServerConfig(config2) {
11255
+ return createHash3("sha256").update(JSON.stringify(config2)).digest("hex");
10908
11256
  }
10909
11257
  function collectProxyGroups(root) {
10910
11258
  const groups = [];
@@ -10982,20 +11330,20 @@ function parseRefreshEnv(value) {
10982
11330
  const names = trimmed.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
10983
11331
  return names.length === 0 ? void 0 : new Set(names);
10984
11332
  }
10985
- async function dialUpstream(name, config) {
11333
+ async function dialUpstream(name, config2) {
10986
11334
  const client = new McpClient({
10987
11335
  clientInfo: {
10988
11336
  name: `${DEFAULT_CLIENT_INFO.name}-${name}`,
10989
11337
  version: DEFAULT_CLIENT_INFO.version
10990
11338
  }
10991
11339
  });
10992
- const transport = config.transport === "stdio" ? new StdioTransport({
10993
- command: config.command,
10994
- ...config.args === void 0 ? {} : { args: config.args },
10995
- ...config.env === void 0 ? {} : { env: config.env }
11340
+ const transport = config2.transport === "stdio" ? new StdioTransport({
11341
+ command: config2.command,
11342
+ ...config2.args === void 0 ? {} : { args: config2.args },
11343
+ ...config2.env === void 0 ? {} : { env: config2.env }
10996
11344
  }) : new HttpTransport({
10997
- url: config.url,
10998
- ...config.headers === void 0 ? {} : { headers: config.headers }
11345
+ url: config2.url,
11346
+ ...config2.headers === void 0 ? {} : { headers: config2.headers }
10999
11347
  });
11000
11348
  await client.connect(transport);
11001
11349
  return client;
@@ -11005,10 +11353,82 @@ async function resolveMcpProxies(root, options = {}) {
11005
11353
  await Promise.all(groups.map((group) => resolveSingleProxy(group, options)));
11006
11354
  }
11007
11355
 
11356
+ // ../toolcraft/src/redaction.ts
11357
+ var REDACTED_VALUE = "<redacted>";
11358
+ var SENSITIVE_NAME_PARTS = ["password", "token", "apikey", "secret"];
11359
+ var AUTHORIZATION_HEADER_NAMES = /* @__PURE__ */ new Set(["authorization", "proxyauthorization"]);
11360
+ var SECRET_HEADER_NAMES = /* @__PURE__ */ new Set(["cookie", "setcookie"]);
11361
+ function isPlainObject2(value) {
11362
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11363
+ }
11364
+ function normalizeName(name) {
11365
+ return name.toLowerCase().replace(/[^a-z0-9]/g, "");
11366
+ }
11367
+ function isSensitiveName(name) {
11368
+ const normalized = normalizeName(name);
11369
+ return SENSITIVE_NAME_PARTS.some((candidate) => normalized.includes(candidate));
11370
+ }
11371
+ function redactSecretLikeFieldsValue(value, name, seen) {
11372
+ if (name.length > 0 && isSensitiveName(name)) {
11373
+ return REDACTED_VALUE;
11374
+ }
11375
+ if (Array.isArray(value)) {
11376
+ if (seen.has(value)) {
11377
+ return "[Circular]";
11378
+ }
11379
+ seen.add(value);
11380
+ return value.map((entry) => redactSecretLikeFieldsValue(entry, name, seen));
11381
+ }
11382
+ if (isPlainObject2(value)) {
11383
+ if (seen.has(value)) {
11384
+ return "[Circular]";
11385
+ }
11386
+ seen.add(value);
11387
+ return Object.fromEntries(
11388
+ Object.entries(value).map(([key2, entry]) => [
11389
+ key2,
11390
+ redactSecretLikeFieldsValue(entry, key2, seen)
11391
+ ])
11392
+ );
11393
+ }
11394
+ return value;
11395
+ }
11396
+ function redactSecretLikeFields(value, name = "") {
11397
+ return redactSecretLikeFieldsValue(value, name, /* @__PURE__ */ new WeakSet());
11398
+ }
11399
+ function parseJsonObjectOrArray(value) {
11400
+ const trimmed = value.trim();
11401
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
11402
+ return void 0;
11403
+ }
11404
+ try {
11405
+ const parsed = JSON.parse(trimmed);
11406
+ return isPlainObject2(parsed) || Array.isArray(parsed) ? parsed : void 0;
11407
+ } catch {
11408
+ return void 0;
11409
+ }
11410
+ }
11411
+ function redactHttpBody(body) {
11412
+ if (typeof body === "string") {
11413
+ const parsed = parseJsonObjectOrArray(body);
11414
+ return parsed === void 0 ? body : redactSecretLikeFields(parsed);
11415
+ }
11416
+ return redactSecretLikeFields(body);
11417
+ }
11418
+ function redactHttpHeaderValue(name, value) {
11419
+ const normalized = normalizeName(name);
11420
+ if (AUTHORIZATION_HEADER_NAMES.has(normalized)) {
11421
+ return "Bearer ****";
11422
+ }
11423
+ if (SECRET_HEADER_NAMES.has(normalized) || isSensitiveName(name)) {
11424
+ return REDACTED_VALUE;
11425
+ }
11426
+ return value;
11427
+ }
11428
+
11008
11429
  // ../toolcraft/src/error-report.ts
11009
11430
  var ERROR_REPORTS_ENV = "TOOLCRAFT_ERROR_REPORTS";
11010
- var DEFAULT_SENSITIVE_NAMES = ["password", "token", "apikey", "secret"];
11011
- function isPlainObject2(value) {
11431
+ function isPlainObject3(value) {
11012
11432
  return typeof value === "object" && value !== null && !Array.isArray(value);
11013
11433
  }
11014
11434
  function unwrapOptional(schema) {
@@ -11018,7 +11438,7 @@ function unwrapOptional(schema) {
11018
11438
  return schema;
11019
11439
  }
11020
11440
  function hasHttpContext(error3) {
11021
- return error3 instanceof Error && error3.name === "HttpError" && isPlainObject2(error3.request) && isPlainObject2(error3.response);
11441
+ return error3 instanceof Error && error3.name === "HttpError" && isPlainObject3(error3.request) && isPlainObject3(error3.response);
11022
11442
  }
11023
11443
  function isSkippedError(error3) {
11024
11444
  if (error3 instanceof ApprovalDeclinedError) {
@@ -11055,8 +11475,8 @@ async function assertReportDirWithinProject(projectRoot, reportDir) {
11055
11475
  throw new Error("Error report directory resolves outside project root.");
11056
11476
  }
11057
11477
  const [canonicalProjectRoot, canonicalReportDir] = await Promise.all([
11058
- realpath(projectRoot),
11059
- realpath(reportDir)
11478
+ realpath2(projectRoot),
11479
+ realpath2(reportDir)
11060
11480
  ]);
11061
11481
  if (!isWithinDirectory(canonicalProjectRoot, canonicalReportDir)) {
11062
11482
  throw new Error("Error report directory resolves outside project root.");
@@ -11111,9 +11531,24 @@ function redactValue(value) {
11111
11531
  }
11112
11532
  return `<set, ${value.length} chars>`;
11113
11533
  }
11114
- function isSensitiveName(name) {
11115
- const normalized = name.toLowerCase();
11116
- return DEFAULT_SENSITIVE_NAMES.some((candidate) => normalized.includes(candidate));
11534
+ function collectStringLeaves(value, output) {
11535
+ if (typeof value === "string") {
11536
+ if (value.length > 0) {
11537
+ output.add(value);
11538
+ }
11539
+ return;
11540
+ }
11541
+ if (Array.isArray(value)) {
11542
+ for (const entry of value) {
11543
+ collectStringLeaves(entry, output);
11544
+ }
11545
+ return;
11546
+ }
11547
+ if (isPlainObject3(value)) {
11548
+ for (const entry of Object.values(value)) {
11549
+ collectStringLeaves(entry, output);
11550
+ }
11551
+ }
11117
11552
  }
11118
11553
  function schemaSecretValue(schema) {
11119
11554
  const unwrapped = unwrapOptional(schema);
@@ -11134,7 +11569,7 @@ function redactParamsValue(value, schema, name) {
11134
11569
  return "<redacted>";
11135
11570
  }
11136
11571
  const unwrapped = unwrapOptional(schema);
11137
- if (unwrapped.kind === "object" && isPlainObject2(value)) {
11572
+ if (unwrapped.kind === "object" && isPlainObject3(value)) {
11138
11573
  return Object.fromEntries(
11139
11574
  Object.entries(value).map(([key2, childValue]) => {
11140
11575
  const childSchema = unwrapped.shape[key2];
@@ -11156,6 +11591,52 @@ function redactParams(params17, command) {
11156
11591
  }
11157
11592
  return redactParamsValue(params17, command.params, "");
11158
11593
  }
11594
+ function collectSensitiveParamValues(value, schema, name, output) {
11595
+ if (shouldRedactParam(name, schema)) {
11596
+ collectStringLeaves(value, output);
11597
+ return;
11598
+ }
11599
+ const unwrapped = unwrapOptional(schema);
11600
+ if (unwrapped.kind === "object" && isPlainObject3(value)) {
11601
+ for (const [key2, childValue] of Object.entries(value)) {
11602
+ const childSchema = unwrapped.shape[key2];
11603
+ if (childSchema !== void 0) {
11604
+ collectSensitiveParamValues(childValue, childSchema, key2, output);
11605
+ }
11606
+ }
11607
+ return;
11608
+ }
11609
+ if (unwrapped.kind === "array" && Array.isArray(value)) {
11610
+ for (const entry of value) {
11611
+ collectSensitiveParamValues(entry, unwrapped.item, name, output);
11612
+ }
11613
+ }
11614
+ }
11615
+ function createReportStringRedactor(context, env) {
11616
+ const values = /* @__PURE__ */ new Set();
11617
+ for (const value of Object.values(context.secrets ?? {})) {
11618
+ if (value !== void 0 && value.length > 0) {
11619
+ values.add(value);
11620
+ }
11621
+ }
11622
+ for (const [name, secret] of Object.entries(context.command?.secrets ?? {})) {
11623
+ const value = context.secrets?.[name] ?? env[secret.env];
11624
+ if (value !== void 0 && value.length > 0) {
11625
+ values.add(value);
11626
+ }
11627
+ }
11628
+ if (context.command !== void 0) {
11629
+ collectSensitiveParamValues(context.params, context.command.params, "", values);
11630
+ }
11631
+ const orderedValues = [...values].sort((left, right) => right.length - left.length);
11632
+ return (value) => {
11633
+ let redacted = value;
11634
+ for (const secretValue of orderedValues) {
11635
+ redacted = redacted.split(secretValue).join("<redacted>");
11636
+ }
11637
+ return redacted;
11638
+ };
11639
+ }
11159
11640
  function commandSecretEnvNames(secrets) {
11160
11641
  if (secrets === void 0) {
11161
11642
  return [];
@@ -11209,28 +11690,42 @@ function redactArgv(argv, options) {
11209
11690
  function stableJson(value) {
11210
11691
  return JSON.stringify(value, null, 2) ?? "undefined";
11211
11692
  }
11212
- function redactStructuredErrorField(name, value) {
11213
- if (typeof value === "string" && name.toLowerCase() === "authorization") {
11214
- return "Bearer ****";
11693
+ function redactStructuredErrorField(name, value, redactString) {
11694
+ if (typeof value === "string") {
11695
+ const redactedHeaderValue = redactHttpHeaderValue(name, value);
11696
+ if (redactedHeaderValue !== value) {
11697
+ return redactedHeaderValue;
11698
+ }
11699
+ if (isSensitiveName(name)) {
11700
+ return "<redacted>";
11701
+ }
11702
+ return redactString(value);
11215
11703
  }
11216
11704
  if (Array.isArray(value)) {
11217
- return value.map((entry) => redactStructuredErrorField(name, entry));
11705
+ return value.map((entry) => redactStructuredErrorField(name, entry, redactString));
11218
11706
  }
11219
- if (isPlainObject2(value)) {
11707
+ if (isPlainObject3(value)) {
11220
11708
  return Object.fromEntries(
11221
- Object.entries(value).map(([key2, entry]) => [key2, redactStructuredErrorField(key2, entry)])
11709
+ Object.entries(value).map(([key2, entry]) => [
11710
+ key2,
11711
+ redactStructuredErrorField(key2, entry, redactString)
11712
+ ])
11222
11713
  );
11223
11714
  }
11224
11715
  return value;
11225
11716
  }
11226
- function ownStructuredFields(error3) {
11717
+ function ownStructuredFields(error3, redactString) {
11227
11718
  const fields = {};
11228
11719
  for (const key2 of Object.keys(error3)) {
11229
11720
  if (key2 === "name" || key2 === "message" || key2 === "stack" || key2 === "cause") {
11230
11721
  continue;
11231
11722
  }
11232
11723
  Object.defineProperty(fields, key2, {
11233
- value: redactStructuredErrorField(key2, error3[key2]),
11724
+ value: redactStructuredErrorField(
11725
+ key2,
11726
+ error3[key2],
11727
+ redactString
11728
+ ),
11234
11729
  enumerable: true,
11235
11730
  configurable: true,
11236
11731
  writable: true
@@ -11238,43 +11733,44 @@ function ownStructuredFields(error3) {
11238
11733
  }
11239
11734
  return fields;
11240
11735
  }
11241
- function formatStackChain(error3) {
11736
+ function formatStackChain(error3, redactString) {
11242
11737
  const lines = [];
11243
11738
  let current = error3;
11244
11739
  let index = 0;
11245
11740
  while (current !== void 0) {
11246
11741
  if (current instanceof Error) {
11247
- lines.push(
11248
- index === 0 ? current.stack ?? String(current) : `Caused by: ${current.stack ?? String(current)}`
11249
- );
11742
+ const stack = current.stack ?? String(current);
11743
+ lines.push(redactString(index === 0 ? stack : `Caused by: ${stack}`));
11250
11744
  current = current.cause;
11251
11745
  } else {
11252
- lines.push(index === 0 ? String(current) : `Caused by: ${String(current)}`);
11746
+ const message2 = String(current);
11747
+ lines.push(redactString(index === 0 ? message2 : `Caused by: ${message2}`));
11253
11748
  current = void 0;
11254
11749
  }
11255
11750
  index += 1;
11256
11751
  }
11257
11752
  return lines.join("\n");
11258
11753
  }
11259
- function formatHeaderValue(name, value) {
11260
- return name.toLowerCase() === "authorization" ? "Bearer ****" : value;
11754
+ function formatHeaderValue(name, value, redactString) {
11755
+ return redactString(redactHttpHeaderValue(name, value));
11261
11756
  }
11262
- function formatHeaders(headers) {
11263
- return Object.entries(headers).map(([name, value]) => `${name}: ${formatHeaderValue(name, value)}`).join("\n");
11757
+ function formatHeaders(headers, redactString) {
11758
+ return Object.entries(headers).map(([name, value]) => `${name}: ${formatHeaderValue(name, value, redactString)}`).join("\n");
11264
11759
  }
11265
- function formatBody(body) {
11266
- if (typeof body === "string") {
11267
- return body;
11760
+ function formatBody(body, redactString) {
11761
+ const redactedBody = redactHttpBody(body);
11762
+ if (typeof redactedBody === "string") {
11763
+ return redactString(redactedBody);
11268
11764
  }
11269
- return stableJson(body);
11765
+ return redactString(stableJson(redactedBody));
11270
11766
  }
11271
- function formatHttpTranscript(error3) {
11767
+ function formatHttpTranscript(error3, redactString) {
11272
11768
  const requestLines = [
11273
11769
  `${error3.request.method} ${error3.request.url}`,
11274
- formatHeaders(error3.request.headers)
11770
+ formatHeaders(error3.request.headers, redactString)
11275
11771
  ].filter((line) => line.length > 0);
11276
11772
  if (error3.request.body !== void 0) {
11277
- requestLines.push("", formatBody(error3.request.body));
11773
+ requestLines.push("", formatBody(error3.request.body, redactString));
11278
11774
  }
11279
11775
  return [
11280
11776
  "Request:",
@@ -11282,9 +11778,9 @@ function formatHttpTranscript(error3) {
11282
11778
  "",
11283
11779
  "Response:",
11284
11780
  `${error3.response.status} ${error3.response.statusText}`,
11285
- formatHeaders(error3.response.headers),
11781
+ formatHeaders(error3.response.headers, redactString),
11286
11782
  "",
11287
- formatBody(error3.response.body)
11783
+ formatBody(error3.response.body, redactString)
11288
11784
  ].join("\n");
11289
11785
  }
11290
11786
  function resolveToolcraftVersion(version) {
@@ -11293,9 +11789,10 @@ function resolveToolcraftVersion(version) {
11293
11789
  function buildReport(context) {
11294
11790
  const env = context.env ?? process.env;
11295
11791
  const error3 = context.error;
11792
+ const redactString = createReportStringRedactor(context, env);
11296
11793
  const errorName = error3 instanceof Error ? error3.name : typeof error3;
11297
- const errorMessage = error3 instanceof Error ? error3.message : String(error3);
11298
- const structuredFields = error3 instanceof Error ? ownStructuredFields(error3) : {};
11794
+ const errorMessage = redactString(error3 instanceof Error ? error3.message : String(error3));
11795
+ const structuredFields = error3 instanceof Error ? ownStructuredFields(error3, redactString) : {};
11299
11796
  const secretLines = Object.entries(context.command?.secrets ?? {}).map(([name, secret]) => {
11300
11797
  const value = context.secrets?.[name] ?? env[secret.env];
11301
11798
  return `${secret.env}=${redactValue(value)}`;
@@ -11309,7 +11806,9 @@ function buildReport(context) {
11309
11806
  `platform: ${process.platform} ${process.arch}`,
11310
11807
  "",
11311
11808
  "Argv",
11312
- stableJson(redactArgv(context.argv, { command: context.command, secrets: context.secrets })),
11809
+ redactString(
11810
+ stableJson(redactArgv(context.argv, { command: context.command, secrets: context.secrets }))
11811
+ ),
11313
11812
  "",
11314
11813
  "Resolved Secrets",
11315
11814
  ...secretLines.length === 0 ? ["<none>"] : secretLines,
@@ -11318,19 +11817,19 @@ function buildReport(context) {
11318
11817
  context.commandPath === void 0 || context.commandPath.length === 0 ? "root" : context.commandPath,
11319
11818
  "",
11320
11819
  "Parsed Params",
11321
- stableJson(redactParams(context.params, context.command)),
11820
+ redactString(stableJson(redactParams(context.params, context.command))),
11322
11821
  "",
11323
11822
  "Error",
11324
11823
  `name: ${errorName}`,
11325
11824
  `message: ${errorMessage}`,
11326
11825
  "structured fields:",
11327
- stableJson(structuredFields),
11826
+ redactString(stableJson(structuredFields)),
11328
11827
  "",
11329
11828
  "Stack",
11330
- formatStackChain(error3)
11829
+ formatStackChain(error3, redactString)
11331
11830
  ];
11332
11831
  if (hasHttpContext(error3)) {
11333
- lines.push("", "HTTP Transcript", formatHttpTranscript(error3));
11832
+ lines.push("", "HTTP Transcript", formatHttpTranscript(error3, redactString));
11334
11833
  }
11335
11834
  return `${lines.join("\n")}
11336
11835
  `;
@@ -11342,7 +11841,7 @@ async function writeErrorReport(context) {
11342
11841
  }
11343
11842
  const projectRoot = resolveProjectRoot(context.projectRoot);
11344
11843
  const reportDir = resolveReportDir(context.errorReports, projectRoot);
11345
- const fileName = `${formatTimestamp(/* @__PURE__ */ new Date())}-${slugifyCommandPath(context.commandPath)}-${randomUUID3()}.log`;
11844
+ const fileName = `${formatTimestamp(/* @__PURE__ */ new Date())}-${slugifyCommandPath(context.commandPath)}-${randomUUID5()}.log`;
11346
11845
  const absolutePath = path13.join(reportDir, fileName);
11347
11846
  await mkdir2(reportDir, { recursive: true });
11348
11847
  if (reportDirMustStayWithinProject(context.errorReports)) {
@@ -11790,6 +12289,7 @@ ${rendered.join("\n")}`);
11790
12289
  }
11791
12290
 
11792
12291
  // ../toolcraft/src/cli.ts
12292
+ configureTheme({ brand: "blue", label: "Toolcraft" });
11793
12293
  var RESERVED_SERVICE_NAMES = /* @__PURE__ */ new Set([
11794
12294
  "params",
11795
12295
  "secrets",
@@ -12820,10 +13320,10 @@ function renderHelpSections(sections) {
12820
13320
  return sections.filter((section) => section.length > 0).join("\n\n");
12821
13321
  }
12822
13322
  function formatHelpCommandList(rows) {
12823
- return process.stdout.isTTY === false ? help_formatter_plain_exports.formatCommandList(rows) : formatCommandList(rows);
13323
+ return process.stdout.isTTY !== true ? help_formatter_plain_exports.formatCommandList(rows) : formatCommandList(rows);
12824
13324
  }
12825
13325
  function formatHelpOptionList(rows) {
12826
- return process.stdout.isTTY === false ? help_formatter_plain_exports.formatOptionList(rows) : formatOptionList(rows);
13326
+ return process.stdout.isTTY !== true ? help_formatter_plain_exports.formatOptionList(rows) : formatOptionList(rows);
12827
13327
  }
12828
13328
  function buildUsageLine(breadcrumb, rootUsageName, suffix) {
12829
13329
  const visibleBreadcrumb = breadcrumb.filter((segment) => segment.length > 0);
@@ -13111,11 +13611,18 @@ function formatResolvedValue(value) {
13111
13611
  function fieldPromptLabel(field) {
13112
13612
  return field.positionalIndex === void 0 ? field.optionFlag : `<${field.displayPath}>`;
13113
13613
  }
13614
+ function enumOptionLabel(schema, value) {
13615
+ const key2 = String(value);
13616
+ if (schema.labels === void 0 || !Object.prototype.hasOwnProperty.call(schema.labels, key2)) {
13617
+ return key2;
13618
+ }
13619
+ return schema.labels[key2] ?? key2;
13620
+ }
13114
13621
  async function promptForField(field) {
13115
13622
  const schema = field.schema;
13116
13623
  if (schema.kind === "enum") {
13117
13624
  const options = schema.loadOptions ? await schema.loadOptions() : schema.values.map((value) => ({
13118
- label: schema.labels?.[String(value)] ?? String(value),
13625
+ label: enumOptionLabel(schema, value),
13119
13626
  value
13120
13627
  }));
13121
13628
  const selected = await select2({
@@ -13200,8 +13707,8 @@ async function withOutputFormat2(output, fn) {
13200
13707
  function createFs2() {
13201
13708
  return {
13202
13709
  readFile: async (path25, encoding = "utf8") => readFile4(path25, { encoding }),
13203
- writeFile: async (path25, contents) => {
13204
- await writeFile5(path25, contents);
13710
+ writeFile: async (path25, contents, options) => {
13711
+ await writeFile5(path25, contents, options);
13205
13712
  },
13206
13713
  exists: async (path25) => {
13207
13714
  try {
@@ -13213,7 +13720,7 @@ function createFs2() {
13213
13720
  },
13214
13721
  lstat: async (path25) => lstat3(path25),
13215
13722
  rename: async (fromPath, toPath) => rename3(fromPath, toPath),
13216
- unlink: async (path25) => unlink2(path25)
13723
+ unlink: async (path25) => unlink3(path25)
13217
13724
  };
13218
13725
  }
13219
13726
  function createEnv2(values = process.env) {
@@ -13223,7 +13730,7 @@ function createEnv2(values = process.env) {
13223
13730
  }
13224
13731
  };
13225
13732
  }
13226
- function isPlainObject3(value) {
13733
+ function isPlainObject4(value) {
13227
13734
  return typeof value === "object" && value !== null && !Array.isArray(value);
13228
13735
  }
13229
13736
  function hasFieldValue(value) {
@@ -13332,7 +13839,7 @@ async function loadPresetValues(fields, presetPath) {
13332
13839
  { cause: error3 }
13333
13840
  );
13334
13841
  }
13335
- if (!isPlainObject3(parsedPreset)) {
13842
+ if (!isPlainObject4(parsedPreset)) {
13336
13843
  throw new UserError(`Preset file "${presetPath}" must contain a JSON object.`);
13337
13844
  }
13338
13845
  const fieldByPath = new Map(fields.map((field) => [field.displayPath, field]));
@@ -13351,7 +13858,7 @@ async function loadPresetValues(fields, presetPath) {
13351
13858
  `Preset file "${presetPath}" contains unknown parameter "${displayPath}".`
13352
13859
  );
13353
13860
  }
13354
- if (!isPlainObject3(value)) {
13861
+ if (!isPlainObject4(value)) {
13355
13862
  throw new UserError(
13356
13863
  `Preset file "${presetPath}" has an invalid value for "${displayPath}". Expected an object, got ${describeReceived(value)}.`
13357
13864
  );
@@ -13394,8 +13901,8 @@ function matchesFixtureValue(expected, actual) {
13394
13901
  }
13395
13902
  return expected.every((item, index) => matchesFixtureValue(item, actual[index]));
13396
13903
  }
13397
- if (isPlainObject3(expected)) {
13398
- if (!isPlainObject3(actual)) {
13904
+ if (isPlainObject4(expected)) {
13905
+ if (!isPlainObject4(actual)) {
13399
13906
  return false;
13400
13907
  }
13401
13908
  return Object.entries(expected).every(
@@ -13458,9 +13965,9 @@ function createFixtureFetch(entries) {
13458
13965
  };
13459
13966
  }
13460
13967
  function createFixtureFs(definition) {
13461
- const fsDefinition = isPlainObject3(definition) ? definition : {};
13462
- const readFileEntries = isPlainObject3(fsDefinition.readFile) ? fsDefinition.readFile : {};
13463
- const existsEntries = isPlainObject3(fsDefinition.exists) ? fsDefinition.exists : {};
13968
+ const fsDefinition = isPlainObject4(definition) ? definition : {};
13969
+ const readFileEntries = isPlainObject4(fsDefinition.readFile) ? fsDefinition.readFile : {};
13970
+ const existsEntries = isPlainObject4(fsDefinition.exists) ? fsDefinition.exists : {};
13464
13971
  return {
13465
13972
  readFile: async (filePath) => {
13466
13973
  if (Object.prototype.hasOwnProperty.call(readFileEntries, filePath)) {
@@ -13483,10 +13990,10 @@ function createFixtureFs(definition) {
13483
13990
  function resolveFixtureMethodResult(methodName, definition, args) {
13484
13991
  if (Array.isArray(definition)) {
13485
13992
  for (const entry of definition) {
13486
- if (!isPlainObject3(entry)) {
13993
+ if (!isPlainObject4(entry)) {
13487
13994
  continue;
13488
13995
  }
13489
- const explicitMatcher = isPlainObject3(entry.request) ? entry.request : void 0;
13996
+ const explicitMatcher = isPlainObject4(entry.request) ? entry.request : void 0;
13490
13997
  const matcher = explicitMatcher ?? Object.fromEntries(
13491
13998
  Object.entries(entry).filter(
13492
13999
  ([key2]) => key2 !== "result" && key2 !== "response" && key2 !== "error"
@@ -13498,7 +14005,7 @@ function resolveFixtureMethodResult(methodName, definition, args) {
13498
14005
  matched = matchesFixtureValue(matcher.args, args);
13499
14006
  } else if (Object.keys(matcher).length === 0) {
13500
14007
  matched = true;
13501
- } else if (isPlainObject3(firstArg)) {
14008
+ } else if (isPlainObject4(firstArg)) {
13502
14009
  matched = matchesFixtureValue(matcher, firstArg);
13503
14010
  } else if (args.length === 1 && Object.keys(matcher).length === 1) {
13504
14011
  const [[, expectedValue]] = Object.entries(matcher);
@@ -13519,7 +14026,7 @@ function resolveFixtureMethodResult(methodName, definition, args) {
13519
14026
  return Promise.resolve(null);
13520
14027
  }
13521
14028
  }
13522
- if (isPlainObject3(definition)) {
14029
+ if (isPlainObject4(definition)) {
13523
14030
  const firstArg = args[0];
13524
14031
  if (typeof firstArg === "string" && Object.prototype.hasOwnProperty.call(definition, firstArg)) {
13525
14032
  return Promise.resolve(definition[firstArg]);
@@ -13531,7 +14038,7 @@ function resolveFixtureMethodResult(methodName, definition, args) {
13531
14038
  return Promise.resolve(null);
13532
14039
  }
13533
14040
  function createFixtureService(definition) {
13534
- const methods = isPlainObject3(definition) ? definition : {};
14041
+ const methods = isPlainObject4(definition) ? definition : {};
13535
14042
  return new Proxy(
13536
14043
  {},
13537
14044
  {
@@ -13629,7 +14136,7 @@ async function resolveFixtureRuntime(command, services, requirementOptions) {
13629
14136
  };
13630
14137
  }
13631
14138
  const scenario = await loadFixtureScenario(command, selector);
13632
- const scenarioServices = isPlainObject3(scenario.services) ? scenario.services : {};
14139
+ const scenarioServices = isPlainObject4(scenario.services) ? scenario.services : {};
13633
14140
  const customServiceNames = /* @__PURE__ */ new Set([
13634
14141
  ...Object.keys(services),
13635
14142
  ...Object.keys(scenarioServices).filter((name) => !RESERVED_SERVICE_NAMES.has(name))
@@ -13911,7 +14418,7 @@ function finalizeDynamicValue(schema, value, displayPath, errors2) {
13911
14418
  if (itemSchema.kind !== "object") {
13912
14419
  return value;
13913
14420
  }
13914
- if (!isPlainObject3(value)) {
14421
+ if (!isPlainObject4(value)) {
13915
14422
  errors2.push({
13916
14423
  path: displayPath,
13917
14424
  message: `Invalid value for "${displayPath}". Expected indexed object entries, got ${describeReceived(value)}.`
@@ -13946,7 +14453,7 @@ function finalizeDynamicValue(schema, value, displayPath, errors2) {
13946
14453
  );
13947
14454
  }
13948
14455
  case "object": {
13949
- if (!isPlainObject3(value)) {
14456
+ if (!isPlainObject4(value)) {
13950
14457
  errors2.push({
13951
14458
  path: displayPath,
13952
14459
  message: `Invalid value for "${displayPath}". Expected an object, got ${describeReceived(value)}.`
@@ -13977,7 +14484,7 @@ function finalizeDynamicValue(schema, value, displayPath, errors2) {
13977
14484
  return result;
13978
14485
  }
13979
14486
  case "record": {
13980
- if (!isPlainObject3(value)) {
14487
+ if (!isPlainObject4(value)) {
13981
14488
  errors2.push({
13982
14489
  path: displayPath,
13983
14490
  message: `Invalid value for "${displayPath}". Expected an object, got ${describeReceived(value)}.`
@@ -14403,10 +14910,10 @@ async function executeCommand(state, services, requirementOptions, runtimeOption
14403
14910
  }
14404
14911
  }
14405
14912
  function isStringRecord(value) {
14406
- return isPlainObject3(value) && Object.values(value).every((entry) => typeof entry === "string");
14913
+ return isPlainObject4(value) && Object.values(value).every((entry) => typeof entry === "string");
14407
14914
  }
14408
14915
  function isHttpErrorLike(error3) {
14409
- if (!isPlainObject3(error3)) {
14916
+ if (!isPlainObject4(error3)) {
14410
14917
  return false;
14411
14918
  }
14412
14919
  if (error3.name !== "HttpError" || typeof error3.message !== "string") {
@@ -14414,7 +14921,7 @@ function isHttpErrorLike(error3) {
14414
14921
  }
14415
14922
  const request = error3.request;
14416
14923
  const response = error3.response;
14417
- 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;
14924
+ 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;
14418
14925
  }
14419
14926
  function hasTypedOptionalField(value, field, type2) {
14420
14927
  return !(field in value) || typeof value[field] === type2;
@@ -14423,7 +14930,7 @@ function isNonEmptyString(value) {
14423
14930
  return typeof value === "string" && value.trim().length > 0;
14424
14931
  }
14425
14932
  function isProblemDetailsLike(body) {
14426
- if (!isPlainObject3(body)) {
14933
+ if (!isPlainObject4(body)) {
14427
14934
  return false;
14428
14935
  }
14429
14936
  if (!hasTypedOptionalField(body, "type", "string")) {
@@ -14444,11 +14951,11 @@ function isProblemDetailsLike(body) {
14444
14951
  return isNonEmptyString(body.title) || isNonEmptyString(body.detail);
14445
14952
  }
14446
14953
  function isGraphQLErrorEnvelopeLike(body) {
14447
- if (!isPlainObject3(body) || !Array.isArray(body.errors) || body.errors.length === 0) {
14954
+ if (!isPlainObject4(body) || !Array.isArray(body.errors) || body.errors.length === 0) {
14448
14955
  return false;
14449
14956
  }
14450
14957
  return body.errors.every((error3) => {
14451
- if (!isPlainObject3(error3) || typeof error3.message !== "string") {
14958
+ if (!isPlainObject4(error3) || typeof error3.message !== "string") {
14452
14959
  return false;
14453
14960
  }
14454
14961
  if ("path" in error3) {
@@ -14458,7 +14965,7 @@ function isGraphQLErrorEnvelopeLike(body) {
14458
14965
  }
14459
14966
  }
14460
14967
  if ("extensions" in error3) {
14461
- if (!isPlainObject3(error3.extensions)) {
14968
+ if (!isPlainObject4(error3.extensions)) {
14462
14969
  return false;
14463
14970
  }
14464
14971
  if ("code" in error3.extensions && typeof error3.extensions.code !== "string") {
@@ -14469,7 +14976,7 @@ function isGraphQLErrorEnvelopeLike(body) {
14469
14976
  });
14470
14977
  }
14471
14978
  function styleHttpErrorLine(value, style) {
14472
- return process.stdout.isTTY === false ? value : style(value);
14979
+ return process.stdout.isTTY !== true ? value : style(value);
14473
14980
  }
14474
14981
  function formatHttpErrorStatus(value) {
14475
14982
  return styleHttpErrorLine(value, text.error);
@@ -14506,23 +15013,24 @@ function formatGraphQLErrorEnvelopeBody(body) {
14506
15013
  }).join("\n\n");
14507
15014
  }
14508
15015
  function formatHttpErrorBody(body) {
14509
- if (typeof body === "string") {
14510
- return body;
15016
+ const redactedBody = redactHttpBody(body);
15017
+ if (typeof redactedBody === "string") {
15018
+ return redactedBody;
14511
15019
  }
14512
- if (isProblemDetailsLike(body)) {
14513
- return formatProblemDetailsBody(body);
15020
+ if (isProblemDetailsLike(redactedBody)) {
15021
+ return formatProblemDetailsBody(redactedBody);
14514
15022
  }
14515
- if (isGraphQLErrorEnvelopeLike(body)) {
14516
- return formatGraphQLErrorEnvelopeBody(body);
15023
+ if (isGraphQLErrorEnvelopeLike(redactedBody)) {
15024
+ return formatGraphQLErrorEnvelopeBody(redactedBody);
14517
15025
  }
14518
- const serialized = JSON.stringify(body, null, 2);
14519
- return serialized === void 0 ? String(body) : serialized;
15026
+ const serialized = JSON.stringify(redactedBody, null, 2);
15027
+ return serialized === void 0 ? String(redactedBody) : serialized;
14520
15028
  }
14521
15029
  function indentHttpErrorBlock(value) {
14522
15030
  return value.split("\n").map((line) => ` ${line}`).join("\n");
14523
15031
  }
14524
15032
  function formatHttpHeaderValue(name, value) {
14525
- return name.toLowerCase() === "authorization" ? "Bearer ****" : value;
15033
+ return redactHttpHeaderValue(name, value);
14526
15034
  }
14527
15035
  function formatHttpErrorHeaders(headers) {
14528
15036
  return Object.entries(headers).map(
@@ -14540,7 +15048,11 @@ function renderHttpError(error3, options) {
14540
15048
  if (detailed) {
14541
15049
  lines.push("", "Request headers:", ...formatHttpErrorHeaders(error3.request.headers), "");
14542
15050
  if (error3.request.body !== void 0) {
14543
- lines.push("Request body:", indentHttpErrorBlock(formatHttpErrorBody(error3.request.body)), "");
15051
+ lines.push(
15052
+ "Request body:",
15053
+ indentHttpErrorBlock(formatHttpErrorBody(error3.request.body)),
15054
+ ""
15055
+ );
14544
15056
  }
14545
15057
  }
14546
15058
  lines.push(
@@ -14946,7 +15458,7 @@ async function runCLI(roots, options = {}) {
14946
15458
  }
14947
15459
 
14948
15460
  // src/terminal-pilot.ts
14949
- import { randomUUID as randomUUID4 } from "node:crypto";
15461
+ import { randomUUID as randomUUID6 } from "node:crypto";
14950
15462
 
14951
15463
  // src/terminal-session.ts
14952
15464
  import { EventEmitter } from "node:events";
@@ -14955,6 +15467,11 @@ import { createRequire } from "node:module";
14955
15467
  import { dirname, join } from "node:path";
14956
15468
  import * as nodePty from "node-pty";
14957
15469
 
15470
+ // src/errors.ts
15471
+ function hasOwnErrorCode(error3, code) {
15472
+ return error3 instanceof Error && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === code;
15473
+ }
15474
+
14958
15475
  // src/terminal-buffer.ts
14959
15476
  var RESET_SGR = "\x1B[0m";
14960
15477
  var DEC_SPECIAL_GRAPHICS = {
@@ -16054,10 +16571,7 @@ function ensureSpawnHelperExecutable() {
16054
16571
  }
16055
16572
  }
16056
16573
  function isMissingFileError(error3) {
16057
- if (!(error3 instanceof Error)) {
16058
- return false;
16059
- }
16060
- return "code" in error3 && error3.code === "ENOENT";
16574
+ return hasOwnErrorCode(error3, "ENOENT");
16061
16575
  }
16062
16576
  function matchPattern(buffer, pattern) {
16063
16577
  const clean = normalizeHistoryBuffer(stripAnsi(buffer));
@@ -16148,7 +16662,7 @@ var TerminalPilot = class _TerminalPilot {
16148
16662
  }
16149
16663
  async newSession(opts) {
16150
16664
  const session = new TerminalSession({
16151
- id: randomUUID4(),
16665
+ id: randomUUID6(),
16152
16666
  command: opts.command,
16153
16667
  args: opts.args,
16154
16668
  cwd: opts.cwd,
@@ -16434,6 +16948,11 @@ var claudeCodeAgent = {
16434
16948
  aliases: ["claude"],
16435
16949
  binaryName: "claude",
16436
16950
  apiShapes: ["anthropic-messages"],
16951
+ otelCapture: {
16952
+ env: {
16953
+ CLAUDE_CODE_ENABLE_TELEMETRY: "1"
16954
+ }
16955
+ },
16437
16956
  configPath: "~/.claude/settings.json",
16438
16957
  branding: {
16439
16958
  colors: {
@@ -16466,6 +16985,16 @@ var codexAgent = {
16466
16985
  summary: "Configure Codex to use Poe as the model provider.",
16467
16986
  binaryName: "codex",
16468
16987
  apiShapes: ["openai-responses"],
16988
+ otelCapture: {
16989
+ args: (endpoint, content) => [
16990
+ "-c",
16991
+ `otel.trace_exporter={"otlp-http"={endpoint=${JSON.stringify(`${endpoint}/v1/traces`)},protocol="json"}}`,
16992
+ "-c",
16993
+ `otel.exporter={"otlp-http"={endpoint=${JSON.stringify(`${endpoint}/v1/logs`)},protocol="json"}}`,
16994
+ "-c",
16995
+ `otel.log_user_prompt=${content}`
16996
+ ]
16997
+ },
16469
16998
  configPath: "~/.codex/config.toml",
16470
16999
  branding: {
16471
17000
  colors: {
@@ -16501,6 +17030,11 @@ var openCodeAgent = {
16501
17030
  summary: "Configure OpenCode CLI to use the Poe API.",
16502
17031
  binaryName: "opencode",
16503
17032
  apiShapes: ["openai-chat-completions"],
17033
+ otelCapture: {
17034
+ env: {
17035
+ OPENCODE_CONFIG_CONTENT: '{"experimental":{"openTelemetry":true}}'
17036
+ }
17037
+ },
16504
17038
  configPath: "~/.config/opencode/config.json",
16505
17039
  branding: {
16506
17040
  colors: {
@@ -16536,6 +17070,7 @@ var gooseAgent = {
16536
17070
  summary: "Block's open-source AI agent with ACP support.",
16537
17071
  binaryName: "goose",
16538
17072
  apiShapes: ["openai-chat-completions"],
17073
+ otelCapture: {},
16539
17074
  configPath: "~/.config/goose/config.yaml",
16540
17075
  branding: {
16541
17076
  colors: {
@@ -16569,6 +17104,12 @@ function freezeAgent(agent) {
16569
17104
  if (agent.apiShapes !== void 0) {
16570
17105
  Object.freeze(agent.apiShapes);
16571
17106
  }
17107
+ if (agent.otelCapture?.env !== void 0) {
17108
+ Object.freeze(agent.otelCapture.env);
17109
+ }
17110
+ if (agent.otelCapture !== void 0) {
17111
+ Object.freeze(agent.otelCapture);
17112
+ }
16572
17113
  Object.freeze(agent.branding.colors);
16573
17114
  Object.freeze(agent.branding);
16574
17115
  return Object.freeze(agent);
@@ -16629,11 +17170,11 @@ function resolveAgentSupport(input, registry = agentSkillConfigs) {
16629
17170
  if (!resolvedId) {
16630
17171
  return { status: "unknown", input };
16631
17172
  }
16632
- const config = registry[resolvedId];
16633
- if (!config) {
17173
+ const config2 = registry[resolvedId];
17174
+ if (!config2) {
16634
17175
  return { status: "unsupported", input, id: resolvedId };
16635
17176
  }
16636
- return { status: "supported", input, id: resolvedId, config: { ...config } };
17177
+ return { status: "supported", input, id: resolvedId, config: { ...config2 } };
16637
17178
  }
16638
17179
  function getAgentConfig(agentId) {
16639
17180
  const support = resolveAgentSupport(agentId);
@@ -16732,6 +17273,7 @@ var templateMutation = {
16732
17273
  };
16733
17274
 
16734
17275
  // ../config-mutations/src/execution/apply-mutation.ts
17276
+ import { randomUUID as randomUUID7 } from "node:crypto";
16735
17277
  import path17 from "node:path";
16736
17278
 
16737
17279
  // ../config-mutations/src/formats/json.ts
@@ -16807,7 +17349,7 @@ function merge(base, patch) {
16807
17349
  if (value === void 0) {
16808
17350
  continue;
16809
17351
  }
16810
- const existing = result[key2];
17352
+ const existing = hasConfigEntry(result, key2) ? result[key2] : void 0;
16811
17353
  if (isConfigObject(existing) && isConfigObject(value)) {
16812
17354
  setConfigEntry(result, key2, merge(existing, value));
16813
17355
  continue;
@@ -16935,7 +17477,7 @@ function merge2(base, patch) {
16935
17477
  if (value === void 0) {
16936
17478
  continue;
16937
17479
  }
16938
- const existing = result[key2];
17480
+ const existing = hasConfigEntry(result, key2) ? result[key2] : void 0;
16939
17481
  if (isConfigObject2(existing) && isConfigObject2(value)) {
16940
17482
  setConfigEntry(result, key2, merge2(existing, value));
16941
17483
  continue;
@@ -17015,7 +17557,7 @@ function merge3(base, patch) {
17015
17557
  if (value === void 0) {
17016
17558
  continue;
17017
17559
  }
17018
- const existing = result[key2];
17560
+ const existing = hasConfigEntry(result, key2) ? result[key2] : void 0;
17019
17561
  if (isConfigObject3(existing) && isConfigObject3(value)) {
17020
17562
  setConfigEntry(result, key2, merge3(existing, value));
17021
17563
  continue;
@@ -17152,7 +17694,7 @@ function resolvePath(rawPath, homeDir, pathMapper) {
17152
17694
 
17153
17695
  // ../config-mutations/src/fs-utils.ts
17154
17696
  function isNotFound(error3) {
17155
- return typeof error3 === "object" && error3 !== null && "code" in error3 && error3.code === "ENOENT";
17697
+ return typeof error3 === "object" && error3 !== null && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "ENOENT";
17156
17698
  }
17157
17699
  async function readFileIfExists(fs4, target) {
17158
17700
  try {
@@ -17201,6 +17743,7 @@ async function backupInvalidDocument(context, targetPath, content) {
17201
17743
  return;
17202
17744
  } catch (error3) {
17203
17745
  if (!isAlreadyExists(error3)) {
17746
+ await context.fs.unlink(backupPath).catch(() => void 0);
17204
17747
  throw error3;
17205
17748
  }
17206
17749
  attempt += 1;
@@ -17208,7 +17751,7 @@ async function backupInvalidDocument(context, targetPath, content) {
17208
17751
  }
17209
17752
  }
17210
17753
  function isAlreadyExists(error3) {
17211
- return Boolean(error3 && typeof error3 === "object" && "code" in error3 && error3.code === "EEXIST");
17754
+ return typeof error3 === "object" && error3 !== null && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "EEXIST";
17212
17755
  }
17213
17756
  async function assertRegularWriteTarget(context, targetPath) {
17214
17757
  const boundary = path17.dirname(path17.resolve(context.homeDir));
@@ -17232,28 +17775,34 @@ async function assertRegularWriteTarget(context, targetPath) {
17232
17775
  }
17233
17776
  async function writeAtomically2(context, targetPath, content) {
17234
17777
  await assertRegularWriteTarget(context, targetPath);
17235
- let attempt = 0;
17236
- while (true) {
17237
- const tempPath = `${targetPath}.mutation-tmp-${attempt}`;
17778
+ for (let attempt = 0; attempt < 10; attempt += 1) {
17779
+ const tempPath = `${targetPath}.mutation-tmp-${process.pid}-${randomUUID7()}`;
17780
+ let tempCreated = false;
17238
17781
  try {
17782
+ await assertRegularWriteTarget(context, tempPath);
17239
17783
  await context.fs.writeFile(tempPath, content, { encoding: "utf8", flag: "wx" });
17784
+ tempCreated = true;
17240
17785
  await context.fs.rename(tempPath, targetPath);
17786
+ tempCreated = false;
17241
17787
  return;
17242
17788
  } catch (error3) {
17243
- if (isAlreadyExists(error3)) {
17244
- attempt += 1;
17245
- continue;
17246
- }
17247
- try {
17248
- await context.fs.unlink(tempPath);
17249
- } catch (cleanupError) {
17250
- if (!isNotFound(cleanupError)) {
17251
- void cleanupError;
17789
+ const alreadyExists = isAlreadyExists(error3);
17790
+ if (tempCreated || !alreadyExists) {
17791
+ try {
17792
+ await context.fs.unlink(tempPath);
17793
+ } catch (cleanupError) {
17794
+ if (!isNotFound(cleanupError)) {
17795
+ void cleanupError;
17796
+ }
17252
17797
  }
17253
17798
  }
17799
+ if (alreadyExists) {
17800
+ continue;
17801
+ }
17254
17802
  throw error3;
17255
17803
  }
17256
17804
  }
17805
+ throw new Error(`Unable to create temporary mutation file for ${targetPath}.`);
17257
17806
  }
17258
17807
  function describeMutation(kind, targetPath) {
17259
17808
  const displayPath = targetPath ?? "target";
@@ -17545,6 +18094,7 @@ async function applyBackup(mutation, context, options) {
17545
18094
  break;
17546
18095
  } catch (error3) {
17547
18096
  if (!isAlreadyExists(error3)) {
18097
+ await context.fs.unlink(backupPath).catch(() => void 0);
17548
18098
  throw error3;
17549
18099
  }
17550
18100
  attempt += 1;
@@ -17952,7 +18502,7 @@ async function pathExists2(fs4, targetPath) {
17952
18502
  await fs4.stat(targetPath);
17953
18503
  return true;
17954
18504
  } catch (error3) {
17955
- if (error3 && typeof error3 === "object" && "code" in error3 && error3.code === "ENOENT") {
18505
+ if (typeof error3 === "object" && error3 !== null && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "ENOENT") {
17956
18506
  return false;
17957
18507
  }
17958
18508
  throw error3;
@@ -17965,14 +18515,14 @@ async function installSkill(agentId, skill, options) {
17965
18515
  throw new UnsupportedAgentError(agentId);
17966
18516
  }
17967
18517
  const scope = options.scope ?? "local";
17968
- const config = support.config;
18518
+ const config2 = support.config;
17969
18519
  if (skill.name.length === 0 || skill.name === "." || skill.name === ".." || skill.name.includes("/") || skill.name.includes("\\") || skill.name.includes("\n") || skill.name.includes("\r")) {
17970
18520
  throw new Error(`Invalid skill name: ${skill.name}`);
17971
18521
  }
17972
- const skillDir = scope === "global" ? config.globalSkillDir : toHomeRelative(config.localSkillDir);
18522
+ const skillDir = scope === "global" ? config2.globalSkillDir : toHomeRelative(config2.localSkillDir);
17973
18523
  const skillFolderPath = `${skillDir}/${skill.name}`;
17974
18524
  const skillFilePath = `${skillFolderPath}/SKILL.md`;
17975
- const displayPath = `${scope === "global" ? config.globalSkillDir : config.localSkillDir}/${skill.name}/SKILL.md`;
18525
+ const displayPath = `${scope === "global" ? config2.globalSkillDir : config2.localSkillDir}/${skill.name}/SKILL.md`;
17976
18526
  const absoluteSkillPath = `${scope === "global" ? options.homeDir : options.cwd}/${skillFilePath.slice(2)}`;
17977
18527
  if (await pathExists2(options.fs, absoluteSkillPath)) {
17978
18528
  throw new Error(`Skill already exists: ${displayPath}`);
@@ -18011,12 +18561,13 @@ import path19 from "node:path";
18011
18561
 
18012
18562
  // ../agent-skill-config/src/git-exclude.ts
18013
18563
  import { execFileSync } from "node:child_process";
18564
+ import { randomUUID as randomUUID8 } from "node:crypto";
18014
18565
  import * as fs2 from "node:fs";
18015
18566
  import path20 from "node:path";
18016
18567
 
18017
18568
  // ../agent-skill-config/src/bridge-active-skills.ts
18018
18569
  import * as fs3 from "node:fs";
18019
- import { createHash as createHash4, randomUUID as randomUUID5 } from "node:crypto";
18570
+ import { createHash as createHash4, randomUUID as randomUUID9 } from "node:crypto";
18020
18571
  import path21 from "node:path";
18021
18572
 
18022
18573
  // src/commands/installer.ts
@@ -18029,7 +18580,7 @@ var DEFAULT_INSTALL_SCOPE = "local";
18029
18580
  var TERMINAL_PILOT_SKILL_NAME = "terminal-pilot";
18030
18581
  var installableAgents = supportedAgents;
18031
18582
  function isNotFoundError2(error3) {
18032
- return typeof error3 === "object" && error3 !== null && "code" in error3 && error3.code === "ENOENT";
18583
+ return hasOwnErrorCode(error3, "ENOENT");
18033
18584
  }
18034
18585
  function resolveInstallerServices(installer) {
18035
18586
  return {
@@ -18093,17 +18644,17 @@ function resolveHomeRelativePath(targetPath, homeDir) {
18093
18644
  return targetPath;
18094
18645
  }
18095
18646
  function getSkillFolderWithHome(agent, scope, cwd, homeDir) {
18096
- const config = getAgentConfig(agent);
18097
- if (!config) {
18647
+ const config2 = getAgentConfig(agent);
18648
+ if (!config2) {
18098
18649
  throwUnsupportedAgent(agent);
18099
18650
  }
18100
18651
  return {
18101
18652
  displayPath: path22.join(
18102
- scope === "global" ? config.globalSkillDir : config.localSkillDir,
18653
+ scope === "global" ? config2.globalSkillDir : config2.localSkillDir,
18103
18654
  TERMINAL_PILOT_SKILL_NAME
18104
18655
  ),
18105
18656
  fullPath: path22.join(
18106
- scope === "global" ? resolveHomeRelativePath(config.globalSkillDir, homeDir) : path22.resolve(cwd, config.localSkillDir),
18657
+ scope === "global" ? resolveHomeRelativePath(config2.globalSkillDir, homeDir) : path22.resolve(cwd, config2.localSkillDir),
18107
18658
  TERMINAL_PILOT_SKILL_NAME
18108
18659
  )
18109
18660
  };
@@ -18260,7 +18811,7 @@ var resize = defineCommand({
18260
18811
  });
18261
18812
 
18262
18813
  // ../terminal-png/src/index.ts
18263
- import { randomUUID as randomUUID6 } from "node:crypto";
18814
+ import { randomUUID as randomUUID10 } from "node:crypto";
18264
18815
  import { rename as rename4, rm, writeFile as writeFile6 } from "node:fs/promises";
18265
18816
 
18266
18817
  // ../terminal-png/src/ansi-parser.ts
@@ -19200,21 +19751,28 @@ async function renderTerminalPng(ansiText, options = {}) {
19200
19751
  });
19201
19752
  const png = renderPng(svg);
19202
19753
  if (options.output) {
19203
- const temporaryPath = `${options.output}.${randomUUID6()}.tmp`;
19754
+ const temporaryPath = `${options.output}.${randomUUID10()}.tmp`;
19755
+ let temporaryCreated = false;
19204
19756
  try {
19205
19757
  await writeFile6(temporaryPath, png, { flag: "wx" });
19758
+ temporaryCreated = true;
19206
19759
  await rename4(temporaryPath, options.output);
19207
19760
  } catch (error3) {
19208
- try {
19209
- await rm(temporaryPath, { force: true });
19210
- } catch (cleanupError) {
19211
- void cleanupError;
19761
+ if (temporaryCreated || !isAlreadyExistsError3(error3)) {
19762
+ try {
19763
+ await rm(temporaryPath, { force: true });
19764
+ } catch (cleanupError) {
19765
+ void cleanupError;
19766
+ }
19212
19767
  }
19213
19768
  throw error3;
19214
19769
  }
19215
19770
  }
19216
19771
  return png;
19217
19772
  }
19773
+ function isAlreadyExistsError3(error3) {
19774
+ return error3 instanceof Error && Object.prototype.hasOwnProperty.call(error3, "code") && error3.code === "EEXIST";
19775
+ }
19218
19776
 
19219
19777
  // src/commands/screenshot.ts
19220
19778
  var params11 = S.Object({
@@ -19277,7 +19835,7 @@ var type = defineCommand({
19277
19835
  });
19278
19836
 
19279
19837
  // src/commands/uninstall.ts
19280
- import { randomUUID as randomUUID7 } from "node:crypto";
19838
+ import { randomUUID as randomUUID11 } from "node:crypto";
19281
19839
  var params14 = S.Object({
19282
19840
  agent: S.Enum(installableAgents, {
19283
19841
  description: "Agent to uninstall terminal-pilot from",
@@ -19313,7 +19871,7 @@ var uninstall = defineCommand({
19313
19871
  if (!await folderExists(services.fs, skill.fullPath)) {
19314
19872
  continue;
19315
19873
  }
19316
- const stagingPath = `${skill.fullPath}.removing-${randomUUID7()}`;
19874
+ const stagingPath = `${skill.fullPath}.removing-${randomUUID11()}`;
19317
19875
  await services.fs.rename(skill.fullPath, stagingPath);
19318
19876
  staged.push({ ...skill, stagingPath });
19319
19877
  }
@@ -19339,7 +19897,7 @@ async function folderExists(fs4, folderPath) {
19339
19897
  await fs4.stat(folderPath);
19340
19898
  return true;
19341
19899
  } catch (error3) {
19342
- if (typeof error3 === "object" && error3 !== null && "code" in error3 && error3.code === "ENOENT") {
19900
+ if (hasOwnErrorCode(error3, "ENOENT")) {
19343
19901
  return false;
19344
19902
  }
19345
19903
  throw error3;
@@ -19420,6 +19978,7 @@ function createTerminalPilotGroup() {
19420
19978
  var terminalPilotGroup = Object.freeze(createTerminalPilotGroup());
19421
19979
 
19422
19980
  // src/cli.ts
19981
+ configureTheme({ brand: "green", label: "Terminal Pilot" });
19423
19982
  function normalizeArgv(argv) {
19424
19983
  if (argv.includes("--json") && !argv.some((argument) => argument === "--output" || argument.startsWith("--output="))) {
19425
19984
  return argv.flatMap((argument) => argument === "--json" ? ["--output", "json"] : [argument]);
@@ -19443,8 +20002,8 @@ async function isDirectExecution(argv) {
19443
20002
  try {
19444
20003
  const modulePath = fileURLToPath5(import.meta.url);
19445
20004
  const [resolvedEntryPoint, resolvedModulePath] = await Promise.all([
19446
- realpath2(path23.resolve(entryPoint)),
19447
- realpath2(modulePath)
20005
+ realpath3(path23.resolve(entryPoint)),
20006
+ realpath3(modulePath)
19448
20007
  ]);
19449
20008
  return resolvedEntryPoint === resolvedModulePath;
19450
20009
  } catch {