stitchkit 0.114.0 → 0.114.2

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 (94) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +1 -1
  3. package/dist/browser/client-url.d.ts.map +1 -1
  4. package/dist/entrypoints/agent-runtime/coding-tools.js +1 -1
  5. package/dist/entrypoints/agent-runtime/harness.js +4 -4
  6. package/dist/entrypoints/agent-runtime/realtime.js +2 -2
  7. package/dist/entrypoints/agent-runtime/sandbox.js +3 -3
  8. package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
  9. package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
  10. package/dist/entrypoints/agent-runtime/testing.js +4 -4
  11. package/dist/entrypoints/agent-runtime.js +12 -12
  12. package/dist/entrypoints/application/directory-inbox.js +3 -3
  13. package/dist/entrypoints/application.js +4 -4
  14. package/dist/entrypoints/cli/publish.js +1 -1
  15. package/dist/entrypoints/cli.js +4 -4
  16. package/dist/entrypoints/contract.js +2 -2
  17. package/dist/entrypoints/http.js +2 -2
  18. package/dist/entrypoints/index.js +5 -5
  19. package/dist/entrypoints/node.js +3 -3
  20. package/dist/entrypoints/observability.js +3 -3
  21. package/dist/entrypoints/react/keyboard/testing.d.ts +2 -0
  22. package/dist/entrypoints/react/keyboard/testing.d.ts.map +1 -0
  23. package/dist/entrypoints/react/keyboard/testing.js +127 -0
  24. package/dist/entrypoints/react/keyboard.d.ts +4 -2
  25. package/dist/entrypoints/react/keyboard.d.ts.map +1 -1
  26. package/dist/entrypoints/react/keyboard.js +83 -319
  27. package/dist/entrypoints/react.js +15 -3
  28. package/dist/entrypoints/realtime.js +1 -1
  29. package/dist/entrypoints/remote.js +1 -1
  30. package/dist/entrypoints/server.js +18 -18
  31. package/dist/entrypoints/telegram/grammy.d.ts +2 -0
  32. package/dist/entrypoints/telegram/grammy.d.ts.map +1 -0
  33. package/dist/entrypoints/telegram/grammy.js +50 -0
  34. package/dist/entrypoints/telegram/screens.js +1 -1
  35. package/dist/entrypoints/telegram.js +16 -10
  36. package/dist/entrypoints/testing.js +3 -3
  37. package/dist/entrypoints/tools/connections.js +10 -10
  38. package/dist/entrypoints/tools.js +19 -19
  39. package/dist/entrypoints/tracking.js +1 -1
  40. package/dist/{index-hs35ss3p.js → index-61hve0ez.js} +4 -25
  41. package/dist/index-6j725ez5.js +25 -0
  42. package/dist/{index-1csp1hwm.js → index-6p3frkv5.js} +1 -1
  43. package/dist/{index-erv5shjq.js → index-912sza5h.js} +1 -1
  44. package/dist/{index-fy4av0hq.js → index-9bwcthxw.js} +1 -1
  45. package/dist/{index-523tq7y4.js → index-a3462dqf.js} +1 -1
  46. package/dist/{index-506kd458.js → index-aw6zahv1.js} +1 -1
  47. package/dist/{index-tpwbct8j.js → index-dc9ere5p.js} +1 -1
  48. package/dist/{index-cxpcdswt.js → index-mgb7r8b8.js} +123 -63
  49. package/dist/{index-7fc0c2np.js → index-n3v695sb.js} +1 -1
  50. package/dist/index-p02zgk8x.js +351 -0
  51. package/dist/{index-vtann8bz.js → index-p0rf7sq9.js} +8 -8
  52. package/dist/{index-aykhzcnf.js → index-qj1sy4ep.js} +1 -1
  53. package/dist/{index-k7z3j3hr.js → index-tnxsq7cw.js} +4 -4
  54. package/dist/{index-c5at3ykd.js → index-tsngj2b5.js} +22 -10
  55. package/dist/internal/pinned-http.d.ts +27 -0
  56. package/dist/internal/pinned-http.d.ts.map +1 -0
  57. package/dist/internal/secure-fetch.d.ts +26 -6
  58. package/dist/internal/secure-fetch.d.ts.map +1 -1
  59. package/dist/react/entity-cache.d.ts +24 -2
  60. package/dist/react/entity-cache.d.ts.map +1 -1
  61. package/dist/react/keyboard/hooks.d.ts +41 -10
  62. package/dist/react/keyboard/hooks.d.ts.map +1 -1
  63. package/dist/react/keyboard/layers.d.ts +27 -8
  64. package/dist/react/keyboard/layers.d.ts.map +1 -1
  65. package/dist/react/keyboard/modality.d.ts +21 -0
  66. package/dist/react/keyboard/modality.d.ts.map +1 -0
  67. package/dist/react/keyboard/refs.d.ts +13 -0
  68. package/dist/react/keyboard/refs.d.ts.map +1 -0
  69. package/dist/react/keyboard/testing.d.ts +80 -0
  70. package/dist/react/keyboard/testing.d.ts.map +1 -0
  71. package/dist/react/keyboard/zone.d.ts +60 -10
  72. package/dist/react/keyboard/zone.d.ts.map +1 -1
  73. package/dist/telegram/budget-transformer.d.ts +35 -0
  74. package/dist/telegram/budget-transformer.d.ts.map +1 -0
  75. package/dist/telegram/outbound-budget.d.ts +4 -2
  76. package/dist/telegram/outbound-budget.d.ts.map +1 -1
  77. package/llms/react-keyboard-testing.txt +24 -0
  78. package/llms/react-keyboard.txt +264 -4
  79. package/llms/react.txt +1 -1
  80. package/llms/server.3.txt +31 -0
  81. package/llms/stitchkit.2.txt +118 -0
  82. package/llms/stitchkit.txt +4 -118
  83. package/llms/telegram-grammy.txt +22 -0
  84. package/llms/telegram.txt +19 -7
  85. package/llms-full.txt +345 -12
  86. package/llms.txt +7 -5
  87. package/package.json +9 -1
  88. package/dist/{index-616xh7f2.js → index-4qnzda76.js} +0 -0
  89. package/dist/{index-fsw1ybf3.js → index-d9hq291n.js} +3 -3
  90. package/dist/{index-bjcjqj46.js → index-m8a44e64.js} +3 -3
  91. package/dist/{index-5efrpfmj.js → index-qndsr7f0.js} +3 -3
  92. package/dist/{index-zktz242w.js → index-s47ac8zt.js} +3 -3
  93. package/dist/{index-56yx8dxp.js → index-tvtacc9a.js} +3 -3
  94. /package/dist/{index-v1tswj0z.js → index-txg1npmg.js} +0 -0
