stitchkit 0.114.1 → 0.115.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/agent-runtime/coding-tool-files.d.ts.map +1 -1
  3. package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
  4. package/dist/agent-runtime/coding-tool-paths.d.ts.map +1 -1
  5. package/dist/agent-runtime/coding-tool-refusals.d.ts +6 -0
  6. package/dist/agent-runtime/coding-tool-refusals.d.ts.map +1 -1
  7. package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
  8. package/dist/agent-runtime/contained-scan.d.ts +1 -1
  9. package/dist/agent-runtime/contained-scan.d.ts.map +1 -1
  10. package/dist/agent-runtime/sandbox-broker.d.ts.map +1 -1
  11. package/dist/agent-runtime/sandbox-bubblewrap-storage.d.ts.map +1 -1
  12. package/dist/application/directory-inbox-files.d.ts.map +1 -1
  13. package/dist/application/file-state-store.d.ts.map +1 -1
  14. package/dist/entrypoints/agent-runtime/coding-tools.js +6 -4
  15. package/dist/entrypoints/agent-runtime/harness.js +2 -1
  16. package/dist/entrypoints/agent-runtime/sandbox.js +13 -8
  17. package/dist/entrypoints/agent-runtime/sqlite/bun.js +8 -6
  18. package/dist/entrypoints/agent-runtime/sqlite/node.js +8 -6
  19. package/dist/entrypoints/agent-runtime/testing.js +8 -6
  20. package/dist/entrypoints/agent-runtime.js +8 -6
  21. package/dist/entrypoints/application/diagnostic-journal.js +2 -2
  22. package/dist/entrypoints/application/directory-inbox.js +10 -7
  23. package/dist/entrypoints/cli/publish.js +11 -8
  24. package/dist/entrypoints/cli.js +6 -3
  25. package/dist/entrypoints/files.js +10 -7
  26. package/dist/entrypoints/process/owner-loss.js +1 -1
  27. package/dist/entrypoints/process.js +3 -3
  28. package/dist/entrypoints/react/keyboard/testing.js +1 -1
  29. package/dist/entrypoints/react/keyboard.js +11 -11
  30. package/dist/entrypoints/server.js +4 -4
  31. package/dist/entrypoints/telegram.js +8 -5
  32. package/dist/entrypoints/tools.js +6 -3
  33. package/dist/files/chunk-spool.d.ts.map +1 -1
  34. package/dist/{index-2f9r0jgr.js → index-364k2zwa.js} +4 -4
  35. package/dist/{index-km2qw407.js → index-3qqdqwxe.js} +91 -36
  36. package/dist/{index-s47ac8zt.js → index-7yx8j6ay.js} +133 -156
  37. package/dist/{index-kdnfe0sr.js → index-90p34rts.js} +2 -2
  38. package/dist/{index-a3462dqf.js → index-944x38nv.js} +1 -1
  39. package/dist/{index-07dcf2yn.js → index-ac6vvm30.js} +5 -2
  40. package/dist/{index-qj1sy4ep.js → index-crmswbrt.js} +1 -1
  41. package/dist/{index-7r4knwf8.js → index-dr3t5n1v.js} +14 -4
  42. package/dist/{index-dc9ere5p.js → index-dx5cm9pc.js} +1 -1
  43. package/dist/{index-84bf5spd.js → index-f6m4c545.js} +5 -2
  44. package/dist/{index-hy802jnr.js → index-fdk4r4r6.js} +6 -3
  45. package/dist/index-j8kf56wx.js +100 -0
  46. package/dist/index-jj9228tt.js +6 -0
  47. package/dist/{index-t65erk4z.js → index-mgb7r8b8.js} +122 -62
  48. package/dist/{index-bh2ht9y5.js → index-n8z3rvzw.js} +4 -1
  49. package/dist/index-nregbbsc.js +107 -0
  50. package/dist/{index-j4zh647a.js → index-tt30h7mr.js} +4 -1
  51. package/dist/{index-zrtrjkbf.js → index-x0ddbj85.js} +148 -172
  52. package/dist/{index-p02zgk8x.js → index-y4rxnvgp.js} +6 -0
  53. package/dist/{index-5v5a9k2n.js → index-z3d6smer.js} +1 -1
  54. package/dist/{index-6b3pcq5z.js → index-zqkz4af9.js} +1 -1
  55. package/dist/internal/atomic-file.d.ts.map +1 -1
  56. package/dist/internal/atomic-staging.d.ts.map +1 -1
  57. package/dist/internal/contained-directory.d.ts +20 -0
  58. package/dist/internal/contained-directory.d.ts.map +1 -0
  59. package/dist/{agent-runtime → internal}/contained-files.d.ts +14 -13
  60. package/dist/internal/contained-files.d.ts.map +1 -0
  61. package/dist/internal/contained-handle.d.ts +30 -0
  62. package/dist/internal/contained-handle.d.ts.map +1 -0
  63. package/dist/internal/contained-write.d.ts +12 -0
  64. package/dist/internal/contained-write.d.ts.map +1 -0
  65. package/dist/internal/darwin-binding.d.ts +1 -1
  66. package/dist/internal/darwin-binding.d.ts.map +1 -1
  67. package/dist/internal/errno.d.ts +3 -0
  68. package/dist/internal/errno.d.ts.map +1 -0
  69. package/dist/internal/pinned-http.d.ts +27 -0
  70. package/dist/internal/pinned-http.d.ts.map +1 -0
  71. package/dist/internal/process-instance.d.ts.map +1 -1
  72. package/dist/internal/secure-fetch.d.ts +26 -6
  73. package/dist/internal/secure-fetch.d.ts.map +1 -1
  74. package/dist/internal/write-download.d.ts +5 -14
  75. package/dist/internal/write-download.d.ts.map +1 -1
  76. package/dist/process/group-diagnostics.d.ts +1 -0
  77. package/dist/process/group-diagnostics.d.ts.map +1 -1
  78. package/dist/process/group-settlement.d.ts +2 -0
  79. package/dist/process/group-settlement.d.ts.map +1 -1
  80. package/dist/process/group.d.ts.map +1 -1
  81. package/dist/process/owner-loss-control.d.ts.map +1 -1
  82. package/dist/react/keyboard/hooks.d.ts +2 -2
  83. package/dist/react/keyboard/hooks.d.ts.map +1 -1
  84. package/dist/react/keyboard/layers.d.ts +2 -0
  85. package/dist/react/keyboard/layers.d.ts.map +1 -1
  86. package/dist/telegram/broadcast-state.d.ts.map +1 -1
  87. package/dist/tools/cli/download.d.ts.map +1 -1
  88. package/dist/tools/cli/publication-storage.d.ts.map +1 -1
  89. package/dist/tools/cli/publication.d.ts.map +1 -1
  90. package/dist/tools/cli/view.d.ts.map +1 -1
  91. package/llms/agent-runtime.txt +16 -6
  92. package/llms/cli.txt +34 -2
  93. package/llms/process.txt +2 -2
  94. package/llms/react-keyboard.txt +18 -2
  95. package/llms/stitchkit.txt +3 -3
  96. package/llms/{upgrading-0.104.0-0.114.0.txt → upgrading-0.104.0-0.115.0.txt} +62 -3
  97. package/llms/upgrading.txt +1 -1
  98. package/llms-full.txt +132 -15
  99. package/llms.txt +5 -5
  100. package/native/darwin-arm64.node +0 -0
  101. package/native/darwin-x64.node +0 -0
  102. package/native-assets.json +4 -4
  103. package/package.json +1 -1
  104. package/dist/agent-runtime/contained-darwin.d.ts +0 -21
  105. package/dist/agent-runtime/contained-darwin.d.ts.map +0 -1
  106. package/dist/agent-runtime/contained-files.d.ts.map +0 -1
  107. package/dist/agent-runtime/contained-write.d.ts +0 -9
  108. package/dist/agent-runtime/contained-write.d.ts.map +0 -1
