@irogane/kaji 0.2.0-beta.11

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 (136) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +598 -0
  3. package/contracts/README.md +14 -0
  4. package/contracts/beta-core-v1.json +52 -0
  5. package/contracts/cli/init-cases-v1.json +27 -0
  6. package/contracts/errors/error-codes.json +48 -0
  7. package/contracts/errors/integration-recovery-v1.json +127 -0
  8. package/contracts/errors/provider-normalization.json +111 -0
  9. package/contracts/events/conformance-invalid.json +20 -0
  10. package/contracts/events/conformance.json +511 -0
  11. package/contracts/events/new-kaji-event-v1.schema.json +1021 -0
  12. package/contracts/events/stored-kaji-event-v1.schema.json +1025 -0
  13. package/contracts/feature-tiers-v1.json +488 -0
  14. package/contracts/integrations/abi-index-v1.json +8 -0
  15. package/contracts/integrations/conformance-invalid.json +443 -0
  16. package/contracts/integrations/conformance-valid.json +121 -0
  17. package/contracts/integrations/copy-provenance-v1.schema.json +61 -0
  18. package/contracts/integrations/echo-tool-abi-v1.json +37 -0
  19. package/contracts/integrations/github-api-conformance-v1.json +644 -0
  20. package/contracts/integrations/github-tool-abi-typescript-v1.json +369 -0
  21. package/contracts/integrations/github-tool-abi-v1.json +146 -0
  22. package/contracts/integrations/gmail-api-conformance-v1.json +750 -0
  23. package/contracts/integrations/gmail-tool-abi-v1.json +62 -0
  24. package/contracts/integrations/index.schema.json +37 -0
  25. package/contracts/integrations/manifest.schema.json +119 -0
  26. package/contracts/parity/expected-normalized.json +4906 -0
  27. package/contracts/parity/scenarios.json +100 -0
  28. package/contracts/parity/scenarios.schema.json +214 -0
  29. package/contracts/providers/cost-conformance.json +112 -0
  30. package/contracts/release/github-proof-v1.schema.json +138 -0
  31. package/contracts/release/gmail-proof-v1.schema.json +138 -0
  32. package/contracts/release/kaji-ts-consumer-handoff-v1.schema.json +1289 -0
  33. package/contracts/release/publisher-identity-receipt-v1.schema.json +319 -0
  34. package/contracts/release/typescript-onboarding-evidence-v1.schema.json +740 -0
  35. package/contracts/tools/conformance-invalid.json +271 -0
  36. package/contracts/tools/conformance-valid.json +78 -0
  37. package/contracts/tools/tool-schema-v1.schema.json +18 -0
  38. package/dist/anthropic.cjs +1231 -0
  39. package/dist/anthropic.cjs.map +1 -0
  40. package/dist/anthropic.d.cts +26 -0
  41. package/dist/anthropic.d.ts +26 -0
  42. package/dist/anthropic.js +270 -0
  43. package/dist/anthropic.js.map +1 -0
  44. package/dist/auth.cjs +1507 -0
  45. package/dist/auth.cjs.map +1 -0
  46. package/dist/auth.d.cts +129 -0
  47. package/dist/auth.d.ts +129 -0
  48. package/dist/auth.js +1039 -0
  49. package/dist/auth.js.map +1 -0
  50. package/dist/base-B9FRMcP8.d.cts +140 -0
  51. package/dist/base-nHQd1VtS.d.ts +140 -0
  52. package/dist/chunk-AAM33KAO.js +4367 -0
  53. package/dist/chunk-AAM33KAO.js.map +1 -0
  54. package/dist/chunk-KAJ6BM64.js +153 -0
  55. package/dist/chunk-KAJ6BM64.js.map +1 -0
  56. package/dist/chunk-KCAXIOZS.js +308 -0
  57. package/dist/chunk-KCAXIOZS.js.map +1 -0
  58. package/dist/chunk-LSJ4AVO2.js +243 -0
  59. package/dist/chunk-LSJ4AVO2.js.map +1 -0
  60. package/dist/chunk-TM7ZGOJX.js +716 -0
  61. package/dist/chunk-TM7ZGOJX.js.map +1 -0
  62. package/dist/cli/bin.d.ts +2 -0
  63. package/dist/cli/bin.js +13 -0
  64. package/dist/cli/bin.js.map +1 -0
  65. package/dist/cli/chunk-2RCWPRVY.js +6277 -0
  66. package/dist/cli/chunk-2RCWPRVY.js.map +1 -0
  67. package/dist/cli/chunk-SEBX54TR.js +681 -0
  68. package/dist/cli/chunk-SEBX54TR.js.map +1 -0
  69. package/dist/cli/index.d.ts +232 -0
  70. package/dist/cli/index.js +11 -0
  71. package/dist/cli/index.js.map +1 -0
  72. package/dist/cli/init-worker.d.ts +2 -0
  73. package/dist/cli/init-worker.js +18 -0
  74. package/dist/cli/init-worker.js.map +1 -0
  75. package/dist/cli/integration-copy-worker.js +48 -0
  76. package/dist/cli/integration-copy-worker.js.map +1 -0
  77. package/dist/cli/package-entry-cjs.cjs +21 -0
  78. package/dist/cli/package-entry-cjs.cjs.map +1 -0
  79. package/dist/cli/package-entry-cjs.d.cts +2 -0
  80. package/dist/cli/package-entry.d.ts +2 -0
  81. package/dist/cli/package-entry.js +13 -0
  82. package/dist/cli/package-entry.js.map +1 -0
  83. package/dist/context-BaFHrQHv.d.cts +21 -0
  84. package/dist/context-BaFHrQHv.d.ts +21 -0
  85. package/dist/context-C-YPY-GS.d.cts +1538 -0
  86. package/dist/context-C-YPY-GS.d.ts +1538 -0
  87. package/dist/index.cjs +12346 -0
  88. package/dist/index.cjs.map +1 -0
  89. package/dist/index.d.cts +1560 -0
  90. package/dist/index.d.ts +1560 -0
  91. package/dist/index.js +7852 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/integrations/github.cjs +2092 -0
  94. package/dist/integrations/github.cjs.map +1 -0
  95. package/dist/integrations/github.d.cts +21 -0
  96. package/dist/integrations/github.d.ts +21 -0
  97. package/dist/integrations/github.js +2088 -0
  98. package/dist/integrations/github.js.map +1 -0
  99. package/dist/integrations.cjs +3370 -0
  100. package/dist/integrations.cjs.map +1 -0
  101. package/dist/integrations.d.cts +202 -0
  102. package/dist/integrations.d.ts +202 -0
  103. package/dist/integrations.js +2650 -0
  104. package/dist/integrations.js.map +1 -0
  105. package/dist/observability-Cj--OkME.d.cts +96 -0
  106. package/dist/observability-Cj--OkME.d.ts +96 -0
  107. package/dist/openai.cjs +1235 -0
  108. package/dist/openai.cjs.map +1 -0
  109. package/dist/openai.d.cts +32 -0
  110. package/dist/openai.d.ts +32 -0
  111. package/dist/openai.js +272 -0
  112. package/dist/openai.js.map +1 -0
  113. package/dist/testing.cjs +554 -0
  114. package/dist/testing.cjs.map +1 -0
  115. package/dist/testing.d.cts +43 -0
  116. package/dist/testing.d.ts +43 -0
  117. package/dist/testing.js +118 -0
  118. package/dist/testing.js.map +1 -0
  119. package/package.json +188 -0
  120. package/registry/echo/index.ts +53 -0
  121. package/registry/echo/manifest.json +53 -0
  122. package/registry/github/LICENSE +105 -0
  123. package/registry/github/client.ts +1727 -0
  124. package/registry/github/index.ts +263 -0
  125. package/registry/github/manifest.json +227 -0
  126. package/registry/github/owner-fixtures.json +10 -0
  127. package/registry/github/tests/github.test.ts +32 -0
  128. package/registry/gmail/LICENSE +105 -0
  129. package/registry/gmail/client.ts +548 -0
  130. package/registry/gmail/index.ts +165 -0
  131. package/registry/gmail/manifest.json +102 -0
  132. package/registry/gmail/owner-fixtures.json +10 -0
  133. package/registry/gmail/tests/gmail.test.ts +32 -0
  134. package/registry/index.json +21 -0
  135. package/registry/index.schema.json +37 -0
  136. package/registry/schema.json +119 -0