@@ -7,15 +7,20 @@ import {
7
7
  attemptExclusiveLock
8
8
  } from "../index-5v5a9k2n.js";
9
9
  import {
10
- TelegramNotDispatchedError2,
11
- isTelegramNotDispatchedError,
12
10
  TELEGRAM_SEND_FAILURE_REASONS2,
13
11
  classifyTelegramSendFailure2
14
- } from "../index-hs35ss3p.js";
12
+ } from "../index-61hve0ez.js";
13
+ import {
14
+ TelegramNotDispatchedError2,
15
+ isTelegramNotDispatchedError
16
+ } from "../index-6j725ez5.js";
15
17
  import {
16
18
  TELEGRAM_TEXT_LIMIT2,
17
19
  truncateTelegramHtml2
18
20
  } from "../index-nmaqxdx7.js";
21
+ import {
22
+ BOT_TOKEN_SECRET
23
+ } from "../index-sznqf8fx.js";
19
24
  import {
20
25
  writeFileAtomic2
21
26
  } from "../index-07dcf2yn.js";
@@ -26,15 +31,12 @@ import {
26
31
  MAX_TIMER_MS,
27
32
  sleep
28
33
  } from "../index-eemvahkc.js";
29
- import {
30
- assertPositiveSafeInteger
31
- } from "../index-0s4xebbg.js";
32
- import {
33
- BOT_TOKEN_SECRET
34
- } from "../index-sznqf8fx.js";
35
34
  import {
36
35
  untilAborted
37
36
  } from "../index-a5qr2rj6.js";