@@ -5,7 +5,7 @@ import {
5
5
  nextZoneIndex2,
6
6
  resolveZoneIndex,
7
7
  createNavZone2
8
- } from "../../index-p02zgk8x.js";
8
+ } from "../../index-y4rxnvgp.js";
9
9
 
10
10
  // src/react/keyboard/hooks.ts
11
11
  import {
@@ -39,15 +39,13 @@ function layerState(options) {
39
39
  function useKeyLayer(options) {
40
40
  const handle = useRef(null);
41
41
  const initial = useRef(options);
42
- useEffect(() => {
43
- const added = stackOf(window).add(layerState(initial.current));
44
- handle.current = added;
45
- return () => {
46
- added.remove();
47
- handle.current = null;
48
- };
42
+ useCommittedEffect(() => {
43
+ const layer = handle.current ?? stackOf(window).add(layerState(initial.current));
44
+ handle.current = layer;
45
+ layer.restore();
46
+ return () => layer.remove();
49
47
  }, []);
50
- useEffect(() => {
48
+ useCommittedEffect(() => {
51
49
  handle.current?.update(layerState(options));
52
50
  });
53
51
  }
@@ -105,12 +103,14 @@ function useNavZone(options) {
105
103
  return {
106
104
  zoneProps: {
107
105
  ref: zoneRef,
108
- "aria-orientation": options.orientation ?? "vertical",
109
106
  [ZONE_ATTRIBUTE]: "",
110
107
  onKeyDown: (event) => {
111
108
  zone.keyDown(event.nativeEvent, element.current);
112
109
  },
113
- ...role !== "none" && { role },
110
+ ...role !== "none" && {
111
+ role,
112
+ "aria-orientation": options.orientation ?? "vertical"
113
+ },
114
114
  ...label !== undefined && { "aria-label": label }
115
115
  },
116
116
  itemProps: (id) => {
@@ -1,6 +1,6 @@
1
1
  import"../index-2kbysk9s.js";
2
- import"../index-bh2ht9y5.js";
3
- import"../index-5v5a9k2n.js";
2
+ import"../index-n8z3rvzw.js";
3
+ import"../index-z3d6smer.js";
4
4
  import {
5
5
  errorCode2,
6
6
  normalizeError2
@@ -52,11 +52,11 @@ import {
52
52
  } from "../index-p0rf7sq9.js";
53
53
  import {
54
54
  createFileStateStore2
55
- } from "../index-hy802jnr.js";
55
+ } from "../index-fdk4r4r6.js";
56
56
  import {
57
57
  bindRealtimeServer2
58
58
  } from "../index-2bqf0a74.js";
59
- import"../index-6b3pcq5z.js";
59
+ import"../index-zqkz4af9.js";
60
60
  import {
61
61
  withDeadline
62
62
  } from "../index-9tqbxv5p.js";
@@ -2,10 +2,10 @@ import {
2
2
  backoffDelay
3
3
  } from "../index-g6a3na27.js";
4
4
  import"../index-2kbysk9s.js";
5
- import"../index-bh2ht9y5.js";
5
+ import"../index-n8z3rvzw.js";
6
6
  import {
7
7
  attemptExclusiveLock
8
- } from "../index-5v5a9k2n.js";
8
+ } from "../index-z3d6smer.js";
9
9
  import {
10
10
  TELEGRAM_SEND_FAILURE_REASONS2,
11
11
  classifyTelegramSendFailure2
@@ -23,7 +23,10 @@ import {
23
23
  } from "../index-sznqf8fx.js";
24
24
  import {
25
25
  writeFileAtomic2
26
- } from "../index-07dcf2yn.js";
26
+ } from "../index-ac6vvm30.js";
27
+ import {
28
+ errnoOf
29
+ } from "../index-jj9228tt.js";
27
30
  import {
28
31
  raceAbort
29
32
  } from "../index-b0kddvzw.js";
@@ -263,7 +266,7 @@ function assertBroadcastName(name) {
263
266
  throw new TypeError("Telegram broadcast name must be 1–128 of [A-Za-z0-9._-] and start with a letter or digit");
264
267
  }
265
268
  }
266
- var absent = (error) => error instanceof Error && ("code" in error) && error.code === "ENOENT";
269
+ var absent = (error) => errnoOf(error) === "ENOENT";
267
270
  function broadcastFiles(directory, name) {
268
271
  return {
269
272
  recipients: join(directory, `${name}.recipients.json`),
@@ -292,7 +295,7 @@ async function prepareJournal(files, lock) {
292
295
  try {
293
296
  await writeFileAtomic2(files.journal, "", { replace: false, durability: "directory" });
294
297
  } catch (error) {
295
- if (!(error instanceof Error && ("code" in error) && error.code === "EEXIST"))
298
+ if (errnoOf(error) !== "EEXIST")
296
299
  throw error;
297
300
  }
298
301
  }
@@ -74,7 +74,8 @@ import {
74
74
  WaitTimeoutError,
75
75
  runWaitOperation,
76
76
  createCli2
77
- } from "../index-km2qw407.js";
77
+ } from "../index-3qqdqwxe.js";
78
+ import"../index-2kbysk9s.js";
78
79
  import {
79
80
  ManagedFilePathSchema2,
80
81
  ManagedFileRefSchema2
@@ -93,6 +94,8 @@ import {
93
94
  import {
94
95
  createToolInvoker2
95
96
  } from "../index-vwhrnp67.js";
97
+ import"../index-j8kf56wx.js";
98
+ import"../index-x0ddbj85.js";
96
99
  import {
97
100
  collectToolSurface
98
101
  } from "../index-86nbfysb.js";
@@ -105,12 +108,12 @@ import {
105
108
  } from "../index-ega3yz4c.js";
106
109
  import {
107
110
  ManagedFileError2
108
- } from "../index-2f9r0jgr.js";
111
+ } from "../index-364k2zwa.js";
109
112
  import {
110
113
  fetchGuarded,
111
114
  fetchPinnedDocument,
112
115
  readCapped
113
- } from "../index-t65erk4z.js";
116
+ } from "../index-mgb7r8b8.js";
114
117
  import"../index-1bx1xv1k.js";
115
118
  import {
116
119
  readBoundedChunks,
@@ -1 +1 @@
1
- {"version":3,"file":"chunk-spool.d.ts","sourceRoot":"","sources":["../../src/files/chunk-spool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgBH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAKnC,MAAM,MAAM,mBAAmB,GAC3B,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,GAClB,iBAAiB,GACjB,2BAA2B,GAC3B,mBAAmB,GACnB,mBAAmB,CAAC;AAYxB;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,mBAAmB,CAE/E;AAED,yCAAyC;AACzC,eAAO,MAAM,uBAAuB,EAAE,SAAS,mBAAmB,EAEjE,CAAC;AAUF,MAAM,WAAW,gBAAgB,CAAC,KAAK;IACrC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,wBAAwB;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc,CAAC,KAAK,CAAE,SAAQ,aAAa;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAC9B,uCAAuC;IACvC,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,UAAU,CAAC,KAAK;IAC/B,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IACpE,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IAC1D,4FAA4F;IAC5F,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,2EAA2E;IAC3E,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1B;AAkED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CA4J1F"}
1
+ {"version":3,"file":"chunk-spool.d.ts","sourceRoot":"","sources":["../../src/files/chunk-spool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgBH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAMnC,MAAM,MAAM,mBAAmB,GAC3B,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,GAClB,iBAAiB,GACjB,2BAA2B,GAC3B,mBAAmB,GACnB,mBAAmB,CAAC;AAYxB;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,mBAAmB,CAE/E;AAED,yCAAyC;AACzC,eAAO,MAAM,uBAAuB,EAAE,SAAS,mBAAmB,EAEjE,CAAC;AAUF,MAAM,WAAW,gBAAgB,CAAC,KAAK;IACrC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,wBAAwB;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc,CAAC,KAAK,CAAE,SAAQ,aAAa;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAC9B,uCAAuC;IACvC,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,UAAU,CAAC,KAAK;IAC/B,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IACpE,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IAC1D,4FAA4F;IAC5F,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,2EAA2E;IAC3E,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1B;AAkED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CA4J1F"}
@@ -2,17 +2,17 @@ import {
2
2
  ManagedFilePathSchema2,
3
3
  ManagedFileRefSchema2
4
4
  } from "./index-xqhede6x.js";
5
+ import {
6
+ isWithinDir2
7
+ } from "./index-5cc6r990.js";
5
8
  import {
6
9
  BoundedFileReadError,
7
10
  readBoundedFile
8
11
  } from "./index-m616f0yz.js";
9
- import {
10
- isWithinDir2
11
- } from "./index-5cc6r990.js";
12
12
  import {
13
13
  writeAllBytes,
14
14
  writeAtomicFileStaged
15
- } from "./index-07dcf2yn.js";
15
+ } from "./index-ac6vvm30.js";
16
16
  import {
17
17
  AtomicFilePublicationError2
18
18
  } from "./index-b56nnscm.js";
@@ -23,16 +23,24 @@ import {
23
23
  createToolRunner,
24
24
  formatToolError
25
25
  } from "./index-htxh46ej.js";
26
+ import {
27
+ writeContainedFile
28
+ } from "./index-j8kf56wx.js";
29
+ import {
30
+ openPinnedDirectory,
31
+ isSafeEntryName,
32
+ containedEntryMetadata
33
+ } from "./index-x0ddbj85.js";
26
34
  import {
27
35
  collectToolSurface
28
36
  } from "./index-86nbfysb.js";
29
37
  import {
30
38
  fetchGuarded,
31
39
  readCapped
32
- } from "./index-t65erk4z.js";
40
+ } from "./index-mgb7r8b8.js";
33
41
  import {
34
- isWithinDir2
35
- } from "./index-5cc6r990.js";
42
+ errnoOf
43
+ } from "./index-jj9228tt.js";
36
44
  import {
37
45
  sleep
38
46
  } from "./index-eemvahkc.js";
@@ -1298,10 +1306,13 @@ function selectRecords(data) {
1298
1306
  }
1299
1307
  throw new CliArgumentError2("an aggregate needs a collection; this result is not one");
1300
1308
  }
1309
+ function isAbsent(value) {
1310
+ return value === undefined || value === null;
1311
+ }
1301
1312
  function readField(record, path) {
1302
1313
  let current = record;
1303
1314
  for (const segment of path) {
1304
- if (!isRecord(current))
1315
+ if (!isRecord(current) || !Object.hasOwn(current, segment))
1305
1316
  return;
1306
1317
  current = current[segment];
1307
1318
  }
@@ -1326,7 +1337,7 @@ function availableFields(records) {
1326
1337
  function assertFieldPresent(records, field) {
1327
1338
  const path = fieldPath(field);
1328
1339
  const present = records.some((record) => readField(record, path) !== undefined);
1329
- if (!present) {
1340
+ if (records.length > 0 && !present) {
1330
1341
  const available = availableFields(records);
1331
1342
  throw new CliArgumentError2(`no record carries the field "${field}"${available.length > 0 ? ` — available: ${available.join(", ")}` : ""}`);
1332
1343
  }
@@ -1347,7 +1358,7 @@ function ordered(totals, top) {
1347
1358
  return Object.fromEntries(sliced);
1348
1359
  }
1349
1360
  function numericValue(value, field) {
1350
- if (value === undefined || value === null)
1361
+ if (isAbsent(value))
1351
1362
  return;
1352
1363
  if (typeof value === "number" && Number.isFinite(value))
1353
1364
  return value;
@@ -1355,8 +1366,8 @@ function numericValue(value, field) {
1355
1366
  return Number(value);
1356
1367
  throw new CliArgumentError2(`--sum ${field}: "${groupKey(value)}" is not a number`);
1357
1368
  }
1358
- function renderTable(records, fields) {
1359
- const paths = fields.map((field) => assertFieldPresent(records, field));
1369
+ function renderTable(records, columns) {
1370
+ const fields = columns.map(({ field }) => field);
1360
1371
  const cell = (value) => {
1361
1372
  if (value === undefined)
1362
1373
  return "";
@@ -1366,7 +1377,7 @@ function renderTable(records, fields) {
1366
1377
  return JSON.stringify(value);
1367
1378
  return String(value);
1368
1379
  };
1369
- const rows = records.map((record) => paths.map((path) => cell(readField(record, path))));
1380
+ const rows = records.map((record) => columns.map(({ path }) => cell(readField(record, path))));
1370
1381
  const widths = fields.map((field, column) => Math.max(field.length, ...rows.map((row) => row[column]?.length ?? 0)));
1371
1382
  const line = (cells) => cells.map((value, column) => value.padEnd(widths[column] ?? value.length)).join(" ").trimEnd();
1372
1383
  return `${[line(fields), line(widths.map((width) => "-".repeat(width))), ...rows.map(line)].join(`
@@ -1374,9 +1385,9 @@ function renderTable(records, fields) {
1374
1385
  `;
1375
1386
  }
1376
1387
  function compareFieldValues(left, right) {
1377
- if (left === undefined || left === null)
1378
- return right === undefined || right === null ? 0 : 1;
1379
- if (right === undefined || right === null)
1388
+ if (isAbsent(left))
1389
+ return isAbsent(right) ? 0 : 1;
1390
+ if (isAbsent(right))
1380
1391
  return -1;
1381
1392
  if (typeof left === "number" && typeof right === "number")
1382
1393
  return left - right;
@@ -1391,17 +1402,35 @@ function renderRecords(records, view) {
1391
1402
  const path = assertFieldPresent(records, view.sort);
1392
1403
  const direction = view.ascending ? 1 : -1;
1393
1404
  selected.sort((left, right) => {
1394
- const order = compareFieldValues(readField(left, path), readField(right, path));
1395
- const absent = readField(left, path) === undefined || readField(right, path) === undefined;
1396
- return absent ? order : order * direction;
1405
+ const leftValue = readField(left, path);
1406
+ const rightValue = readField(right, path);
1407
+ const order = compareFieldValues(leftValue, rightValue);
1408
+ return isAbsent(leftValue) || isAbsent(rightValue) ? order : order * direction;
1397
1409
  });
1398
1410
  }
1411
+ const columns = view.table?.map((field) => ({
1412
+ field,
1413
+ path: assertFieldPresent(records, field)
1414
+ }));
1399
1415
  if (view.top !== undefined)
1400
1416
  selected = selected.slice(0, view.top);
1401
- return view.table ? { kind: "text", text: renderTable(selected, view.table) } : { kind: "json", data: selected };
1417
+ return columns ? { kind: "text", text: renderTable(selected, columns) } : { kind: "json", data: selected };
1418
+ }
1419
+ function refuseEnvelopeFields(data, view) {
1420
+ if (!isRecord(data))
1421
+ return;
1422
+ const fields = view.kind === "records" ? [...view.sort === undefined ? [] : [view.sort], ...view.table ?? []] : [view.field, ...view.kind === "sum" && view.by !== undefined ? [view.by] : []];
1423
+ for (const field of fields) {
1424
+ const first = field.split(".")[0] ?? "";
1425
+ if (Object.hasOwn(data, first) && !Array.isArray(data[first])) {
1426
+ throw new CliArgumentError2(`"${field}" belongs to the result object, not to its empty collection`);
1427
+ }
1428
+ }
1402
1429
  }
1403
1430
  function renderCliView2(data, view) {
1404
1431
  const records = selectRecords(data);
1432
+ if (records.length === 0)
1433
+ refuseEnvelopeFields(data, view);
1405
1434
  if (view.kind === "records")
1406
1435
  return renderRecords(records, view);
1407
1436
  if (view.kind === "count") {
@@ -1646,37 +1675,63 @@ function createCliIo(config) {
1646
1675
  import { basename, resolve } from "node:path";
1647
1676
 
1648
1677
  // src/internal/write-download.ts
1649
- import { mkdir, writeFile } from "node:fs/promises";
1650
- import { dirname } from "node:path";
1651
- async function writeDownload(root, target, data) {
1652
- if (!isWithinDir2(root, target)) {
1678
+ import path from "node:path";
1679
+ async function writeDownload(root, name, data) {
1680
+ if (!isSafeEntryName(name) || path.basename(name) !== name) {
1653
1681
  throw new Error("download name escapes the output dir");
1654
1682
  }
1655
- await mkdir(dirname(target), { recursive: true });
1656
- await writeFile(target, data);
1683
+ const parent = { handle: root, basename: name };
1684
+ const metadata = await containedEntryMetadata(parent);
1685
+ await writeContainedFile({
1686
+ parent,
1687
+ content: data,
1688
+ replace: true,
1689
+ ...metadata?.isFile() && { mode: metadata.mode }
1690
+ });
1657
1691
  }
1658
1692
 
1659
1693
  // src/tools/cli/download.ts
1660
1694
  var DEFAULT_DOWNLOAD_MAX_BYTES = 100 * 1024 * 1024;
1661
1695
  async function downloadResults(files, dir, stderr, quiet, allowPrivate, maxBytes, timeoutMs) {
1662
1696
  const root = resolve(dir);
1697
+ if (files.length === 0)
1698
+ return true;
1699
+ let directory;
1700
+ try {
1701
+ directory = await openPinnedDirectory(root, { create: true, readable: false });
1702
+ } catch (error) {
1703
+ stderr(`failed to prepare download directory: ${error instanceof Error ? error.message : String(error)}
1704
+ `);
1705
+ return false;
1706
+ }
1663
1707
  let succeeded = true;
1664
- for (const file of files) {
1665
- try {
1666
- const res = await fetchGuarded(new URL(file.url), allowPrivate, { timeoutMs });
1667
- if (!res.ok)
1668
- throw new Error(`HTTP ${res.status}`);
1669
- const buffer = await readCapped(res, maxBytes);
1670
- if (!buffer)
1671
- throw new Error(`file exceeds the ${maxBytes}-byte cap`);
1672
- const target = resolve(root, basename(file.name));
1673
- await writeDownload(root, target, buffer);
1674
- if (!quiet)
1675
- stderr(`saved ${target} (${(buffer.length / 1024).toFixed(0)}KB)
1708
+ try {
1709
+ for (const file of files) {
1710
+ try {
1711
+ const res = await fetchGuarded(new URL(file.url), allowPrivate, { timeoutMs });
1712
+ if (!res.ok)
1713
+ throw new Error(`HTTP ${res.status}`);
1714
+ const buffer = await readCapped(res, maxBytes);
1715
+ if (!buffer)
1716
+ throw new Error(`file exceeds the ${maxBytes}-byte cap`);
1717
+ const name = basename(file.name);
1718
+ await writeDownload(directory, name, buffer);
1719
+ if (!quiet)
1720
+ stderr(`saved ${resolve(root, name)} (${(buffer.length / 1024).toFixed(0)}KB)
1676
1721
  `);
1677
- } catch (err) {
1722
+ } catch (err) {
1723
+ succeeded = false;
1724
+ const reason = errnoOf(err) ?? (err instanceof Error ? err.message : String(err));
1725
+ stderr(`failed to download ${file.url}: ${reason}
1726
+ `);
1727
+ }
1728
+ }
1729
+ } finally {
1730
+ try {
1731
+ await directory.close();
1732
+ } catch (error) {
1678
1733
  succeeded = false;
1679
- stderr(`failed to download ${file.url}: ${err instanceof Error ? err.message : String(err)}
1734
+ stderr(`failed to close download directory: ${error instanceof Error ? error.message : String(error)}
1680
1735
  `);
1681
1736
  }
1682
1737
  }