@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.
- package/LICENSE +105 -0
- package/README.md +598 -0
- package/contracts/README.md +14 -0
- package/contracts/beta-core-v1.json +52 -0
- package/contracts/cli/init-cases-v1.json +27 -0
- package/contracts/errors/error-codes.json +48 -0
- package/contracts/errors/integration-recovery-v1.json +127 -0
- package/contracts/errors/provider-normalization.json +111 -0
- package/contracts/events/conformance-invalid.json +20 -0
- package/contracts/events/conformance.json +511 -0
- package/contracts/events/new-kaji-event-v1.schema.json +1021 -0
- package/contracts/events/stored-kaji-event-v1.schema.json +1025 -0
- package/contracts/feature-tiers-v1.json +488 -0
- package/contracts/integrations/abi-index-v1.json +8 -0
- package/contracts/integrations/conformance-invalid.json +443 -0
- package/contracts/integrations/conformance-valid.json +121 -0
- package/contracts/integrations/copy-provenance-v1.schema.json +61 -0
- package/contracts/integrations/echo-tool-abi-v1.json +37 -0
- package/contracts/integrations/github-api-conformance-v1.json +644 -0
- package/contracts/integrations/github-tool-abi-typescript-v1.json +369 -0
- package/contracts/integrations/github-tool-abi-v1.json +146 -0
- package/contracts/integrations/gmail-api-conformance-v1.json +750 -0
- package/contracts/integrations/gmail-tool-abi-v1.json +62 -0
- package/contracts/integrations/index.schema.json +37 -0
- package/contracts/integrations/manifest.schema.json +119 -0
- package/contracts/parity/expected-normalized.json +4906 -0
- package/contracts/parity/scenarios.json +100 -0
- package/contracts/parity/scenarios.schema.json +214 -0
- package/contracts/providers/cost-conformance.json +112 -0
- package/contracts/release/github-proof-v1.schema.json +138 -0
- package/contracts/release/gmail-proof-v1.schema.json +138 -0
- package/contracts/release/kaji-ts-consumer-handoff-v1.schema.json +1289 -0
- package/contracts/release/publisher-identity-receipt-v1.schema.json +319 -0
- package/contracts/release/typescript-onboarding-evidence-v1.schema.json +740 -0
- package/contracts/tools/conformance-invalid.json +271 -0
- package/contracts/tools/conformance-valid.json +78 -0
- package/contracts/tools/tool-schema-v1.schema.json +18 -0
- package/dist/anthropic.cjs +1231 -0
- package/dist/anthropic.cjs.map +1 -0
- package/dist/anthropic.d.cts +26 -0
- package/dist/anthropic.d.ts +26 -0
- package/dist/anthropic.js +270 -0
- package/dist/anthropic.js.map +1 -0
- package/dist/auth.cjs +1507 -0
- package/dist/auth.cjs.map +1 -0
- package/dist/auth.d.cts +129 -0
- package/dist/auth.d.ts +129 -0
- package/dist/auth.js +1039 -0
- package/dist/auth.js.map +1 -0
- package/dist/base-B9FRMcP8.d.cts +140 -0
- package/dist/base-nHQd1VtS.d.ts +140 -0
- package/dist/chunk-AAM33KAO.js +4367 -0
- package/dist/chunk-AAM33KAO.js.map +1 -0
- package/dist/chunk-KAJ6BM64.js +153 -0
- package/dist/chunk-KAJ6BM64.js.map +1 -0
- package/dist/chunk-KCAXIOZS.js +308 -0
- package/dist/chunk-KCAXIOZS.js.map +1 -0
- package/dist/chunk-LSJ4AVO2.js +243 -0
- package/dist/chunk-LSJ4AVO2.js.map +1 -0
- package/dist/chunk-TM7ZGOJX.js +716 -0
- package/dist/chunk-TM7ZGOJX.js.map +1 -0
- package/dist/cli/bin.d.ts +2 -0
- package/dist/cli/bin.js +13 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/chunk-2RCWPRVY.js +6277 -0
- package/dist/cli/chunk-2RCWPRVY.js.map +1 -0
- package/dist/cli/chunk-SEBX54TR.js +681 -0
- package/dist/cli/chunk-SEBX54TR.js.map +1 -0
- package/dist/cli/index.d.ts +232 -0
- package/dist/cli/index.js +11 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-worker.d.ts +2 -0
- package/dist/cli/init-worker.js +18 -0
- package/dist/cli/init-worker.js.map +1 -0
- package/dist/cli/integration-copy-worker.js +48 -0
- package/dist/cli/integration-copy-worker.js.map +1 -0
- package/dist/cli/package-entry-cjs.cjs +21 -0
- package/dist/cli/package-entry-cjs.cjs.map +1 -0
- package/dist/cli/package-entry-cjs.d.cts +2 -0
- package/dist/cli/package-entry.d.ts +2 -0
- package/dist/cli/package-entry.js +13 -0
- package/dist/cli/package-entry.js.map +1 -0
- package/dist/context-BaFHrQHv.d.cts +21 -0
- package/dist/context-BaFHrQHv.d.ts +21 -0
- package/dist/context-C-YPY-GS.d.cts +1538 -0
- package/dist/context-C-YPY-GS.d.ts +1538 -0
- package/dist/index.cjs +12346 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1560 -0
- package/dist/index.d.ts +1560 -0
- package/dist/index.js +7852 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/github.cjs +2092 -0
- package/dist/integrations/github.cjs.map +1 -0
- package/dist/integrations/github.d.cts +21 -0
- package/dist/integrations/github.d.ts +21 -0
- package/dist/integrations/github.js +2088 -0
- package/dist/integrations/github.js.map +1 -0
- package/dist/integrations.cjs +3370 -0
- package/dist/integrations.cjs.map +1 -0
- package/dist/integrations.d.cts +202 -0
- package/dist/integrations.d.ts +202 -0
- package/dist/integrations.js +2650 -0
- package/dist/integrations.js.map +1 -0
- package/dist/observability-Cj--OkME.d.cts +96 -0
- package/dist/observability-Cj--OkME.d.ts +96 -0
- package/dist/openai.cjs +1235 -0
- package/dist/openai.cjs.map +1 -0
- package/dist/openai.d.cts +32 -0
- package/dist/openai.d.ts +32 -0
- package/dist/openai.js +272 -0
- package/dist/openai.js.map +1 -0
- package/dist/testing.cjs +554 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +43 -0
- package/dist/testing.d.ts +43 -0
- package/dist/testing.js +118 -0
- package/dist/testing.js.map +1 -0
- package/package.json +188 -0
- package/registry/echo/index.ts +53 -0
- package/registry/echo/manifest.json +53 -0
- package/registry/github/LICENSE +105 -0
- package/registry/github/client.ts +1727 -0
- package/registry/github/index.ts +263 -0
- package/registry/github/manifest.json +227 -0
- package/registry/github/owner-fixtures.json +10 -0
- package/registry/github/tests/github.test.ts +32 -0
- package/registry/gmail/LICENSE +105 -0
- package/registry/gmail/client.ts +548 -0
- package/registry/gmail/index.ts +165 -0
- package/registry/gmail/manifest.json +102 -0
- package/registry/gmail/owner-fixtures.json +10 -0
- package/registry/gmail/tests/gmail.test.ts +32 -0
- package/registry/index.json +21 -0
- package/registry/index.schema.json +37 -0
- 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
|