37
+ import {
38
+ assertPositiveSafeInteger
39
+ } from "../index-0s4xebbg.js";
38
40
  import {
39
41
  argumentsDigest
40
42
  } from "../index-r7a7r7ha.js";
@@ -1087,12 +1089,16 @@ function createBudget(rate, fallback, now, sleepFor) {
1087
1089
  await acquire(cost, signal);
1088
1090
  if (signal?.aborted)
1089
1091
  throw signal.reason;
1092
+ let result;
1090
1093
  try {
1091
- return await send();
1094
+ result = await send();
1092
1095
  } catch (error) {
1093
1096
  pauseAfter(error);
1094
1097
  throw error;
1095
1098
  }
1099
+ if (isRecord(result) && result.ok === false)
1100
+ pauseAfter(result);
1101
+ return result;
1096
1102
  };
1097
1103
  const budget = {
1098
1104
  run,
@@ -6,7 +6,7 @@ import"../index-p6apg0jg.js";
6
6
  import"../index-q0th8q0z.js";
7
7
  import {
8
8
  createApplication2
9
- } from "../index-v1tswj0z.js";
9
+ } from "../index-txg1npmg.js";
10
10
  import"../index-w5s3xftz.js";
11
11
  import {
12
12
  RealtimeRequestTimeoutError2,
@@ -15,7 +15,7 @@ import {
15
15
  } from "../index-4s0fep5q.js";
16
16
  import {
17
17
  TOOL_TRANSPORTS2
18
- } from "../index-fsw1ybf3.js";
18
+ } from "../index-d9hq291n.js";
19
19
  import {
20
20
  RealtimeRejectDirectionSchema,
21
21
  RealtimeRejectPhaseSchema,
@@ -35,7 +35,7 @@ import"../index-k42ckyzx.js";
35
35
  import {
36
36
  createClient2,
37
37
  createClients2
38
- } from "../index-c5at3ykd.js";
38
+ } from "../index-tsngj2b5.js";
39
39
  import {
40
40
  assertPositiveSafeInteger
41
41
  } from "../index-0s4xebbg.js";
@@ -11,28 +11,28 @@ import {
11
11
  import {
12
12
  withSignalDeadline
13
13
  } from "../../index-9tqbxv5p.js";
14
+ import {
15
+ defineRuntimeTool2
16
+ } from "../../index-ega3yz4c.js";
17
+ import {
18
+ TOOL_ERROR_PROJECTION
19
+ } from "../../index-98hv3sba.js";
14
20
  import {
15
21
  raceAbort
16
22
  } from "../../index-b0kddvzw.js";
17
23
  import {
18
24
  readBoundedChunks,
19
25
  concatChunks
20
- } from "../../index-5efrpfmj.js";
26
+ } from "../../index-qndsr7f0.js";
21
27
  import {
22
28
  MAX_TIMER_MS
23
29
  } from "../../index-eemvahkc.js";
24
- import {
25
- assertPositiveSafeInteger
26
- } from "../../index-0s4xebbg.js";
27
- import {
28
- defineRuntimeTool2
29
- } from "../../index-ega3yz4c.js";
30
- import {
31
- TOOL_ERROR_PROJECTION
32
- } from "../../index-98hv3sba.js";
33
30
  import {
34
31
  safeJsonParse
35
32
  } from "../../index-zsarb5xp.js";