@@ -0,0 +1,2092 @@
1
+ 'use strict';
2
+
3
+ var kaji = require('@irogane/kaji');
4
+ var integrations = require('@irogane/kaji/integrations');
5
+ var buffer = require('buffer');
6
+
7
+ // src/integrations/github.ts
8
+ var REPOSITORY = /^[A-Za-z0-9_.-]{1,100}\/[A-Za-z0-9_.-]{1,100}$/;
9
+ var SCOPE_QUALIFIER = /(?:repo|org|user):/i;
10
+ var MAX_SEARCH_RESULT_BYTES = 32 * 1024;
11
+ var MAX_FILE_BYTES = 48 * 1024;
12
+ var MAX_MODEL_RESULT_BYTES = 60 * 1024;
13
+ var MAX_MODEL_TEXT_BYTES = 8 * 1024;
14
+ var MAX_PROVIDER_TEXT_BYTES = 1024 * 1024;
15
+ var MAX_TOKEN_CHARACTERS = 4096;
16
+ var MAX_URL_CHARACTERS = 2048;
17
+ var GENERAL_ACCEPT = "application/vnd.github+json";
18
+ var SEARCH_ACCEPT = "application/vnd.github.text-match+json";
19
+ var GITHUB_API_VERSION = "2026-03-10";
20
+ var GITHUB_CATALOG_VERSION = "0.2.0";
21
+ var GITHUB_USER_AGENT = `kaji-github/${GITHUB_CATALOG_VERSION}`;
22
+ var ProviderShapeError = class extends Error {
23
+ };
24
+ var UnknownMutationError = class extends Error {
25
+ error_code = "TOOL_EXECUTION_FAILED";
26
+ reason_code = "github_mutation_unknown";
27
+ recovery_code = "RECONCILE_GITHUB_MUTATION";
28
+ doc_url = "https://kaji.dev/docs/integrations/recovery-v1#github-mutation-unknown";
29
+ constructor() {
30
+ super("GitHub mutation outcome is unknown");
31
+ this.name = "UnknownMutationError";
32
+ }
33
+ };
34
+ function policyError() {
35
+ return new integrations.IntegrationPolicyError();
36
+ }
37
+ function authError() {
38
+ return new integrations.IntegrationAuthRequiredError("github_token_missing");
39
+ }
40
+ function apiError() {
41
+ return new integrations.IntegrationExecutionError("api_rejected");
42
+ }
43
+ function transientError() {
44
+ return new integrations.IntegrationTransientReadError();
45
+ }
46
+ function rateError() {
47
+ return new integrations.IntegrationRateLimitedError();
48
+ }
49
+ function requireRepository(value, allowed) {
50
+ if (typeof value !== "string" || !REPOSITORY.test(value) || !repositoryComponentsAreSafe(value) || !allowed.has(value)) {
51
+ throw policyError();
52
+ }
53
+ return value;
54
+ }
55
+ function repositoryComponentsAreSafe(value) {
56
+ return value.split("/").every((part) => part !== "." && part !== "..");
57
+ }
58
+ function policyString(value, minimum, maximum) {
59
+ if (typeof value !== "string") {
60
+ throw policyError();
61
+ }
62
+ assertScalarString(value, policyError);
63
+ const length = Array.from(value).length;
64
+ if (length < minimum || length > maximum) throw policyError();
65
+ return value;
66
+ }
67
+ function policyInteger(value, minimum, maximum) {
68
+ if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
69
+ throw policyError();
70
+ }
71
+ return value;
72
+ }
73
+ function providerCharacterString(value, minimum, maximum) {
74
+ if (typeof value !== "string") {
75
+ throw new ProviderShapeError();
76
+ }
77
+ assertScalarString(value, () => new ProviderShapeError());
78
+ const length = Array.from(value).length;
79
+ if (length < minimum || length > maximum) throw new ProviderShapeError();
80
+ return value;
81
+ }
82
+ function providerGitHubUrl(value, origin, pathSegments) {
83
+ const raw = providerCharacterString(value, 1, MAX_URL_CHARACTERS);
84
+ const encodedSegments = pathSegments.map((segment) => {
85
+ providerCharacterString(segment, 1, MAX_URL_CHARACTERS);
86
+ if (segment === "." || segment === ".." || segment.includes("\\") || Array.from(segment, (character) => character.charCodeAt(0)).some(
87
+ (codePoint) => codePoint < 32 || codePoint === 127
88
+ )) {
89
+ throw new ProviderShapeError();
90
+ }
91
+ return encodeURIComponent(segment).replace(
92
+ /[!'()*]/g,
93
+ (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`
94
+ );
95
+ });
96
+ const expected = `${origin}/${encodedSegments.join("/")}`;
97
+ let parsed;
98
+ try {
99
+ parsed = new URL(raw);
100
+ } catch {
101
+ throw new ProviderShapeError();
102
+ }
103
+ if (raw !== expected || parsed.href !== raw || parsed.protocol !== "https:" || parsed.origin !== origin || parsed.username !== "" || parsed.password !== "" || parsed.port !== "" || parsed.search !== "" || parsed.hash !== "") {
104
+ throw new ProviderShapeError();
105
+ }
106
+ return raw;
107
+ }
108
+ function providerByteString(value, minimum, maximum) {
109
+ if (typeof value !== "string") {
110
+ throw new ProviderShapeError();
111
+ }
112
+ assertScalarString(value, () => new ProviderShapeError());
113
+ if (Array.from(value).length < minimum || utf8Size(value) > maximum) {
114
+ throw new ProviderShapeError();
115
+ }
116
+ return value;
117
+ }
118
+ function providerInteger(value, minimum = 0) {
119
+ if (!Number.isSafeInteger(value) || value < minimum) {
120
+ throw new ProviderShapeError();
121
+ }
122
+ return value;
123
+ }
124
+ function providerBoolean(value) {
125
+ if (typeof value !== "boolean") throw new ProviderShapeError();
126
+ return value;
127
+ }
128
+ function providerNullableCharacterString(value, minimum, maximum) {
129
+ return value === null ? null : providerCharacterString(value, minimum, maximum);
130
+ }
131
+ function providerOptionalNullableCharacterString(value, minimum, maximum) {
132
+ return value === void 0 || value === null ? null : providerCharacterString(value, minimum, maximum);
133
+ }
134
+ function objectValue(value) {
135
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
136
+ throw new ProviderShapeError();
137
+ }
138
+ const prototype = Object.getPrototypeOf(value);
139
+ if (prototype !== Object.prototype && prototype !== null) throw new ProviderShapeError();
140
+ return value;
141
+ }
142
+ function arrayValue(value) {
143
+ if (!Array.isArray(value)) throw new ProviderShapeError();
144
+ return value;
145
+ }
146
+ function assertScalarString(value, makeError) {
147
+ for (let index = 0; index < value.length; index += 1) {
148
+ const unit = value.charCodeAt(index);
149
+ if (unit >= 55296 && unit <= 56319) {
150
+ const next = value.charCodeAt(index + 1);
151
+ if (next < 56320 || next > 57343) throw makeError();
152
+ index += 1;
153
+ } else if (unit >= 56320 && unit <= 57343) {
154
+ throw makeError();
155
+ }
156
+ }
157
+ }
158
+ function utf8Size(value) {
159
+ assertScalarString(value, () => new ProviderShapeError());
160
+ return new TextEncoder().encode(value).byteLength;
161
+ }
162
+ function truncateUtf8(value, maximum) {
163
+ const bytes = new TextEncoder().encode(value);
164
+ if (bytes.byteLength <= maximum) return value;
165
+ for (let end = maximum; end >= Math.max(0, maximum - 3); end -= 1) {
166
+ try {
167
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes.slice(0, end));
168
+ } catch {
169
+ }
170
+ }
171
+ throw new ProviderShapeError();
172
+ }
173
+ function serializedBytes(value) {
174
+ return new TextEncoder().encode(JSON.stringify(value)).byteLength;
175
+ }
176
+ function boundedText(value, nullable = false) {
177
+ if (value === null && nullable) return { text: null, truncated: false };
178
+ const text = providerByteString(value, 0, MAX_PROVIDER_TEXT_BYTES);
179
+ const truncated = utf8Size(text) > MAX_MODEL_TEXT_BYTES;
180
+ return {
181
+ text: truncated ? truncateUtf8(text, MAX_MODEL_TEXT_BYTES) : text,
182
+ truncated
183
+ };
184
+ }
185
+ function valueAtPath(root, path) {
186
+ let value = root;
187
+ for (const segment of path) {
188
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
189
+ throw new ProviderShapeError();
190
+ }
191
+ value = value[segment];
192
+ }
193
+ return value;
194
+ }
195
+ function setValueAtPath(root, path, value) {
196
+ let target = root;
197
+ for (const segment of path.slice(0, -1)) {
198
+ const next = target[segment];
199
+ if (next === null || typeof next !== "object" || Array.isArray(next)) {
200
+ throw new ProviderShapeError();
201
+ }
202
+ target = next;
203
+ }
204
+ target[path.at(-1)] = value;
205
+ }
206
+ function shrinkTextFieldsToFit(row, fields, fits) {
207
+ const candidate = structuredClone(row);
208
+ if (fits(candidate)) return candidate;
209
+ for (const field of fields) {
210
+ const current = valueAtPath(candidate, field.path);
211
+ if (current === null) continue;
212
+ if (typeof current !== "string") throw new ProviderShapeError();
213
+ const byteLength = utf8Size(current);
214
+ let low = 0;
215
+ let high = byteLength;
216
+ let best;
217
+ while (low <= high) {
218
+ const middle = Math.floor((low + high) / 2);
219
+ const text = truncateUtf8(current, middle);
220
+ const trial = structuredClone(candidate);
221
+ setValueAtPath(trial, field.path, text);
222
+ setValueAtPath(trial, field.truncatedPath, true);
223
+ if (fits(trial)) {
224
+ best = text;
225
+ low = middle + 1;
226
+ } else {
227
+ high = middle - 1;
228
+ }
229
+ }
230
+ if (best !== void 0) {
231
+ setValueAtPath(candidate, field.path, best);
232
+ setValueAtPath(candidate, field.truncatedPath, true);
233
+ return candidate;
234
+ }
235
+ setValueAtPath(candidate, field.path, "");
236
+ setValueAtPath(candidate, field.truncatedPath, true);
237
+ }
238
+ return fits(candidate) ? candidate : void 0;
239
+ }
240
+ function boundedRows(value, maximum = 20) {
241
+ const rows = arrayValue(value);
242
+ return {
243
+ rows: rows.slice(0, maximum),
244
+ omitted: Math.max(0, rows.length - maximum)
245
+ };
246
+ }
247
+ function fitRows(rows, build, options = {}) {
248
+ const items = [];
249
+ let omitted = options.initialOmitted ?? 0;
250
+ for (const row of rows) {
251
+ const fits = (candidate2) => serializedBytes(build([...items, candidate2], omitted)) <= MAX_MODEL_RESULT_BYTES;
252
+ let candidate = row;
253
+ if (!fits(candidate)) {
254
+ if (options.shrink !== void 0) {
255
+ candidate = options.shrink(candidate, fits);
256
+ } else if (options.textFields !== void 0) {
257
+ candidate = shrinkTextFieldsToFit(candidate, options.textFields, fits);
258
+ }
259
+ }
260
+ if (candidate === void 0 || !fits(candidate)) {
261
+ omitted += 1;
262
+ } else {
263
+ items.push(candidate);
264
+ }
265
+ }
266
+ let result = build(items, omitted);
267
+ while (serializedBytes(result) > MAX_MODEL_RESULT_BYTES && items.length > 0) {
268
+ items.pop();
269
+ omitted += 1;
270
+ result = build(items, omitted);
271
+ }
272
+ if (serializedBytes(result) > MAX_MODEL_RESULT_BYTES) throw new ProviderShapeError();
273
+ return result;
274
+ }
275
+ function assertModelResultBudget(value) {
276
+ if (serializedBytes(value) > MAX_MODEL_RESULT_BYTES) throw new ProviderShapeError();
277
+ return value;
278
+ }
279
+ function fitObjectToModelBudget(value, textFields) {
280
+ return shrinkTextFieldsToFit(
281
+ value,
282
+ textFields,
283
+ (candidate) => serializedBytes(candidate) <= MAX_MODEL_RESULT_BYTES
284
+ );
285
+ }
286
+ function requireObjectWithinModelBudget(value, textFields) {
287
+ const fitted = fitObjectToModelBudget(value, textFields);
288
+ if (fitted === void 0) throw new ProviderShapeError();
289
+ return fitted;
290
+ }
291
+ function encodeComponent(value) {
292
+ try {
293
+ return encodeURIComponent(String(value)).replace(
294
+ /[!'()*]/g,
295
+ (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`
296
+ );
297
+ } catch {
298
+ throw policyError();
299
+ }
300
+ }
301
+ function queryString(query) {
302
+ if (query === void 0 || Object.keys(query).length === 0) return "";
303
+ const pairs = [];
304
+ for (const key of Object.keys(query).sort()) {
305
+ const value = query[key];
306
+ if (key.length === 0 || typeof value !== "string" && typeof value !== "number") {
307
+ throw policyError();
308
+ }
309
+ pairs.push(`${encodeComponent(key)}=${encodeComponent(value)}`);
310
+ }
311
+ return `?${pairs.join("&")}`;
312
+ }
313
+ function validateContentPath(value) {
314
+ const path = policyString(value, 1, 512);
315
+ const parts = path.split("/");
316
+ if (path.includes("\\") || parts.some((part) => part === "" || part === "." || part === "..")) {
317
+ throw policyError();
318
+ }
319
+ return path;
320
+ }
321
+ function encodeContentPath(value) {
322
+ return validateContentPath(value).split("/").map(encodeComponent).join("/");
323
+ }
324
+ function validateEncodedContentPath(value) {
325
+ const decoded = [];
326
+ for (const part of value.split("/")) {
327
+ let plain;
328
+ try {
329
+ plain = decodeURIComponent(part);
330
+ } catch {
331
+ throw policyError();
332
+ }
333
+ if (plain === "" || plain === "." || plain === ".." || plain.includes("/") || plain.includes("\\") || encodeComponent(plain) !== part) {
334
+ throw policyError();
335
+ }
336
+ decoded.push(plain);
337
+ }
338
+ policyString(decoded.join("/"), 1, 512);
339
+ }
340
+ function encodePathSegment(value, maximum = 100) {
341
+ const segment = policyString(value, 1, maximum);
342
+ if (segment === "." || segment === ".." || segment.includes("\\")) throw policyError();
343
+ return encodeComponent(segment);
344
+ }
345
+ function validateEncodedPathSegment(value, maximum = 100) {
346
+ let decoded;
347
+ try {
348
+ decoded = decodeURIComponent(value);
349
+ } catch {
350
+ throw policyError();
351
+ }
352
+ if (decoded === "." || decoded === ".." || decoded.includes("\\") || encodeComponent(decoded) !== value) {
353
+ throw policyError();
354
+ }
355
+ policyString(decoded, 1, maximum);
356
+ }
357
+ function validatePage(page, perPage) {
358
+ policyInteger(page, 1, 1e3);
359
+ policyInteger(perPage, 1, 20);
360
+ }
361
+ function validateFilter(value) {
362
+ if (value !== "latest" && value !== "all") throw policyError();
363
+ }
364
+ function validateDeploymentSha(value) {
365
+ const sha = policyString(value, 1, 64);
366
+ if (!/^[0-9A-Fa-f]{1,64}$/.test(sha)) throw policyError();
367
+ return sha;
368
+ }
369
+ function normalizedToken(value) {
370
+ if (typeof value !== "string" || value.includes("\r") || value.includes("\n")) {
371
+ throw authError();
372
+ }
373
+ const token = value.trim();
374
+ if (token.length === 0 || Array.from(token).length > MAX_TOKEN_CHARACTERS) throw authError();
375
+ assertScalarString(token, authError);
376
+ return token;
377
+ }
378
+ function retryAfter(headers) {
379
+ const raw = headers["retry-after"];
380
+ if (raw === void 0) return void 0;
381
+ const normalized = raw.trim();
382
+ if (!/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(normalized)) return void 0;
383
+ const delaySeconds = Number(normalized);
384
+ if (!Number.isFinite(delaySeconds) || delaySeconds < 0 || delaySeconds > 2) return void 0;
385
+ return delaySeconds;
386
+ }
387
+ function isRateLimited(response) {
388
+ return response.status === 429 || response.status === 403 && (retryAfter(response.headers) !== void 0 || response.headers["x-ratelimit-remaining"] === "0");
389
+ }
390
+ function validateSearchInput(query, page, perPage) {
391
+ const value = policyString(query, 1, 256);
392
+ if (SCOPE_QUALIFIER.test(value)) throw policyError();
393
+ policyInteger(page, 1, 50);
394
+ policyInteger(perPage, 1, 20);
395
+ return value;
396
+ }
397
+ function validateListInput(state, page, perPage) {
398
+ if (state !== "open" && state !== "closed" && state !== "all") throw policyError();
399
+ validatePage(page, perPage);
400
+ }
401
+ function validateCreateInput(title, body) {
402
+ policyString(title, 1, 256);
403
+ const value = policyString(body, 0, 16384);
404
+ if (new TextEncoder().encode(value).byteLength > 16384) throw policyError();
405
+ }
406
+ function validateCommentBody(body) {
407
+ const value = policyString(body, 1, 16384);
408
+ if (new TextEncoder().encode(value).byteLength > 16384) throw policyError();
409
+ }
410
+ function routeFor(options) {
411
+ const { method, repository: repository2, path, query, body, mutation = false } = options;
412
+ const prefix = `/repos/${repository2}`;
413
+ const queryKeys = Object.keys(query ?? {}).sort();
414
+ const bodyKeys = Object.keys(body ?? {}).sort();
415
+ if (method === "GET" && !mutation && path === "/search/code") {
416
+ if (query === void 0 || queryKeys.join(",") !== "page,per_page,q" || body !== void 0) {
417
+ throw policyError();
418
+ }
419
+ const suffix = ` repo:${repository2}`;
420
+ const value = query.q;
421
+ if (typeof value !== "string" || !value.endsWith(suffix)) throw policyError();
422
+ validateSearchInput(value.slice(0, -suffix.length), query.page, query.per_page);
423
+ return "search_code";
424
+ }
425
+ if (method === "GET" && !mutation && path.startsWith(`${prefix}/contents/`)) {
426
+ if (body !== void 0 || queryKeys.some((key) => key !== "ref")) throw policyError();
427
+ validateEncodedContentPath(path.slice(`${prefix}/contents/`.length));
428
+ if (query?.ref !== void 0) policyString(query.ref, 1, 100);
429
+ return "get_file";
430
+ }
431
+ if (path === `${prefix}/issues`) {
432
+ if (method === "GET" && !mutation) {
433
+ if (query === void 0 || queryKeys.join(",") !== "page,per_page,state" || body !== void 0) {
434
+ throw policyError();
435
+ }
436
+ validateListInput(query.state, query.page, query.per_page);
437
+ return "list_issues";
438
+ }
439
+ if (method === "POST" && mutation) {
440
+ if (query !== void 0 || body === void 0 || bodyKeys.join(",") !== "body,title") {
441
+ throw policyError();
442
+ }
443
+ validateCreateInput(body.title, body.body);
444
+ return "create_issue";
445
+ }
446
+ }
447
+ const escaped = prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
448
+ const issue = new RegExp(`^${escaped}/issues/([1-9][0-9]*)$`).exec(path);
449
+ if (issue !== null && method === "GET" && !mutation && query === void 0 && body === void 0) {
450
+ policyInteger(Number(issue[1]), 1, Number.MAX_SAFE_INTEGER);
451
+ return "get_issue";
452
+ }
453
+ const comment = new RegExp(`^${escaped}/issues/([1-9][0-9]*)/comments$`).exec(path);
454
+ if (comment !== null && method === "POST" && mutation && query === void 0) {
455
+ if (body === void 0 || bodyKeys.join(",") !== "body") throw policyError();
456
+ policyInteger(Number(comment[1]), 1, Number.MAX_SAFE_INTEGER);
457
+ validateCommentBody(body.body);
458
+ return "add_comment";
459
+ }
460
+ const commit = new RegExp(`^${escaped}/commits/([^/]+)$`).exec(path);
461
+ if (commit !== null && method === "GET" && !mutation && body === void 0) {
462
+ if (query === void 0 || queryKeys.join(",") !== "page,per_page") throw policyError();
463
+ validateEncodedPathSegment(commit[1]);
464
+ validatePage(query.page, query.per_page);
465
+ return "get_commit";
466
+ }
467
+ const pull = new RegExp(`^${escaped}/pulls/([1-9][0-9]*)$`).exec(path);
468
+ if (pull !== null && method === "GET" && !mutation && query === void 0 && body === void 0) {
469
+ policyInteger(Number(pull[1]), 1, Number.MAX_SAFE_INTEGER);
470
+ return "get_pull_request";
471
+ }
472
+ const pullFiles = new RegExp(`^${escaped}/pulls/([1-9][0-9]*)/files$`).exec(path);
473
+ if (pullFiles !== null && method === "GET" && !mutation && body === void 0) {
474
+ if (query === void 0 || queryKeys.join(",") !== "page,per_page") throw policyError();
475
+ policyInteger(Number(pullFiles[1]), 1, Number.MAX_SAFE_INTEGER);
476
+ validatePage(query.page, query.per_page);
477
+ return "list_pull_request_files";
478
+ }
479
+ const checks = new RegExp(`^${escaped}/commits/([^/]+)/check-runs$`).exec(path);
480
+ if (checks !== null && method === "GET" && !mutation && body === void 0) {
481
+ if (query === void 0 || queryKeys.join(",") !== "filter,page,per_page") {
482
+ throw policyError();
483
+ }
484
+ validateEncodedPathSegment(checks[1]);
485
+ validateFilter(query.filter);
486
+ validatePage(query.page, query.per_page);
487
+ return "list_check_runs";
488
+ }
489
+ const workflowRun = new RegExp(`^${escaped}/actions/runs/([1-9][0-9]*)$`).exec(path);
490
+ if (workflowRun !== null && method === "GET" && !mutation && query === void 0 && body === void 0) {
491
+ policyInteger(Number(workflowRun[1]), 1, Number.MAX_SAFE_INTEGER);
492
+ return "get_workflow_run";
493
+ }
494
+ const workflowJobs = new RegExp(`^${escaped}/actions/runs/([1-9][0-9]*)/jobs$`).exec(path);
495
+ if (workflowJobs !== null && method === "GET" && !mutation && body === void 0) {
496
+ if (query === void 0 || queryKeys.join(",") !== "filter,page,per_page") {
497
+ throw policyError();
498
+ }
499
+ policyInteger(Number(workflowJobs[1]), 1, Number.MAX_SAFE_INTEGER);
500
+ validateFilter(query.filter);
501
+ validatePage(query.page, query.per_page);
502
+ return "list_workflow_jobs";
503
+ }
504
+ if (path === `${prefix}/commits` && method === "GET" && !mutation && body === void 0) {
505
+ if (query === void 0 || queryKeys.join(",") !== "page,path,per_page" && queryKeys.join(",") !== "page,path,per_page,sha") {
506
+ throw policyError();
507
+ }
508
+ validateContentPath(query.path);
509
+ validatePage(query.page, query.per_page);
510
+ if (query.sha !== void 0) policyString(query.sha, 1, 100);
511
+ return "list_file_commits";
512
+ }
513
+ const release = new RegExp(`^${escaped}/releases/tags/([^/]+)$`).exec(path);
514
+ if (release !== null && method === "GET" && !mutation && query === void 0 && body === void 0) {
515
+ validateEncodedPathSegment(release[1]);
516
+ return "get_release";
517
+ }
518
+ if (path === `${prefix}/deployments` && method === "GET" && !mutation && body === void 0) {
519
+ if (query === void 0 || !queryKeys.includes("page") || !queryKeys.includes("per_page")) {
520
+ throw policyError();
521
+ }
522
+ if (queryKeys.some(
523
+ (key) => !["environment", "page", "per_page", "ref", "sha", "task"].includes(key)
524
+ )) {
525
+ throw policyError();
526
+ }
527
+ validatePage(query.page, query.per_page);
528
+ for (const key of ["environment", "ref", "task"]) {
529
+ if (query[key] !== void 0) policyString(query[key], 1, 100);
530
+ }
531
+ if (query.sha !== void 0) validateDeploymentSha(query.sha);
532
+ return "list_deployments";
533
+ }
534
+ throw policyError();
535
+ }
536
+ function defaultSleep(delayMs, signal) {
537
+ if (signal.aborted) return Promise.reject(signal.reason);
538
+ return new Promise((resolve, reject) => {
539
+ const timer = setTimeout(() => {
540
+ signal.removeEventListener("abort", onAbort);
541
+ resolve();
542
+ }, delayMs);
543
+ const onAbort = () => {
544
+ clearTimeout(timer);
545
+ reject(signal.reason);
546
+ };
547
+ signal.addEventListener("abort", onAbort, { once: true });
548
+ });
549
+ }
550
+ function isAbortOrTimeout(error) {
551
+ return error instanceof DOMException && (error.name === "AbortError" || error.name === "TimeoutError");
552
+ }
553
+ var GitHubClient = class {
554
+ repositories;
555
+ tokenFor;
556
+ http;
557
+ sleep;
558
+ monotonicNow;
559
+ constructor(options, runtime = { sleep: defaultSleep, monotonicNow: () => performance.now() }) {
560
+ if (typeof options?.tokenFor !== "function" || !Array.isArray(options.repositories) || typeof options.http?.request !== "function" || typeof runtime.sleep !== "function" || typeof runtime.monotonicNow !== "function") {
561
+ throw policyError();
562
+ }
563
+ const repositories = Object.freeze([...options.repositories]);
564
+ if (repositories.some(
565
+ (repository2) => !REPOSITORY.test(repository2) || !repositoryComponentsAreSafe(repository2)
566
+ )) {
567
+ throw policyError();
568
+ }
569
+ this.repositories = new Set(repositories);
570
+ this.tokenFor = options.tokenFor;
571
+ this.http = options.http;
572
+ this.sleep = runtime.sleep;
573
+ this.monotonicNow = runtime.monotonicNow;
574
+ }
575
+ async searchCode(context, input) {
576
+ const repository2 = requireRepository(input.repository, this.repositories);
577
+ const page = input.page ?? 1;
578
+ const perPage = input.perPage ?? 10;
579
+ const query = validateSearchInput(input.query, page, perPage);
580
+ return this.requestJson(context, {
581
+ method: "GET",
582
+ repository: repository2,
583
+ path: "/search/code",
584
+ query: { q: `${query} repo:${repository2}`, page, per_page: perPage }
585
+ });
586
+ }
587
+ async getFile(context, input) {
588
+ const repository2 = requireRepository(input.repository, this.repositories);
589
+ const path = encodeContentPath(input.path);
590
+ const query = input.ref === void 0 ? void 0 : { ref: policyString(input.ref, 1, 100) };
591
+ return this.requestJson(context, {
592
+ method: "GET",
593
+ repository: repository2,
594
+ path: `/repos/${repository2}/contents/${path}`,
595
+ ...query === void 0 ? {} : { query }
596
+ });
597
+ }
598
+ async listIssues(context, input) {
599
+ const repository2 = requireRepository(input.repository, this.repositories);
600
+ const state = input.state ?? "open";
601
+ const page = input.page ?? 1;
602
+ const perPage = input.perPage ?? 10;
603
+ validateListInput(state, page, perPage);
604
+ return this.requestJson(context, {
605
+ method: "GET",
606
+ repository: repository2,
607
+ path: `/repos/${repository2}/issues`,
608
+ query: { state, page, per_page: perPage }
609
+ });
610
+ }
611
+ async getIssue(context, input) {
612
+ const repository2 = requireRepository(input.repository, this.repositories);
613
+ const issueNumber2 = policyInteger(input.issueNumber, 1, Number.MAX_SAFE_INTEGER);
614
+ return this.requestJson(context, {
615
+ method: "GET",
616
+ repository: repository2,
617
+ path: `/repos/${repository2}/issues/${issueNumber2}`
618
+ });
619
+ }
620
+ async createIssue(context, input) {
621
+ const repository2 = requireRepository(input.repository, this.repositories);
622
+ validateCreateInput(input.title, input.body);
623
+ return this.requestJson(context, {
624
+ method: "POST",
625
+ repository: repository2,
626
+ path: `/repos/${repository2}/issues`,
627
+ body: { title: input.title, body: input.body },
628
+ mutation: true
629
+ });
630
+ }
631
+ async addComment(context, input) {
632
+ const repository2 = requireRepository(input.repository, this.repositories);
633
+ const issueNumber2 = policyInteger(input.issueNumber, 1, Number.MAX_SAFE_INTEGER);
634
+ validateCommentBody(input.body);
635
+ return this.requestJson(context, {
636
+ method: "POST",
637
+ repository: repository2,
638
+ path: `/repos/${repository2}/issues/${issueNumber2}/comments`,
639
+ body: { body: input.body },
640
+ mutation: true
641
+ });
642
+ }
643
+ async getCommit(context, input) {
644
+ const repository2 = requireRepository(input.repository, this.repositories);
645
+ const ref = encodePathSegment(input.ref);
646
+ const page = input.page ?? 1;
647
+ const perPage = input.perPage ?? 10;
648
+ validatePage(page, perPage);
649
+ return this.requestJson(context, {
650
+ method: "GET",
651
+ repository: repository2,
652
+ path: `/repos/${repository2}/commits/${ref}`,
653
+ query: { page, per_page: perPage }
654
+ });
655
+ }
656
+ async getPullRequest(context, input) {
657
+ const repository2 = requireRepository(input.repository, this.repositories);
658
+ const pullNumber = policyInteger(input.pullNumber, 1, Number.MAX_SAFE_INTEGER);
659
+ return this.requestJson(context, {
660
+ method: "GET",
661
+ repository: repository2,
662
+ path: `/repos/${repository2}/pulls/${pullNumber}`
663
+ });
664
+ }
665
+ async listPullRequestFiles(context, input) {
666
+ const repository2 = requireRepository(input.repository, this.repositories);
667
+ const pullNumber = policyInteger(input.pullNumber, 1, Number.MAX_SAFE_INTEGER);
668
+ const page = input.page ?? 1;
669
+ const perPage = input.perPage ?? 10;
670
+ validatePage(page, perPage);
671
+ return this.requestJson(context, {
672
+ method: "GET",
673
+ repository: repository2,
674
+ path: `/repos/${repository2}/pulls/${pullNumber}/files`,
675
+ query: { page, per_page: perPage }
676
+ });
677
+ }
678
+ async listCheckRuns(context, input) {
679
+ const repository2 = requireRepository(input.repository, this.repositories);
680
+ const ref = encodePathSegment(input.ref);
681
+ const filter = input.filter ?? "latest";
682
+ const page = input.page ?? 1;
683
+ const perPage = input.perPage ?? 10;
684
+ validateFilter(filter);
685
+ validatePage(page, perPage);
686
+ return this.requestJson(context, {
687
+ method: "GET",
688
+ repository: repository2,
689
+ path: `/repos/${repository2}/commits/${ref}/check-runs`,
690
+ query: { filter, page, per_page: perPage }
691
+ });
692
+ }
693
+ async getWorkflowRun(context, input) {
694
+ const repository2 = requireRepository(input.repository, this.repositories);
695
+ const runId = policyInteger(input.runId, 1, Number.MAX_SAFE_INTEGER);
696
+ return this.requestJson(context, {
697
+ method: "GET",
698
+ repository: repository2,
699
+ path: `/repos/${repository2}/actions/runs/${runId}`
700
+ });
701
+ }
702
+ async listWorkflowJobs(context, input) {
703
+ const repository2 = requireRepository(input.repository, this.repositories);
704
+ const runId = policyInteger(input.runId, 1, Number.MAX_SAFE_INTEGER);
705
+ const filter = input.filter ?? "latest";
706
+ const page = input.page ?? 1;
707
+ const perPage = input.perPage ?? 10;
708
+ validateFilter(filter);
709
+ validatePage(page, perPage);
710
+ return this.requestJson(context, {
711
+ method: "GET",
712
+ repository: repository2,
713
+ path: `/repos/${repository2}/actions/runs/${runId}/jobs`,
714
+ query: { filter, page, per_page: perPage }
715
+ });
716
+ }
717
+ async listFileCommits(context, input) {
718
+ const repository2 = requireRepository(input.repository, this.repositories);
719
+ const path = validateContentPath(input.path);
720
+ const page = input.page ?? 1;
721
+ const perPage = input.perPage ?? 10;
722
+ validatePage(page, perPage);
723
+ const ref = input.ref === void 0 ? void 0 : policyString(input.ref, 1, 100);
724
+ return this.requestJson(context, {
725
+ method: "GET",
726
+ repository: repository2,
727
+ path: `/repos/${repository2}/commits`,
728
+ query: { page, path, per_page: perPage, ...ref === void 0 ? {} : { sha: ref } }
729
+ });
730
+ }
731
+ async getRelease(context, input) {
732
+ const repository2 = requireRepository(input.repository, this.repositories);
733
+ const tag = encodePathSegment(input.tag);
734
+ return this.requestJson(context, {
735
+ method: "GET",
736
+ repository: repository2,
737
+ path: `/repos/${repository2}/releases/tags/${tag}`
738
+ });
739
+ }
740
+ async listDeployments(context, input) {
741
+ const repository2 = requireRepository(input.repository, this.repositories);
742
+ const page = input.page ?? 1;
743
+ const perPage = input.perPage ?? 10;
744
+ validatePage(page, perPage);
745
+ const ref = input.ref === void 0 ? void 0 : policyString(input.ref, 1, 100);
746
+ const sha = input.sha === void 0 ? void 0 : validateDeploymentSha(input.sha);
747
+ const environment = input.environment === void 0 ? void 0 : policyString(input.environment, 1, 100);
748
+ const task = input.task === void 0 ? void 0 : policyString(input.task, 1, 100);
749
+ return this.requestJson(context, {
750
+ method: "GET",
751
+ repository: repository2,
752
+ path: `/repos/${repository2}/deployments`,
753
+ query: {
754
+ page,
755
+ per_page: perPage,
756
+ ...ref === void 0 ? {} : { ref },
757
+ ...sha === void 0 ? {} : { sha },
758
+ ...environment === void 0 ? {} : { environment },
759
+ ...task === void 0 ? {} : { task }
760
+ }
761
+ });
762
+ }
763
+ async requestJson(context, options) {
764
+ const repository2 = requireRepository(options.repository, this.repositories);
765
+ const route = routeFor({ ...options, repository: repository2 });
766
+ const mutation = options.mutation ?? false;
767
+ const pathAndQuery = options.path + queryString(options.query);
768
+ const requestBody = options.body === void 0 ? void 0 : new TextEncoder().encode(JSON.stringify(integrations.snapshotIntegrationResult(options.body)));
769
+ const identityHeaders = {
770
+ accept: route === "search_code" ? SEARCH_ACCEPT : GENERAL_ACCEPT,
771
+ "user-agent": GITHUB_USER_AGENT,
772
+ "x-github-api-version": GITHUB_API_VERSION
773
+ };
774
+ if (context.signal.aborted) throw context.signal.reason;
775
+ let token;
776
+ try {
777
+ token = await this.tokenFor(context);
778
+ } catch (error) {
779
+ if (isAbortOrTimeout(error) || error instanceof integrations.IntegrationExecutionError) throw error;
780
+ throw authError();
781
+ }
782
+ if (context.signal.aborted) throw context.signal.reason;
783
+ const headers = Object.freeze({
784
+ ...identityHeaders,
785
+ authorization: `Bearer ${normalizedToken(token)}`,
786
+ ...requestBody === void 0 ? {} : { "content-type": "application/json" }
787
+ });
788
+ let response;
789
+ for (let attempt = 0; attempt < 2; attempt += 1) {
790
+ try {
791
+ response = await this.http.request(
792
+ pathAndQuery,
793
+ {
794
+ method: options.method,
795
+ headers,
796
+ ...requestBody === void 0 ? {} : { body: requestBody }
797
+ },
798
+ context
799
+ );
800
+ } catch (error) {
801
+ if (isAbortOrTimeout(error) || error instanceof integrations.IntegrationExecutionError) throw error;
802
+ if (mutation) throw new UnknownMutationError();
803
+ throw transientError();
804
+ }
805
+ if (isRateLimited(response)) {
806
+ const delay = retryAfter(response.headers);
807
+ if (options.method === "GET" && attempt === 0 && delay !== void 0 && this.deadlineAllows(context, delay * 1e3)) {
808
+ await this.sleep(delay * 1e3, context.signal);
809
+ if (context.signal.aborted) throw context.signal.reason;
810
+ continue;
811
+ }
812
+ throw rateError();
813
+ }
814
+ break;
815
+ }
816
+ if (response === void 0) throw rateError();
817
+ if (response.status === 401) throw authError();
818
+ if (response.status === 403) throw apiError();
819
+ if (response.status < 200 || response.status >= 300) {
820
+ if (mutation && response.status >= 500) throw new UnknownMutationError();
821
+ if (response.status === 404 || response.status === 422 || response.status < 500) {
822
+ throw apiError();
823
+ }
824
+ if (mutation) throw new UnknownMutationError();
825
+ throw transientError();
826
+ }
827
+ try {
828
+ const decoded = new TextDecoder("utf-8", { fatal: true }).decode(response.bytes);
829
+ const document = JSON.parse(decoded);
830
+ return integrations.snapshotIntegrationResult(this.normalize(route, repository2, document, options));
831
+ } catch {
832
+ if (mutation) throw new UnknownMutationError();
833
+ throw transientError();
834
+ }
835
+ }
836
+ deadlineAllows(context, delayMs) {
837
+ return context.deadlineMonotonicMs === void 0 || context.deadlineMonotonicMs - this.monotonicNow() > delayMs;
838
+ }
839
+ normalize(route, repository2, document, options) {
840
+ if (route === "search_code") return this.normalizeSearch(repository2, document);
841
+ if (route === "get_file") return this.normalizeFile(document);
842
+ if (route === "list_issues") return this.normalizeIssueList(document);
843
+ if (route === "get_issue" || route === "create_issue") return this.normalizeIssue(document);
844
+ if (route === "add_comment") return this.normalizeComment(document);
845
+ const page = options.query?.page;
846
+ const perPage = options.query?.per_page;
847
+ if (route === "get_commit") return this.normalizeCommit(repository2, document, page, perPage);
848
+ if (route === "get_pull_request") return this.normalizePullRequest(repository2, document);
849
+ if (route === "list_pull_request_files") {
850
+ return this.normalizePullRequestFiles(document, page, perPage);
851
+ }
852
+ if (route === "list_check_runs") {
853
+ return this.normalizeCheckRuns(repository2, document, page, perPage);
854
+ }
855
+ if (route === "get_workflow_run") return this.normalizeWorkflowRun(repository2, document);
856
+ if (route === "list_workflow_jobs") {
857
+ return this.normalizeWorkflowJobs(
858
+ repository2,
859
+ options.path.split("/").at(-2),
860
+ document,
861
+ page,
862
+ perPage
863
+ );
864
+ }
865
+ if (route === "list_file_commits") {
866
+ return this.normalizeFileCommits(repository2, document, page, perPage);
867
+ }
868
+ if (route === "get_release") return this.normalizeRelease(repository2, document);
869
+ return this.normalizeDeployments(repository2, document, page, perPage);
870
+ }
871
+ normalizeSearch(repository2, document) {
872
+ const root = objectValue(document);
873
+ const totalCount = providerInteger(root.total_count);
874
+ const rows = arrayValue(root.items);
875
+ for (const value of rows) {
876
+ const item = objectValue(value);
877
+ if (objectValue(item.repository).full_name !== repository2) throw new ProviderShapeError();
878
+ }
879
+ const items = rows.slice(0, 20).map((value) => {
880
+ const item = objectValue(value);
881
+ const matches = item.text_matches ?? [];
882
+ let fragment = "";
883
+ if (matches !== null) {
884
+ const matchRows = arrayValue(matches);
885
+ if (matchRows.length > 0) {
886
+ fragment = providerByteString(objectValue(matchRows[0]).fragment, 0, 1048576);
887
+ }
888
+ }
889
+ return {
890
+ path: providerCharacterString(item.path, 1, 512),
891
+ sha: providerCharacterString(item.sha, 1, 64),
892
+ fragment: truncateUtf8(fragment, 1024)
893
+ };
894
+ });
895
+ const result = integrations.snapshotIntegrationResult({ total_count: totalCount, items });
896
+ if (new TextEncoder().encode(JSON.stringify(result)).byteLength > MAX_SEARCH_RESULT_BYTES) {
897
+ throw new ProviderShapeError();
898
+ }
899
+ return result;
900
+ }
901
+ normalizeFile(document) {
902
+ const root = objectValue(document);
903
+ if (root.type !== "file" || root.encoding !== "base64") throw new ProviderShapeError();
904
+ const path = providerCharacterString(root.path, 1, 512);
905
+ const sha = providerCharacterString(root.sha, 1, 64);
906
+ const size = providerInteger(root.size);
907
+ const content = providerCharacterString(root.content, 0, 1048576);
908
+ if (size > MAX_FILE_BYTES) return { path, sha, size, content_omitted: true };
909
+ const normalized = content.replace(/[\r\n]/g, "");
910
+ if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(normalized)) {
911
+ throw new ProviderShapeError();
912
+ }
913
+ const decoded = buffer.Buffer.from(normalized, "base64");
914
+ if (decoded.toString("base64") !== normalized || decoded.byteLength !== size) {
915
+ throw new ProviderShapeError();
916
+ }
917
+ if (decoded.byteLength > MAX_FILE_BYTES) return { path, sha, size, content_omitted: true };
918
+ const text = new TextDecoder("utf-8", { fatal: true }).decode(decoded);
919
+ return { path, sha, size, content: text, content_omitted: false };
920
+ }
921
+ normalizeIssueList(document) {
922
+ const items = arrayValue(document).slice(0, 20).map((value) => {
923
+ const issue = objectValue(value);
924
+ const body = issue.body === null ? "" : providerByteString(issue.body, 0, 1048576);
925
+ const state = issue.state;
926
+ if (state !== "open" && state !== "closed") throw new ProviderShapeError();
927
+ return {
928
+ number: providerInteger(issue.number, 1),
929
+ state,
930
+ title: providerCharacterString(issue.title, 1, 256),
931
+ body_preview: truncateUtf8(body, 1024)
932
+ };
933
+ });
934
+ return { items };
935
+ }
936
+ normalizeIssue(document) {
937
+ const issue = objectValue(document);
938
+ const state = issue.state;
939
+ if (state !== "open" && state !== "closed") throw new ProviderShapeError();
940
+ const body = issue.body === null ? "" : providerByteString(issue.body, 0, 16384);
941
+ if (utf8Size(body) > 16384) throw new ProviderShapeError();
942
+ return {
943
+ number: providerInteger(issue.number, 1),
944
+ state,
945
+ title: providerCharacterString(issue.title, 1, 256),
946
+ body,
947
+ url: providerCharacterString(issue.html_url, 1, MAX_URL_CHARACTERS)
948
+ };
949
+ }
950
+ normalizeComment(document) {
951
+ const comment = objectValue(document);
952
+ return {
953
+ id: providerInteger(comment.id, 1),
954
+ url: providerCharacterString(comment.html_url, 1, MAX_URL_CHARACTERS)
955
+ };
956
+ }
957
+ normalizeCommit(repository2, document, page, perPage) {
958
+ const root = objectValue(document);
959
+ const commit = objectValue(root.commit);
960
+ const message = boundedText(commit.message);
961
+ const repositorySegments = repository2.split("/");
962
+ const authorValue = commit.author;
963
+ const author = authorValue === null || authorValue === void 0 ? null : (() => {
964
+ const value = objectValue(authorValue);
965
+ return {
966
+ name: providerCharacterString(value.name, 1, 256),
967
+ date: providerCharacterString(value.date, 1, 100)
968
+ };
969
+ })();
970
+ const statsValue = objectValue(root.stats);
971
+ const sha = providerCharacterString(root.sha, 1, 64);
972
+ const base = {
973
+ sha,
974
+ url: providerGitHubUrl(root.html_url, "https://github.com", [
975
+ ...repositorySegments,
976
+ "commit",
977
+ sha
978
+ ]),
979
+ author,
980
+ message: message.text,
981
+ message_truncated: message.truncated,
982
+ stats: {
983
+ additions: providerInteger(statsValue.additions),
984
+ deletions: providerInteger(statsValue.deletions),
985
+ total: providerInteger(statsValue.total)
986
+ },
987
+ page,
988
+ per_page: perPage
989
+ };
990
+ const parentSource = boundedRows(root.parents);
991
+ const parents = parentSource.rows.map((value) => {
992
+ const parent = objectValue(value);
993
+ const parentSha = providerCharacterString(parent.sha, 1, 64);
994
+ return {
995
+ sha: parentSha,
996
+ url: providerGitHubUrl(parent.html_url, "https://github.com", [
997
+ ...repositorySegments,
998
+ "commit",
999
+ parentSha
1000
+ ])
1001
+ };
1002
+ });
1003
+ const fileSource = boundedRows(root.files);
1004
+ const files = fileSource.rows.map((value) => {
1005
+ const file = objectValue(value);
1006
+ return {
1007
+ filename: providerCharacterString(file.filename, 1, 512),
1008
+ status: providerCharacterString(file.status, 1, 100),
1009
+ additions: providerInteger(file.additions),
1010
+ deletions: providerInteger(file.deletions),
1011
+ changes: providerInteger(file.changes)
1012
+ };
1013
+ });
1014
+ const complete = {
1015
+ ...base,
1016
+ parents,
1017
+ parents_omitted_count: parentSource.omitted,
1018
+ files,
1019
+ files_omitted_count: fileSource.omitted
1020
+ };
1021
+ const fittedComplete = fitObjectToModelBudget(complete, [
1022
+ { path: ["message"], truncatedPath: ["message_truncated"] }
1023
+ ]);
1024
+ if (fittedComplete !== void 0) return fittedComplete;
1025
+ const rowFittingBase = { ...base, message: "", message_truncated: true };
1026
+ const parentResult = fitRows(
1027
+ parents,
1028
+ (items, omittedCount) => ({
1029
+ ...rowFittingBase,
1030
+ parents: items,
1031
+ parents_omitted_count: omittedCount,
1032
+ files: [],
1033
+ files_omitted_count: 0
1034
+ }),
1035
+ { initialOmitted: parentSource.omitted }
1036
+ );
1037
+ return fitRows(
1038
+ files,
1039
+ (items, omittedCount) => ({
1040
+ ...rowFittingBase,
1041
+ parents: parentResult.parents,
1042
+ parents_omitted_count: parentResult.parents_omitted_count,
1043
+ files: items,
1044
+ files_omitted_count: omittedCount
1045
+ }),
1046
+ { initialOmitted: fileSource.omitted }
1047
+ );
1048
+ }
1049
+ normalizePullRequest(repository2, document) {
1050
+ const root = objectValue(document);
1051
+ const title = boundedText(root.title);
1052
+ const body = boundedText(root.body ?? null, true);
1053
+ const base = objectValue(root.base);
1054
+ const head = objectValue(root.head);
1055
+ const number = providerInteger(root.number, 1);
1056
+ return requireObjectWithinModelBudget(
1057
+ {
1058
+ number,
1059
+ state: providerCharacterString(root.state, 1, 100),
1060
+ title: title.text,
1061
+ title_truncated: title.truncated,
1062
+ body: body.text,
1063
+ body_truncated: body.truncated,
1064
+ base_sha: providerCharacterString(base.sha, 1, 64),
1065
+ head_sha: providerCharacterString(head.sha, 1, 64),
1066
+ merge_sha: providerNullableCharacterString(root.merge_commit_sha, 1, 64),
1067
+ url: providerGitHubUrl(root.html_url, "https://github.com", [
1068
+ ...repository2.split("/"),
1069
+ "pull",
1070
+ String(number)
1071
+ ])
1072
+ },
1073
+ [
1074
+ { path: ["body"], truncatedPath: ["body_truncated"] },
1075
+ { path: ["title"], truncatedPath: ["title_truncated"] }
1076
+ ]
1077
+ );
1078
+ }
1079
+ normalizePullRequestFiles(document, page, perPage) {
1080
+ const source = boundedRows(document);
1081
+ const rows = source.rows.map((value) => {
1082
+ const root = objectValue(value);
1083
+ const patch = boundedText(root.patch ?? null, true);
1084
+ return {
1085
+ filename: providerCharacterString(root.filename, 1, 512),
1086
+ status: providerCharacterString(root.status, 1, 100),
1087
+ additions: providerInteger(root.additions),
1088
+ deletions: providerInteger(root.deletions),
1089
+ changes: providerInteger(root.changes),
1090
+ patch: patch.text,
1091
+ patch_truncated: patch.truncated
1092
+ };
1093
+ });
1094
+ return fitRows(
1095
+ rows,
1096
+ (items, omittedCount) => ({ items, omitted_count: omittedCount, page, per_page: perPage }),
1097
+ {
1098
+ initialOmitted: source.omitted,
1099
+ textFields: [{ path: ["patch"], truncatedPath: ["patch_truncated"] }]
1100
+ }
1101
+ );
1102
+ }
1103
+ normalizeCheckRuns(repository2, document, page, perPage) {
1104
+ const root = objectValue(document);
1105
+ const totalCount = providerInteger(root.total_count);
1106
+ const source = boundedRows(root.check_runs);
1107
+ const rows = source.rows.map((value) => {
1108
+ const run = objectValue(value);
1109
+ const output = objectValue(run.output);
1110
+ const title = boundedText(output.title ?? null, true);
1111
+ const summary = boundedText(output.summary ?? null, true);
1112
+ const text = boundedText(output.text ?? null, true);
1113
+ const id = providerInteger(run.id, 1);
1114
+ return {
1115
+ id,
1116
+ name: providerCharacterString(run.name, 1, 256),
1117
+ status: providerCharacterString(run.status, 1, 100),
1118
+ conclusion: providerNullableCharacterString(run.conclusion, 1, 100),
1119
+ url: providerGitHubUrl(run.html_url, "https://github.com", [
1120
+ ...repository2.split("/"),
1121
+ "runs",
1122
+ String(id)
1123
+ ]),
1124
+ output: {
1125
+ title: title.text,
1126
+ title_truncated: title.truncated,
1127
+ summary: summary.text,
1128
+ summary_truncated: summary.truncated,
1129
+ text: text.text,
1130
+ text_truncated: text.truncated
1131
+ }
1132
+ };
1133
+ });
1134
+ return fitRows(
1135
+ rows,
1136
+ (items, omittedCount) => ({
1137
+ total_count: totalCount,
1138
+ items,
1139
+ omitted_count: omittedCount,
1140
+ page,
1141
+ per_page: perPage
1142
+ }),
1143
+ {
1144
+ initialOmitted: source.omitted,
1145
+ textFields: [
1146
+ {
1147
+ path: ["output", "title"],
1148
+ truncatedPath: ["output", "title_truncated"]
1149
+ },
1150
+ {
1151
+ path: ["output", "summary"],
1152
+ truncatedPath: ["output", "summary_truncated"]
1153
+ },
1154
+ { path: ["output", "text"], truncatedPath: ["output", "text_truncated"] }
1155
+ ]
1156
+ }
1157
+ );
1158
+ }
1159
+ normalizeWorkflowRun(repository2, document) {
1160
+ const root = objectValue(document);
1161
+ const id = providerInteger(root.id, 1);
1162
+ return assertModelResultBudget({
1163
+ id,
1164
+ workflow: providerCharacterString(root.name, 1, 256),
1165
+ event: providerCharacterString(root.event, 1, 100),
1166
+ status: providerCharacterString(root.status, 1, 100),
1167
+ conclusion: providerNullableCharacterString(root.conclusion, 1, 100),
1168
+ head_sha: providerCharacterString(root.head_sha, 1, 64),
1169
+ attempt: providerInteger(root.run_attempt, 1),
1170
+ url: providerGitHubUrl(root.html_url, "https://github.com", [
1171
+ ...repository2.split("/"),
1172
+ "actions",
1173
+ "runs",
1174
+ String(id)
1175
+ ])
1176
+ });
1177
+ }
1178
+ normalizeWorkflowJobs(repository2, runId, document, page, perPage) {
1179
+ const root = objectValue(document);
1180
+ const totalCount = providerInteger(root.total_count);
1181
+ const source = boundedRows(root.jobs);
1182
+ const rows = source.rows.map((value) => {
1183
+ const job = objectValue(value);
1184
+ const stepSource = job.steps === void 0 || job.steps === null ? { rows: [], omitted: 0 } : boundedRows(job.steps);
1185
+ const steps = stepSource.rows.map((stepValue) => {
1186
+ const step = objectValue(stepValue);
1187
+ return {
1188
+ number: providerInteger(step.number, 1),
1189
+ name: providerCharacterString(step.name, 1, 256),
1190
+ status: providerCharacterString(step.status, 1, 100),
1191
+ conclusion: providerOptionalNullableCharacterString(step.conclusion, 1, 100),
1192
+ started_at: providerOptionalNullableCharacterString(step.started_at, 1, 100),
1193
+ completed_at: providerOptionalNullableCharacterString(step.completed_at, 1, 100)
1194
+ };
1195
+ });
1196
+ const id = providerInteger(job.id, 1);
1197
+ return {
1198
+ id,
1199
+ name: providerCharacterString(job.name, 1, 256),
1200
+ status: providerCharacterString(job.status, 1, 100),
1201
+ conclusion: providerOptionalNullableCharacterString(job.conclusion, 1, 100),
1202
+ started_at: providerOptionalNullableCharacterString(job.started_at, 1, 100),
1203
+ completed_at: providerOptionalNullableCharacterString(job.completed_at, 1, 100),
1204
+ url: providerGitHubUrl(job.html_url, "https://github.com", [
1205
+ ...repository2.split("/"),
1206
+ "actions",
1207
+ "runs",
1208
+ runId,
1209
+ "job",
1210
+ String(id)
1211
+ ]),
1212
+ steps,
1213
+ steps_omitted_count: stepSource.omitted
1214
+ };
1215
+ });
1216
+ return fitRows(
1217
+ rows,
1218
+ (items, omittedCount) => ({
1219
+ total_count: totalCount,
1220
+ items,
1221
+ omitted_count: omittedCount,
1222
+ page,
1223
+ per_page: perPage
1224
+ }),
1225
+ {
1226
+ initialOmitted: source.omitted,
1227
+ shrink: (row, fits) => {
1228
+ const candidate = structuredClone(row);
1229
+ const steps = candidate.steps;
1230
+ while (!fits(candidate) && steps.length > 0) {
1231
+ steps.pop();
1232
+ candidate.steps_omitted_count = candidate.steps_omitted_count + 1;
1233
+ }
1234
+ return fits(candidate) ? candidate : void 0;
1235
+ }
1236
+ }
1237
+ );
1238
+ }
1239
+ normalizeFileCommits(repository2, document, page, perPage) {
1240
+ const source = boundedRows(document);
1241
+ const rows = source.rows.map((value) => {
1242
+ const root = objectValue(value);
1243
+ const commit = objectValue(root.commit);
1244
+ const message = boundedText(commit.message);
1245
+ const authorValue = commit.author;
1246
+ const authorDate = authorValue === null || authorValue === void 0 ? null : providerOptionalNullableCharacterString(objectValue(authorValue).date, 1, 100);
1247
+ const sha = providerCharacterString(root.sha, 1, 64);
1248
+ return {
1249
+ sha,
1250
+ message: message.text,
1251
+ message_truncated: message.truncated,
1252
+ author_date: authorDate,
1253
+ url: providerGitHubUrl(root.html_url, "https://github.com", [
1254
+ ...repository2.split("/"),
1255
+ "commit",
1256
+ sha
1257
+ ])
1258
+ };
1259
+ });
1260
+ return fitRows(
1261
+ rows,
1262
+ (items, omittedCount) => ({ items, omitted_count: omittedCount, page, per_page: perPage }),
1263
+ {
1264
+ initialOmitted: source.omitted,
1265
+ textFields: [{ path: ["message"], truncatedPath: ["message_truncated"] }]
1266
+ }
1267
+ );
1268
+ }
1269
+ normalizeRelease(repository2, document) {
1270
+ const root = objectValue(document);
1271
+ const body = boundedText(root.body ?? null, true);
1272
+ const tag = providerCharacterString(root.tag_name, 1, 100);
1273
+ return requireObjectWithinModelBudget(
1274
+ {
1275
+ tag,
1276
+ target: providerCharacterString(root.target_commitish, 1, 100),
1277
+ draft: providerBoolean(root.draft),
1278
+ prerelease: providerBoolean(root.prerelease),
1279
+ published_at: providerOptionalNullableCharacterString(root.published_at, 1, 100),
1280
+ body: body.text,
1281
+ body_truncated: body.truncated,
1282
+ url: providerGitHubUrl(root.html_url, "https://github.com", [
1283
+ ...repository2.split("/"),
1284
+ "releases",
1285
+ "tag",
1286
+ ...tag.split("/")
1287
+ ])
1288
+ },
1289
+ [{ path: ["body"], truncatedPath: ["body_truncated"] }]
1290
+ );
1291
+ }
1292
+ normalizeDeployments(repository2, document, page, perPage) {
1293
+ const source = boundedRows(document);
1294
+ const rows = source.rows.map((value) => {
1295
+ const root = objectValue(value);
1296
+ const id = providerInteger(root.id, 1);
1297
+ return {
1298
+ id,
1299
+ ref: providerCharacterString(root.ref, 1, 100),
1300
+ sha: providerCharacterString(root.sha, 1, 64),
1301
+ environment: providerCharacterString(root.environment, 1, 100),
1302
+ task: providerCharacterString(root.task, 1, 100),
1303
+ created_at: providerCharacterString(root.created_at, 1, 100),
1304
+ url: providerGitHubUrl(root.url, "https://api.github.com", [
1305
+ "repos",
1306
+ ...repository2.split("/"),
1307
+ "deployments",
1308
+ String(id)
1309
+ ])
1310
+ };
1311
+ });
1312
+ return fitRows(
1313
+ rows,
1314
+ (items, omittedCount) => ({ items, omitted_count: omittedCount, page, per_page: perPage }),
1315
+ { initialOmitted: source.omitted }
1316
+ );
1317
+ }
1318
+ };
1319
+
1320
+ // registry/github/index.ts
1321
+ var repository = {
1322
+ type: "string",
1323
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1324
+ };
1325
+ var issueNumber = { type: "integer", minimum: 1, maximum: Number.MAX_SAFE_INTEGER };
1326
+ function parameters(properties, required) {
1327
+ return {
1328
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1329
+ type: "object",
1330
+ properties,
1331
+ required: [...required],
1332
+ additionalProperties: false
1333
+ };
1334
+ }
1335
+ function specs() {
1336
+ return [
1337
+ {
1338
+ name: "add_comment",
1339
+ description: "Add a comment to a GitHub issue.",
1340
+ parameters: parameters(
1341
+ {
1342
+ repository,
1343
+ issue_number: issueNumber,
1344
+ body: { type: "string", minLength: 1, maxLength: 16384 }
1345
+ },
1346
+ ["repository", "issue_number", "body"]
1347
+ ),
1348
+ risk: "external_effect",
1349
+ parallel_safe: false,
1350
+ timeout_ms: 15e3
1351
+ },
1352
+ {
1353
+ name: "create_issue",
1354
+ description: "Create a GitHub issue.",
1355
+ parameters: parameters(
1356
+ {
1357
+ repository,
1358
+ title: { type: "string", minLength: 1, maxLength: 256 },
1359
+ body: { type: "string", minLength: 0, maxLength: 16384 }
1360
+ },
1361
+ ["repository", "title", "body"]
1362
+ ),
1363
+ risk: "external_effect",
1364
+ parallel_safe: false,
1365
+ timeout_ms: 15e3
1366
+ },
1367
+ {
1368
+ name: "get_file",
1369
+ description: "Get a file from a GitHub repository.",
1370
+ parameters: parameters(
1371
+ {
1372
+ repository,
1373
+ path: { type: "string", minLength: 1, maxLength: 512 },
1374
+ ref: { type: "string", minLength: 1, maxLength: 100 }
1375
+ },
1376
+ ["repository", "path"]
1377
+ ),
1378
+ risk: "read",
1379
+ parallel_safe: true,
1380
+ timeout_ms: 1e4
1381
+ },
1382
+ {
1383
+ name: "get_issue",
1384
+ description: "Get a GitHub issue.",
1385
+ parameters: parameters({ repository, issue_number: issueNumber }, [
1386
+ "repository",
1387
+ "issue_number"
1388
+ ]),
1389
+ risk: "read",
1390
+ parallel_safe: true,
1391
+ timeout_ms: 1e4
1392
+ },
1393
+ {
1394
+ name: "list_issues",
1395
+ description: "List GitHub issues.",
1396
+ parameters: parameters(
1397
+ {
1398
+ repository,
1399
+ state: { type: "string", enum: ["open", "closed", "all"], default: "open" },
1400
+ page: { type: "integer", minimum: 1, maximum: 1e3, default: 1 },
1401
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1402
+ },
1403
+ ["repository"]
1404
+ ),
1405
+ risk: "read",
1406
+ parallel_safe: true,
1407
+ timeout_ms: 1e4
1408
+ },
1409
+ {
1410
+ name: "search_code",
1411
+ description: "Search code in a GitHub repository.",
1412
+ parameters: parameters(
1413
+ {
1414
+ repository,
1415
+ query: { type: "string", minLength: 1, maxLength: 256 },
1416
+ page: { type: "integer", minimum: 1, maximum: 50, default: 1 },
1417
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1418
+ },
1419
+ ["repository", "query"]
1420
+ ),
1421
+ risk: "read",
1422
+ parallel_safe: true,
1423
+ timeout_ms: 1e4
1424
+ }
1425
+ ];
1426
+ }
1427
+ function objectResult(value) {
1428
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1429
+ throw new Error("GitHub client returned an invalid tool result");
1430
+ }
1431
+ return value;
1432
+ }
1433
+ function handler(client, name) {
1434
+ return async (args, context) => {
1435
+ switch (name) {
1436
+ case "add_comment":
1437
+ return objectResult(
1438
+ await client.addComment(context, {
1439
+ repository: args.repository,
1440
+ issueNumber: args.issue_number,
1441
+ body: args.body
1442
+ })
1443
+ );
1444
+ case "create_issue":
1445
+ return objectResult(
1446
+ await client.createIssue(context, {
1447
+ repository: args.repository,
1448
+ title: args.title,
1449
+ body: args.body
1450
+ })
1451
+ );
1452
+ case "get_file":
1453
+ return objectResult(
1454
+ await client.getFile(context, {
1455
+ repository: args.repository,
1456
+ path: args.path,
1457
+ ...args.ref === void 0 ? {} : { ref: args.ref }
1458
+ })
1459
+ );
1460
+ case "get_issue":
1461
+ return objectResult(
1462
+ await client.getIssue(context, {
1463
+ repository: args.repository,
1464
+ issueNumber: args.issue_number
1465
+ })
1466
+ );
1467
+ case "list_issues":
1468
+ return objectResult(
1469
+ await client.listIssues(context, {
1470
+ repository: args.repository,
1471
+ ...args.state === void 0 ? {} : { state: args.state },
1472
+ ...args.page === void 0 ? {} : { page: args.page },
1473
+ ...args.per_page === void 0 ? {} : { perPage: args.per_page }
1474
+ })
1475
+ );
1476
+ case "search_code":
1477
+ return objectResult(
1478
+ await client.searchCode(context, {
1479
+ repository: args.repository,
1480
+ query: args.query,
1481
+ ...args.page === void 0 ? {} : { page: args.page },
1482
+ ...args.per_page === void 0 ? {} : { perPage: args.per_page }
1483
+ })
1484
+ );
1485
+ default:
1486
+ throw new Error("Unknown GitHub tool");
1487
+ }
1488
+ };
1489
+ }
1490
+ function createSharedGitHubToolBindings(client) {
1491
+ return specs().map((spec) => [spec, handler(client, spec.name)]);
1492
+ }
1493
+ new Proxy(
1494
+ {},
1495
+ {
1496
+ get: () => async () => {
1497
+ throw new Error("inspection dependencies must not execute");
1498
+ }
1499
+ }
1500
+ );
1501
+
1502
+ // contracts/integrations/github-tool-abi-typescript-v1.json
1503
+ var github_tool_abi_typescript_v1_default = {
1504
+ tools: [
1505
+ {
1506
+ name: "add_comment",
1507
+ description: "Add a comment to a GitHub issue.",
1508
+ parameters: {
1509
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1510
+ type: "object",
1511
+ properties: {
1512
+ repository: {
1513
+ type: "string",
1514
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1515
+ },
1516
+ issue_number: {
1517
+ type: "integer",
1518
+ minimum: 1,
1519
+ maximum: 9007199254740991
1520
+ },
1521
+ body: { type: "string", minLength: 1, maxLength: 16384 }
1522
+ },
1523
+ required: ["repository", "issue_number", "body"],
1524
+ additionalProperties: false
1525
+ },
1526
+ risk: "external_effect",
1527
+ parallel_safe: false,
1528
+ timeout_ms: 15e3
1529
+ },
1530
+ {
1531
+ name: "create_issue",
1532
+ description: "Create a GitHub issue.",
1533
+ parameters: {
1534
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1535
+ type: "object",
1536
+ properties: {
1537
+ repository: {
1538
+ type: "string",
1539
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1540
+ },
1541
+ title: { type: "string", minLength: 1, maxLength: 256 },
1542
+ body: { type: "string", minLength: 0, maxLength: 16384 }
1543
+ },
1544
+ required: ["repository", "title", "body"],
1545
+ additionalProperties: false
1546
+ },
1547
+ risk: "external_effect",
1548
+ parallel_safe: false,
1549
+ timeout_ms: 15e3
1550
+ },
1551
+ {
1552
+ name: "get_file",
1553
+ description: "Get a file from a GitHub repository.",
1554
+ parameters: {
1555
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1556
+ type: "object",
1557
+ properties: {
1558
+ repository: {
1559
+ type: "string",
1560
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1561
+ },
1562
+ path: { type: "string", minLength: 1, maxLength: 512 },
1563
+ ref: { type: "string", minLength: 1, maxLength: 100 }
1564
+ },
1565
+ required: ["repository", "path"],
1566
+ additionalProperties: false
1567
+ },
1568
+ risk: "read",
1569
+ parallel_safe: true,
1570
+ timeout_ms: 1e4
1571
+ },
1572
+ {
1573
+ name: "get_issue",
1574
+ description: "Get a GitHub issue.",
1575
+ parameters: {
1576
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1577
+ type: "object",
1578
+ properties: {
1579
+ repository: {
1580
+ type: "string",
1581
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1582
+ },
1583
+ issue_number: {
1584
+ type: "integer",
1585
+ minimum: 1,
1586
+ maximum: 9007199254740991
1587
+ }
1588
+ },
1589
+ required: ["repository", "issue_number"],
1590
+ additionalProperties: false
1591
+ },
1592
+ risk: "read",
1593
+ parallel_safe: true,
1594
+ timeout_ms: 1e4
1595
+ },
1596
+ {
1597
+ name: "list_issues",
1598
+ description: "List GitHub issues.",
1599
+ parameters: {
1600
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1601
+ type: "object",
1602
+ properties: {
1603
+ repository: {
1604
+ type: "string",
1605
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1606
+ },
1607
+ state: {
1608
+ type: "string",
1609
+ enum: ["open", "closed", "all"],
1610
+ default: "open"
1611
+ },
1612
+ page: { type: "integer", minimum: 1, maximum: 1e3, default: 1 },
1613
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1614
+ },
1615
+ required: ["repository"],
1616
+ additionalProperties: false
1617
+ },
1618
+ risk: "read",
1619
+ parallel_safe: true,
1620
+ timeout_ms: 1e4
1621
+ },
1622
+ {
1623
+ name: "search_code",
1624
+ description: "Search code in a GitHub repository.",
1625
+ parameters: {
1626
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1627
+ type: "object",
1628
+ properties: {
1629
+ repository: {
1630
+ type: "string",
1631
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1632
+ },
1633
+ query: { type: "string", minLength: 1, maxLength: 256 },
1634
+ page: { type: "integer", minimum: 1, maximum: 50, default: 1 },
1635
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1636
+ },
1637
+ required: ["repository", "query"],
1638
+ additionalProperties: false
1639
+ },
1640
+ risk: "read",
1641
+ parallel_safe: true,
1642
+ timeout_ms: 1e4
1643
+ },
1644
+ {
1645
+ name: "get_commit",
1646
+ description: "Get bounded commit evidence from a GitHub repository.",
1647
+ parameters: {
1648
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1649
+ type: "object",
1650
+ properties: {
1651
+ repository: {
1652
+ type: "string",
1653
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1654
+ },
1655
+ ref: { type: "string", minLength: 1, maxLength: 100 },
1656
+ page: { type: "integer", minimum: 1, maximum: 1e3, default: 1 },
1657
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1658
+ },
1659
+ required: ["repository", "ref"],
1660
+ additionalProperties: false
1661
+ },
1662
+ risk: "read",
1663
+ parallel_safe: true,
1664
+ timeout_ms: 1e4
1665
+ },
1666
+ {
1667
+ name: "get_pull_request",
1668
+ description: "Get bounded pull request evidence from GitHub.",
1669
+ parameters: {
1670
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1671
+ type: "object",
1672
+ properties: {
1673
+ repository: {
1674
+ type: "string",
1675
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1676
+ },
1677
+ pull_number: {
1678
+ type: "integer",
1679
+ minimum: 1,
1680
+ maximum: 9007199254740991
1681
+ }
1682
+ },
1683
+ required: ["repository", "pull_number"],
1684
+ additionalProperties: false
1685
+ },
1686
+ risk: "read",
1687
+ parallel_safe: true,
1688
+ timeout_ms: 1e4
1689
+ },
1690
+ {
1691
+ name: "list_pull_request_files",
1692
+ description: "List bounded changed-file evidence for a GitHub pull request.",
1693
+ parameters: {
1694
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1695
+ type: "object",
1696
+ properties: {
1697
+ repository: {
1698
+ type: "string",
1699
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1700
+ },
1701
+ pull_number: {
1702
+ type: "integer",
1703
+ minimum: 1,
1704
+ maximum: 9007199254740991
1705
+ },
1706
+ page: { type: "integer", minimum: 1, maximum: 1e3, default: 1 },
1707
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1708
+ },
1709
+ required: ["repository", "pull_number"],
1710
+ additionalProperties: false
1711
+ },
1712
+ risk: "read",
1713
+ parallel_safe: true,
1714
+ timeout_ms: 1e4
1715
+ },
1716
+ {
1717
+ name: "list_check_runs",
1718
+ description: "List bounded GitHub check-run evidence for a ref.",
1719
+ parameters: {
1720
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1721
+ type: "object",
1722
+ properties: {
1723
+ repository: {
1724
+ type: "string",
1725
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1726
+ },
1727
+ ref: { type: "string", minLength: 1, maxLength: 100 },
1728
+ filter: {
1729
+ type: "string",
1730
+ enum: ["latest", "all"],
1731
+ default: "latest"
1732
+ },
1733
+ page: { type: "integer", minimum: 1, maximum: 1e3, default: 1 },
1734
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1735
+ },
1736
+ required: ["repository", "ref"],
1737
+ additionalProperties: false
1738
+ },
1739
+ risk: "read",
1740
+ parallel_safe: true,
1741
+ timeout_ms: 1e4
1742
+ },
1743
+ {
1744
+ name: "get_workflow_run",
1745
+ description: "Get bounded GitHub workflow-run evidence.",
1746
+ parameters: {
1747
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1748
+ type: "object",
1749
+ properties: {
1750
+ repository: {
1751
+ type: "string",
1752
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1753
+ },
1754
+ run_id: {
1755
+ type: "integer",
1756
+ minimum: 1,
1757
+ maximum: 9007199254740991
1758
+ }
1759
+ },
1760
+ required: ["repository", "run_id"],
1761
+ additionalProperties: false
1762
+ },
1763
+ risk: "read",
1764
+ parallel_safe: true,
1765
+ timeout_ms: 1e4
1766
+ },
1767
+ {
1768
+ name: "list_workflow_jobs",
1769
+ description: "List bounded GitHub workflow-job evidence.",
1770
+ parameters: {
1771
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1772
+ type: "object",
1773
+ properties: {
1774
+ repository: {
1775
+ type: "string",
1776
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1777
+ },
1778
+ run_id: {
1779
+ type: "integer",
1780
+ minimum: 1,
1781
+ maximum: 9007199254740991
1782
+ },
1783
+ filter: {
1784
+ type: "string",
1785
+ enum: ["latest", "all"],
1786
+ default: "latest"
1787
+ },
1788
+ page: { type: "integer", minimum: 1, maximum: 1e3, default: 1 },
1789
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1790
+ },
1791
+ required: ["repository", "run_id"],
1792
+ additionalProperties: false
1793
+ },
1794
+ risk: "read",
1795
+ parallel_safe: true,
1796
+ timeout_ms: 1e4
1797
+ },
1798
+ {
1799
+ name: "list_file_commits",
1800
+ description: "List bounded GitHub commit history for a file path.",
1801
+ parameters: {
1802
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1803
+ type: "object",
1804
+ properties: {
1805
+ repository: {
1806
+ type: "string",
1807
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1808
+ },
1809
+ path: { type: "string", minLength: 1, maxLength: 512 },
1810
+ ref: { type: "string", minLength: 1, maxLength: 100 },
1811
+ page: { type: "integer", minimum: 1, maximum: 1e3, default: 1 },
1812
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1813
+ },
1814
+ required: ["repository", "path"],
1815
+ additionalProperties: false
1816
+ },
1817
+ risk: "read",
1818
+ parallel_safe: true,
1819
+ timeout_ms: 1e4
1820
+ },
1821
+ {
1822
+ name: "get_release",
1823
+ description: "Get bounded published-release evidence for a GitHub tag.",
1824
+ parameters: {
1825
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1826
+ type: "object",
1827
+ properties: {
1828
+ repository: {
1829
+ type: "string",
1830
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1831
+ },
1832
+ tag: { type: "string", minLength: 1, maxLength: 100 }
1833
+ },
1834
+ required: ["repository", "tag"],
1835
+ additionalProperties: false
1836
+ },
1837
+ risk: "read",
1838
+ parallel_safe: true,
1839
+ timeout_ms: 1e4
1840
+ },
1841
+ {
1842
+ name: "list_deployments",
1843
+ description: "List bounded GitHub deployment evidence.",
1844
+ parameters: {
1845
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1846
+ type: "object",
1847
+ properties: {
1848
+ repository: {
1849
+ type: "string",
1850
+ pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
1851
+ },
1852
+ ref: { type: "string", minLength: 1, maxLength: 100 },
1853
+ sha: { type: "string", pattern: "^[0-9A-Fa-f]{1,64}$" },
1854
+ environment: { type: "string", minLength: 1, maxLength: 100 },
1855
+ task: { type: "string", minLength: 1, maxLength: 100 },
1856
+ page: { type: "integer", minimum: 1, maximum: 1e3, default: 1 },
1857
+ per_page: { type: "integer", minimum: 1, maximum: 20, default: 10 }
1858
+ },
1859
+ required: ["repository"],
1860
+ additionalProperties: false
1861
+ },
1862
+ risk: "read",
1863
+ parallel_safe: true,
1864
+ timeout_ms: 1e4
1865
+ }
1866
+ ]
1867
+ };
1868
+
1869
+ // registry/github/package-tools.ts
1870
+ function objectResult2(value) {
1871
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1872
+ throw new Error("GitHub client returned an invalid tool result");
1873
+ }
1874
+ return value;
1875
+ }
1876
+ function extensionSpecs() {
1877
+ return github_tool_abi_typescript_v1_default.tools.slice(6).map((tool) => ({
1878
+ name: tool.name,
1879
+ description: tool.description,
1880
+ parameters: tool.parameters,
1881
+ risk: "read",
1882
+ parallel_safe: true,
1883
+ timeout_ms: 1e4
1884
+ }));
1885
+ }
1886
+ function extensionHandler(client, name) {
1887
+ return async (args, context) => {
1888
+ switch (name) {
1889
+ case "get_commit":
1890
+ return objectResult2(
1891
+ await client.getCommit(context, {
1892
+ repository: args.repository,
1893
+ ref: args.ref,
1894
+ ...args.page === void 0 ? {} : { page: args.page },
1895
+ ...args.per_page === void 0 ? {} : { perPage: args.per_page }
1896
+ })
1897
+ );
1898
+ case "get_pull_request":
1899
+ return objectResult2(
1900
+ await client.getPullRequest(context, {
1901
+ repository: args.repository,
1902
+ pullNumber: args.pull_number
1903
+ })
1904
+ );
1905
+ case "list_pull_request_files":
1906
+ return objectResult2(
1907
+ await client.listPullRequestFiles(context, {
1908
+ repository: args.repository,
1909
+ pullNumber: args.pull_number,
1910
+ ...args.page === void 0 ? {} : { page: args.page },
1911
+ ...args.per_page === void 0 ? {} : { perPage: args.per_page }
1912
+ })
1913
+ );
1914
+ case "list_check_runs":
1915
+ return objectResult2(
1916
+ await client.listCheckRuns(context, {
1917
+ repository: args.repository,
1918
+ ref: args.ref,
1919
+ ...args.filter === void 0 ? {} : { filter: args.filter },
1920
+ ...args.page === void 0 ? {} : { page: args.page },
1921
+ ...args.per_page === void 0 ? {} : { perPage: args.per_page }
1922
+ })
1923
+ );
1924
+ case "get_workflow_run":
1925
+ return objectResult2(
1926
+ await client.getWorkflowRun(context, {
1927
+ repository: args.repository,
1928
+ runId: args.run_id
1929
+ })
1930
+ );
1931
+ case "list_workflow_jobs":
1932
+ return objectResult2(
1933
+ await client.listWorkflowJobs(context, {
1934
+ repository: args.repository,
1935
+ runId: args.run_id,
1936
+ ...args.filter === void 0 ? {} : { filter: args.filter },
1937
+ ...args.page === void 0 ? {} : { page: args.page },
1938
+ ...args.per_page === void 0 ? {} : { perPage: args.per_page }
1939
+ })
1940
+ );
1941
+ case "list_file_commits":
1942
+ return objectResult2(
1943
+ await client.listFileCommits(context, {
1944
+ repository: args.repository,
1945
+ path: args.path,
1946
+ ...args.ref === void 0 ? {} : { ref: args.ref },
1947
+ ...args.page === void 0 ? {} : { page: args.page },
1948
+ ...args.per_page === void 0 ? {} : { perPage: args.per_page }
1949
+ })
1950
+ );
1951
+ case "get_release":
1952
+ return objectResult2(
1953
+ await client.getRelease(context, {
1954
+ repository: args.repository,
1955
+ tag: args.tag
1956
+ })
1957
+ );
1958
+ case "list_deployments":
1959
+ return objectResult2(
1960
+ await client.listDeployments(context, {
1961
+ repository: args.repository,
1962
+ ...args.ref === void 0 ? {} : { ref: args.ref },
1963
+ ...args.sha === void 0 ? {} : { sha: args.sha },
1964
+ ...args.environment === void 0 ? {} : { environment: args.environment },
1965
+ ...args.task === void 0 ? {} : { task: args.task },
1966
+ ...args.page === void 0 ? {} : { page: args.page },
1967
+ ...args.per_page === void 0 ? {} : { perPage: args.per_page }
1968
+ })
1969
+ );
1970
+ default:
1971
+ throw new Error("Unknown GitHub package tool");
1972
+ }
1973
+ };
1974
+ }
1975
+ function createPackageGitHubToolBindings(client) {
1976
+ return extensionSpecs().map((spec) => [spec, extensionHandler(client, spec.name)]);
1977
+ }
1978
+ var productionRuntime = {
1979
+ createRequester: (observability) => integrations.createGitHubRequester(observability),
1980
+ createClient: (options) => new GitHubClient(options)
1981
+ };
1982
+ function createPackageGitHubState(options, runtime = productionRuntime) {
1983
+ const { metricsSink, traceSink, tokenFor, ...clientOptions } = options;
1984
+ const metrics = metricsSink ?? kaji.NOOP_METRICS;
1985
+ const trace = traceSink ?? kaji.NOOP_TRACE;
1986
+ const instrumentedTokenFor = async (context) => {
1987
+ const started = performance.now();
1988
+ const span = kaji.startSpan(trace, "kaji.integration.auth", {
1989
+ "session.id": context.sessionId,
1990
+ "turn.id": context.turnId,
1991
+ "request.id": context.requestId,
1992
+ "trace.id": context.traceId,
1993
+ "tool.call_id": context.toolCallId,
1994
+ "integration.name": "github",
1995
+ "integration.operation": "token",
1996
+ "http.status_family": "none"
1997
+ });
1998
+ let outcome = "error";
1999
+ try {
2000
+ const token = await tokenFor(context);
2001
+ outcome = "success";
2002
+ return token;
2003
+ } catch (error) {
2004
+ if (error instanceof DOMException && error.name === "AbortError") outcome = "cancelled";
2005
+ span.recordError(error);
2006
+ throw error;
2007
+ } finally {
2008
+ kaji.recordMetric(metrics, "kaji.integration.auth_ms", Math.max(0, performance.now() - started), {
2009
+ integration: "github",
2010
+ operation: "token",
2011
+ outcome
2012
+ });
2013
+ span.end();
2014
+ }
2015
+ };
2016
+ const requester = runtime.createRequester({ metricsSink, traceSink });
2017
+ try {
2018
+ return {
2019
+ client: runtime.createClient({
2020
+ ...clientOptions,
2021
+ tokenFor: instrumentedTokenFor,
2022
+ http: requester
2023
+ }),
2024
+ close: () => requester.close()
2025
+ };
2026
+ } catch (error) {
2027
+ try {
2028
+ requester.close();
2029
+ } catch {
2030
+ }
2031
+ throw error;
2032
+ }
2033
+ }
2034
+
2035
+ // src/integrations/github.ts
2036
+ var GitHubIntegration = class extends kaji.Integration {
2037
+ namespace = "github";
2038
+ #client;
2039
+ #closeOwnedRequester;
2040
+ #toolExposure;
2041
+ #closed = false;
2042
+ constructor(options) {
2043
+ super();
2044
+ if (options.toolExposure !== void 0 && options.toolExposure !== "read-only" && options.toolExposure !== "all") {
2045
+ throw new TypeError('GitHub toolExposure must be "all" or "read-only"');
2046
+ }
2047
+ this.#toolExposure = options.toolExposure ?? "all";
2048
+ const state = createPackageGitHubState(options);
2049
+ this.#client = state.client;
2050
+ this.#closeOwnedRequester = state.close;
2051
+ }
2052
+ tools() {
2053
+ const bindings = [
2054
+ ...createSharedGitHubToolBindings(this.#client),
2055
+ ...createPackageGitHubToolBindings(this.#client)
2056
+ ];
2057
+ const exposed = this.#toolExposure === "read-only" ? bindings.filter(([spec]) => spec.risk === "read") : bindings;
2058
+ return exposed.map(([spec, handler2]) => [
2059
+ spec,
2060
+ async (args, context) => {
2061
+ if (this.#closed) throw new integrations.IntegrationPolicyError();
2062
+ return handler2(args, context);
2063
+ }
2064
+ ]);
2065
+ }
2066
+ close() {
2067
+ const close = this.#closeOwnedRequester;
2068
+ if (close === void 0) return;
2069
+ close();
2070
+ this.#closeOwnedRequester = void 0;
2071
+ this.#closed = true;
2072
+ }
2073
+ };
2074
+ function createGithubIntegration(options) {
2075
+ return new GitHubIntegration(options);
2076
+ }
2077
+ function inspectIntegration() {
2078
+ const integration = createGithubIntegration({
2079
+ tokenFor: async () => {
2080
+ throw new Error("inspection dependencies must not execute");
2081
+ },
2082
+ repositories: []
2083
+ });
2084
+ integration.close();
2085
+ return integration;
2086
+ }
2087
+
2088
+ exports.GitHubIntegration = GitHubIntegration;
2089
+ exports.createGithubIntegration = createGithubIntegration;
2090
+ exports.inspectIntegration = inspectIntegration;
2091
+ //# sourceMappingURL=github.cjs.map
2092
+ //# sourceMappingURL=github.cjs.map