33
+ import {
34
+ assertPositiveSafeInteger
35
+ } from "../../index-0s4xebbg.js";
36
36
  import {
37
37
  AppError2,
38
38
  STITCH_ERROR_STATUS2,
@@ -5,7 +5,7 @@ import {
5
5
  createLocalStepDurability2,
6
6
  AgentToolError2,
7
7
  isAgentToolError2
8
- } from "../index-56yx8dxp.js";
8
+ } from "../index-tvtacc9a.js";
9
9
  import {
10
10
  normalizeError2
11
11
  } from "../index-k42ckyzx.js";
@@ -33,13 +33,13 @@ import {
33
33
  mountAgent2,
34
34
  describeToolCatalog2,
35
35
  buildToolManifest2
36
- } from "../index-1csp1hwm.js";
36
+ } from "../index-6p3frkv5.js";
37
37
  import"../index-m38ej7e5.js";
38
38
  import {
39
39
  ALL_TRANSPORTS2,
40
40
  TOOL_TRANSPORTS2,
41
41
  defineContract2
42
- } from "../index-fsw1ybf3.js";
42
+ } from "../index-d9hq291n.js";
43
43
  import {
44
44
  PROTECTED_RESOURCE_PATH2,
45
45
  protectedResourceMetadataUrl2,
@@ -74,7 +74,7 @@ import {
74
74
  WaitTimeoutError,
75
75
  runWaitOperation,
76
76
  createCli2
77
- } from "../index-k7z3j3hr.js";
77
+ } from "../index-tnxsq7cw.js";
78
78
  import {
79
79
  ManagedFilePathSchema2,
80
80
  ManagedFileRefSchema2
@@ -87,9 +87,22 @@ import {
87
87
  contractOnlyService,
88
88
  mediaTypeEssence
89
89
  } from "../index-cqmqyjax.js";
90
+ import {
91
+ DEFAULT_CORS_ALLOW_HEADERS2
92
+ } from "../index-yk4g8805.js";
90
93
  import {
91
94
  createToolInvoker2
92
95
  } from "../index-vwhrnp67.js";
96
+ import {
97
+ collectToolSurface
98
+ } from "../index-86nbfysb.js";
99
+ import {
100
+ getTraceId2
101
+ } from "../index-r6v4mc67.js";
102
+ import {
103
+ defineRuntimeTool2,
104
+ createRuntimeToolFactory2
105
+ } from "../index-ega3yz4c.js";
93
106
  import {
94
107
  ManagedFileError2
95
108
  } from "../index-2f9r0jgr.js";
@@ -97,28 +110,15 @@ import {
97
110
  fetchGuarded,
98
111
  fetchPinnedDocument,
99
112
  readCapped
100
- } from "../index-cxpcdswt.js";
113
+ } from "../index-mgb7r8b8.js";
101
114
  import"../index-1bx1xv1k.js";
102
115
  import {
103
116
  readBoundedChunks,
104
117
  concatChunks
105
- } from "../index-5efrpfmj.js";
118
+ } from "../index-qndsr7f0.js";
106
119
  import {
107
120
  assertPositiveSafeInteger
108
121
  } from "../index-0s4xebbg.js";
109
- import {
110
- DEFAULT_CORS_ALLOW_HEADERS2
111
- } from "../index-yk4g8805.js";
112
- import {
113
- collectToolSurface
114
- } from "../index-86nbfysb.js";
115
- import {
116
- getTraceId2
117
- } from "../index-r6v4mc67.js";
118
- import {
119
- defineRuntimeTool2,
120
- createRuntimeToolFactory2
121
- } from "../index-ega3yz4c.js";
122
122
  import {
123
123
  formatZodError2
124
124
  } from "../index-1eeqpadm.js";
@@ -1,7 +1,7 @@
1
1
  import"../index-m38ej7e5.js";
2
2
  import {
3
3
  defineContract2
4
- } from "../index-fsw1ybf3.js";
4
+ } from "../index-d9hq291n.js";
5
5
  import {
6
6
  ApiError2
7
7
  } from "../index-kfjkb396.js";
@@ -1,31 +1,10 @@
1
+ import {
2
+ isTelegramNotDispatched
3
+ } from "./index-6j725ez5.js";
1
4
  import {
2
5
  isRecord
3
6
  } from "./index-9jfdm5tg.js";
4
7
 
5
- // src/telegram/not-dispatched.ts
6
- class TelegramNotDispatchedError2 extends Error {
7
- stage;
8
- name = "TelegramNotDispatchedError";
9
- code = "TELEGRAM_NOT_DISPATCHED";
10
- constructor(stage, message, options) {
11
- super(message, options);
12
- this.stage = stage;
13
- }
14
- }
15
- function isTelegramNotDispatchedError(error) {
16
- return error instanceof TelegramNotDispatchedError2 || error instanceof Error && error.name === "TelegramNotDispatchedError" && Reflect.get(error, "code") === "TELEGRAM_NOT_DISPATCHED";
17
- }
18
- function isTelegramNotDispatched(error, depth = 0) {
19
- if (error instanceof TelegramNotDispatchedError2)
20
- return true;
21
- if (typeof error !== "object" || error === null || depth > 4)
22
- return false;
23
- if (Reflect.get(error, "code") === "TELEGRAM_NOT_DISPATCHED")
24
- return true;
25
- const nested = Reflect.get(error, "cause") ?? Reflect.get(error, "error");
26
- return nested !== error && isTelegramNotDispatched(nested, depth + 1);
27
- }
28
-
29
8
  // src/telegram/send-failure.ts
30
9
  var BY_DESCRIPTION = [
31
10
  [/bot was blocked by the user|bot was kicked/i, "blocked-by-user"],
@@ -176,4 +155,4 @@ function classifyTelegramEditRefusal(error) {
176
155
  return "other";
177
156
  }
178
157
 
179
- export { TelegramNotDispatchedError2, isTelegramNotDispatchedError, TELEGRAM_SEND_FAILURE_REASONS2, classifyTelegramSendFailure2, classifyTelegramEditRefusal };
158
+ export { TELEGRAM_SEND_FAILURE_REASONS2, classifyTelegramSendFailure2, classifyTelegramEditRefusal };
@@ -0,0 +1,25 @@
1
+ // src/telegram/not-dispatched.ts
2
+ class TelegramNotDispatchedError2 extends Error {
3
+ stage;
4
+ name = "TelegramNotDispatchedError";
5
+ code = "TELEGRAM_NOT_DISPATCHED";
6
+ constructor(stage, message, options) {
7
+ super(message, options);
8
+ this.stage = stage;
9
+ }
10
+ }
11
+ function isTelegramNotDispatchedError(error) {
12
+ return error instanceof TelegramNotDispatchedError2 || error instanceof Error && error.name === "TelegramNotDispatchedError" && Reflect.get(error, "code") === "TELEGRAM_NOT_DISPATCHED";
13
+ }
14
+ function isTelegramNotDispatched(error, depth = 0) {
15
+ if (error instanceof TelegramNotDispatchedError2)
16
+ return true;
17
+ if (typeof error !== "object" || error === null || depth > 4)
18
+ return false;
19
+ if (Reflect.get(error, "code") === "TELEGRAM_NOT_DISPATCHED")
20
+ return true;
21
+ const nested = Reflect.get(error, "cause") ?? Reflect.get(error, "error");
22
+ return nested !== error && isTelegramNotDispatched(nested, depth + 1);
23
+ }
24
+
25
+ export { TelegramNotDispatchedError2, isTelegramNotDispatchedError, isTelegramNotDispatched };
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  AgentToolError2,
12
12
  resolveToolDurability
13
- } from "./index-56yx8dxp.js";
13
+ } from "./index-tvtacc9a.js";
14
14
  import {
15
15
  collectToolSurface
16
16
  } from "./index-86nbfysb.js";
@@ -5,7 +5,7 @@ import {
5
5
  fetchGuarded,
6
6
  PrivateAddressRefusal,
7
7
  readCapped
8
- } from "./index-cxpcdswt.js";
8
+ } from "./index-mgb7r8b8.js";
9
9
  import {
10
10
  writeFileAtomicSync2
11
11
  } from "./index-07dcf2yn.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineContract2
3
- } from "./index-fsw1ybf3.js";
3
+ } from "./index-d9hq291n.js";
4
4
  import {
5
5
  bytesToBase64Url,
6
6
  base64UrlToBytes
@@ -4,7 +4,7 @@ import {
4
4
  AgentSandboxRestrictionSchema2,
5
5
  AgentSandboxGradeSchema2,
6
6
  AGENT_CODING_TOOL_NAMES
7
- } from "./index-zktz242w.js";
7
+ } from "./index-s47ac8zt.js";
8
8
  import {
9
9
  AgentRecordIdSchema2,
10
10
  AgentRecordVersionSchema2,
@@ -4,7 +4,7 @@ import {
4
4
  } from "./index-b0w7rbpt.js";
5
5
  import {
6
6
  createAgentRuntimeEventSink2
7
- } from "./index-616xh7f2.js";
7
+ } from "./index-4qnzda76.js";
8
8
  import {
9
9
  assertPositiveSafeInteger
10
10
  } from "./index-0s4xebbg.js";
@@ -17,7 +17,7 @@ import {
17
17
  replaceMessage,
18
18
  ArchiveSpillSchema,
19
19
  createAgentRuntimeStore2
20
- } from "./index-523tq7y4.js";
20
+ } from "./index-a3462dqf.js";
21
21
 
22
22
  // src/agent-runtime/store-memory.ts
23
23
  import { z as z2 } from "zod";
@@ -3,13 +3,92 @@ import {
3
3
  } from "./index-b0kddvzw.js";
4
4
  import {
5
5
  readBoundedChunks
6
- } from "./index-5efrpfmj.js";
6
+ } from "./index-qndsr7f0.js";
7
7
 
8
8
  // src/internal/secure-fetch.ts
9
9
  import { lookup } from "node:dns/promises";
10
+ import { isIP } from "node:net";
11
+
12
+ // src/internal/pinned-http.ts
10
13
  import { request as httpRequest } from "node:http";
11
14
  import { request as httpsRequest } from "node:https";
12
- import { isIP } from "node:net";
15
+ async function requestPinned(url, resolved, signal, headers = {}) {
16
+ const transport = url.protocol === "https:" ? httpsRequest : httpRequest;
17
+ const incoming = await new Promise((resolve, reject) => {
18
+ let answered = false;
19
+ const request = transport({
20
+ protocol: url.protocol,
21
+ hostname: resolved.address,
22
+ family: resolved.family,
23
+ port: url.port || undefined,
24
+ path: `${url.pathname}${url.search}`,
25
+ method: "GET",
26
+ signal,
27
+ ...url.protocol === "https:" ? { servername: url.hostname } : {},
28
+ headers: { host: url.host, accept: "*/*", ...headers }
29
+ }, (response) => {
30
+ answered = true;
31
+ resolve(response);
32
+ });
33
+ request.once("error", (error) => {
34
+ if (answered)
35
+ return;
36
+ reject(signal?.aborted && signal.reason !== undefined ? signal.reason : error);
37
+ });
38
+ request.end();
39
+ });
40
+ return pinnedResponse(incoming);
41
+ }
42
+ function pinnedResponse(incoming) {
43
+ const status = incoming.statusCode ?? 0;
44
+ const headers = new Headers;
45
+ for (const [name, value] of Object.entries(incoming.headers)) {
46
+ if (Array.isArray(value)) {
47
+ for (const item of value)
48
+ headers.append(name, item);
49
+ } else if (value !== undefined) {
50
+ headers.set(name, value);
51
+ }
52
+ }
53
+ if (status === 204 || status === 205 || status === 304) {
54
+ incoming.resume();
55
+ return new Response(null, { status, statusText: incoming.statusMessage, headers });
56
+ }
57
+ let done = false;
58
+ const body = new ReadableStream({
59
+ start(controller) {
60
+ incoming.on("data", (chunk) => {
61
+ if (done)
62
+ return;
63
+ controller.enqueue(chunk);
64
+ if ((controller.desiredSize ?? 1) <= 0)
65
+ incoming.pause();
66
+ });
67
+ incoming.once("end", () => {
68
+ if (done)
69
+ return;
70
+ done = true;
71
+ controller.close();
72
+ });
73
+ incoming.once("error", (error) => {
74
+ if (done)
75
+ return;
76
+ done = true;
77
+ controller.error(error);
78
+ });
79
+ },
80
+ pull() {
81
+ incoming.resume();
82
+ },
83
+ cancel() {
84
+ done = true;
85
+ incoming.destroy();
86
+ }
87
+ });
88
+ return new Response(body, { status, statusText: incoming.statusMessage, headers });
89
+ }
90
+
91
+ // src/internal/secure-fetch.ts
13
92
  var NUMERIC_HOST = /^(0x[0-9a-f]+|[0-9.]+)$/i;
14
93
  var MAX_REDIRECTS = 5;
15
94
  function assertHttpUrl(url) {
@@ -102,9 +181,10 @@ function isPrivateIp(ip) {
102
181
  }
103
182
  return false;
104
183
  }
105
- async function assertPublicUrl(url, signal) {
106
- await resolvePublicAddress(url, signal);
107
- }
184
+ var defaultLookup = async (host) => {
185
+ const records = await lookup(host, { all: true });
186
+ return Array.isArray(records) ? records : [records];
187
+ };
108
188
  async function fetchGuarded(start, allowPrivate, options = {}) {
109
189
  const timeoutMs = options.timeoutMs ?? 15000;
110
190
  const bodyTimeoutMs = options.bodyTimeoutMs ?? 120000;
@@ -120,15 +200,16 @@ async function fetchGuarded(start, allowPrivate, options = {}) {
120
200
  controller.abort(new Error(`fetch did not produce response headers within ${timeoutMs}ms`));
121
201
  }, timeoutMs);
122
202
  headerTimer.unref?.();
203
+ const transport = options.transport ?? requestPinned;
123
204
  let settled = false;
124
205
  try {
125
206
  let url = start;
126
207
  for (let hop = 0;hop <= MAX_REDIRECTS; hop++) {
127
- if (allowPrivate)
128
- assertHttpUrl(url);
129
- else
130
- await assertPublicUrl(url, signal);
131
- const res = await fetch(url, { redirect: "manual", signal });
208
+ if (url.username || url.password) {
209
+ throw new Error("refusing to fetch a URL that carries credentials");
210
+ }
211
+ const resolved = await resolveAddress(url, allowPrivate, signal, options.dns);
212
+ const res = await transport(url, resolved, signal);
132
213
  const location = res.status >= 300 && res.status < 400 ? res.headers.get("location") : null;
133
214
  if (location === null) {
134
215
  settled = true;
@@ -148,11 +229,27 @@ async function fetchGuarded(start, allowPrivate, options = {}) {
148
229
  clearTimeout(headerTimer);
149
230
  }
150
231
  }
232
+ async function resolveAddress(url, allowPrivate, signal, dns) {
233
+ if (!allowPrivate)
234
+ return resolvePublicAddress(url, signal, dns);
235
+ assertHttpUrl(url);
236
+ const host = url.hostname.replace(/^\[|\]$/g, "");
237
+ if (!host)
238
+ throw new Error("refusing to fetch a URL with no host");
239
+ const ipFamily = isIP(host);
240
+ if (ipFamily)
241
+ return { address: host, family: ipFamily === 6 ? 6 : 4 };
242
+ const records = await (dns ?? defaultLookup)(host, { all: true });
243
+ const record = records[0];
244
+ if (!record)
245
+ throw new Error("host resolved to no addresses");
246
+ return { address: record.address, family: record.family === 6 ? 6 : 4 };
247
+ }
151
248
 
152
249
  class PrivateAddressRefusal extends Error {
153
250
  name = "PrivateAddressRefusal";
154
251
  }
155
- async function resolvePublicAddress(url, signal) {
252
+ async function resolvePublicAddress(url, signal, dns) {
156
253
  assertHttpUrl(url);
157
254
  const host = url.hostname.replace(/^\[|\]$/g, "");
158
255
  if (!host)
@@ -169,7 +266,7 @@ async function resolvePublicAddress(url, signal) {
169
266
  if (host === "localhost" || host.endsWith(".local") || host.endsWith(".internal")) {
170
267
  throw new PrivateAddressRefusal("refusing to fetch an internal host");
171
268
  }
172
- const pending = lookup(host, { all: true });
269
+ const pending = (dns ?? defaultLookup)(host, { all: true });
173
270
  const records = signal ? await raceAbort(pending, signal) : await pending;
174
271
  for (const record of records) {
175
272
  if (isPrivateIp(record.address)) {
@@ -202,61 +299,24 @@ async function fetchPinnedDocument(start, options) {
202
299
  throw new Error("document URL cannot contain credentials");
203
300
  }
204
301
  const resolved = await resolvePublicAddress(url, signal);
205
- const transport = url.protocol === "https:" ? httpsRequest : httpRequest;
206
- const response = await new Promise((resolve, reject) => {
207
- const request = transport({
208
- protocol: url.protocol,
209
- hostname: resolved.address,
210
- family: resolved.family,
211
- port: url.port || undefined,
212
- path: `${url.pathname}${url.search}`,
213
- method: "GET",
214
- signal,
215
- servername: url.hostname,
216
- headers: {
217
- host: url.host,
218
- accept: "application/json",
219
- ...options.headers
220
- }
221
- }, (incoming) => {
222
- const headers = new Headers;
223
- for (const [name, value] of Object.entries(incoming.headers)) {
224
- if (Array.isArray(value)) {
225
- for (const item of value)
226
- headers.append(name, item);
227
- } else if (value !== undefined) {
228
- headers.set(name, value);
229
- }
230
- }
231
- const chunks = [];
232
- let total = 0;
233
- incoming.on("data", (chunk) => {
234
- total += chunk.byteLength;
235
- if (total > options.maxBytes) {
236
- incoming.destroy(new Error("response body exceeds configured byte limit"));
237
- return;
238
- }
239
- chunks.push(chunk);
240
- });
241
- incoming.once("error", reject);
242
- incoming.once("end", () => {
243
- const body = new Uint8Array(total);
244
- let offset = 0;
245
- for (const chunk of chunks) {
246
- body.set(chunk, offset);
247
- offset += chunk.byteLength;
248
- }
249
- resolve({ status: incoming.statusCode ?? 0, headers, body, url });
250
- });
251
- });
252
- request.once("error", reject);
253
- request.end();
302
+ const response = await requestPinned(url, resolved, signal, {
303
+ accept: "application/json",
304
+ ...options.headers
254
305
  });
306
+ const body = await readCapped(response, options.maxBytes);
307
+ if (body === null)
308
+ throw new Error("response body exceeds configured byte limit");
309
+ const document = {
310
+ status: response.status,
311
+ headers: response.headers,
312
+ body: new Uint8Array(body),
313
+ url
314
+ };
255
315
  if (response.status < 300 || response.status >= 400)
256
- return response;
316
+ return document;
257
317
  const location = response.headers.get("location");
258
318
  if (!location)
259
- return response;
319
+ return document;
260
320
  url = new URL(location, url);
261
321
  }
262
322
  throw new Error("too many redirects");
@@ -22,7 +22,7 @@ import {
22
22
  createLocalStepDurability2,
23
23
  isAgentToolError2,
24
24
  createToolDurabilityContext
25
- } from "./index-56yx8dxp.js";
25
+ } from "./index-tvtacc9a.js";
26
26
  import {
27
27
  canonicalAgentJson2,
28
28
  createToolChronology,