@akagilnc/pi-workflow-roles 0.1.3758 → 0.1.3771
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/README.md +3 -2
- package/README.zh-CN.md +3 -2
- package/dist/acp-host/production-host.js +1389 -751
- package/dist/collector-config.js +0 -1
- package/dist/collector-github.js +199 -2
- package/dist/collector-identity.js +128 -41
- package/dist/collector-ledger.js +38 -9
- package/dist/collector-receipt.js +19 -7
- package/dist/collector-role.js +330 -369
- package/dist/collector-target.js +169 -0
- package/dist/collector-tool-schemas.js +51 -14
- package/dist/package-contracts/collector-output.js +32 -0
- package/dist/package-contracts/terminating-infrastructure.js +13 -12
- package/dist/pi/role-turn-host.js +1 -2
- package/dist/public-cli/github-remote.js +45 -0
- package/dist/public-cli/invocation.js +53 -54
- package/dist/public-cli/main.js +615 -148
- package/dist/public-cli/option-definitions.js +6 -4
- package/dist/public-cli/run-lifecycle.js +3 -3
- package/dist/public-cli/settlement.js +83 -6
- package/dist/role-runtime.js +137 -7
- package/dist/submission-correctable-error.js +24 -0
- package/extensions/role-runtime.ts +0 -1
- package/package.json +1 -1
- package/src/acp-host/role-envelope.ts +8 -22
- package/src/collector-config.ts +0 -1
- package/src/collector-github.ts +236 -2
- package/src/collector-identity.ts +148 -40
- package/src/collector-ledger.ts +48 -10
- package/src/collector-receipt.ts +33 -14
- package/src/collector-role.ts +376 -450
- package/src/collector-target.ts +207 -0
- package/src/collector-tool-schemas.ts +62 -15
- package/src/host-contracts.ts +2 -1
- package/src/package-contracts/collector-output.ts +72 -0
- package/src/package-contracts/terminating-infrastructure.ts +24 -13
- package/src/pi/role-turn-host.ts +1 -2
- package/src/public-cli/cli.ts +10 -1
- package/src/public-cli/collector-run.ts +3 -2
- package/src/public-cli/github-remote.ts +45 -0
- package/src/public-cli/invocation.ts +60 -59
- package/src/public-cli/option-definitions.ts +6 -4
- package/src/public-cli/run-lifecycle.ts +2 -2
- package/src/public-cli/settlement.ts +82 -6
- package/src/role-runtime.ts +166 -13
- package/src/submission-correctable-error.ts +38 -0
|
@@ -13,9 +13,88 @@ var __export = (target, all) => {
|
|
|
13
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
// src/collector-config.ts
|
|
17
|
+
import { createHash } from "node:crypto";
|
|
18
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
19
|
+
function fail(message, cause) {
|
|
20
|
+
throw new Error(message, cause === void 0 ? void 0 : { cause });
|
|
21
|
+
}
|
|
22
|
+
function conservativeAscii(input) {
|
|
23
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
24
|
+
const code = input.charCodeAt(i);
|
|
25
|
+
if (code <= 31 || code === 127 || code > 127) return false;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
function parseCollectorRepository(raw) {
|
|
30
|
+
if (typeof raw !== "string" || raw.trim() !== raw || raw.length === 0) fail("Collector repository must be a string owner/repo");
|
|
31
|
+
if (!conservativeAscii(raw) || raw.includes("://") || /[?#@%\\ ]/.test(raw)) fail("Collector repository rejects URL syntax and non-identity bytes");
|
|
32
|
+
const parts = raw.split("/");
|
|
33
|
+
if (parts.length !== 2) fail("Collector repository must contain exactly one '/' separating owner and repo");
|
|
34
|
+
const [ownerDisplay, repoDisplay] = parts;
|
|
35
|
+
if (!COLLECTOR_OWNER_PATTERN.test(ownerDisplay) || !COLLECTOR_REPO_PATTERN.test(repoDisplay)) fail("Collector repository does not match the conservative owner/repo grammar");
|
|
36
|
+
const owner = ownerDisplay.toLowerCase();
|
|
37
|
+
const repo = repoDisplay.toLowerCase();
|
|
38
|
+
return { display: raw, canonical: `${owner}/${repo}`, owner, repo };
|
|
39
|
+
}
|
|
40
|
+
function parseCollectorPrNumber(raw) {
|
|
41
|
+
if (typeof raw === "string" && !/^[1-9][0-9]*$/.test(raw)) fail("Collector pull request number must be a positive safe integer string");
|
|
42
|
+
if (typeof raw !== "string" && typeof raw !== "number") fail("Collector pull request number is required");
|
|
43
|
+
const value = Number(raw);
|
|
44
|
+
if (!Number.isSafeInteger(value) || value < 1) fail("Collector pull request number must be a positive safe integer");
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
function record(value) {
|
|
48
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
49
|
+
}
|
|
50
|
+
function canonicalManifest(requests) {
|
|
51
|
+
return `${JSON.stringify({ requests: requests.map((request) => ({ id: request.id, body: request.requestBody })) })}
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
function emptyCollectorManifest() {
|
|
55
|
+
const canonicalJson2 = canonicalManifest([]);
|
|
56
|
+
return { requests: [], canonicalJson: canonicalJson2, digest: createHash("sha256").update(canonicalJson2).digest("hex") };
|
|
57
|
+
}
|
|
58
|
+
async function loadCollectorManifest(path) {
|
|
59
|
+
let bytes;
|
|
60
|
+
try {
|
|
61
|
+
bytes = await readFile2(path);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
fail(`Collector request manifest is unreadable at ${path}`, error);
|
|
64
|
+
}
|
|
65
|
+
let parsed;
|
|
66
|
+
try {
|
|
67
|
+
parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
68
|
+
} catch (error) {
|
|
69
|
+
fail("Collector request manifest must be UTF-8 JSON", error);
|
|
70
|
+
}
|
|
71
|
+
if (!record(parsed)) fail("Collector request manifest must be an object");
|
|
72
|
+
const rawRequests = parsed.requests ?? [];
|
|
73
|
+
if (!Array.isArray(rawRequests)) fail("Collector request manifest requests must be an array");
|
|
74
|
+
const requests = [];
|
|
75
|
+
const ids = /* @__PURE__ */ new Set();
|
|
76
|
+
for (const [index, item] of rawRequests.entries()) {
|
|
77
|
+
if (!record(item) || typeof item.id !== "string" || item.id.length === 0 || typeof item.body !== "string" || item.body.trim() === "") fail(`Collector request manifest requests[${index}] is invalid`);
|
|
78
|
+
if (ids.has(item.id)) fail(`Collector request manifest has duplicate request id "${item.id}"`);
|
|
79
|
+
ids.add(item.id);
|
|
80
|
+
requests.push({ id: item.id, requestBody: item.body });
|
|
81
|
+
}
|
|
82
|
+
const canonicalJson2 = canonicalManifest(requests);
|
|
83
|
+
return { requests, canonicalJson: canonicalJson2, digest: createHash("sha256").update(canonicalJson2).digest("hex"), sourcePath: path };
|
|
84
|
+
}
|
|
85
|
+
var COLLECTOR_HOST, COLLECTOR_OWNER_PATTERN, COLLECTOR_REPO_PATTERN;
|
|
86
|
+
var init_collector_config = __esm({
|
|
87
|
+
"src/collector-config.ts"() {
|
|
88
|
+
"use strict";
|
|
89
|
+
COLLECTOR_HOST = "github.com";
|
|
90
|
+
COLLECTOR_OWNER_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
|
|
91
|
+
COLLECTOR_REPO_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,98}[A-Za-z0-9])?$/;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
16
95
|
// src/collector-github.ts
|
|
17
96
|
import { spawn } from "node:child_process";
|
|
18
|
-
import { createHash } from "node:crypto";
|
|
97
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
19
98
|
function isRecord(value) {
|
|
20
99
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21
100
|
}
|
|
@@ -49,6 +128,178 @@ function parseJson(text, label) {
|
|
|
49
128
|
throw new Error(`GitHub ${label} returned malformed JSON`, { cause: error });
|
|
50
129
|
}
|
|
51
130
|
}
|
|
131
|
+
function parsePullRequestNumberList(raw, label) {
|
|
132
|
+
if (!Array.isArray(raw)) {
|
|
133
|
+
throw new Error(`GitHub ${label} payload is not a list`);
|
|
134
|
+
}
|
|
135
|
+
const numbers = [];
|
|
136
|
+
for (const item of raw) {
|
|
137
|
+
if (!isRecord(item)) {
|
|
138
|
+
throw new Error(`GitHub ${label} payload contains a non-object pull request entry`);
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
numbers.push(parseCollectorPrNumber(item["number"]));
|
|
142
|
+
} catch (error) {
|
|
143
|
+
throw new Error(`GitHub ${label} payload contains an invalid pull request number`, {
|
|
144
|
+
cause: error
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return numbers;
|
|
149
|
+
}
|
|
150
|
+
async function listPullRequestNumbersByHead(runner, input) {
|
|
151
|
+
const head = `${input.headOwner}:${input.headRef}`;
|
|
152
|
+
const path = `/repos/${input.owner}/${input.repo}/pulls?head=${encodeURIComponent(head)}&state=all&per_page=100`;
|
|
153
|
+
const response = await runner(
|
|
154
|
+
["api", "--hostname", "github.com", "--include", "-X", "GET", path],
|
|
155
|
+
input.signal === void 0 ? {} : { signal: input.signal }
|
|
156
|
+
);
|
|
157
|
+
if (response.status < 200 || response.status >= 300) {
|
|
158
|
+
throw new Error(`GitHub ${path} failed with HTTP ${response.status}`, {
|
|
159
|
+
cause: {
|
|
160
|
+
endpoint: path,
|
|
161
|
+
status: response.status,
|
|
162
|
+
headers: response.headers,
|
|
163
|
+
body: response.bodyText
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return parsePullRequestNumberList(parseJson(response.bodyText, path), path);
|
|
168
|
+
}
|
|
169
|
+
async function listPullRequestNumbersByCommit(runner, input) {
|
|
170
|
+
const path = `/repos/${input.owner}/${input.repo}/commits/${encodeURIComponent(input.commitSha)}/pulls`;
|
|
171
|
+
const response = await runner(
|
|
172
|
+
["api", "--hostname", "github.com", "--include", "-X", "GET", path],
|
|
173
|
+
input.signal === void 0 ? {} : { signal: input.signal }
|
|
174
|
+
);
|
|
175
|
+
if (response.status < 200 || response.status >= 300) {
|
|
176
|
+
throw new Error(`GitHub ${path} failed with HTTP ${response.status}`, {
|
|
177
|
+
cause: {
|
|
178
|
+
endpoint: path,
|
|
179
|
+
status: response.status,
|
|
180
|
+
headers: response.headers,
|
|
181
|
+
body: response.bodyText
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return parsePullRequestNumberList(parseJson(response.bodyText, path), path);
|
|
186
|
+
}
|
|
187
|
+
async function listPullRequestNumbersByTicket(runner, input) {
|
|
188
|
+
const issuePath = `/repos/${input.owner}/${input.repo}/issues/${input.ticketNumber}`;
|
|
189
|
+
const issueResponse = await runner(
|
|
190
|
+
["api", "--hostname", "github.com", "--include", "-X", "GET", issuePath],
|
|
191
|
+
input.signal === void 0 ? {} : { signal: input.signal }
|
|
192
|
+
);
|
|
193
|
+
if (issueResponse.status === 404) return [];
|
|
194
|
+
if (issueResponse.status < 200 || issueResponse.status >= 300) {
|
|
195
|
+
throw new Error(`GitHub ${issuePath} failed with HTTP ${issueResponse.status}`, {
|
|
196
|
+
cause: {
|
|
197
|
+
endpoint: issuePath,
|
|
198
|
+
status: issueResponse.status,
|
|
199
|
+
headers: issueResponse.headers,
|
|
200
|
+
body: issueResponse.bodyText
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
const issueRaw = parseJson(issueResponse.bodyText, issuePath);
|
|
205
|
+
if (!isRecord(issueRaw)) {
|
|
206
|
+
throw new Error(`GitHub ${issuePath} payload is not an object`);
|
|
207
|
+
}
|
|
208
|
+
if (Object.hasOwn(issueRaw, "pull_request")) {
|
|
209
|
+
return [parseCollectorPrNumber(issueRaw["number"] ?? input.ticketNumber)];
|
|
210
|
+
}
|
|
211
|
+
const query = `query($owner: String!, $repo: String!, $number: Int!) {
|
|
212
|
+
repository(owner: $owner, name: $repo) {
|
|
213
|
+
issue(number: $number) {
|
|
214
|
+
closedByPullRequestsReferences(first: 50) { nodes { number } }
|
|
215
|
+
timelineItems(first: 100, itemTypes: [CROSS_REFERENCED_EVENT, CONNECTED_EVENT]) {
|
|
216
|
+
nodes {
|
|
217
|
+
__typename
|
|
218
|
+
... on CrossReferencedEvent {
|
|
219
|
+
source { ... on PullRequest { number } }
|
|
220
|
+
}
|
|
221
|
+
... on ConnectedEvent {
|
|
222
|
+
subject { ... on PullRequest { number } }
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}`;
|
|
229
|
+
const args = [
|
|
230
|
+
"api",
|
|
231
|
+
"graphql",
|
|
232
|
+
"--hostname",
|
|
233
|
+
"github.com",
|
|
234
|
+
"--include",
|
|
235
|
+
"-f",
|
|
236
|
+
`query=${query}`,
|
|
237
|
+
"-f",
|
|
238
|
+
`owner=${input.owner}`,
|
|
239
|
+
"-f",
|
|
240
|
+
`repo=${input.repo}`,
|
|
241
|
+
"-F",
|
|
242
|
+
`number=${input.ticketNumber}`
|
|
243
|
+
];
|
|
244
|
+
const gqlResponse = await runner(
|
|
245
|
+
args,
|
|
246
|
+
input.signal === void 0 ? {} : { signal: input.signal }
|
|
247
|
+
);
|
|
248
|
+
if (gqlResponse.status < 200 || gqlResponse.status >= 300) {
|
|
249
|
+
throw new Error(`GitHub GraphQL issue\u2192PR failed with HTTP ${gqlResponse.status}`, {
|
|
250
|
+
cause: {
|
|
251
|
+
endpoint: "graphql",
|
|
252
|
+
status: gqlResponse.status,
|
|
253
|
+
headers: gqlResponse.headers,
|
|
254
|
+
body: gqlResponse.bodyText
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
let payload;
|
|
259
|
+
try {
|
|
260
|
+
payload = JSON.parse(gqlResponse.bodyText);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
throw new Error("GitHub GraphQL issue\u2192PR returned malformed JSON", { cause: error });
|
|
263
|
+
}
|
|
264
|
+
if (!isRecord(payload)) {
|
|
265
|
+
throw new Error("GitHub GraphQL issue\u2192PR payload is not an object");
|
|
266
|
+
}
|
|
267
|
+
if (payload.errors !== void 0) {
|
|
268
|
+
throw new Error(`GitHub GraphQL issue\u2192PR errors: ${JSON.stringify(payload.errors).slice(0, 600)}`, {
|
|
269
|
+
cause: { body: gqlResponse.bodyText, errors: payload.errors }
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
const data = payload.data;
|
|
273
|
+
if (!isRecord(data)) return [];
|
|
274
|
+
const repository = data["repository"];
|
|
275
|
+
if (!isRecord(repository)) return [];
|
|
276
|
+
const issue = repository["issue"];
|
|
277
|
+
if (!isRecord(issue)) return [];
|
|
278
|
+
const numbers = [];
|
|
279
|
+
const closedBy = issue["closedByPullRequestsReferences"];
|
|
280
|
+
if (isRecord(closedBy) && Array.isArray(closedBy["nodes"])) {
|
|
281
|
+
for (const node of closedBy["nodes"]) {
|
|
282
|
+
if (isRecord(node) && typeof node["number"] === "number") {
|
|
283
|
+
numbers.push(parseCollectorPrNumber(node["number"]));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const timeline = issue["timelineItems"];
|
|
288
|
+
if (isRecord(timeline) && Array.isArray(timeline["nodes"])) {
|
|
289
|
+
for (const node of timeline["nodes"]) {
|
|
290
|
+
if (!isRecord(node)) continue;
|
|
291
|
+
const source = node["source"];
|
|
292
|
+
if (isRecord(source) && typeof source["number"] === "number") {
|
|
293
|
+
numbers.push(parseCollectorPrNumber(source["number"]));
|
|
294
|
+
}
|
|
295
|
+
const subject = node["subject"];
|
|
296
|
+
if (isRecord(subject) && typeof subject["number"] === "number") {
|
|
297
|
+
numbers.push(parseCollectorPrNumber(subject["number"]));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return [...new Set(numbers)];
|
|
302
|
+
}
|
|
52
303
|
function commentFailureCause(error) {
|
|
53
304
|
return {
|
|
54
305
|
name: error instanceof Error ? error.name : typeof error,
|
|
@@ -89,11 +340,13 @@ function normalizePullRequest(raw) {
|
|
|
89
340
|
throw new Error("GitHub pull request payload missing head.sha");
|
|
90
341
|
}
|
|
91
342
|
const number = requireNumber(raw["number"], "number");
|
|
92
|
-
const
|
|
343
|
+
const mergedFlag = raw["merged"] === true || typeof raw["merged_at"] === "string" && raw["merged_at"].length > 0;
|
|
344
|
+
const rawState = requireString(raw["state"], "state").toUpperCase();
|
|
345
|
+
const state = mergedFlag ? "MERGED" : rawState;
|
|
93
346
|
const htmlUrl = typeof raw["html_url"] === "string" ? raw["html_url"] : `https://github.com/unknown/unknown/pull/${number}`;
|
|
94
347
|
return {
|
|
95
348
|
number,
|
|
96
|
-
state
|
|
349
|
+
state,
|
|
97
350
|
headOid: head["sha"],
|
|
98
351
|
...typeof raw["updated_at"] === "string" ? { updatedAt: raw["updated_at"] } : {},
|
|
99
352
|
url: htmlUrl,
|
|
@@ -483,7 +736,7 @@ function createGhCollectorGitHubTransport(runner = createGhApiRunner()) {
|
|
|
483
736
|
}
|
|
484
737
|
function buildCollectorRequestMarker(input) {
|
|
485
738
|
const prefix = input.manifestDigest.slice(0, 12);
|
|
486
|
-
const requestMarkerId =
|
|
739
|
+
const requestMarkerId = createHash2("sha256").update(input.requestId).digest("hex");
|
|
487
740
|
return `<!-- ak-collector:v1 manifest=${prefix} request=${requestMarkerId} head=${input.headOid} -->`;
|
|
488
741
|
}
|
|
489
742
|
function buildCollectorRequestBody(input) {
|
|
@@ -498,6 +751,7 @@ var commentFailureEvidence;
|
|
|
498
751
|
var init_collector_github = __esm({
|
|
499
752
|
"src/collector-github.ts"() {
|
|
500
753
|
"use strict";
|
|
754
|
+
init_collector_config();
|
|
501
755
|
commentFailureEvidence = 0;
|
|
502
756
|
}
|
|
503
757
|
});
|
|
@@ -1370,7 +1624,7 @@ var init_sitian_contracts = __esm({
|
|
|
1370
1624
|
});
|
|
1371
1625
|
|
|
1372
1626
|
// src/sitian-appender.ts
|
|
1373
|
-
import { createHash as
|
|
1627
|
+
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
1374
1628
|
import {
|
|
1375
1629
|
appendFileSync,
|
|
1376
1630
|
existsSync,
|
|
@@ -1386,7 +1640,7 @@ function errorCodeOf(error) {
|
|
|
1386
1640
|
return error.code;
|
|
1387
1641
|
}
|
|
1388
1642
|
function identityClaimPath(recordFile, identity) {
|
|
1389
|
-
const digest =
|
|
1643
|
+
const digest = createHash3("sha256").update(identity, "utf8").digest("hex");
|
|
1390
1644
|
return `${recordFile}.id-${digest}`;
|
|
1391
1645
|
}
|
|
1392
1646
|
function createExclusiveFile(path, contents) {
|
|
@@ -1530,7 +1784,7 @@ function resolveSitianRecordPathInLedger(input, ledgerHome) {
|
|
|
1530
1784
|
} else {
|
|
1531
1785
|
subjectStr = JSON.stringify(input.subject);
|
|
1532
1786
|
}
|
|
1533
|
-
const digest =
|
|
1787
|
+
const digest = createHash3("sha256").update(subjectStr).digest("hex").slice(0, 32);
|
|
1534
1788
|
sessionDir = join6(bookDir, category, digest);
|
|
1535
1789
|
} else {
|
|
1536
1790
|
sessionDir = join6(bookDir, category);
|
|
@@ -1594,7 +1848,7 @@ var init_sitian_appender = __esm({
|
|
|
1594
1848
|
|
|
1595
1849
|
// src/sitian-reader.ts
|
|
1596
1850
|
import { existsSync as existsSync2 } from "node:fs";
|
|
1597
|
-
import { readFile as
|
|
1851
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
1598
1852
|
function isRecord4(value) {
|
|
1599
1853
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1600
1854
|
}
|
|
@@ -1602,7 +1856,7 @@ async function readSitianRecords(recordFile) {
|
|
|
1602
1856
|
if (!existsSync2(recordFile)) {
|
|
1603
1857
|
return { records: [], diagnostics: [] };
|
|
1604
1858
|
}
|
|
1605
|
-
const text = await
|
|
1859
|
+
const text = await readFile3(recordFile, "utf8");
|
|
1606
1860
|
const lines = text.split("\n");
|
|
1607
1861
|
const records2 = [];
|
|
1608
1862
|
const diagnostics = [];
|
|
@@ -1666,7 +1920,7 @@ __export(role_turn_host_exports, {
|
|
|
1666
1920
|
});
|
|
1667
1921
|
import { execFile, spawn as spawn3 } from "node:child_process";
|
|
1668
1922
|
import { constants } from "node:fs";
|
|
1669
|
-
import { access, appendFile, readFile as
|
|
1923
|
+
import { access, appendFile, readFile as readFile4, realpath as realpath2 } from "node:fs/promises";
|
|
1670
1924
|
import { delimiter, isAbsolute as isAbsolute3, join as join7, resolve as resolve6 } from "node:path";
|
|
1671
1925
|
import { platform } from "node:process";
|
|
1672
1926
|
import { promisify } from "node:util";
|
|
@@ -1727,8 +1981,7 @@ function buildActivationFlagArgs(activation) {
|
|
|
1727
1981
|
"collector",
|
|
1728
1982
|
"--ak-collector-repo",
|
|
1729
1983
|
activation.repo,
|
|
1730
|
-
"--ak-collector-pr",
|
|
1731
|
-
activation.pr,
|
|
1984
|
+
...activation.pr === void 0 ? [] : ["--ak-collector-pr", activation.pr],
|
|
1732
1985
|
...activation.requestManifestPath === void 0 ? [] : ["--ak-collector-request-manifest", activation.requestManifestPath]
|
|
1733
1986
|
];
|
|
1734
1987
|
case "doctor":
|
|
@@ -1975,7 +2228,7 @@ ${paths.join("\n")}`
|
|
|
1975
2228
|
}
|
|
1976
2229
|
async function appendPiSessionCustomEntry(authority, principal, customType, data) {
|
|
1977
2230
|
const { sessionFile } = authority.decode(principal);
|
|
1978
|
-
const text = await
|
|
2231
|
+
const text = await readFile4(sessionFile, "utf8");
|
|
1979
2232
|
let parentId = null;
|
|
1980
2233
|
for (const line2 of text.trim().split("\n").filter(Boolean)) {
|
|
1981
2234
|
const entry = JSON.parse(line2);
|
|
@@ -2024,7 +2277,7 @@ var init_role_turn_host = __esm({
|
|
|
2024
2277
|
});
|
|
2025
2278
|
|
|
2026
2279
|
// src/run-ticket-number.ts
|
|
2027
|
-
import { readFile as
|
|
2280
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
2028
2281
|
import { join as join8 } from "node:path";
|
|
2029
2282
|
function isEnoent(error) {
|
|
2030
2283
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
@@ -2038,7 +2291,7 @@ function ticketFromRecord(record4) {
|
|
|
2038
2291
|
}
|
|
2039
2292
|
async function readPageTicketNumber(runDirectory, page) {
|
|
2040
2293
|
try {
|
|
2041
|
-
const raw = JSON.parse(await
|
|
2294
|
+
const raw = JSON.parse(await readFile5(join8(runDirectory, page), "utf8"));
|
|
2042
2295
|
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
2043
2296
|
return void 0;
|
|
2044
2297
|
}
|
|
@@ -2058,9 +2311,9 @@ var init_run_ticket_number = __esm({
|
|
|
2058
2311
|
});
|
|
2059
2312
|
|
|
2060
2313
|
// src/sha256.ts
|
|
2061
|
-
import { createHash as
|
|
2314
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
2062
2315
|
function sha256Hex(bytes) {
|
|
2063
|
-
return
|
|
2316
|
+
return createHash4("sha256").update(bytes).digest("hex");
|
|
2064
2317
|
}
|
|
2065
2318
|
var init_sha256 = __esm({
|
|
2066
2319
|
"src/sha256.ts"() {
|
|
@@ -2093,10 +2346,16 @@ function validateAcceptedCollectorReceipt(value) {
|
|
|
2093
2346
|
materials: records(safeGet(group, "materials")),
|
|
2094
2347
|
findings: records(safeGet(group, "findings"))
|
|
2095
2348
|
}));
|
|
2349
|
+
const unfinishedRaw = safeGet(value, "unfinishedReasons");
|
|
2350
|
+
const unfinishedReasons = strings(unfinishedRaw);
|
|
2351
|
+
const submissionProjection = projectSubmissionProjection(safeGet(value, "submissionProjection"));
|
|
2352
|
+
const prStateRaw = safeGet(value, "prState");
|
|
2353
|
+
const prState = typeof prStateRaw === "string" ? prStateRaw : void 0;
|
|
2096
2354
|
return {
|
|
2097
2355
|
host: safeGet(value, "host"),
|
|
2098
2356
|
repository: safeGet(value, "repository"),
|
|
2099
2357
|
prNumber: safeGet(value, "prNumber"),
|
|
2358
|
+
...prState === void 0 ? {} : { prState },
|
|
2100
2359
|
manifestDigest: safeGet(value, "manifestDigest"),
|
|
2101
2360
|
activationTime: safeGet(value, "activationTime"),
|
|
2102
2361
|
deadlineTime: safeGet(value, "deadlineTime"),
|
|
@@ -2104,6 +2363,8 @@ function validateAcceptedCollectorReceipt(value) {
|
|
|
2104
2363
|
finalSnapshotId: safeGet(value, "finalSnapshotId"),
|
|
2105
2364
|
targetHead: safeGet(value, "targetHead"),
|
|
2106
2365
|
groups,
|
|
2366
|
+
...unfinishedReasons.length > 0 ? { unfinishedReasons } : {},
|
|
2367
|
+
...submissionProjection === void 0 ? {} : { submissionProjection },
|
|
2107
2368
|
requestAttempts: records(safeGet(value, "requestAttempts")),
|
|
2108
2369
|
snapshots: records(safeGet(value, "snapshots")).map((snapshot) => ({
|
|
2109
2370
|
snapshotId: safeGet(snapshot, "snapshotId"),
|
|
@@ -2123,6 +2384,30 @@ function validateAcceptedCollectorReceipt(value) {
|
|
|
2123
2384
|
evidenceRecords: records(safeGet(value, "evidenceRecords")).map((record4) => ({ evidenceId: safeGet(record4, "evidenceId"), kind: safeGet(record4, "kind"), versionId: safeGet(record4, "versionId"), contentDigest: safeGet(record4, "contentDigest"), firstObservedAt: safeGet(record4, "firstObservedAt"), githubId: safeGet(record4, "githubId"), authorLogin: safeGet(record4, "authorLogin"), htmlUrl: safeGet(record4, "htmlUrl"), authoritativeTime: safeGet(record4, "authoritativeTime") }))
|
|
2124
2385
|
};
|
|
2125
2386
|
}
|
|
2387
|
+
function projectSubmissionProjection(raw) {
|
|
2388
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
2389
|
+
const p = raw;
|
|
2390
|
+
const out = {};
|
|
2391
|
+
if (p["findingsSource"] === "absent" || p["findingsSource"] === "array" || p["findingsSource"] === "unreadable") {
|
|
2392
|
+
out.findingsSource = p["findingsSource"];
|
|
2393
|
+
}
|
|
2394
|
+
if (typeof p["findingsProjectedCount"] === "number") {
|
|
2395
|
+
out.findingsProjectedCount = p["findingsProjectedCount"];
|
|
2396
|
+
}
|
|
2397
|
+
if (typeof p["findingsUnprojected"] === "boolean") {
|
|
2398
|
+
out.findingsUnprojected = p["findingsUnprojected"];
|
|
2399
|
+
}
|
|
2400
|
+
if (p["unfinishedReasonsSource"] === "absent" || p["unfinishedReasonsSource"] === "array" || p["unfinishedReasonsSource"] === "unreadable") {
|
|
2401
|
+
out.unfinishedReasonsSource = p["unfinishedReasonsSource"];
|
|
2402
|
+
}
|
|
2403
|
+
if (typeof p["unfinishedReasonsProjectedCount"] === "number") {
|
|
2404
|
+
out.unfinishedReasonsProjectedCount = p["unfinishedReasonsProjectedCount"];
|
|
2405
|
+
}
|
|
2406
|
+
if (typeof p["unfinishedReasonsUnprojected"] === "boolean") {
|
|
2407
|
+
out.unfinishedReasonsUnprojected = p["unfinishedReasonsUnprojected"];
|
|
2408
|
+
}
|
|
2409
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
2410
|
+
}
|
|
2126
2411
|
var COLLECTOR_OUTPUT_TOOL, COLLECTOR_ACCEPTED_TEXT;
|
|
2127
2412
|
var init_collector_output = __esm({
|
|
2128
2413
|
"src/package-contracts/collector-output.ts"() {
|
|
@@ -2431,6 +2716,24 @@ function isCorrectableSubmissionError(error) {
|
|
|
2431
2716
|
function isCorrectableExecuteError(error) {
|
|
2432
2717
|
return isCorrectableSubmissionError(error) || error instanceof GatekeeperDecisionError || error instanceof ParentQueueReaskError || error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError;
|
|
2433
2718
|
}
|
|
2719
|
+
function projectCorrectableExecuteRejection(error) {
|
|
2720
|
+
const diagnostic = error instanceof Error ? error.message : String(error);
|
|
2721
|
+
if (error instanceof GatekeeperDecisionError) {
|
|
2722
|
+
return { diagnostic, details: { ...error.result } };
|
|
2723
|
+
}
|
|
2724
|
+
if (error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError) {
|
|
2725
|
+
return { diagnostic, details: { code: error.code } };
|
|
2726
|
+
}
|
|
2727
|
+
if (typeof error.code === "string") {
|
|
2728
|
+
return { diagnostic, details: { code: error.code } };
|
|
2729
|
+
}
|
|
2730
|
+
return {
|
|
2731
|
+
diagnostic,
|
|
2732
|
+
details: {
|
|
2733
|
+
code: error instanceof Error && error.name ? error.name : "correctable-submission-error"
|
|
2734
|
+
}
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2434
2737
|
var correctableSubmissionErrorBrand, CorrectableSubmissionError;
|
|
2435
2738
|
var init_submission_correctable_error = __esm({
|
|
2436
2739
|
"src/submission-correctable-error.ts"() {
|
|
@@ -2609,26 +2912,27 @@ function failOnInfrastructureFailureDeclaration(parameters, hostActions, ctx, to
|
|
|
2609
2912
|
toolCallId
|
|
2610
2913
|
);
|
|
2611
2914
|
}
|
|
2612
|
-
var INFRASTRUCTURE_FAILURE_DECLARATION_KEY, INFRASTRUCTURE_FAILURE_DIAGNOSTIC_KEY, infrastructureFailureDeclarationSchema;
|
|
2915
|
+
var INFRASTRUCTURE_FAILURE_DECLARATION_KEY, INFRASTRUCTURE_FAILURE_DIAGNOSTIC_KEY, infrastructureFailureNested, infrastructureFailureDeclarationSchema;
|
|
2613
2916
|
var init_terminating_infrastructure = __esm({
|
|
2614
2917
|
"src/package-contracts/terminating-infrastructure.ts"() {
|
|
2615
2918
|
"use strict";
|
|
2616
2919
|
INFRASTRUCTURE_FAILURE_DECLARATION_KEY = "infrastructureFailure";
|
|
2617
2920
|
INFRASTRUCTURE_FAILURE_DIAGNOSTIC_KEY = "diagnostic";
|
|
2921
|
+
infrastructureFailureNested = Type4.Object(
|
|
2922
|
+
{
|
|
2923
|
+
[INFRASTRUCTURE_FAILURE_DIAGNOSTIC_KEY]: Type4.Unknown({
|
|
2924
|
+
description: "\u975E\u7A7A\u57FA\u7840\u8BBE\u65BD\u5931\u8D25\u8BCA\u65AD\u5B57\u7B26\u4E32\u3002\u65E0\u5931\u8D25\u65F6\u5FC5\u987B\u7701\u7565\u6574\u4E2A infrastructureFailure\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
|
|
2925
|
+
})
|
|
2926
|
+
},
|
|
2927
|
+
{
|
|
2928
|
+
additionalProperties: true,
|
|
2929
|
+
description: "\u57FA\u7840\u8BBE\u65BD\u771F\u5B9E\u5931\u8D25\u58F0\u660E\uFF08\u5982\u9700\uFF09\u3002\u89C4\u8303\u5F62\uFF1A{ diagnostic: \u975E\u7A7A\u8BCA\u65AD\u5B57\u7B26\u4E32 }\uFF1B\u65E0\u5931\u8D25\u65F6\u5FC5\u987B\u7701\u7565\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
|
|
2930
|
+
}
|
|
2931
|
+
);
|
|
2932
|
+
infrastructureFailureNested.required = [];
|
|
2618
2933
|
infrastructureFailureDeclarationSchema = Type4.Object(
|
|
2619
2934
|
{
|
|
2620
|
-
[INFRASTRUCTURE_FAILURE_DECLARATION_KEY]:
|
|
2621
|
-
{
|
|
2622
|
-
[INFRASTRUCTURE_FAILURE_DIAGNOSTIC_KEY]: Type4.String({
|
|
2623
|
-
minLength: 1,
|
|
2624
|
-
description: "\u975E\u7A7A\u57FA\u7840\u8BBE\u65BD\u5931\u8D25\u8BCA\u65AD"
|
|
2625
|
-
})
|
|
2626
|
-
},
|
|
2627
|
-
{
|
|
2628
|
-
additionalProperties: true,
|
|
2629
|
-
description: "\u57FA\u7840\u8BBE\u65BD\u5931\u8D25\u58F0\u660E"
|
|
2630
|
-
}
|
|
2631
|
-
)
|
|
2935
|
+
[INFRASTRUCTURE_FAILURE_DECLARATION_KEY]: infrastructureFailureNested
|
|
2632
2936
|
},
|
|
2633
2937
|
{ additionalProperties: true }
|
|
2634
2938
|
);
|
|
@@ -3011,21 +3315,21 @@ var init_exact_utf8 = __esm({
|
|
|
3011
3315
|
|
|
3012
3316
|
// src/merger-contracts.ts
|
|
3013
3317
|
import { Type as Type9 } from "typebox";
|
|
3014
|
-
function
|
|
3318
|
+
function fail2(message = "Merger input violates its exact contract") {
|
|
3015
3319
|
throw new MergerInputContractError(message);
|
|
3016
3320
|
}
|
|
3017
3321
|
function canonicalPath(path) {
|
|
3018
3322
|
return typeof path === "string" && path.length > 0 && !path.startsWith("/") && !path.includes("\0") && path.split("/").every((part) => part !== "" && part !== "." && part !== "..");
|
|
3019
3323
|
}
|
|
3020
3324
|
function validatePathSet(value, label) {
|
|
3021
|
-
if (!Array.isArray(value) || value.length === 0 || !value.every(canonicalPath))
|
|
3325
|
+
if (!Array.isArray(value) || value.length === 0 || !value.every(canonicalPath)) fail2(`Merger ${label} must be a non-empty canonical path set`);
|
|
3022
3326
|
return value;
|
|
3023
3327
|
}
|
|
3024
3328
|
function validateMaterial(value, label) {
|
|
3025
|
-
if (!
|
|
3329
|
+
if (!record2(value) || typeof value.bytesBase64 !== "string" || typeof value.sha256 !== "string") fail2(`Merger ${label} material is malformed`);
|
|
3026
3330
|
const bytes = Buffer.from(value.bytesBase64, "base64");
|
|
3027
3331
|
exactUtf8(bytes, `Merger ${label} material`);
|
|
3028
|
-
if (sha256Hex(bytes) !== value.sha256)
|
|
3332
|
+
if (sha256Hex(bytes) !== value.sha256) fail2(`Merger ${label} material digest mismatch`);
|
|
3029
3333
|
}
|
|
3030
3334
|
function deepFreeze(value) {
|
|
3031
3335
|
if (value && typeof value === "object") {
|
|
@@ -3035,26 +3339,26 @@ function deepFreeze(value) {
|
|
|
3035
3339
|
return value;
|
|
3036
3340
|
}
|
|
3037
3341
|
function validateMergerInput(value) {
|
|
3038
|
-
if (!
|
|
3039
|
-
if (!
|
|
3342
|
+
if (!record2(value) || blank(value.attemptId) || !isFullGitObjectId(value.targetObjectId) || !isFullGitObjectId(value.sourceObjectId) || value.targetObjectId.length !== value.sourceObjectId.length) fail2("Merger input has invalid identity or object ID");
|
|
3343
|
+
if (!record2(value.materials)) fail2();
|
|
3040
3344
|
for (const key of ["task", "authority", "targetIntent", "sourceIntent"]) validateMaterial(value.materials[key], key);
|
|
3041
3345
|
const conflicts = validatePathSet(value.expectedConflictPaths, "expected conflict paths");
|
|
3042
3346
|
const scope = validatePathSet(value.resolutionScope, "resolution scope");
|
|
3043
|
-
if (!conflicts.every((path) => scope.includes(path)))
|
|
3044
|
-
if (!Array.isArray(value.authorizedChecks))
|
|
3347
|
+
if (!conflicts.every((path) => scope.includes(path))) fail2("Merger resolution scope must contain the complete conflict set");
|
|
3348
|
+
if (!Array.isArray(value.authorizedChecks)) fail2("Merger authorized checks are malformed");
|
|
3045
3349
|
for (const check of value.authorizedChecks) {
|
|
3046
|
-
if (!
|
|
3350
|
+
if (!record2(check) || !Array.isArray(check.argv) || check.argv.length === 0 || check.argv.some(blank)) fail2("Merger authorized check is malformed");
|
|
3047
3351
|
}
|
|
3048
3352
|
return deepFreeze(structuredClone(value));
|
|
3049
3353
|
}
|
|
3050
3354
|
function validateMergerOutput(value, expectedAttemptId) {
|
|
3051
|
-
if (!
|
|
3355
|
+
if (!record2(value) || expectedAttemptId !== void 0 && value.attemptId !== expectedAttemptId) throw new Error("\u5408\u5E76\u56DE\u6267 attempt \u4E0D\u5339\u914D");
|
|
3052
3356
|
const status = typeof value.status === "string" ? value.status : void 0;
|
|
3053
3357
|
if (status === "completed" && isFullGitObjectId(value.mergeCommitId)) return structuredClone(value);
|
|
3054
3358
|
if (status === "escalate") return structuredClone(value);
|
|
3055
3359
|
throw new Error("\u5408\u5E76\u56DE\u6267\u65E0\u5DF2\u8BC6\u522B\u7684\u6267\u884C\u5224\u522B");
|
|
3056
3360
|
}
|
|
3057
|
-
var oidPattern, materialSchema, checkSchema, mergerInputSchema, mergerOutputVariants, mergerOutputSchema, MERGER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT,
|
|
3361
|
+
var oidPattern, materialSchema, checkSchema, mergerInputSchema, mergerOutputVariants, mergerOutputSchema, MERGER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT, record2, blank, MergerInputContractError;
|
|
3058
3362
|
var init_merger_contracts = __esm({
|
|
3059
3363
|
"src/merger-contracts.ts"() {
|
|
3060
3364
|
"use strict";
|
|
@@ -3085,7 +3389,7 @@ var init_merger_contracts = __esm({
|
|
|
3085
3389
|
);
|
|
3086
3390
|
MERGER_OUTPUT_TOOL_NAME = "ak_merger_output";
|
|
3087
3391
|
MERGER_ACCEPTED_TEXT = "\u5408\u5E76\u56DE\u6267\u5DF2\u63A5\u53D7";
|
|
3088
|
-
|
|
3392
|
+
record2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3089
3393
|
blank = (v) => typeof v !== "string" || v.trim().length === 0;
|
|
3090
3394
|
MergerInputContractError = class extends Error {
|
|
3091
3395
|
constructor(message = "Merger input violates its exact contract") {
|
|
@@ -3309,27 +3613,27 @@ function causeMessage(cause) {
|
|
|
3309
3613
|
return String(cause);
|
|
3310
3614
|
}
|
|
3311
3615
|
}
|
|
3312
|
-
function
|
|
3616
|
+
function fail3(cause) {
|
|
3313
3617
|
throw new FixerPacketValidationError(cause);
|
|
3314
3618
|
}
|
|
3315
3619
|
function parseFailure(value) {
|
|
3316
|
-
if (!Array.isArray(value))
|
|
3620
|
+
if (!Array.isArray(value)) fail3(new Error("Fixer prerequisites must be a JSON array"));
|
|
3317
3621
|
for (const entry of value) {
|
|
3318
3622
|
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
3319
|
-
|
|
3623
|
+
fail3(new Error("Fixer prerequisite entry must be an object with id and requirement fields"));
|
|
3320
3624
|
}
|
|
3321
3625
|
const keys = Object.keys(entry);
|
|
3322
3626
|
if (keys.length !== 2 || !keys.includes("id") || !keys.includes("requirement")) {
|
|
3323
|
-
|
|
3627
|
+
fail3(new Error("Fixer prerequisite entry fields must be exactly id and requirement"));
|
|
3324
3628
|
}
|
|
3325
3629
|
if (typeof entry.id !== "string" || !new RegExp(FIXER_PREREQUISITE_ID_PATTERN).test(entry.id)) {
|
|
3326
|
-
|
|
3630
|
+
fail3(new Error(`Fixer prerequisite id violates pattern ${FIXER_PREREQUISITE_ID_PATTERN}`));
|
|
3327
3631
|
}
|
|
3328
3632
|
if (typeof entry.requirement !== "string" || !/\S/.test(entry.requirement)) {
|
|
3329
|
-
|
|
3633
|
+
fail3(new Error("Fixer prerequisite requirement must be nonblank"));
|
|
3330
3634
|
}
|
|
3331
3635
|
}
|
|
3332
|
-
|
|
3636
|
+
fail3(new Error("Fixer prerequisites violate the attachment schema"));
|
|
3333
3637
|
}
|
|
3334
3638
|
function validateFixerPrerequisites(value) {
|
|
3335
3639
|
if (!Value.Check(fixerPrerequisitesSchema, value)) parseFailure(value);
|
|
@@ -3337,7 +3641,7 @@ function validateFixerPrerequisites(value) {
|
|
|
3337
3641
|
const ids = /* @__PURE__ */ new Set();
|
|
3338
3642
|
const prerequisites = entries.map((entry) => {
|
|
3339
3643
|
if (ids.has(entry.id)) {
|
|
3340
|
-
|
|
3644
|
+
fail3(new Error(`Fixer prerequisites contain duplicate id: ${entry.id}`));
|
|
3341
3645
|
}
|
|
3342
3646
|
ids.add(entry.id);
|
|
3343
3647
|
return Object.freeze({ id: entry.id, requirement: entry.requirement });
|
|
@@ -3349,7 +3653,7 @@ function parseFixerPrerequisites(source) {
|
|
|
3349
3653
|
try {
|
|
3350
3654
|
decoded = JSON.parse(source);
|
|
3351
3655
|
} catch (error) {
|
|
3352
|
-
|
|
3656
|
+
fail3(error);
|
|
3353
3657
|
}
|
|
3354
3658
|
return validateFixerPrerequisites(decoded);
|
|
3355
3659
|
}
|
|
@@ -3634,9 +3938,9 @@ var init_terminating_tools = __esm({
|
|
|
3634
3938
|
});
|
|
3635
3939
|
|
|
3636
3940
|
// src/doctor-evidence.ts
|
|
3637
|
-
import { readdir, readFile as
|
|
3941
|
+
import { readdir, readFile as readFile6, realpath as realpath3, stat } from "node:fs/promises";
|
|
3638
3942
|
import { dirname as dirname6, relative as relative2, resolve as resolve7, sep as sep2 } from "node:path";
|
|
3639
|
-
function
|
|
3943
|
+
function record3(value) {
|
|
3640
3944
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3641
3945
|
}
|
|
3642
3946
|
async function discoverCaseFiles(root) {
|
|
@@ -3685,7 +3989,7 @@ function deriveSession(content, id) {
|
|
|
3685
3989
|
for (const line2 of content.split("\n")) if (line2.trim()) {
|
|
3686
3990
|
try {
|
|
3687
3991
|
const row = JSON.parse(line2);
|
|
3688
|
-
if (!
|
|
3992
|
+
if (!record3(row)) {
|
|
3689
3993
|
degradationReasons.push(`non-object session row in ${id}`);
|
|
3690
3994
|
break;
|
|
3691
3995
|
}
|
|
@@ -3704,16 +4008,16 @@ function deriveSession(content, id) {
|
|
|
3704
4008
|
let accepted, observedCommit, turns = 0, calls = 0, tokens = 0;
|
|
3705
4009
|
const statuses = [], commits = [];
|
|
3706
4010
|
for (const row of rows) {
|
|
3707
|
-
const message =
|
|
4011
|
+
const message = record3(row.message) ? row.message : void 0;
|
|
3708
4012
|
if (message?.role === "assistant") {
|
|
3709
|
-
for (const part of Array.isArray(message.content) ? message.content : []) if (
|
|
4013
|
+
for (const part of Array.isArray(message.content) ? message.content : []) if (record3(part) && part.type === "toolCall") calls++;
|
|
3710
4014
|
if (typeof message.responseId === "string") {
|
|
3711
4015
|
turns++;
|
|
3712
|
-
const usage =
|
|
4016
|
+
const usage = record3(message.usage) ? message.usage : void 0;
|
|
3713
4017
|
if (usage && typeof usage.output === "number") tokens += usage.output;
|
|
3714
4018
|
}
|
|
3715
4019
|
}
|
|
3716
|
-
if (message?.role === "toolResult" && message.isError !== true && typeof message.toolName === "string" && isTerminatingToolName(message.toolName) &&
|
|
4020
|
+
if (message?.role === "toolResult" && message.isError !== true && typeof message.toolName === "string" && isTerminatingToolName(message.toolName) && record3(message.details)) {
|
|
3717
4021
|
let details;
|
|
3718
4022
|
try {
|
|
3719
4023
|
details = validateAcceptedDetails(message.toolName, message.details);
|
|
@@ -3753,7 +4057,7 @@ async function loadDoctorCase(runsPath) {
|
|
|
3753
4057
|
const turns = { count: 0, sources: [] }, calls = { count: 0, sources: [] }, tokens = { count: 0, sources: [] };
|
|
3754
4058
|
for (const path of await discoverCaseFiles(root)) {
|
|
3755
4059
|
const id = relative2(root, path).split(sep2).join("/");
|
|
3756
|
-
const bytes = await
|
|
4060
|
+
const bytes = await readFile6(path);
|
|
3757
4061
|
const content = bytes.toString("utf8");
|
|
3758
4062
|
const kind = id.endsWith(".jsonl") ? "session" : "stderr";
|
|
3759
4063
|
evidence.push({ id, kind, byteLength: bytes.byteLength, contentLength: content.length, sha256: sha256Hex(bytes), content });
|
|
@@ -3781,83 +4085,197 @@ var init_doctor_evidence = __esm({
|
|
|
3781
4085
|
}
|
|
3782
4086
|
});
|
|
3783
4087
|
|
|
3784
|
-
// src/
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
4088
|
+
// src/public-cli/cli-errors.ts
|
|
4089
|
+
var CliUsageError;
|
|
4090
|
+
var init_cli_errors = __esm({
|
|
4091
|
+
"src/public-cli/cli-errors.ts"() {
|
|
4092
|
+
"use strict";
|
|
4093
|
+
CliUsageError = class extends Error {
|
|
4094
|
+
code = "AK_ROLE_USAGE";
|
|
4095
|
+
constructor(message, options) {
|
|
4096
|
+
super(
|
|
4097
|
+
message,
|
|
4098
|
+
options?.cause === void 0 ? void 0 : { cause: options.cause }
|
|
4099
|
+
);
|
|
4100
|
+
this.name = "CliUsageError";
|
|
4101
|
+
}
|
|
4102
|
+
};
|
|
4103
|
+
}
|
|
4104
|
+
});
|
|
4105
|
+
|
|
4106
|
+
// src/public-cli/github-remote.ts
|
|
4107
|
+
function ownerFromGitHubRemoteUrl(remoteUrl) {
|
|
4108
|
+
const ownerRepo = ownerRepoFromGitHubRemoteUrl(remoteUrl);
|
|
4109
|
+
if (ownerRepo === void 0) return void 0;
|
|
4110
|
+
return ownerRepo.split("/")[0].toLowerCase();
|
|
3789
4111
|
}
|
|
3790
|
-
function
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
4112
|
+
function ownerRepoFromGitHubRemoteUrl(remoteUrl) {
|
|
4113
|
+
const trimmed = remoteUrl.trim();
|
|
4114
|
+
const scp = /^git@github\.com:([^/\s]+)\/([^/\s]+?)(?:\.git)?$/i.exec(trimmed);
|
|
4115
|
+
if (scp) {
|
|
4116
|
+
return `${scp[1]}/${stripGitSuffix(scp[2])}`;
|
|
3794
4117
|
}
|
|
3795
|
-
|
|
4118
|
+
const ssh = /^ssh:\/\/git@github\.com\/([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/i.exec(
|
|
4119
|
+
trimmed
|
|
4120
|
+
);
|
|
4121
|
+
if (ssh) {
|
|
4122
|
+
return `${ssh[1]}/${stripGitSuffix(ssh[2])}`;
|
|
4123
|
+
}
|
|
4124
|
+
let parsed;
|
|
4125
|
+
try {
|
|
4126
|
+
parsed = new URL(trimmed);
|
|
4127
|
+
} catch {
|
|
4128
|
+
return void 0;
|
|
4129
|
+
}
|
|
4130
|
+
if (!/^github\.com$/i.test(parsed.hostname)) return void 0;
|
|
4131
|
+
if (parsed.search !== "" || parsed.hash !== "") return void 0;
|
|
4132
|
+
const parts = parsed.pathname.split("/").filter((p) => p.length > 0);
|
|
4133
|
+
if (parts.length !== 2) return void 0;
|
|
4134
|
+
return `${parts[0]}/${stripGitSuffix(parts[1])}`;
|
|
3796
4135
|
}
|
|
3797
|
-
function
|
|
3798
|
-
|
|
3799
|
-
if (!conservativeAscii(raw) || raw.includes("://") || /[?#@%\\ ]/.test(raw)) fail3("Collector repository rejects URL syntax and non-identity bytes");
|
|
3800
|
-
const parts = raw.split("/");
|
|
3801
|
-
if (parts.length !== 2) fail3("Collector repository must contain exactly one '/' separating owner and repo");
|
|
3802
|
-
const [ownerDisplay, repoDisplay] = parts;
|
|
3803
|
-
if (!COLLECTOR_OWNER_PATTERN.test(ownerDisplay) || !COLLECTOR_REPO_PATTERN.test(repoDisplay)) fail3("Collector repository does not match the conservative owner/repo grammar");
|
|
3804
|
-
const owner = ownerDisplay.toLowerCase();
|
|
3805
|
-
const repo = repoDisplay.toLowerCase();
|
|
3806
|
-
return { display: raw, canonical: `${owner}/${repo}`, owner, repo };
|
|
4136
|
+
function stripGitSuffix(name) {
|
|
4137
|
+
return name.toLowerCase().endsWith(".git") ? name.slice(0, -4) : name;
|
|
3807
4138
|
}
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
4139
|
+
var init_github_remote = __esm({
|
|
4140
|
+
"src/public-cli/github-remote.ts"() {
|
|
4141
|
+
"use strict";
|
|
4142
|
+
}
|
|
4143
|
+
});
|
|
4144
|
+
|
|
4145
|
+
// src/collector-target.ts
|
|
4146
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
4147
|
+
function ambiguousTarget(detail, cause) {
|
|
4148
|
+
throw new CliUsageError(
|
|
4149
|
+
`collector target is ambiguous: ${detail}; pass an explicit --pr`,
|
|
4150
|
+
cause === void 0 ? void 0 : { cause }
|
|
4151
|
+
);
|
|
3814
4152
|
}
|
|
3815
|
-
function
|
|
3816
|
-
|
|
4153
|
+
function gitFailure(detail, cause) {
|
|
4154
|
+
throw new Error(`collector git failed: ${detail}`, {
|
|
4155
|
+
cause: cause instanceof Error ? cause : new Error(String(cause))
|
|
4156
|
+
});
|
|
3817
4157
|
}
|
|
3818
|
-
function
|
|
3819
|
-
return
|
|
3820
|
-
|
|
4158
|
+
function gitText(projectRoot, args) {
|
|
4159
|
+
return execFileSync2("git", [...args], {
|
|
4160
|
+
cwd: projectRoot,
|
|
4161
|
+
encoding: "utf8",
|
|
4162
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
4163
|
+
}).trim();
|
|
3821
4164
|
}
|
|
3822
|
-
function
|
|
3823
|
-
|
|
3824
|
-
|
|
4165
|
+
function isGitConfigMissing(error) {
|
|
4166
|
+
if (typeof error !== "object" || error === null) return false;
|
|
4167
|
+
const status = error.status;
|
|
4168
|
+
return status === 1;
|
|
3825
4169
|
}
|
|
3826
|
-
|
|
3827
|
-
let bytes;
|
|
4170
|
+
function readCurrentBranch(projectRoot) {
|
|
3828
4171
|
try {
|
|
3829
|
-
|
|
4172
|
+
return gitText(projectRoot, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
3830
4173
|
} catch (error) {
|
|
3831
|
-
|
|
4174
|
+
gitFailure("cannot read current git branch", error);
|
|
3832
4175
|
}
|
|
3833
|
-
|
|
4176
|
+
}
|
|
4177
|
+
function readHeadSha(projectRoot) {
|
|
3834
4178
|
try {
|
|
3835
|
-
|
|
4179
|
+
return gitText(projectRoot, ["rev-parse", "HEAD"]);
|
|
3836
4180
|
} catch (error) {
|
|
3837
|
-
|
|
4181
|
+
gitFailure("cannot read current HEAD", error);
|
|
3838
4182
|
}
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
if (ids.has(item.id)) fail3(`Collector request manifest has duplicate request id "${item.id}"`);
|
|
3847
|
-
ids.add(item.id);
|
|
3848
|
-
requests.push({ id: item.id, requestBody: item.body });
|
|
4183
|
+
}
|
|
4184
|
+
function headRefFromMerge(merge) {
|
|
4185
|
+
const trimmed = merge.trim();
|
|
4186
|
+
if (trimmed.length === 0) return void 0;
|
|
4187
|
+
if (trimmed.startsWith("refs/heads/")) {
|
|
4188
|
+
const ref = trimmed.slice("refs/heads/".length);
|
|
4189
|
+
return ref.length > 0 ? ref : void 0;
|
|
3849
4190
|
}
|
|
3850
|
-
|
|
3851
|
-
return
|
|
4191
|
+
if (trimmed.startsWith("refs/")) return void 0;
|
|
4192
|
+
return trimmed;
|
|
3852
4193
|
}
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
4194
|
+
function readUpstreamHeadBinding(projectRoot, branch) {
|
|
4195
|
+
let remote;
|
|
4196
|
+
try {
|
|
4197
|
+
remote = gitText(projectRoot, ["config", "--get", `branch.${branch}.remote`]);
|
|
4198
|
+
} catch (error) {
|
|
4199
|
+
if (isGitConfigMissing(error)) remote = void 0;
|
|
4200
|
+
else gitFailure(`cannot read branch.${branch}.remote`, error);
|
|
4201
|
+
}
|
|
4202
|
+
if (remote === void 0 || remote.length === 0) return void 0;
|
|
4203
|
+
let merge;
|
|
4204
|
+
try {
|
|
4205
|
+
merge = gitText(projectRoot, ["config", "--get", `branch.${branch}.merge`]);
|
|
4206
|
+
} catch (error) {
|
|
4207
|
+
if (isGitConfigMissing(error)) merge = void 0;
|
|
4208
|
+
else gitFailure(`cannot read branch.${branch}.merge`, error);
|
|
4209
|
+
}
|
|
4210
|
+
if (merge === void 0 || merge.length === 0) return void 0;
|
|
4211
|
+
const headRef = headRefFromMerge(merge);
|
|
4212
|
+
if (headRef === void 0) return void 0;
|
|
4213
|
+
let remoteUrl;
|
|
4214
|
+
try {
|
|
4215
|
+
remoteUrl = gitText(projectRoot, ["remote", "get-url", remote]);
|
|
4216
|
+
} catch (error) {
|
|
4217
|
+
gitFailure(`cannot read remote URL for ${remote}`, error);
|
|
4218
|
+
}
|
|
4219
|
+
const headOwner = ownerFromGitHubRemoteUrl(remoteUrl);
|
|
4220
|
+
if (headOwner === void 0) return void 0;
|
|
4221
|
+
return { headOwner, headRef };
|
|
4222
|
+
}
|
|
4223
|
+
async function resolveCollectorTarget(input) {
|
|
4224
|
+
if (input.explicitPrNumber !== void 0) {
|
|
4225
|
+
return { kind: "bound", prNumber: input.explicitPrNumber };
|
|
4226
|
+
}
|
|
4227
|
+
const branch = readCurrentBranch(input.projectRoot);
|
|
4228
|
+
const detached = branch.length === 0 || branch === "HEAD";
|
|
4229
|
+
const runner = createGhApiRunner();
|
|
4230
|
+
const { owner, repo } = input.repository;
|
|
4231
|
+
const numbers = [];
|
|
4232
|
+
if (!detached) {
|
|
4233
|
+
const headSha = readHeadSha(input.projectRoot);
|
|
4234
|
+
const upstream = readUpstreamHeadBinding(input.projectRoot, branch);
|
|
4235
|
+
if (upstream !== void 0) {
|
|
4236
|
+
numbers.push(
|
|
4237
|
+
...await listPullRequestNumbersByHead(runner, {
|
|
4238
|
+
owner,
|
|
4239
|
+
repo,
|
|
4240
|
+
headOwner: upstream.headOwner,
|
|
4241
|
+
headRef: upstream.headRef
|
|
4242
|
+
})
|
|
4243
|
+
);
|
|
4244
|
+
}
|
|
4245
|
+
numbers.push(
|
|
4246
|
+
...await listPullRequestNumbersByCommit(runner, {
|
|
4247
|
+
owner,
|
|
4248
|
+
repo,
|
|
4249
|
+
commitSha: headSha
|
|
4250
|
+
})
|
|
4251
|
+
);
|
|
4252
|
+
} else {
|
|
4253
|
+
const headSha = readHeadSha(input.projectRoot);
|
|
4254
|
+
numbers.push(
|
|
4255
|
+
...await listPullRequestNumbersByCommit(runner, {
|
|
4256
|
+
owner,
|
|
4257
|
+
repo,
|
|
4258
|
+
commitSha: headSha
|
|
4259
|
+
})
|
|
4260
|
+
);
|
|
4261
|
+
}
|
|
4262
|
+
const unique = [...new Set(numbers)];
|
|
4263
|
+
if (unique.length === 1) {
|
|
4264
|
+
return { kind: "bound", prNumber: unique[0] };
|
|
4265
|
+
}
|
|
4266
|
+
if (unique.length > 1) {
|
|
4267
|
+
ambiguousTarget(
|
|
4268
|
+
`multiple PRs associated with context: ${unique.join(", ")}`
|
|
4269
|
+
);
|
|
4270
|
+
}
|
|
4271
|
+
return { kind: "unbound" };
|
|
4272
|
+
}
|
|
4273
|
+
var init_collector_target = __esm({
|
|
4274
|
+
"src/collector-target.ts"() {
|
|
3856
4275
|
"use strict";
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
COLLECTOR_FIXED_KICKOFF = "\u91C7\u96C6\u76EE\u6807\u5DF2\u53D7\u7406\uFF0C\u672C\u5C40\u5F00\u59CB\u3002";
|
|
4276
|
+
init_collector_github();
|
|
4277
|
+
init_cli_errors();
|
|
4278
|
+
init_github_remote();
|
|
3861
4279
|
}
|
|
3862
4280
|
});
|
|
3863
4281
|
|
|
@@ -3961,24 +4379,6 @@ var init_uuidv7 = __esm({
|
|
|
3961
4379
|
}
|
|
3962
4380
|
});
|
|
3963
4381
|
|
|
3964
|
-
// src/public-cli/cli-errors.ts
|
|
3965
|
-
var CliUsageError;
|
|
3966
|
-
var init_cli_errors = __esm({
|
|
3967
|
-
"src/public-cli/cli-errors.ts"() {
|
|
3968
|
-
"use strict";
|
|
3969
|
-
CliUsageError = class extends Error {
|
|
3970
|
-
code = "AK_ROLE_USAGE";
|
|
3971
|
-
constructor(message, options) {
|
|
3972
|
-
super(
|
|
3973
|
-
message,
|
|
3974
|
-
options?.cause === void 0 ? void 0 : { cause: options.cause }
|
|
3975
|
-
);
|
|
3976
|
-
this.name = "CliUsageError";
|
|
3977
|
-
}
|
|
3978
|
-
};
|
|
3979
|
-
}
|
|
3980
|
-
});
|
|
3981
|
-
|
|
3982
4382
|
// src/typed-provider-http.ts
|
|
3983
4383
|
import { readFile as readFile7, unlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
3984
4384
|
import { join as join9 } from "node:path";
|
|
@@ -5652,12 +6052,13 @@ var init_option_definitions = __esm({
|
|
|
5652
6052
|
canonical: "--pr",
|
|
5653
6053
|
aliases: [],
|
|
5654
6054
|
valueMetavar: "number",
|
|
5655
|
-
|
|
6055
|
+
// #676 D1: optional when context uniquely determines the PR; ambiguous → require explicit.
|
|
6056
|
+
required: false,
|
|
5656
6057
|
repeatable: false,
|
|
5657
6058
|
form: "option",
|
|
5658
6059
|
description: {
|
|
5659
|
-
en: "
|
|
5660
|
-
zh: "\
|
|
6060
|
+
en: "Positive GitHub pull request number. Optional when unique branch/HEAD association binds the PR, or when the Collector role can decide the target from task materials via bind-target; multi-candidate git context or a role that cannot decide requires an explicit value.",
|
|
6061
|
+
zh: "\u6B63\u6574\u6570 GitHub PR \u53F7\u3002\u5206\u652F/HEAD \u552F\u4E00\u5173\u8054\u53EF\u7ED1\u5B9A\u65F6\u53EF\u7701\u7565\uFF1B\u4EA6\u53EF\u7531\u901A\u8FDB\u53F8\u4ECE\u4EFB\u52A1\u6750\u6599\u7ECF bind-target \u5224\u5B9A\u3002git \u591A\u5019\u9009\u6216\u89D2\u8272\u65E0\u6CD5\u5224\u5B9A\u65F6\u5FC5\u987B\u663E\u5F0F\u63D0\u4F9B\u3002"
|
|
5661
6062
|
}
|
|
5662
6063
|
},
|
|
5663
6064
|
{
|
|
@@ -5975,9 +6376,10 @@ var init_option_definitions = __esm({
|
|
|
5975
6376
|
collector: {
|
|
5976
6377
|
command: "collector",
|
|
5977
6378
|
summary: "Collect GitHub PR review evidence.",
|
|
5978
|
-
usage: ["ak-role collector --pr <number> [options] [instruction]"],
|
|
6379
|
+
usage: ["ak-role collector [--pr <number>] [options] [instruction]"],
|
|
5979
6380
|
examples: [
|
|
5980
6381
|
"ak-role collector --pr 42 --repo owner/repository",
|
|
6382
|
+
'ak-role collector --repo owner/repository "Collect findings for #42"',
|
|
5981
6383
|
"ak-role collector --pr 42 --request-manifest ./requests.json"
|
|
5982
6384
|
]
|
|
5983
6385
|
},
|
|
@@ -6194,7 +6596,7 @@ __export(invocation_exports, {
|
|
|
6194
6596
|
resolveDoctorCaseRunsPath: () => resolveDoctorCaseRunsPath,
|
|
6195
6597
|
resolveGitHubRemoteRepository: () => resolveGitHubRemoteRepository
|
|
6196
6598
|
});
|
|
6197
|
-
import { execFileSync as
|
|
6599
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
6198
6600
|
import { existsSync as existsSync4 } from "node:fs";
|
|
6199
6601
|
import {
|
|
6200
6602
|
lstat as lstat3,
|
|
@@ -7140,7 +7542,7 @@ function parseCollectorArgv(args) {
|
|
|
7140
7542
|
}
|
|
7141
7543
|
options.assertRequired();
|
|
7142
7544
|
return {
|
|
7143
|
-
prNumber,
|
|
7545
|
+
...prNumber === void 0 ? {} : { prNumber },
|
|
7144
7546
|
instruction: positional.join(" "),
|
|
7145
7547
|
attachmentPaths,
|
|
7146
7548
|
...project === void 0 ? {} : { project },
|
|
@@ -7151,16 +7553,21 @@ function parseCollectorArgv(args) {
|
|
|
7151
7553
|
function resolveGitHubRemoteRepository(projectRoot) {
|
|
7152
7554
|
let remoteUrl;
|
|
7153
7555
|
try {
|
|
7154
|
-
remoteUrl =
|
|
7556
|
+
remoteUrl = execFileSync3("git", ["remote", "get-url", "origin"], {
|
|
7155
7557
|
cwd: projectRoot,
|
|
7156
7558
|
encoding: "utf8",
|
|
7157
7559
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7158
7560
|
}).trim();
|
|
7159
7561
|
} catch (error) {
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7562
|
+
if (isGitRemoteMissing(error)) {
|
|
7563
|
+
throw new CliUsageError(
|
|
7564
|
+
"collector requires a github.com origin remote or an explicit --repo owner/repo",
|
|
7565
|
+
{ cause: error }
|
|
7566
|
+
);
|
|
7567
|
+
}
|
|
7568
|
+
throw new Error("collector git failed: cannot read origin remote URL", {
|
|
7569
|
+
cause: error instanceof Error ? error : new Error(String(error))
|
|
7570
|
+
});
|
|
7164
7571
|
}
|
|
7165
7572
|
if (remoteUrl.length === 0) {
|
|
7166
7573
|
throw new CliUsageError(
|
|
@@ -7180,43 +7587,23 @@ function resolveGitHubRemoteRepository(projectRoot) {
|
|
|
7180
7587
|
throw new CliUsageError(detail, { cause: error });
|
|
7181
7588
|
}
|
|
7182
7589
|
}
|
|
7183
|
-
function
|
|
7184
|
-
|
|
7185
|
-
const
|
|
7186
|
-
|
|
7187
|
-
return `${scp[1]}/${stripGitSuffix(scp[2])}`;
|
|
7188
|
-
}
|
|
7189
|
-
const ssh = /^ssh:\/\/git@github\.com\/([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/i.exec(
|
|
7190
|
-
trimmed
|
|
7191
|
-
);
|
|
7192
|
-
if (ssh) {
|
|
7193
|
-
return `${ssh[1]}/${stripGitSuffix(ssh[2])}`;
|
|
7194
|
-
}
|
|
7195
|
-
let parsed;
|
|
7196
|
-
try {
|
|
7197
|
-
parsed = new URL(trimmed);
|
|
7198
|
-
} catch {
|
|
7199
|
-
return void 0;
|
|
7200
|
-
}
|
|
7201
|
-
if (!/^github\.com$/i.test(parsed.hostname)) return void 0;
|
|
7202
|
-
if (parsed.search !== "" || parsed.hash !== "") return void 0;
|
|
7203
|
-
const parts = parsed.pathname.split("/").filter((p) => p.length > 0);
|
|
7204
|
-
if (parts.length !== 2) return void 0;
|
|
7205
|
-
return `${parts[0]}/${stripGitSuffix(parts[1])}`;
|
|
7206
|
-
}
|
|
7207
|
-
function stripGitSuffix(name) {
|
|
7208
|
-
return name.toLowerCase().endsWith(".git") ? name.slice(0, -4) : name;
|
|
7590
|
+
function isGitRemoteMissing(error) {
|
|
7591
|
+
if (typeof error !== "object" || error === null) return false;
|
|
7592
|
+
const status = error.status;
|
|
7593
|
+
return status === 2;
|
|
7209
7594
|
}
|
|
7210
7595
|
async function admitCollectorInvocation(options) {
|
|
7211
7596
|
if (options.project !== void 0) {
|
|
7212
7597
|
requireOptionPath("--project", options.project);
|
|
7213
7598
|
}
|
|
7214
|
-
let
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7599
|
+
let explicitPrNumber;
|
|
7600
|
+
if (options.prNumber !== void 0) {
|
|
7601
|
+
try {
|
|
7602
|
+
explicitPrNumber = parseCollectorPrNumber(options.prNumber);
|
|
7603
|
+
} catch (error) {
|
|
7604
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
7605
|
+
throw new CliUsageError(detail, { cause: error });
|
|
7606
|
+
}
|
|
7220
7607
|
}
|
|
7221
7608
|
const projectRoot = resolve9(options.project ?? options.cwd);
|
|
7222
7609
|
let repository;
|
|
@@ -7259,13 +7646,19 @@ async function admitCollectorInvocation(options) {
|
|
|
7259
7646
|
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
7260
7647
|
ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
|
|
7261
7648
|
const attachments = await freezeAttachments(options.attachmentPaths ?? [], attachmentsDirectory);
|
|
7649
|
+
const instruction = options.instruction ?? "";
|
|
7650
|
+
const instructionEmpty = instruction.trim() === "";
|
|
7651
|
+
const target = await resolveCollectorTarget({
|
|
7652
|
+
projectRoot,
|
|
7653
|
+
repository,
|
|
7654
|
+
...explicitPrNumber === void 0 ? {} : { explicitPrNumber }
|
|
7655
|
+
});
|
|
7656
|
+
const prNumber = target.kind === "bound" ? target.prNumber : void 0;
|
|
7262
7657
|
let requestManifestPath;
|
|
7263
7658
|
if (manifestCanonicalJson !== void 0) {
|
|
7264
7659
|
requestManifestPath = join13(runDirectory, "request-manifest.json");
|
|
7265
7660
|
await writeFile4(requestManifestPath, manifestCanonicalJson, "utf8");
|
|
7266
7661
|
}
|
|
7267
|
-
const instruction = options.instruction ?? "";
|
|
7268
|
-
const instructionEmpty = instruction.trim() === "";
|
|
7269
7662
|
const admitted = {
|
|
7270
7663
|
role: "collector",
|
|
7271
7664
|
runId,
|
|
@@ -7275,7 +7668,7 @@ async function admitCollectorInvocation(options) {
|
|
|
7275
7668
|
principal,
|
|
7276
7669
|
instruction,
|
|
7277
7670
|
instructionEmpty,
|
|
7278
|
-
prNumber,
|
|
7671
|
+
...prNumber === void 0 ? {} : { prNumber },
|
|
7279
7672
|
repository: repository.canonical,
|
|
7280
7673
|
repositoryDisplay: repository.display,
|
|
7281
7674
|
...requestManifestPath === void 0 ? {} : { requestManifestPath },
|
|
@@ -7305,14 +7698,14 @@ async function admitCollectorInvocation(options) {
|
|
|
7305
7698
|
runDirectory,
|
|
7306
7699
|
principal,
|
|
7307
7700
|
admittedRequestPath,
|
|
7308
|
-
prNumber,
|
|
7701
|
+
...prNumber === void 0 ? {} : { prNumber },
|
|
7309
7702
|
repository,
|
|
7310
7703
|
...requestManifestPath === void 0 ? {} : { requestManifestPath },
|
|
7311
7704
|
manifestDigest
|
|
7312
7705
|
};
|
|
7313
7706
|
}
|
|
7314
|
-
function buildCollectorTransportPrompt(
|
|
7315
|
-
return
|
|
7707
|
+
function buildCollectorTransportPrompt(admitted, engineMaterial) {
|
|
7708
|
+
return buildInstructionTransportPrompt(admitted, engineMaterial);
|
|
7316
7709
|
}
|
|
7317
7710
|
function parseDoctorIssueNumber(raw) {
|
|
7318
7711
|
const trimmed = raw.trim();
|
|
@@ -8332,6 +8725,8 @@ var init_invocation = __esm({
|
|
|
8332
8725
|
init_run_ticket_number();
|
|
8333
8726
|
init_doctor_evidence();
|
|
8334
8727
|
init_collector_config();
|
|
8728
|
+
init_collector_target();
|
|
8729
|
+
init_github_remote();
|
|
8335
8730
|
init_fixer_packet();
|
|
8336
8731
|
init_merger_git_state();
|
|
8337
8732
|
init_merger_contracts();
|
|
@@ -10924,19 +11319,19 @@ function branchNamesAtPinnedHead(pin) {
|
|
|
10924
11319
|
}
|
|
10925
11320
|
return Object.freeze([...names]);
|
|
10926
11321
|
}
|
|
10927
|
-
async function
|
|
11322
|
+
async function gitText2(root, args) {
|
|
10928
11323
|
const { stdout } = await execGit(["-C", root, ...args], { encoding: "utf8" });
|
|
10929
11324
|
return stdout.trim();
|
|
10930
11325
|
}
|
|
10931
11326
|
async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
10932
|
-
const discoveredRoot = await
|
|
11327
|
+
const discoveredRoot = await gitText2(root, ["rev-parse", "--show-toplevel"]);
|
|
10933
11328
|
const repositoryRoot = await realpath6(discoveredRoot);
|
|
10934
|
-
const objectFormat = await
|
|
11329
|
+
const objectFormat = await gitText2(repositoryRoot, ["rev-parse", "--show-object-format"]);
|
|
10935
11330
|
if (objectFormat !== "sha1" && objectFormat !== "sha256") throw new Error("Unsupported Git object format");
|
|
10936
11331
|
const oidWidth = objectFormat === "sha1" ? 40 : 64;
|
|
10937
|
-
const targetHead = await
|
|
10938
|
-
const reachableCommitIds = Object.freeze((await
|
|
10939
|
-
const refs = parseReviewerRefSnapshot(await
|
|
11332
|
+
const targetHead = await gitText2(repositoryRoot, ["rev-parse", "HEAD^{commit}"]);
|
|
11333
|
+
const reachableCommitIds = Object.freeze((await gitText2(repositoryRoot, ["rev-list", targetHead])).split("\n").filter(Boolean));
|
|
11334
|
+
const refs = parseReviewerRefSnapshot(await gitText2(repositoryRoot, reviewerRefSnapshotArgs()));
|
|
10940
11335
|
const pin = immutableReviewerPin({ repositoryRoot, objectFormat, targetHead, refs });
|
|
10941
11336
|
const invalid = (code, diagnostic, cause) => {
|
|
10942
11337
|
throw new ReviewerCorrectablePreflightError(code, diagnostic, cause === void 0 ? void 0 : { cause });
|
|
@@ -10955,9 +11350,9 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
10955
11350
|
return Object.freeze({
|
|
10956
11351
|
pin,
|
|
10957
11352
|
async snapshot() {
|
|
10958
|
-
const liveObjectFormat = await
|
|
11353
|
+
const liveObjectFormat = await gitText2(repositoryRoot, ["rev-parse", "--show-object-format"]);
|
|
10959
11354
|
if (liveObjectFormat !== "sha1" && liveObjectFormat !== "sha256") throw new Error("Unsupported Git object format");
|
|
10960
|
-
return immutableReviewerPin({ repositoryRoot, objectFormat: liveObjectFormat, targetHead: await
|
|
11355
|
+
return immutableReviewerPin({ repositoryRoot, objectFormat: liveObjectFormat, targetHead: await gitText2(repositoryRoot, ["rev-parse", "HEAD^{commit}"]), refs: parseReviewerRefSnapshot(await gitText2(repositoryRoot, reviewerRefSnapshotArgs())) });
|
|
10961
11356
|
},
|
|
10962
11357
|
async resolve(base) {
|
|
10963
11358
|
if (!/^[A-Za-z0-9._/~^+-]+$/.test(base) || base.startsWith("-") || base.includes("..") || base.includes("@{")) {
|
|
@@ -10967,7 +11362,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
10967
11362
|
const headExpression = /^HEAD((?:~[0-9]+|\^[0-9]+)*)$/.exec(base);
|
|
10968
11363
|
if (headExpression) {
|
|
10969
11364
|
try {
|
|
10970
|
-
commit = await
|
|
11365
|
+
commit = await gitText2(repositoryRoot, ["rev-parse", "--verify", `${targetHead}${headExpression[1]}^{commit}`]);
|
|
10971
11366
|
} catch (error) {
|
|
10972
11367
|
if (exitCode(error) === 128) {
|
|
10973
11368
|
const repository = await repositoryIsAvailable(repositoryRoot);
|
|
@@ -10983,7 +11378,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
10983
11378
|
} else commit = symbolic(base);
|
|
10984
11379
|
if (commit === void 0) invalid("base-invalid", "base revision must name an existing pinned ref or reachable commit");
|
|
10985
11380
|
try {
|
|
10986
|
-
commit = await
|
|
11381
|
+
commit = await gitText2(repositoryRoot, ["rev-parse", "--verify", `${commit}^{commit}`]);
|
|
10987
11382
|
} catch (error) {
|
|
10988
11383
|
if (exitCode(error) === 128) {
|
|
10989
11384
|
const repository = await repositoryIsAvailable(repositoryRoot);
|
|
@@ -10992,7 +11387,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
10992
11387
|
throw error;
|
|
10993
11388
|
}
|
|
10994
11389
|
try {
|
|
10995
|
-
await
|
|
11390
|
+
await gitText2(repositoryRoot, ["merge-base", "--is-ancestor", commit, targetHead]);
|
|
10996
11391
|
} catch (error) {
|
|
10997
11392
|
if (exitCode(error) === 1) invalid("base-invalid", "base revision must be an ancestor of the pinned target", error);
|
|
10998
11393
|
throw error;
|
|
@@ -11002,7 +11397,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11002
11397
|
async range(base) {
|
|
11003
11398
|
let mergeBase;
|
|
11004
11399
|
try {
|
|
11005
|
-
mergeBase = await
|
|
11400
|
+
mergeBase = await gitText2(repositoryRoot, ["merge-base", base, targetHead]);
|
|
11006
11401
|
} catch (error) {
|
|
11007
11402
|
if (exitCode(error) === 1) {
|
|
11008
11403
|
invalid("range-invalid", "review range requires a common ancestor for base and pinned target", error);
|
|
@@ -11013,7 +11408,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11013
11408
|
const diffCommand = `git diff ${mergeBase}...${targetHead}`;
|
|
11014
11409
|
const [{ stdout: diff }, commitsText] = await Promise.all([
|
|
11015
11410
|
execGit(["-C", repositoryRoot, "diff", `${mergeBase}...${targetHead}`], { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 }),
|
|
11016
|
-
|
|
11411
|
+
gitText2(repositoryRoot, ["rev-list", "--reverse", `${mergeBase}..${targetHead}`])
|
|
11017
11412
|
]);
|
|
11018
11413
|
if (diff.length === 0) invalid("range-invalid", "review range must contain a non-empty diff between base and pinned target");
|
|
11019
11414
|
return Object.freeze({ base: mergeBase, target: targetHead, diffCommand, diffSha256: sha256Hex(Uint8Array.from(diff)), commits: Object.freeze(commitsText ? commitsText.split("\n") : []) });
|
|
@@ -11029,7 +11424,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11029
11424
|
},
|
|
11030
11425
|
async listSpecCandidatePaths() {
|
|
11031
11426
|
const roots = ["docs", "specs", ".scratch"];
|
|
11032
|
-
const text = await
|
|
11427
|
+
const text = await gitText2(repositoryRoot, [
|
|
11033
11428
|
"ls-tree",
|
|
11034
11429
|
"-r",
|
|
11035
11430
|
"--name-only",
|
|
@@ -11042,7 +11437,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11042
11437
|
async originRepository() {
|
|
11043
11438
|
let remoteUrl;
|
|
11044
11439
|
try {
|
|
11045
|
-
remoteUrl = await
|
|
11440
|
+
remoteUrl = await gitText2(repositoryRoot, ["remote", "get-url", "origin"]);
|
|
11046
11441
|
} catch (error) {
|
|
11047
11442
|
if (isConfirmedMissingOriginRemote(error)) return void 0;
|
|
11048
11443
|
throw error;
|
|
@@ -11050,7 +11445,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11050
11445
|
return parseGitHubOriginRemote(remoteUrl);
|
|
11051
11446
|
},
|
|
11052
11447
|
async commitMessagesNewestFirst(base) {
|
|
11053
|
-
const text = await
|
|
11448
|
+
const text = await gitText2(repositoryRoot, [
|
|
11054
11449
|
"log",
|
|
11055
11450
|
"--format=%s",
|
|
11056
11451
|
`${base}..${targetHead}`
|
|
@@ -11827,21 +12222,214 @@ function assignWindowRelations(records2, activationTime, deadlineTime) {
|
|
|
11827
12222
|
}
|
|
11828
12223
|
}
|
|
11829
12224
|
}
|
|
11830
|
-
var COLLECTOR_ELIGIBILITY_MS;
|
|
11831
|
-
var init_collector_evidence = __esm({
|
|
11832
|
-
"src/collector-evidence.ts"() {
|
|
12225
|
+
var COLLECTOR_ELIGIBILITY_MS;
|
|
12226
|
+
var init_collector_evidence = __esm({
|
|
12227
|
+
"src/collector-evidence.ts"() {
|
|
12228
|
+
"use strict";
|
|
12229
|
+
COLLECTOR_ELIGIBILITY_MS = 15 * 60 * 1e3;
|
|
12230
|
+
}
|
|
12231
|
+
});
|
|
12232
|
+
|
|
12233
|
+
// src/collector-identity.ts
|
|
12234
|
+
function identityKey(identity) {
|
|
12235
|
+
if (identity === null) return "unassigned";
|
|
12236
|
+
return String(identity.userId);
|
|
12237
|
+
}
|
|
12238
|
+
function mergeMachineIdentity(current, observed) {
|
|
12239
|
+
if (current === null) return observed;
|
|
12240
|
+
if (observed === null) return current;
|
|
12241
|
+
if (current.appId === void 0 && observed.appId !== void 0) return observed;
|
|
12242
|
+
if (current.appId !== void 0 && observed.appId === void 0) return current;
|
|
12243
|
+
return observed.userType < current.userType ? observed : current;
|
|
12244
|
+
}
|
|
12245
|
+
function headRelationFor(record4, targetHead) {
|
|
12246
|
+
return record4.commitOid === void 0 || record4.commitOid === null ? "unbound" : record4.commitOid === targetHead ? "current" : "prior";
|
|
12247
|
+
}
|
|
12248
|
+
function extractCollectorEvidenceIdentityGroups(records2, targetHead) {
|
|
12249
|
+
const groups = /* @__PURE__ */ new Map();
|
|
12250
|
+
for (const record4 of records2) {
|
|
12251
|
+
if (record4.kind !== "review" && record4.kind !== "issue_comment" && record4.kind !== "review_comment" && record4.kind !== "reaction") continue;
|
|
12252
|
+
if (record4.githubId === void 0) continue;
|
|
12253
|
+
const identity = record4.machineIdentity ?? null;
|
|
12254
|
+
const kind = record4.kind;
|
|
12255
|
+
const source = {
|
|
12256
|
+
kind,
|
|
12257
|
+
id: record4.githubId,
|
|
12258
|
+
evidenceId: record4.evidenceId,
|
|
12259
|
+
headRelation: headRelationFor(record4, targetHead)
|
|
12260
|
+
};
|
|
12261
|
+
const key = identityKey(identity);
|
|
12262
|
+
let group = groups.get(key);
|
|
12263
|
+
if (group === void 0) {
|
|
12264
|
+
group = {
|
|
12265
|
+
identity,
|
|
12266
|
+
...record4.authorLogin === void 0 ? {} : { displayLogin: record4.authorLogin },
|
|
12267
|
+
attendance: true,
|
|
12268
|
+
findings: [],
|
|
12269
|
+
materials: []
|
|
12270
|
+
};
|
|
12271
|
+
groups.set(key, group);
|
|
12272
|
+
} else {
|
|
12273
|
+
group.identity = mergeMachineIdentity(group.identity, identity);
|
|
12274
|
+
}
|
|
12275
|
+
group.materials.push(source);
|
|
12276
|
+
}
|
|
12277
|
+
return [...groups.values()];
|
|
12278
|
+
}
|
|
12279
|
+
function candidateRecord(candidate) {
|
|
12280
|
+
if (candidate === void 0 || candidate === null || typeof candidate !== "object" || Array.isArray(candidate)) {
|
|
12281
|
+
return void 0;
|
|
12282
|
+
}
|
|
12283
|
+
return candidate;
|
|
12284
|
+
}
|
|
12285
|
+
function hasNonCanonicalOwnKeys(record4) {
|
|
12286
|
+
for (const key of Object.keys(record4)) {
|
|
12287
|
+
if (!COLLECTOR_OUTPUT_CANONICAL_KEYS.has(key)) return true;
|
|
12288
|
+
}
|
|
12289
|
+
return false;
|
|
12290
|
+
}
|
|
12291
|
+
function enrichCollectorFindings(input) {
|
|
12292
|
+
if (input.candidate !== void 0 && input.candidate !== null && candidateRecord(input.candidate) === void 0) {
|
|
12293
|
+
return { findingsSource: "unreadable", findingsProjectedCount: 0, findingsUnprojected: true };
|
|
12294
|
+
}
|
|
12295
|
+
const record4 = candidateRecord(input.candidate);
|
|
12296
|
+
if (record4 === void 0) {
|
|
12297
|
+
return { findingsSource: "absent", findingsProjectedCount: 0, findingsUnprojected: false };
|
|
12298
|
+
}
|
|
12299
|
+
if (!Object.hasOwn(record4, "findings")) {
|
|
12300
|
+
if (hasNonCanonicalOwnKeys(record4)) {
|
|
12301
|
+
return { findingsSource: "unreadable", findingsProjectedCount: 0, findingsUnprojected: true };
|
|
12302
|
+
}
|
|
12303
|
+
return { findingsSource: "absent", findingsProjectedCount: 0, findingsUnprojected: false };
|
|
12304
|
+
}
|
|
12305
|
+
const rawFindings = record4["findings"];
|
|
12306
|
+
if (!Array.isArray(rawFindings)) {
|
|
12307
|
+
return { findingsSource: "unreadable", findingsProjectedCount: 0, findingsUnprojected: true };
|
|
12308
|
+
}
|
|
12309
|
+
const byEvidenceId = new Map(input.records.map((evidence) => [evidence.evidenceId, evidence]));
|
|
12310
|
+
let projected = 0;
|
|
12311
|
+
let unprojected = false;
|
|
12312
|
+
for (const raw of rawFindings) {
|
|
12313
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
12314
|
+
unprojected = true;
|
|
12315
|
+
continue;
|
|
12316
|
+
}
|
|
12317
|
+
const item = raw;
|
|
12318
|
+
const evidenceId = item.evidenceId;
|
|
12319
|
+
if (typeof evidenceId !== "string" || evidenceId.length === 0) {
|
|
12320
|
+
unprojected = true;
|
|
12321
|
+
continue;
|
|
12322
|
+
}
|
|
12323
|
+
const evidence = byEvidenceId.get(evidenceId);
|
|
12324
|
+
if (evidence === void 0) {
|
|
12325
|
+
throw new CollectorUnknownEvidenceError(evidenceId);
|
|
12326
|
+
}
|
|
12327
|
+
if (evidence.kind !== "review" && evidence.kind !== "issue_comment" && evidence.kind !== "review_comment") {
|
|
12328
|
+
throw new CollectorFindingsValidationError(`\u901A\u8FDB\u53F8 finding \u6307\u9488\u6307\u5411\u4E0D\u53EF\u627F finding \u7684\u8BC1\u636E\u79CD\u7C7B ${evidence.kind}`);
|
|
12329
|
+
}
|
|
12330
|
+
if (evidence.githubId === void 0) {
|
|
12331
|
+
throw new CollectorFindingsValidationError(`\u901A\u8FDB\u53F8 finding \u6307\u9488\u8BC1\u636E ${evidenceId} \u7F3A\u5C11 GitHub id`);
|
|
12332
|
+
}
|
|
12333
|
+
const identity = evidence.machineIdentity ?? null;
|
|
12334
|
+
const group = input.groups.find((candidateGroup) => identityKey(candidateGroup.identity) === identityKey(identity));
|
|
12335
|
+
if (group === void 0) {
|
|
12336
|
+
throw new CollectorFindingsValidationError(`\u901A\u8FDB\u53F8 finding \u6307\u9488\u8BC1\u636E ${evidenceId} \u65E0\u5F52\u5C5E\u8EAB\u4EFD\u7EC4`);
|
|
12337
|
+
}
|
|
12338
|
+
const category = item.category;
|
|
12339
|
+
const summary = item.summary;
|
|
12340
|
+
if (Object.hasOwn(item, "category") && typeof category !== "string") unprojected = true;
|
|
12341
|
+
if (Object.hasOwn(item, "summary") && typeof summary !== "string") unprojected = true;
|
|
12342
|
+
group.findings.push({
|
|
12343
|
+
identity,
|
|
12344
|
+
source: {
|
|
12345
|
+
kind: evidence.kind,
|
|
12346
|
+
id: evidence.githubId,
|
|
12347
|
+
evidenceId: evidence.evidenceId,
|
|
12348
|
+
headRelation: headRelationFor(evidence, input.targetHead)
|
|
12349
|
+
},
|
|
12350
|
+
...typeof category === "string" ? { category } : {},
|
|
12351
|
+
...typeof summary === "string" ? { summary } : {},
|
|
12352
|
+
pointer: {
|
|
12353
|
+
repository: input.repository,
|
|
12354
|
+
prNumber: input.prNumber,
|
|
12355
|
+
commentId: evidence.githubId,
|
|
12356
|
+
...evidence.htmlUrl === void 0 ? {} : { htmlUrl: evidence.htmlUrl },
|
|
12357
|
+
...evidence.authorLogin === void 0 ? {} : { authorLogin: evidence.authorLogin },
|
|
12358
|
+
kind: evidence.kind,
|
|
12359
|
+
authoritativeTime: evidence.authoritativeTime ?? null,
|
|
12360
|
+
...evidence.commitOid === void 0 ? {} : { commitOid: evidence.commitOid }
|
|
12361
|
+
}
|
|
12362
|
+
});
|
|
12363
|
+
projected += 1;
|
|
12364
|
+
}
|
|
12365
|
+
return {
|
|
12366
|
+
findingsSource: "array",
|
|
12367
|
+
findingsProjectedCount: projected,
|
|
12368
|
+
findingsUnprojected: unprojected
|
|
12369
|
+
};
|
|
12370
|
+
}
|
|
12371
|
+
function extractCollectorUnfinishedReasons(candidate) {
|
|
12372
|
+
if (candidate !== void 0 && candidate !== null && candidateRecord(candidate) === void 0) {
|
|
12373
|
+
return { reasons: void 0, source: "unreadable", unprojected: true };
|
|
12374
|
+
}
|
|
12375
|
+
const record4 = candidateRecord(candidate);
|
|
12376
|
+
if (record4 === void 0) {
|
|
12377
|
+
return { reasons: void 0, source: "absent", unprojected: false };
|
|
12378
|
+
}
|
|
12379
|
+
if (!Object.hasOwn(record4, "unfinishedReasons")) {
|
|
12380
|
+
return { reasons: void 0, source: "absent", unprojected: false };
|
|
12381
|
+
}
|
|
12382
|
+
const raw = record4["unfinishedReasons"];
|
|
12383
|
+
if (!Array.isArray(raw)) {
|
|
12384
|
+
return { reasons: void 0, source: "unreadable", unprojected: true };
|
|
12385
|
+
}
|
|
12386
|
+
const reasons = raw.filter((item) => typeof item === "string");
|
|
12387
|
+
const unprojected = reasons.length !== raw.length;
|
|
12388
|
+
return {
|
|
12389
|
+
reasons: reasons.length > 0 ? reasons : void 0,
|
|
12390
|
+
source: "array",
|
|
12391
|
+
unprojected
|
|
12392
|
+
};
|
|
12393
|
+
}
|
|
12394
|
+
var CollectorUnknownEvidenceError, CollectorFindingsValidationError, CollectorNonOpenRequestError, COLLECTOR_OUTPUT_CANONICAL_KEYS;
|
|
12395
|
+
var init_collector_identity = __esm({
|
|
12396
|
+
"src/collector-identity.ts"() {
|
|
11833
12397
|
"use strict";
|
|
11834
|
-
|
|
12398
|
+
init_submission_correctable_error();
|
|
12399
|
+
CollectorUnknownEvidenceError = class extends CorrectableSubmissionError {
|
|
12400
|
+
constructor(evidenceId) {
|
|
12401
|
+
super(`\u672A\u5728\u672C\u5C40\u5DF2\u89C2\u6D4B\u6750\u6599\u4E2D\u627E\u5230 evidenceId ${evidenceId}\uFF1B\u8BF7\u7528 observe \u8FD4\u56DE\u7684\u6307\u9488\u91CD\u8BD5\u3002`);
|
|
12402
|
+
this.name = "CollectorUnknownEvidenceError";
|
|
12403
|
+
}
|
|
12404
|
+
};
|
|
12405
|
+
CollectorFindingsValidationError = class extends CorrectableSubmissionError {
|
|
12406
|
+
constructor(message) {
|
|
12407
|
+
super(message);
|
|
12408
|
+
this.name = "CollectorFindingsValidationError";
|
|
12409
|
+
}
|
|
12410
|
+
};
|
|
12411
|
+
CollectorNonOpenRequestError = class extends CorrectableSubmissionError {
|
|
12412
|
+
constructor(prState) {
|
|
12413
|
+
super(`\u901A\u8FDB\u53F8\u8BF7\u6C42\u8981\u6C42 OPEN \u72B6\u6001\u7684 PR \u5FEB\u7167\uFF1B\u5F53\u524D\u4E3A ${prState}\uFF0C\u4E0D\u518D\u89E6\u53D1\u65B0\u8BC4\u5BA1\uFF0C\u8BF7\u76F4\u63A5\u4EA4\u56DE\u5DF2\u6709\u6750\u6599`);
|
|
12414
|
+
this.name = "CollectorNonOpenRequestError";
|
|
12415
|
+
}
|
|
12416
|
+
};
|
|
12417
|
+
COLLECTOR_OUTPUT_CANONICAL_KEYS = /* @__PURE__ */ new Set([
|
|
12418
|
+
"findings",
|
|
12419
|
+
"unfinishedReasons",
|
|
12420
|
+
"infrastructureFailure"
|
|
12421
|
+
]);
|
|
11835
12422
|
}
|
|
11836
12423
|
});
|
|
11837
12424
|
|
|
11838
12425
|
// src/collector-tool-schemas.ts
|
|
11839
12426
|
import { Type as Type13 } from "typebox";
|
|
11840
|
-
var collectorObserveArgsSchema, collectorRequestArgsSchema, collectorReadArgsSchema, collectorWaitArgsSchema,
|
|
12427
|
+
var collectorObserveArgsSchema, collectorRequestArgsSchema, collectorReadArgsSchema, collectorWaitArgsSchema, collectorBindTargetArgsSchema, collectorFindingItemDeclaration, collectorOutputBaseSchema, collectorOutputArgsSchema;
|
|
11841
12428
|
var init_collector_tool_schemas = __esm({
|
|
11842
12429
|
"src/collector-tool-schemas.ts"() {
|
|
11843
12430
|
"use strict";
|
|
11844
12431
|
init_collector_evidence();
|
|
12432
|
+
init_open_tool_schema();
|
|
11845
12433
|
init_terminating_infrastructure();
|
|
11846
12434
|
collectorObserveArgsSchema = Type13.Object({}, { additionalProperties: false });
|
|
11847
12435
|
collectorRequestArgsSchema = Type13.Object({
|
|
@@ -11854,19 +12442,51 @@ var init_collector_tool_schemas = __esm({
|
|
|
11854
12442
|
collectorWaitArgsSchema = Type13.Object({
|
|
11855
12443
|
durationMs: Type13.Integer({ minimum: 1, maximum: COLLECTOR_ELIGIBILITY_MS, description: "\u7B49\u5F85\u6BEB\u79D2\uFF1B\u5355\u6B21\u4E0A\u9650\u4E94\u5206\u949F\u4E14\u4E0D\u8D85\u5269\u4F59\u8D44\u683C" })
|
|
11856
12444
|
}, { additionalProperties: false });
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
description: "\u672C\u6B21\u6536\u96C6\u5230\u7684\u9010\u6761 findings\uFF1B\u96F6 finding \u7684\u6A21\u677F\u901A\u77E5\u4E0D\u5F97\u8FDB\u5165\u3002\u6B63\u5E38\u5B8C\u5DE5\u65E0 finding \u65F6\u7701\u7565\u3002"
|
|
12445
|
+
collectorBindTargetArgsSchema = Type13.Object({
|
|
12446
|
+
prNumber: Type13.Optional(Type13.Unknown({
|
|
12447
|
+
description: "\u89D2\u8272\u5224\u5B9A\u7684\u672C\u4ED3 PR \u53F7\uFF08\u6B63\u6574\u6570\uFF09\u3002\u4E0E issueNumber \u4E8C\u9009\u4E00\u6216\u540C\u6307\u552F\u4E00\u76EE\u6807\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
|
|
12448
|
+
})),
|
|
12449
|
+
issueNumber: Type13.Optional(Type13.Unknown({
|
|
12450
|
+
description: "\u89D2\u8272\u5224\u5B9A\u7684\u672C\u4ED3 issue \u53F7\uFF08\u6B63\u6574\u6570\uFF09\uFF1Bruntime \u7ECF\u7EBF\u4E0A\u5173\u8054\u89E3\u6790\u552F\u4E00 PR\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
|
|
11864
12451
|
}))
|
|
11865
|
-
}, { additionalProperties: true
|
|
12452
|
+
}, { additionalProperties: true });
|
|
12453
|
+
collectorFindingItemDeclaration = (() => {
|
|
12454
|
+
const item = Type13.Object(
|
|
12455
|
+
{
|
|
12456
|
+
evidenceId: Type13.Unknown({
|
|
12457
|
+
description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u6307\u9488\uFF08\u5FC5\u586B\u8BED\u4E49\uFF09"
|
|
12458
|
+
}),
|
|
12459
|
+
category: Type13.Unknown({
|
|
12460
|
+
description: "\u7B80\u77ED\u5F52\u7C7B\u6807\u7B7E\uFF0C\u4E0D\u662F\u6458\u8981"
|
|
12461
|
+
}),
|
|
12462
|
+
summary: Type13.Unknown({
|
|
12463
|
+
description: "\u54EA\u4E2A bot\u3001\u4EC0\u4E48\u95EE\u9898\u7684\u6458\u8981\uFF1B\u4E0D\u8A8A\u6284\u6B63\u6587"
|
|
12464
|
+
})
|
|
12465
|
+
},
|
|
12466
|
+
{
|
|
12467
|
+
additionalProperties: true,
|
|
12468
|
+
description: "\u5355\u6761 finding \u6307\u9488\uFF1AevidenceId + \u53EF\u9009 category/summary\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
|
|
12469
|
+
}
|
|
12470
|
+
);
|
|
12471
|
+
item.required = [];
|
|
12472
|
+
return item;
|
|
12473
|
+
})();
|
|
12474
|
+
collectorOutputBaseSchema = openToolObject(
|
|
12475
|
+
Type13.Object({
|
|
12476
|
+
// No root type:array — host must not shape-reject non-array findings (#676 C).
|
|
12477
|
+
// Nested item declarations ride `items` for registration preservation (ADR 0057).
|
|
12478
|
+
findings: Type13.Unsafe({
|
|
12479
|
+
description: "\u672C\u6B21\u6536\u96C6\u5230\u7684\u9010\u6761 findings\uFF08\u6307\u9488\u6570\u7EC4\u4E3A\u89C4\u8303\u5F62\uFF09\u3002\u96F6 finding \u7684\u6A21\u677F\u901A\u77E5\u4E0D\u5F97\u8FDB\u5165\uFF1B\u6B63\u5E38\u5B8C\u5DE5\u65E0 finding \u65F6\u7701\u7565\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002",
|
|
12480
|
+
items: collectorFindingItemDeclaration
|
|
12481
|
+
}),
|
|
12482
|
+
unfinishedReasons: Type13.Unknown({
|
|
12483
|
+
description: "\u672A\u5B8C\u6210\u539F\u56E0\u5B57\u7B26\u4E32\u6570\u7EC4\uFF08\u989D\u5EA6/\u6545\u969C/\u7B49\u5F85\u5C4A\u6EE1\u7B49\u73B0\u573A\u4F9D\u636E\uFF09\uFF1B\u4E0D\u5F97\u628A\u672A\u5B8C\u6210\u8868\u8FF0\u4E3A\u65E0\u95EE\u9898\u3002\u65E0\u53EF\u62A5\u544A\u65F6\u7701\u7565\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
|
|
12484
|
+
})
|
|
12485
|
+
})
|
|
12486
|
+
);
|
|
11866
12487
|
collectorOutputArgsSchema = withInfrastructureFailureDeclaration(
|
|
11867
12488
|
collectorOutputBaseSchema
|
|
11868
12489
|
);
|
|
11869
|
-
collectorOutputArgsSchema.required = [];
|
|
11870
12490
|
}
|
|
11871
12491
|
});
|
|
11872
12492
|
|
|
@@ -11942,10 +12562,18 @@ function createCollectorLedger(config, options) {
|
|
|
11942
12562
|
return Math.max(0, deadlineMono - monoNowOrThrow(clock2));
|
|
11943
12563
|
};
|
|
11944
12564
|
const prIdentity = (pr) => `${pr.state}|${pr.headOid}|${pr.updatedAt ?? ""}`;
|
|
12565
|
+
const requireBoundPr = () => {
|
|
12566
|
+
if (config.prNumber === void 0) {
|
|
12567
|
+
throw new Error(
|
|
12568
|
+
"Collector PR target is unbound; call ak_collector_bind_target with the role-decided issue/PR or pass --pr"
|
|
12569
|
+
);
|
|
12570
|
+
}
|
|
12571
|
+
return config.prNumber;
|
|
12572
|
+
};
|
|
11945
12573
|
const fetchObserveSurfaces = async (transport, observedAt, signal) => {
|
|
11946
12574
|
const owner = config.repository.owner;
|
|
11947
12575
|
const repo = config.repository.repo;
|
|
11948
|
-
const prNumber =
|
|
12576
|
+
const prNumber = requireBoundPr();
|
|
11949
12577
|
const signalOpt = signal === void 0 ? {} : { signal };
|
|
11950
12578
|
const user = await transport.getAuthenticatedUser(signalOpt);
|
|
11951
12579
|
const prInitial = await transport.getPullRequest({
|
|
@@ -12214,6 +12842,25 @@ function createCollectorLedger(config, options) {
|
|
|
12214
12842
|
assertNotFatal();
|
|
12215
12843
|
outputCandidate = true;
|
|
12216
12844
|
},
|
|
12845
|
+
bindTarget(prNumber) {
|
|
12846
|
+
assertNotFatal();
|
|
12847
|
+
if (outputCandidate || pendingOutputCallId !== void 0) {
|
|
12848
|
+
throw new Error("\u901A\u8FDB\u53F8\u5DF2\u4EA7\u51FA\u8F93\u51FA\u5019\u9009\uFF0C\u672C\u5C40\u4E0D\u518D\u53D7\u7406\u76EE\u6807\u7ED1\u5B9A");
|
|
12849
|
+
}
|
|
12850
|
+
if (!Number.isSafeInteger(prNumber) || prNumber < 1) {
|
|
12851
|
+
throw new Error("Collector bind target requires a positive safe-integer PR number");
|
|
12852
|
+
}
|
|
12853
|
+
if (config.prNumber !== void 0 && config.prNumber !== prNumber) {
|
|
12854
|
+
throw new Error(
|
|
12855
|
+
`Collector target already bound to PR ${config.prNumber}; cannot rebind to ${prNumber}`
|
|
12856
|
+
);
|
|
12857
|
+
}
|
|
12858
|
+
config.prNumber = prNumber;
|
|
12859
|
+
appendJournal("ak-collector-target-bound", {
|
|
12860
|
+
prNumber,
|
|
12861
|
+
repository: config.repository.canonical
|
|
12862
|
+
});
|
|
12863
|
+
},
|
|
12217
12864
|
beginOperational(toolName, toolCallId) {
|
|
12218
12865
|
assertNotFatal();
|
|
12219
12866
|
if (toolName !== COLLECTOR_OUTPUT_TOOL && (outputCandidate || pendingOutputCallId !== void 0)) {
|
|
@@ -12360,7 +13007,7 @@ function createCollectorLedger(config, options) {
|
|
|
12360
13007
|
completedMono,
|
|
12361
13008
|
host: "github.com",
|
|
12362
13009
|
repository: config.repository.canonical,
|
|
12363
|
-
prNumber:
|
|
13010
|
+
prNumber: requireBoundPr(),
|
|
12364
13011
|
prState: pr.state,
|
|
12365
13012
|
headOid: pr.headOid,
|
|
12366
13013
|
complete: true,
|
|
@@ -12399,10 +13046,6 @@ function createCollectorLedger(config, options) {
|
|
|
12399
13046
|
if (activationTime === void 0 || deadlineTime === void 0) {
|
|
12400
13047
|
throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u9700\u8981\u6FC0\u6D3B");
|
|
12401
13048
|
}
|
|
12402
|
-
if (pastCutoff(clock2)) {
|
|
12403
|
-
finalObservationRequired = true;
|
|
12404
|
-
throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u4E0D\u5728\u8D44\u683C\u622A\u6B62\u524D");
|
|
12405
|
-
}
|
|
12406
13049
|
if (ledger.unresolvedTransportFailure) {
|
|
12407
13050
|
throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u65F6\u5B58\u5728\u672A\u6062\u590D\u7684\u4F20\u8F93\u5931\u8D25");
|
|
12408
13051
|
}
|
|
@@ -12418,7 +13061,11 @@ function createCollectorLedger(config, options) {
|
|
|
12418
13061
|
throw new Error("\u901A\u8FDB\u53F8\u8BF7\u6C42\u8981\u6C42\u6700\u65B0\u5B8C\u6574\u5FEB\u7167");
|
|
12419
13062
|
}
|
|
12420
13063
|
if (snapshot.prState !== "OPEN") {
|
|
12421
|
-
throw
|
|
13064
|
+
throw new CollectorNonOpenRequestError(snapshot.prState);
|
|
13065
|
+
}
|
|
13066
|
+
if (pastCutoff(clock2)) {
|
|
13067
|
+
finalObservationRequired = true;
|
|
13068
|
+
throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u4E0D\u5728\u8D44\u683C\u622A\u6B62\u524D");
|
|
12422
13069
|
}
|
|
12423
13070
|
const { body, marker } = buildCollectorRequestBody({
|
|
12424
13071
|
configuredBody: request.requestBody,
|
|
@@ -12435,9 +13082,10 @@ function createCollectorLedger(config, options) {
|
|
|
12435
13082
|
`\u901A\u8FDB\u53F8\u5728\u6B64 HEAD \u5DF2\u6709\u540C marker \u7684\u5DF2\u8BA4\u8BC1\u8BF7\u6C42 "${input.requestId}"`
|
|
12436
13083
|
);
|
|
12437
13084
|
}
|
|
13085
|
+
const boundPr = requireBoundPr();
|
|
12438
13086
|
const attemptKey = [
|
|
12439
13087
|
config.repository.canonical,
|
|
12440
|
-
String(
|
|
13088
|
+
String(boundPr),
|
|
12441
13089
|
snapshot.headOid,
|
|
12442
13090
|
request.id
|
|
12443
13091
|
].join("|");
|
|
@@ -12466,7 +13114,7 @@ function createCollectorLedger(config, options) {
|
|
|
12466
13114
|
const result = await transport.createIssueComment({
|
|
12467
13115
|
owner: config.repository.owner,
|
|
12468
13116
|
repo: config.repository.repo,
|
|
12469
|
-
prNumber:
|
|
13117
|
+
prNumber: boundPr,
|
|
12470
13118
|
body,
|
|
12471
13119
|
...signal === void 0 ? {} : { signal }
|
|
12472
13120
|
});
|
|
@@ -12632,19 +13280,22 @@ function buildObserveModelView(input) {
|
|
|
12632
13280
|
}))
|
|
12633
13281
|
};
|
|
12634
13282
|
}
|
|
12635
|
-
var COLLECTOR_OBSERVE_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, COLLECTOR_OPERATIONAL_TOOLS, COLLECTOR_OBSERVE_BODY_HEAD_BYTES, COLLECTOR_ACTIVATION_ENTRY_TYPE, COLLECTOR_SNAPSHOT_ENTRY_TYPE, COLLECTOR_REQUEST_ENTRY_TYPE, COLLECTOR_WAIT_ENTRY_TYPE;
|
|
13283
|
+
var COLLECTOR_OBSERVE_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, COLLECTOR_BIND_TARGET_TOOL, COLLECTOR_OPERATIONAL_TOOLS, COLLECTOR_OBSERVE_BODY_HEAD_BYTES, COLLECTOR_ACTIVATION_ENTRY_TYPE, COLLECTOR_SNAPSHOT_ENTRY_TYPE, COLLECTOR_REQUEST_ENTRY_TYPE, COLLECTOR_WAIT_ENTRY_TYPE;
|
|
12636
13284
|
var init_collector_ledger = __esm({
|
|
12637
13285
|
"src/collector-ledger.ts"() {
|
|
12638
13286
|
"use strict";
|
|
12639
13287
|
init_collector_evidence();
|
|
12640
13288
|
init_collector_github();
|
|
13289
|
+
init_collector_identity();
|
|
12641
13290
|
init_collector_tool_schemas();
|
|
12642
13291
|
init_collector_output();
|
|
12643
13292
|
COLLECTOR_OBSERVE_TOOL = "ak_collector_observe";
|
|
12644
13293
|
COLLECTOR_READ_TOOL = "ak_collector_read";
|
|
12645
13294
|
COLLECTOR_REQUEST_TOOL = "ak_collector_request";
|
|
12646
13295
|
COLLECTOR_WAIT_TOOL = "ak_collector_wait";
|
|
13296
|
+
COLLECTOR_BIND_TARGET_TOOL = "ak_collector_bind_target";
|
|
12647
13297
|
COLLECTOR_OPERATIONAL_TOOLS = [
|
|
13298
|
+
COLLECTOR_BIND_TARGET_TOOL,
|
|
12648
13299
|
COLLECTOR_OBSERVE_TOOL,
|
|
12649
13300
|
COLLECTOR_READ_TOOL,
|
|
12650
13301
|
COLLECTOR_REQUEST_TOOL,
|
|
@@ -13397,8 +14048,27 @@ function formatFailureStderrDiagnostic(failure2) {
|
|
|
13397
14048
|
const oneLine2 = selected.split(/\r?\n/).map((line2) => line2.trim()).find((line2) => line2.length > 0) ?? "failure";
|
|
13398
14049
|
return formatCliDiagnostic(boundConciseDiagnostic(oneLine2));
|
|
13399
14050
|
}
|
|
14051
|
+
function formatErrorCauseDetail(cause) {
|
|
14052
|
+
if (cause instanceof Error) return cause.message;
|
|
14053
|
+
if (typeof cause === "object" && cause !== null) {
|
|
14054
|
+
try {
|
|
14055
|
+
return JSON.stringify(cause);
|
|
14056
|
+
} catch {
|
|
14057
|
+
return String(cause);
|
|
14058
|
+
}
|
|
14059
|
+
}
|
|
14060
|
+
return String(cause);
|
|
14061
|
+
}
|
|
13400
14062
|
function presentStructuralRejection(error, io) {
|
|
13401
|
-
|
|
14063
|
+
let message = error.message;
|
|
14064
|
+
const cause = error.cause;
|
|
14065
|
+
if (cause !== void 0) {
|
|
14066
|
+
const detail = formatErrorCauseDetail(cause);
|
|
14067
|
+
if (detail.trim().length > 0) {
|
|
14068
|
+
message = `${message}; cause: ${detail}`;
|
|
14069
|
+
}
|
|
14070
|
+
}
|
|
14071
|
+
io.stderr(formatCliDiagnostic(message));
|
|
13402
14072
|
}
|
|
13403
14073
|
async function inspectJudgeSession(sessionFile) {
|
|
13404
14074
|
try {
|
|
@@ -14086,6 +14756,22 @@ function toolResultText(message) {
|
|
|
14086
14756
|
return "";
|
|
14087
14757
|
}).join("").trim();
|
|
14088
14758
|
}
|
|
14759
|
+
function extractCollectorTargetBindRejection(entries) {
|
|
14760
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
14761
|
+
const entry = entries[i];
|
|
14762
|
+
if (entry?.type !== "message") continue;
|
|
14763
|
+
const message = entry.message;
|
|
14764
|
+
if (message?.role !== "toolResult") continue;
|
|
14765
|
+
if (message.toolName !== COLLECTOR_BIND_TARGET_TOOL) continue;
|
|
14766
|
+
if (message.isError !== true) return void 0;
|
|
14767
|
+
const diagnostic = toolResultText(message);
|
|
14768
|
+
if (diagnostic.length === 0) return void 0;
|
|
14769
|
+
const details = message.details;
|
|
14770
|
+
const code = isRecord16(details) && typeof details.code === "string" && details.code.trim() !== "" ? details.code : void 0;
|
|
14771
|
+
return code === void 0 ? { diagnostic } : { diagnostic, code };
|
|
14772
|
+
}
|
|
14773
|
+
return void 0;
|
|
14774
|
+
}
|
|
14089
14775
|
function boundErroredToolCandidate(entries, resultIndex, message, toolName) {
|
|
14090
14776
|
if (message.toolName !== toolName || message.isError !== true) return void 0;
|
|
14091
14777
|
const bound = boundRoleToolCallForResult(entries, resultIndex, message, toolName);
|
|
@@ -14891,7 +15577,18 @@ async function settleFailureTerminalResult(admitted, failure2, authority, option
|
|
|
14891
15577
|
try {
|
|
14892
15578
|
const facts = parseNoReceiptLifecycleFacts(raw);
|
|
14893
15579
|
if (facts.runPointer === admitted.runDirectory && facts.attemptPointer === `current:${admitted.runDirectory}`) {
|
|
14894
|
-
|
|
15580
|
+
let decisiveFacts2 = facts;
|
|
15581
|
+
if (admitted.role === "collector") {
|
|
15582
|
+
const bindRejection = extractCollectorTargetBindRejection(entries.slice(attemptStart));
|
|
15583
|
+
if (bindRejection !== void 0) {
|
|
15584
|
+
decisiveFacts2 = {
|
|
15585
|
+
...facts,
|
|
15586
|
+
targetBindRejected: true,
|
|
15587
|
+
targetBindDiagnostic: bindRejection.diagnostic,
|
|
15588
|
+
...bindRejection.code === void 0 ? {} : { targetBindCode: bindRejection.code }
|
|
15589
|
+
};
|
|
15590
|
+
}
|
|
15591
|
+
}
|
|
14895
15592
|
return withOptionalGateProjection(
|
|
14896
15593
|
{
|
|
14897
15594
|
roleOutcome: { kind: "no_receipt", role: admitted.role, status: "no-accepted-receipt", ...facts, decisiveFacts: decisiveFacts2 },
|
|
@@ -14972,6 +15669,14 @@ function presentFailureTerminal(terminal, io) {
|
|
|
14972
15669
|
cause: terminal.roleOutcome.cause,
|
|
14973
15670
|
diagnostic: terminal.roleOutcome.diagnostic
|
|
14974
15671
|
}));
|
|
15672
|
+
return;
|
|
15673
|
+
}
|
|
15674
|
+
const bindDiagnostic = terminal.roleOutcome.decisiveFacts.targetBindDiagnostic;
|
|
15675
|
+
if (typeof bindDiagnostic === "string" && bindDiagnostic.trim() !== "") {
|
|
15676
|
+
io.stderr(formatFailureStderrDiagnostic({
|
|
15677
|
+
cause: "output",
|
|
15678
|
+
diagnostic: bindDiagnostic
|
|
15679
|
+
}));
|
|
14975
15680
|
}
|
|
14976
15681
|
}
|
|
14977
15682
|
function defaultNavigatorGraceSleep() {
|
|
@@ -19432,132 +20137,6 @@ var init_tool_execution_observation = __esm({
|
|
|
19432
20137
|
}
|
|
19433
20138
|
});
|
|
19434
20139
|
|
|
19435
|
-
// src/collector-identity.ts
|
|
19436
|
-
function identityKey(identity) {
|
|
19437
|
-
if (identity === null) return "unassigned";
|
|
19438
|
-
return String(identity.userId);
|
|
19439
|
-
}
|
|
19440
|
-
function mergeMachineIdentity(current, observed) {
|
|
19441
|
-
if (current === null) return observed;
|
|
19442
|
-
if (observed === null) return current;
|
|
19443
|
-
if (current.appId === void 0 && observed.appId !== void 0) return observed;
|
|
19444
|
-
if (current.appId !== void 0 && observed.appId === void 0) return current;
|
|
19445
|
-
return observed.userType < current.userType ? observed : current;
|
|
19446
|
-
}
|
|
19447
|
-
function headRelationFor(record4, targetHead) {
|
|
19448
|
-
return record4.commitOid === void 0 || record4.commitOid === null ? "unbound" : record4.commitOid === targetHead ? "current" : "prior";
|
|
19449
|
-
}
|
|
19450
|
-
function extractCollectorEvidenceIdentityGroups(records2, targetHead) {
|
|
19451
|
-
const groups = /* @__PURE__ */ new Map();
|
|
19452
|
-
for (const record4 of records2) {
|
|
19453
|
-
if (record4.kind !== "review" && record4.kind !== "issue_comment" && record4.kind !== "review_comment" && record4.kind !== "reaction") continue;
|
|
19454
|
-
if (record4.githubId === void 0) continue;
|
|
19455
|
-
const identity = record4.machineIdentity ?? null;
|
|
19456
|
-
const kind = record4.kind;
|
|
19457
|
-
const source = {
|
|
19458
|
-
kind,
|
|
19459
|
-
id: record4.githubId,
|
|
19460
|
-
evidenceId: record4.evidenceId,
|
|
19461
|
-
headRelation: headRelationFor(record4, targetHead)
|
|
19462
|
-
};
|
|
19463
|
-
const key = identityKey(identity);
|
|
19464
|
-
let group = groups.get(key);
|
|
19465
|
-
if (group === void 0) {
|
|
19466
|
-
group = {
|
|
19467
|
-
identity,
|
|
19468
|
-
...record4.authorLogin === void 0 ? {} : { displayLogin: record4.authorLogin },
|
|
19469
|
-
attendance: true,
|
|
19470
|
-
findings: [],
|
|
19471
|
-
materials: []
|
|
19472
|
-
};
|
|
19473
|
-
groups.set(key, group);
|
|
19474
|
-
} else {
|
|
19475
|
-
group.identity = mergeMachineIdentity(group.identity, identity);
|
|
19476
|
-
}
|
|
19477
|
-
group.materials.push(source);
|
|
19478
|
-
}
|
|
19479
|
-
return [...groups.values()];
|
|
19480
|
-
}
|
|
19481
|
-
function enrichCollectorFindings(input) {
|
|
19482
|
-
const candidate = input.candidate;
|
|
19483
|
-
if (candidate === void 0 || candidate === null) return;
|
|
19484
|
-
if (typeof candidate !== "object" || Array.isArray(candidate)) {
|
|
19485
|
-
throw new CollectorFindingsValidationError("\u901A\u8FDB\u53F8\u4EA4\u4EF6\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61");
|
|
19486
|
-
}
|
|
19487
|
-
const rawFindings = candidate.findings;
|
|
19488
|
-
if (rawFindings === void 0) return;
|
|
19489
|
-
if (!Array.isArray(rawFindings)) {
|
|
19490
|
-
throw new CollectorFindingsValidationError("\u901A\u8FDB\u53F8 findings \u5FC5\u987B\u4E3A\u6570\u7EC4");
|
|
19491
|
-
}
|
|
19492
|
-
const byEvidenceId = new Map(input.records.map((record4) => [record4.evidenceId, record4]));
|
|
19493
|
-
for (const raw of rawFindings) {
|
|
19494
|
-
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
19495
|
-
throw new CollectorFindingsValidationError("\u901A\u8FDB\u53F8 finding \u5FC5\u987B\u4E3A\u5BF9\u8C61");
|
|
19496
|
-
}
|
|
19497
|
-
const evidenceId = raw.evidenceId;
|
|
19498
|
-
if (typeof evidenceId !== "string" || evidenceId.length === 0) {
|
|
19499
|
-
throw new CollectorFindingsValidationError("\u901A\u8FDB\u53F8 finding \u7F3A\u5C11\u53EF\u89E3\u6790\u7684 evidenceId \u6307\u9488");
|
|
19500
|
-
}
|
|
19501
|
-
const record4 = byEvidenceId.get(evidenceId);
|
|
19502
|
-
if (record4 === void 0) {
|
|
19503
|
-
throw new CollectorUnknownEvidenceError(evidenceId);
|
|
19504
|
-
}
|
|
19505
|
-
if (record4.kind !== "review" && record4.kind !== "issue_comment" && record4.kind !== "review_comment") {
|
|
19506
|
-
throw new CollectorFindingsValidationError(`\u901A\u8FDB\u53F8 finding \u6307\u9488\u6307\u5411\u4E0D\u53EF\u627F finding \u7684\u8BC1\u636E\u79CD\u7C7B ${record4.kind}`);
|
|
19507
|
-
}
|
|
19508
|
-
if (record4.githubId === void 0) {
|
|
19509
|
-
throw new CollectorFindingsValidationError(`\u901A\u8FDB\u53F8 finding \u6307\u9488\u8BC1\u636E ${evidenceId} \u7F3A\u5C11 GitHub id`);
|
|
19510
|
-
}
|
|
19511
|
-
const category = raw.category;
|
|
19512
|
-
if (category !== void 0 && (typeof category !== "string" || category.trim().length === 0)) {
|
|
19513
|
-
throw new CollectorFindingsValidationError("\u901A\u8FDB\u53F8 finding category \u5FC5\u987B\u4E3A\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
19514
|
-
}
|
|
19515
|
-
const identity = record4.machineIdentity ?? null;
|
|
19516
|
-
const group = input.groups.find((candidateGroup) => identityKey(candidateGroup.identity) === identityKey(identity));
|
|
19517
|
-
if (group === void 0) {
|
|
19518
|
-
throw new CollectorFindingsValidationError(`\u901A\u8FDB\u53F8 finding \u6307\u9488\u8BC1\u636E ${evidenceId} \u65E0\u5F52\u5C5E\u8EAB\u4EFD\u7EC4`);
|
|
19519
|
-
}
|
|
19520
|
-
group.findings.push({
|
|
19521
|
-
identity,
|
|
19522
|
-
source: {
|
|
19523
|
-
kind: record4.kind,
|
|
19524
|
-
id: record4.githubId,
|
|
19525
|
-
evidenceId: record4.evidenceId,
|
|
19526
|
-
headRelation: headRelationFor(record4, input.targetHead)
|
|
19527
|
-
},
|
|
19528
|
-
...category === void 0 ? {} : { category: category.trim() },
|
|
19529
|
-
pointer: {
|
|
19530
|
-
repository: input.repository,
|
|
19531
|
-
prNumber: input.prNumber,
|
|
19532
|
-
commentId: record4.githubId,
|
|
19533
|
-
...record4.htmlUrl === void 0 ? {} : { htmlUrl: record4.htmlUrl },
|
|
19534
|
-
...record4.authorLogin === void 0 ? {} : { authorLogin: record4.authorLogin },
|
|
19535
|
-
kind: record4.kind,
|
|
19536
|
-
authoritativeTime: record4.authoritativeTime ?? null
|
|
19537
|
-
}
|
|
19538
|
-
});
|
|
19539
|
-
}
|
|
19540
|
-
}
|
|
19541
|
-
var CollectorUnknownEvidenceError, CollectorFindingsValidationError;
|
|
19542
|
-
var init_collector_identity = __esm({
|
|
19543
|
-
"src/collector-identity.ts"() {
|
|
19544
|
-
"use strict";
|
|
19545
|
-
init_submission_correctable_error();
|
|
19546
|
-
CollectorUnknownEvidenceError = class extends CorrectableSubmissionError {
|
|
19547
|
-
constructor(evidenceId) {
|
|
19548
|
-
super(`\u672A\u5728\u672C\u5C40\u5DF2\u89C2\u6D4B\u6750\u6599\u4E2D\u627E\u5230 evidenceId ${evidenceId}\uFF1B\u8BF7\u7528 observe \u8FD4\u56DE\u7684\u6307\u9488\u91CD\u8BD5\u3002`);
|
|
19549
|
-
this.name = "CollectorUnknownEvidenceError";
|
|
19550
|
-
}
|
|
19551
|
-
};
|
|
19552
|
-
CollectorFindingsValidationError = class extends CorrectableSubmissionError {
|
|
19553
|
-
constructor(message) {
|
|
19554
|
-
super(message);
|
|
19555
|
-
this.name = "CollectorFindingsValidationError";
|
|
19556
|
-
}
|
|
19557
|
-
};
|
|
19558
|
-
}
|
|
19559
|
-
});
|
|
19560
|
-
|
|
19561
20140
|
// src/collector-receipt.ts
|
|
19562
20141
|
function fail4(message) {
|
|
19563
20142
|
throw new Error(message);
|
|
@@ -19567,13 +20146,15 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19567
20146
|
if (ledger.unresolvedTransportFailure) fail4("Collector cannot output while a transport failure is unrecovered");
|
|
19568
20147
|
if (ledger.latestCompleteSnapshotId === void 0) fail4("Collector output requires a complete final snapshot");
|
|
19569
20148
|
if (ledger.activationTime === void 0 || ledger.deadlineTime === void 0) fail4("Collector output requires activation timeline");
|
|
20149
|
+
if (ledger.config.prNumber === void 0) {
|
|
20150
|
+
fail4("Collector output requires a bound PR target; call ak_collector_bind_target first or pass --pr");
|
|
20151
|
+
}
|
|
19570
20152
|
if (clock !== void 0) ledger.assertOutputObservationLaw(clock);
|
|
19571
20153
|
else if (ledger.observedGeneration !== ledger.mutationGeneration || ledger.finalObservationRequired && !ledger.finalObservationCompleted) {
|
|
19572
20154
|
fail4("Collector output requires a complete observe after the latest request/wait mutation");
|
|
19573
20155
|
}
|
|
19574
20156
|
const finalSnapshot = ledger.getSnapshot(ledger.latestCompleteSnapshotId);
|
|
19575
20157
|
if (finalSnapshot === void 0 || !finalSnapshot.complete) fail4("Collector final snapshot is incomplete");
|
|
19576
|
-
if (finalSnapshot.prState !== "OPEN") fail4("Collector final snapshot PR state is not OPEN");
|
|
19577
20158
|
const evidenceRecords = [...ledger.allEvidence()];
|
|
19578
20159
|
const snapshots = [...ledger.allSnapshots()];
|
|
19579
20160
|
const evidenceIndex = new Map(evidenceRecords.map((record4) => [record4.evidenceId, record4]));
|
|
@@ -19586,7 +20167,7 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19586
20167
|
for (const id of snapshot.evidenceIds) if (!evidenceIndex.has(id)) fail4(`Collector snapshot ref "${id}" does not resolve`);
|
|
19587
20168
|
}
|
|
19588
20169
|
const groups = extractCollectorEvidenceIdentityGroups(evidenceRecords, finalSnapshot.headOid);
|
|
19589
|
-
enrichCollectorFindings({
|
|
20170
|
+
const findingsProjection = enrichCollectorFindings({
|
|
19590
20171
|
candidate: candidateRaw,
|
|
19591
20172
|
records: evidenceRecords,
|
|
19592
20173
|
groups,
|
|
@@ -19595,7 +20176,6 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19595
20176
|
prNumber: ledger.config.prNumber
|
|
19596
20177
|
});
|
|
19597
20178
|
for (const group of groups) {
|
|
19598
|
-
if (group.attendance !== true) fail4("Collector group lacks attendance");
|
|
19599
20179
|
for (const material of group.materials) {
|
|
19600
20180
|
if (material.evidenceId === void 0 || !evidenceIndex.has(material.evidenceId)) fail4("Collector material lacks a receipt-local evidence ref");
|
|
19601
20181
|
}
|
|
@@ -19603,10 +20183,20 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19603
20183
|
if (finding2.source.evidenceId === void 0 || !evidenceIndex.has(finding2.source.evidenceId)) fail4("Collector finding lacks a receipt-local evidence ref");
|
|
19604
20184
|
}
|
|
19605
20185
|
}
|
|
20186
|
+
const unfinished = extractCollectorUnfinishedReasons(candidateRaw);
|
|
20187
|
+
const submissionProjection = {
|
|
20188
|
+
findingsSource: findingsProjection.findingsSource,
|
|
20189
|
+
findingsProjectedCount: findingsProjection.findingsProjectedCount,
|
|
20190
|
+
findingsUnprojected: findingsProjection.findingsUnprojected,
|
|
20191
|
+
unfinishedReasonsSource: unfinished.source,
|
|
20192
|
+
unfinishedReasonsProjectedCount: unfinished.reasons?.length ?? 0,
|
|
20193
|
+
unfinishedReasonsUnprojected: unfinished.unprojected
|
|
20194
|
+
};
|
|
19606
20195
|
return {
|
|
19607
20196
|
host: COLLECTOR_HOST,
|
|
19608
20197
|
repository: ledger.config.repository.canonical,
|
|
19609
20198
|
prNumber: ledger.config.prNumber,
|
|
20199
|
+
prState: finalSnapshot.prState,
|
|
19610
20200
|
manifestDigest: ledger.config.manifest.digest,
|
|
19611
20201
|
activationTime: ledger.activationTime.toISOString(),
|
|
19612
20202
|
deadlineTime: ledger.deadlineTime.toISOString(),
|
|
@@ -19614,6 +20204,8 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19614
20204
|
finalSnapshotId: finalSnapshot.snapshotId,
|
|
19615
20205
|
targetHead: finalSnapshot.headOid,
|
|
19616
20206
|
groups,
|
|
20207
|
+
...unfinished.reasons === void 0 ? {} : { unfinishedReasons: unfinished.reasons },
|
|
20208
|
+
submissionProjection,
|
|
19617
20209
|
requestAttempts: [...ledger.requestAttempts()],
|
|
19618
20210
|
snapshots,
|
|
19619
20211
|
evidenceRecords: evidenceRecords.map(toReceiptEvidenceRecord)
|
|
@@ -19643,120 +20235,76 @@ var init_collector_receipt = __esm({
|
|
|
19643
20235
|
|
|
19644
20236
|
// src/collector-role.ts
|
|
19645
20237
|
function buildMethodContext(activation) {
|
|
20238
|
+
const pr = activation.ledger.config.prNumber;
|
|
19646
20239
|
return [
|
|
19647
20240
|
"<collector_method>",
|
|
19648
20241
|
`host: github.com`,
|
|
19649
20242
|
`repository: ${activation.repository.canonical}`,
|
|
19650
|
-
`prNumber: ${
|
|
20243
|
+
`prNumber: ${pr === void 0 ? "unbound \u2014 call ak_collector_bind_target with the role-decided issue/PR before observe" : String(pr)}`,
|
|
19651
20244
|
`requests: ${JSON.stringify(activation.manifest.requests.map((request) => ({ id: request.id })))}`,
|
|
19652
20245
|
"</collector_method>"
|
|
19653
20246
|
].join("\n");
|
|
19654
20247
|
}
|
|
20248
|
+
function parsePositiveTicket(raw, label) {
|
|
20249
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
20250
|
+
if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) return raw;
|
|
20251
|
+
if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) return Number(raw.trim());
|
|
20252
|
+
throw new CollectorTargetBindError(`ak_collector_bind_target ${label} must be a positive safe integer`);
|
|
20253
|
+
}
|
|
19655
20254
|
function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
19656
|
-
let activation;
|
|
19657
|
-
let inputCount = 0;
|
|
19658
|
-
let lifecycleRegistered = false;
|
|
19659
20255
|
let toolsRegistered = false;
|
|
19660
|
-
|
|
19661
|
-
|
|
19662
|
-
|
|
19663
|
-
|
|
19664
|
-
|
|
19665
|
-
|
|
19666
|
-
|
|
19667
|
-
|
|
19668
|
-
|
|
19669
|
-
pi.registerFlag("ak-collector-request-manifest", {
|
|
19670
|
-
description: "Path to the Collector v1 request manifest JSON file. In Pi latest, late hostile sibling-extension Skill injection is unsupported and fail-closed when detected; drift prevention only, not a security boundary or provider-zero guarantee",
|
|
19671
|
-
type: "string"
|
|
19672
|
-
});
|
|
19673
|
-
const ensureLifecycle = () => {
|
|
19674
|
-
if (lifecycleRegistered) return;
|
|
19675
|
-
lifecycleRegistered = true;
|
|
19676
|
-
pi.on("input", (event, ctx) => {
|
|
19677
|
-
if (activation === void 0) {
|
|
19678
|
-
return { action: "continue" };
|
|
19679
|
-
}
|
|
19680
|
-
if (inputCount >= 1) {
|
|
19681
|
-
activation.ledger.latchFatal("\u901A\u8FDB\u53F8\u5DF2\u62D2\u7EDD\u540E\u7EED\u8F93\u5165");
|
|
19682
|
-
if (process.exitCode === void 0 || process.exitCode === 0) {
|
|
19683
|
-
process.exitCode = 1;
|
|
19684
|
-
}
|
|
19685
|
-
console.error("Collector rejected later input");
|
|
19686
|
-
return { action: "handled" };
|
|
19687
|
-
}
|
|
19688
|
-
inputCount += 1;
|
|
19689
|
-
return {
|
|
19690
|
-
action: "transform",
|
|
19691
|
-
text: COLLECTOR_FIXED_KICKOFF,
|
|
19692
|
-
images: []
|
|
19693
|
-
};
|
|
19694
|
-
});
|
|
19695
|
-
pi.on("before_agent_start", (event, ctx) => {
|
|
19696
|
-
if (activation === void 0) return;
|
|
19697
|
-
const options = event.systemPromptOptions;
|
|
19698
|
-
if (options.skills && options.skills.length > 0) {
|
|
19699
|
-
hostActions.failInfrastructure(
|
|
19700
|
-
activation.ledger.latchFatal(
|
|
19701
|
-
"\u901A\u8FDB\u53F8\u68C0\u6D4B\u5230\u7CFB\u7EDF\u63D0\u793A\u4E2D\u7684\u73AF\u5883 skills"
|
|
19702
|
-
),
|
|
19703
|
-
ctx
|
|
19704
|
-
);
|
|
19705
|
-
}
|
|
19706
|
-
if (options.contextFiles && options.contextFiles.length > 0) {
|
|
19707
|
-
hostActions.failInfrastructure(
|
|
19708
|
-
activation.ledger.latchFatal(
|
|
19709
|
-
"\u901A\u8FDB\u53F8\u68C0\u6D4B\u5230\u7CFB\u7EDF\u63D0\u793A\u4E2D\u7684\u73AF\u5883 context files"
|
|
19710
|
-
),
|
|
19711
|
-
ctx
|
|
19712
|
-
);
|
|
19713
|
-
}
|
|
19714
|
-
if (typeof options.appendSystemPrompt === "string" && options.appendSystemPrompt.trim().length > 0) {
|
|
19715
|
-
hostActions.failInfrastructure(
|
|
19716
|
-
activation.ledger.latchFatal(
|
|
19717
|
-
"\u901A\u8FDB\u53F8\u68C0\u6D4B\u5230 appendSystemPrompt \u6F02\u79FB"
|
|
19718
|
-
),
|
|
19719
|
-
ctx
|
|
19720
|
-
);
|
|
19721
|
-
}
|
|
19722
|
-
if (event.prompt !== COLLECTOR_FIXED_KICKOFF) {
|
|
19723
|
-
hostActions.failInfrastructure(
|
|
19724
|
-
activation.ledger.latchFatal(
|
|
19725
|
-
"\u901A\u8FDB\u53F8\u9996\u6761\u63D0\u793A\u4E0D\u662F\u56FA\u5B9A\u5F00\u573A\u4EE4"
|
|
19726
|
-
),
|
|
19727
|
-
ctx
|
|
19728
|
-
);
|
|
20256
|
+
return {
|
|
20257
|
+
async activate(ctx) {
|
|
20258
|
+
const soul = (await dependencies.loadSoul()).trim();
|
|
20259
|
+
if (soul.length === 0) throw new Error("Collector soul is empty");
|
|
20260
|
+
const repoFlag = pi.getFlag("ak-collector-repo");
|
|
20261
|
+
const prFlag = pi.getFlag("ak-collector-pr");
|
|
20262
|
+
const requestManifestFlag = pi.getFlag("ak-collector-request-manifest");
|
|
20263
|
+
if (typeof repoFlag !== "string" || repoFlag.trim().length === 0) {
|
|
20264
|
+
throw new Error("Collector requires --ak-collector-repo");
|
|
19729
20265
|
}
|
|
19730
|
-
|
|
19731
|
-
|
|
19732
|
-
|
|
20266
|
+
const repository = parseCollectorRepository(repoFlag);
|
|
20267
|
+
let prNumber;
|
|
20268
|
+
if (typeof prFlag === "string" && prFlag.trim().length > 0) {
|
|
20269
|
+
prNumber = parseCollectorPrNumber(prFlag);
|
|
20270
|
+
} else if (typeof prFlag === "number") {
|
|
20271
|
+
prNumber = parseCollectorPrNumber(prFlag);
|
|
19733
20272
|
}
|
|
20273
|
+
const manifest = typeof requestManifestFlag === "string" && requestManifestFlag.trim().length > 0 ? await loadCollectorManifest(requestManifestFlag) : emptyCollectorManifest();
|
|
20274
|
+
const clock = dependencies.createClock?.() ?? createSystemCollectorClock();
|
|
20275
|
+
const transport = dependencies.createTransport();
|
|
20276
|
+
const ledger = dependencies.createLedger(
|
|
20277
|
+
{ repository, prNumber, manifest },
|
|
20278
|
+
clock,
|
|
20279
|
+
ctx
|
|
20280
|
+
);
|
|
19734
20281
|
return {
|
|
19735
|
-
|
|
19736
|
-
|
|
19737
|
-
|
|
19738
|
-
|
|
19739
|
-
|
|
19740
|
-
|
|
19741
|
-
"",
|
|
19742
|
-
buildMethodContext(activation)
|
|
19743
|
-
].join("\n")
|
|
20282
|
+
soul,
|
|
20283
|
+
repository,
|
|
20284
|
+
manifest,
|
|
20285
|
+
ledger,
|
|
20286
|
+
transport,
|
|
20287
|
+
clock
|
|
19744
20288
|
};
|
|
19745
|
-
}
|
|
19746
|
-
|
|
19747
|
-
|
|
20289
|
+
},
|
|
20290
|
+
assembleMaterials(activation, baseSystemPrompt) {
|
|
20291
|
+
return [
|
|
20292
|
+
baseSystemPrompt,
|
|
20293
|
+
"",
|
|
20294
|
+
"<collector_soul>",
|
|
20295
|
+
activation.soul,
|
|
20296
|
+
"</collector_soul>",
|
|
20297
|
+
"",
|
|
20298
|
+
buildMethodContext(activation)
|
|
20299
|
+
].join("\n");
|
|
20300
|
+
},
|
|
20301
|
+
onToolCall(activation, event) {
|
|
19748
20302
|
if (activation.ledger.fatal) {
|
|
19749
20303
|
return {
|
|
19750
20304
|
block: true,
|
|
19751
20305
|
reason: activation.ledger.fatalReason ?? "\u901A\u8FDB\u53F8\u81F4\u547D\u72B6\u6001"
|
|
19752
20306
|
};
|
|
19753
20307
|
}
|
|
19754
|
-
if (!COLLECTOR_REQUIRED_TOOLS.includes(event.toolName)) {
|
|
19755
|
-
return {
|
|
19756
|
-
block: true,
|
|
19757
|
-
reason: `\u901A\u8FDB\u53F8\u7981\u7528\u5DE5\u5177 ${event.toolName}`
|
|
19758
|
-
};
|
|
19759
|
-
}
|
|
19760
20308
|
if (event.toolName === COLLECTOR_OUTPUT_TOOL) {
|
|
19761
20309
|
activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, event.toolCallId);
|
|
19762
20310
|
}
|
|
@@ -19767,304 +20315,255 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
19767
20315
|
};
|
|
19768
20316
|
}
|
|
19769
20317
|
return void 0;
|
|
19770
|
-
}
|
|
19771
|
-
|
|
19772
|
-
if (activation === void 0) return;
|
|
20318
|
+
},
|
|
20319
|
+
onToolResult(activation, event) {
|
|
19773
20320
|
activation.ledger.completeOperational(event.toolCallId);
|
|
19774
|
-
}
|
|
19775
|
-
|
|
19776
|
-
if (
|
|
19777
|
-
|
|
19778
|
-
|
|
19779
|
-
|
|
19780
|
-
|
|
19781
|
-
|
|
19782
|
-
|
|
19783
|
-
|
|
19784
|
-
|
|
19785
|
-
|
|
19786
|
-
|
|
19787
|
-
|
|
19788
|
-
|
|
19789
|
-
|
|
19790
|
-
|
|
19791
|
-
|
|
19792
|
-
|
|
19793
|
-
|
|
19794
|
-
|
|
19795
|
-
|
|
19796
|
-
|
|
19797
|
-
|
|
19798
|
-
|
|
19799
|
-
|
|
19800
|
-
|
|
19801
|
-
|
|
19802
|
-
|
|
19803
|
-
|
|
19804
|
-
|
|
19805
|
-
|
|
20321
|
+
},
|
|
20322
|
+
registerBusinessTools(getActivation) {
|
|
20323
|
+
if (toolsRegistered) return;
|
|
20324
|
+
toolsRegistered = true;
|
|
20325
|
+
pi.registerTool({
|
|
20326
|
+
name: COLLECTOR_BIND_TARGET_TOOL,
|
|
20327
|
+
label: "\u901A\u8FDB\u53F8\u8BA4\u7968\u7ED1\u5B9A",
|
|
20328
|
+
description: "\u89D2\u8272\u5224\u5B9A\u4EFB\u52A1\u6750\u6599\u540E\u7ED1\u5B9A\u672C\u4ED3\u552F\u4E00 PR \u76EE\u6807\u3002\u53EF\u63D0\u4EA4 prNumber \u6216 issueNumber\uFF08\u7EBF\u4E0A\u5173\u8054\u552F\u4E00 PR\uFF09\uFF1B\u663E\u5F0F --pr \u5DF2\u7ED1\u5B9A\u65F6\u65E0\u9700\u518D\u8C03\u3002\u591A\u4E49\u6216\u65E0\u6CD5\u786E\u5B9A\u65F6\u4F1A\u6B63\u786E\u9A73\u56DE\uFF0C\u8981\u6C42\u8C03\u7528\u65B9\u660E\u786E --pr\u3002",
|
|
20329
|
+
promptSnippet: "\u7ED1\u5B9A\u89D2\u8272\u5224\u5B9A\u7684 issue/PR \u76EE\u6807",
|
|
20330
|
+
parameters: bindSchema,
|
|
20331
|
+
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20332
|
+
const activation = getActivation();
|
|
20333
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20334
|
+
try {
|
|
20335
|
+
activation.ledger.beginOperational(COLLECTOR_BIND_TARGET_TOOL, toolCallId);
|
|
20336
|
+
const prNumber = parsePositiveTicket(params.prNumber, "prNumber");
|
|
20337
|
+
const issueNumber = parsePositiveTicket(params.issueNumber, "issueNumber");
|
|
20338
|
+
if (prNumber === void 0 && issueNumber === void 0) {
|
|
20339
|
+
throw new CollectorTargetBindError(
|
|
20340
|
+
"ak_collector_bind_target requires role-decided prNumber and/or issueNumber"
|
|
20341
|
+
);
|
|
20342
|
+
}
|
|
20343
|
+
let bound = prNumber;
|
|
20344
|
+
if (issueNumber !== void 0) {
|
|
20345
|
+
const associated = await listPullRequestNumbersByTicket(createGhApiRunner(), {
|
|
20346
|
+
owner: activation.repository.owner,
|
|
20347
|
+
repo: activation.repository.repo,
|
|
20348
|
+
ticketNumber: issueNumber
|
|
20349
|
+
});
|
|
20350
|
+
if (associated.length === 0) {
|
|
20351
|
+
throw new CollectorTargetBindError(
|
|
20352
|
+
`no PR associated with issue #${issueNumber} in ${activation.repository.canonical}; pass an explicit --pr or a different issueNumber`
|
|
20353
|
+
);
|
|
20354
|
+
}
|
|
20355
|
+
if (associated.length > 1) {
|
|
20356
|
+
throw new CollectorTargetBindError(
|
|
20357
|
+
`multiple PRs associated with issue #${issueNumber}: ${associated.join(", ")}; pass an explicit prNumber or --pr`
|
|
20358
|
+
);
|
|
20359
|
+
}
|
|
20360
|
+
const fromIssue = associated[0];
|
|
20361
|
+
if (prNumber !== void 0 && prNumber !== fromIssue) {
|
|
20362
|
+
throw new CollectorTargetBindError(
|
|
20363
|
+
`prNumber ${prNumber} conflicts with issue #${issueNumber} association PR ${fromIssue}`
|
|
20364
|
+
);
|
|
20365
|
+
}
|
|
20366
|
+
bound = fromIssue;
|
|
20367
|
+
}
|
|
20368
|
+
activation.ledger.bindTarget(bound);
|
|
20369
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20370
|
+
return {
|
|
20371
|
+
content: [{
|
|
20372
|
+
type: "text",
|
|
20373
|
+
text: `\u76EE\u6807\u5DF2\u7ED1\u5B9A\uFF1A${activation.repository.canonical}#${bound}`
|
|
20374
|
+
}],
|
|
20375
|
+
details: {
|
|
20376
|
+
repository: activation.repository.canonical,
|
|
20377
|
+
prNumber: bound,
|
|
20378
|
+
...issueNumber === void 0 ? {} : { issueNumber }
|
|
20379
|
+
}
|
|
20380
|
+
};
|
|
20381
|
+
} catch (error) {
|
|
20382
|
+
if (isCorrectableExecuteError(error)) throw error;
|
|
20383
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20384
|
+
} finally {
|
|
20385
|
+
try {
|
|
20386
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20387
|
+
} catch {
|
|
20388
|
+
}
|
|
19806
20389
|
}
|
|
19807
|
-
return {
|
|
19808
|
-
content: [{
|
|
19809
|
-
type: "text",
|
|
19810
|
-
// #641 chain①: model context carries bounded body heads + pointers only.
|
|
19811
|
-
text: JSON.stringify(contextView)
|
|
19812
|
-
}],
|
|
19813
|
-
// #641 the bounded projection is the only provider-visible face on every host
|
|
19814
|
-
// (Grok/ACP relays tool details as MCP structuredContent); full bodies stay
|
|
19815
|
-
// in the ledger volume and enter context only by explicit ak_collector_read.
|
|
19816
|
-
details: contextView
|
|
19817
|
-
};
|
|
19818
|
-
} catch (error) {
|
|
19819
|
-
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
19820
20390
|
}
|
|
19821
|
-
}
|
|
19822
|
-
|
|
19823
|
-
|
|
19824
|
-
|
|
19825
|
-
|
|
19826
|
-
|
|
19827
|
-
|
|
19828
|
-
|
|
19829
|
-
|
|
19830
|
-
|
|
19831
|
-
|
|
19832
|
-
|
|
19833
|
-
|
|
19834
|
-
|
|
19835
|
-
|
|
19836
|
-
|
|
19837
|
-
|
|
20391
|
+
});
|
|
20392
|
+
pi.registerTool({
|
|
20393
|
+
name: COLLECTOR_OBSERVE_TOOL,
|
|
20394
|
+
label: "\u901A\u8FDB\u53F8\u89C2\u5BDF",
|
|
20395
|
+
description: "\u6293\u53D6\u914D\u7F6E\u76EE\u6807\u7684\u5B8C\u6574 GitHub PR \u8BC1\u636E\uFF0C\u5B58\u4E0D\u53EF\u53D8\u5FEB\u7167\u5165\u5377\u3002\u6B63\u6587\u5728\u4E0A\u4E0B\u6587\u4E2D\u53EA\u7ED9\u5934\u90E8\u6458\u5F55\u52A0\u6307\u9488\uFF1B\u9700\u8981\u5934\u90E8\u4E4B\u5916\u7684\u6B63\u6587\u65F6\uFF0C\u7528 ak_collector_read \u6309 evidenceId \u5F00\u5377\uFF1Bfindings \u7684\u62C6\u5206\u4E0E\u5F52\u7C7B\u7531\u4F60\u5728\u4EA4\u4EF6\u65F6\u5B8C\u6210\u3002\u76EE\u6807\u672A\u7ED1\u5B9A\u524D\u987B\u5148 ak_collector_bind_target\u3002",
|
|
20396
|
+
promptSnippet: "\u6293\u53D6\u914D\u7F6E\u76EE\u6807 PR \u8BC1\u636E",
|
|
20397
|
+
parameters: observeSchema,
|
|
20398
|
+
async execute(toolCallId, _params, signal, _onUpdate, ctx) {
|
|
20399
|
+
const activation = getActivation();
|
|
20400
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20401
|
+
try {
|
|
20402
|
+
activation.ledger.beginOperational(COLLECTOR_OBSERVE_TOOL, toolCallId);
|
|
20403
|
+
const { snapshot, contextView } = await activation.ledger.observe(
|
|
20404
|
+
activation.transport,
|
|
20405
|
+
activation.clock,
|
|
20406
|
+
signal
|
|
20407
|
+
);
|
|
20408
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20409
|
+
return {
|
|
20410
|
+
content: [{
|
|
20411
|
+
type: "text",
|
|
20412
|
+
text: JSON.stringify(contextView)
|
|
20413
|
+
}],
|
|
20414
|
+
details: contextView
|
|
20415
|
+
};
|
|
20416
|
+
} catch (error) {
|
|
20417
|
+
if (isCorrectableExecuteError(error)) throw error;
|
|
20418
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
19838
20419
|
}
|
|
19839
|
-
const material = projectEvidenceEntryView(record4);
|
|
19840
|
-
activation.ledger.completeOperational(toolCallId);
|
|
19841
|
-
return {
|
|
19842
|
-
content: [{
|
|
19843
|
-
type: "text",
|
|
19844
|
-
// #641 chain①: full bodies enter provider context only by explicit pointer.
|
|
19845
|
-
text: JSON.stringify(material)
|
|
19846
|
-
}],
|
|
19847
|
-
details: material
|
|
19848
|
-
};
|
|
19849
|
-
} catch (error) {
|
|
19850
|
-
if (isCorrectableExecuteError(error)) throw error;
|
|
19851
|
-
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
19852
|
-
}
|
|
19853
|
-
}
|
|
19854
|
-
});
|
|
19855
|
-
pi.registerTool({
|
|
19856
|
-
name: COLLECTOR_REQUEST_TOOL,
|
|
19857
|
-
label: "\u901A\u8FDB\u53F8\u8BF7\u6C42",
|
|
19858
|
-
description: "\u6309\u914D\u7F6E\u8BF7\u6C42\u4F53\u4E0E\u5173\u8054\u6807\u8BB0\uFF0C\u5728\u6240\u5F15\u6700\u65B0\u5FEB\u7167 HEAD \u53D1\u4E00\u6B21\u8BF7\u6C42\u3002",
|
|
19859
|
-
promptSnippet: "\u6309\u914D\u7F6E\u53D1\u4E00\u6B21\u8BF7\u6C42",
|
|
19860
|
-
parameters: requestSchema,
|
|
19861
|
-
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
19862
|
-
if (activation === void 0) {
|
|
19863
|
-
throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
19864
|
-
}
|
|
19865
|
-
try {
|
|
19866
|
-
activation.ledger.beginOperational(COLLECTOR_REQUEST_TOOL, toolCallId);
|
|
19867
|
-
const details = await activation.ledger.request(
|
|
19868
|
-
params,
|
|
19869
|
-
activation.transport,
|
|
19870
|
-
activation.clock,
|
|
19871
|
-
signal
|
|
19872
|
-
);
|
|
19873
|
-
activation.ledger.completeOperational(toolCallId);
|
|
19874
|
-
return {
|
|
19875
|
-
content: [{
|
|
19876
|
-
type: "text",
|
|
19877
|
-
text: `\u8BF7\u6C42\u5C1D\u8BD5\u5DF2\u8BB0\u5F55\uFF1Arequest ${params.requestId}`
|
|
19878
|
-
}],
|
|
19879
|
-
details
|
|
19880
|
-
};
|
|
19881
|
-
} catch (error) {
|
|
19882
|
-
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
19883
|
-
}
|
|
19884
|
-
}
|
|
19885
|
-
});
|
|
19886
|
-
pi.registerTool({
|
|
19887
|
-
name: COLLECTOR_WAIT_TOOL,
|
|
19888
|
-
label: "\u901A\u8FDB\u53F8\u7B49\u5F85",
|
|
19889
|
-
description: "\u518D\u89C2\u5BDF\u524D\u7B49\u5F85\uFF1B\u5355\u6B21\u4E0A\u9650\u4E94\u5206\u949F\u4E14\u4E0D\u8D85\u5269\u4F59\u8D44\u683C\u3002",
|
|
19890
|
-
promptSnippet: "\u8D44\u683C\u622A\u6B62\u524D\u7B49\u5F85",
|
|
19891
|
-
parameters: waitSchema,
|
|
19892
|
-
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
19893
|
-
if (activation === void 0) {
|
|
19894
|
-
throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
19895
|
-
}
|
|
19896
|
-
try {
|
|
19897
|
-
activation.ledger.beginOperational(COLLECTOR_WAIT_TOOL, toolCallId);
|
|
19898
|
-
const details = await activation.ledger.wait(
|
|
19899
|
-
params,
|
|
19900
|
-
activation.clock,
|
|
19901
|
-
signal
|
|
19902
|
-
);
|
|
19903
|
-
activation.ledger.completeOperational(toolCallId);
|
|
19904
|
-
return {
|
|
19905
|
-
content: [{
|
|
19906
|
-
type: "text",
|
|
19907
|
-
text: `\u5DF2\u7B49\u5F85 ${String(details.effectiveMs)}ms`
|
|
19908
|
-
}],
|
|
19909
|
-
details
|
|
19910
|
-
};
|
|
19911
|
-
} catch (error) {
|
|
19912
|
-
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
19913
|
-
}
|
|
19914
|
-
}
|
|
19915
|
-
});
|
|
19916
|
-
pi.registerTool({
|
|
19917
|
-
name: COLLECTOR_OUTPUT_TOOL,
|
|
19918
|
-
label: "\u901A\u8FDB\u53F8\u8F93\u51FA",
|
|
19919
|
-
description: "\u89C2\u5BDF\u5B8C\u6210\u540E\u63D0\u4EA4\uFF1B\u56DE\u6267\u7531 runtime \u7EC4\u88C5\u3002\u6B63\u5E38\u5B8C\u5DE5\u63D0\u4EA4\u7A7A\u5BF9\u8C61 {}\uFF08\u5982\u9700\u62A5 finding\uFF0C\u586B findings \u6307\u9488\u6570\u7EC4\uFF09\uFF1B\u4EC5\u5728\u57FA\u7840\u8BBE\u65BD\u771F\u5B9E\u5931\u8D25\u65F6\u624D\u53EF\u586B infrastructureFailure\uFF0C\u65E0\u5931\u8D25\u65F6\u5FC5\u987B\u7701\u7565\u8BE5\u5B57\u6BB5\u3002",
|
|
19920
|
-
promptSnippet: "\u63D0\u4EA4\u901A\u8FDB\u53F8\u56DE\u6267",
|
|
19921
|
-
// #641 chain②: the seat owns the normal-completion decision. The probe
|
|
19922
|
-
// runs the exact receipt assembly (validation only, no accept side
|
|
19923
|
-
// effects); success ⇒ machine-verified normal completion ⇒ bounce.
|
|
19924
|
-
bounceInfrastructureDeclaration(params) {
|
|
19925
|
-
if (activation === void 0) return void 0;
|
|
19926
|
-
try {
|
|
19927
|
-
buildCollectorReceipt(activation.ledger, params, activation.clock);
|
|
19928
|
-
} catch {
|
|
19929
|
-
return void 0;
|
|
19930
|
-
}
|
|
19931
|
-
return new CollectorNormalCompletionDeclarationError();
|
|
19932
|
-
},
|
|
19933
|
-
parameters: outputSchema,
|
|
19934
|
-
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
19935
|
-
if (activation === void 0) {
|
|
19936
|
-
throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
19937
20420
|
}
|
|
19938
|
-
|
|
19939
|
-
|
|
19940
|
-
|
|
19941
|
-
|
|
19942
|
-
|
|
19943
|
-
|
|
19944
|
-
|
|
19945
|
-
|
|
19946
|
-
const
|
|
19947
|
-
|
|
19948
|
-
|
|
19949
|
-
|
|
19950
|
-
|
|
19951
|
-
|
|
19952
|
-
|
|
19953
|
-
|
|
19954
|
-
|
|
19955
|
-
|
|
19956
|
-
|
|
20421
|
+
});
|
|
20422
|
+
pi.registerTool({
|
|
20423
|
+
name: COLLECTOR_READ_TOOL,
|
|
20424
|
+
label: "\u901A\u8FDB\u53F8\u5F00\u5377",
|
|
20425
|
+
description: "\u6309 evidenceId \u5F00\u5377\u8BFB\u53D6\u4E00\u6761\u5DF2\u89C2\u6D4B\u6750\u6599\u7684\u5168\u91CF\u6B63\u6587\u4E0E\u6307\u9488\uFF1B\u53EA\u5728\u89C2\u5BDF\u5934\u90E8\u6458\u5F55\u4E0D\u8DB3\u4EE5\u5224\u8BFB\u65F6\u8C03\u7528\u3002",
|
|
20426
|
+
promptSnippet: "\u6309\u6307\u9488\u5F00\u5377\u8BFB\u6750\u6599",
|
|
20427
|
+
parameters: readSchema,
|
|
20428
|
+
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20429
|
+
const activation = getActivation();
|
|
20430
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20431
|
+
try {
|
|
20432
|
+
activation.ledger.beginOperational(COLLECTOR_READ_TOOL, toolCallId);
|
|
20433
|
+
const record4 = activation.ledger.getEvidence(params.evidenceId);
|
|
20434
|
+
if (record4 === void 0 || record4.kind !== "review" && record4.kind !== "issue_comment" && record4.kind !== "review_comment" && record4.kind !== "reaction" || typeof record4.body !== "string") {
|
|
20435
|
+
throw new CollectorUnknownEvidenceError(params.evidenceId);
|
|
20436
|
+
}
|
|
20437
|
+
const material = projectEvidenceEntryView(record4);
|
|
20438
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20439
|
+
return {
|
|
20440
|
+
content: [{
|
|
20441
|
+
type: "text",
|
|
20442
|
+
text: JSON.stringify(material)
|
|
20443
|
+
}],
|
|
20444
|
+
details: material
|
|
20445
|
+
};
|
|
20446
|
+
} catch (error) {
|
|
20447
|
+
if (isCorrectableExecuteError(error)) throw error;
|
|
19957
20448
|
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
19958
20449
|
}
|
|
19959
|
-
throw error;
|
|
19960
|
-
} finally {
|
|
19961
|
-
activation.ledger.completeOperational(toolCallId);
|
|
19962
20450
|
}
|
|
19963
|
-
}
|
|
19964
|
-
});
|
|
19965
|
-
};
|
|
19966
|
-
return {
|
|
19967
|
-
async activate(ctx, event) {
|
|
19968
|
-
activation = void 0;
|
|
19969
|
-
ensureLifecycle();
|
|
19970
|
-
if (ctx.mode !== "print" && ctx.mode !== "json") {
|
|
19971
|
-
throw new Error(
|
|
19972
|
-
`Collector supports only print or json mode (got ${ctx.mode})`
|
|
19973
|
-
);
|
|
19974
|
-
}
|
|
19975
|
-
if (event.reason === "fork" || event.reason === "reload") {
|
|
19976
|
-
throw new Error(
|
|
19977
|
-
`Collector does not support session_start reason ${event.reason}`
|
|
19978
|
-
);
|
|
19979
|
-
}
|
|
19980
|
-
const soul = (await dependencies.loadSoul()).trim();
|
|
19981
|
-
if (soul.length === 0) throw new Error("Collector soul is empty");
|
|
19982
|
-
const repoFlag = pi.getFlag("ak-collector-repo");
|
|
19983
|
-
const prFlag = pi.getFlag("ak-collector-pr");
|
|
19984
|
-
const requestManifestFlag = pi.getFlag("ak-collector-request-manifest");
|
|
19985
|
-
if (typeof repoFlag !== "string" || repoFlag.trim().length === 0) {
|
|
19986
|
-
throw new Error("Collector requires --ak-collector-repo");
|
|
19987
|
-
}
|
|
19988
|
-
if (typeof prFlag !== "string" && typeof prFlag !== "number") {
|
|
19989
|
-
throw new Error("Collector requires --ak-collector-pr");
|
|
19990
|
-
}
|
|
19991
|
-
const repository = parseCollectorRepository(repoFlag);
|
|
19992
|
-
const prNumber = parseCollectorPrNumber(prFlag);
|
|
19993
|
-
const manifest = typeof requestManifestFlag === "string" && requestManifestFlag.trim().length > 0 ? await loadCollectorManifest(requestManifestFlag) : emptyCollectorManifest();
|
|
19994
|
-
const commands = pi.getCommands?.() ?? [];
|
|
19995
|
-
const ambientCommands = commands.filter((command) => {
|
|
19996
|
-
const name = command.name.toLowerCase();
|
|
19997
|
-
return name.includes("skill") || name.includes("prompt") || name.startsWith("template");
|
|
19998
20451
|
});
|
|
19999
|
-
|
|
20000
|
-
|
|
20001
|
-
|
|
20002
|
-
|
|
20003
|
-
|
|
20004
|
-
|
|
20005
|
-
|
|
20006
|
-
|
|
20007
|
-
|
|
20008
|
-
|
|
20009
|
-
|
|
20010
|
-
|
|
20011
|
-
|
|
20012
|
-
|
|
20013
|
-
|
|
20014
|
-
|
|
20015
|
-
|
|
20016
|
-
|
|
20017
|
-
|
|
20018
|
-
|
|
20019
|
-
|
|
20020
|
-
|
|
20021
|
-
|
|
20022
|
-
|
|
20023
|
-
|
|
20024
|
-
|
|
20025
|
-
|
|
20452
|
+
pi.registerTool({
|
|
20453
|
+
name: COLLECTOR_REQUEST_TOOL,
|
|
20454
|
+
label: "\u901A\u8FDB\u53F8\u8BF7\u6C42",
|
|
20455
|
+
description: "\u6309\u914D\u7F6E\u8BF7\u6C42\u4F53\u4E0E\u5173\u8054\u6807\u8BB0\uFF0C\u5728\u6240\u5F15\u6700\u65B0\u5FEB\u7167 HEAD \u53D1\u4E00\u6B21\u8BF7\u6C42\u3002",
|
|
20456
|
+
promptSnippet: "\u6309\u914D\u7F6E\u53D1\u4E00\u6B21\u8BF7\u6C42",
|
|
20457
|
+
parameters: requestSchema,
|
|
20458
|
+
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
20459
|
+
const activation = getActivation();
|
|
20460
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20461
|
+
try {
|
|
20462
|
+
activation.ledger.beginOperational(COLLECTOR_REQUEST_TOOL, toolCallId);
|
|
20463
|
+
const details = await activation.ledger.request(
|
|
20464
|
+
params,
|
|
20465
|
+
activation.transport,
|
|
20466
|
+
activation.clock,
|
|
20467
|
+
signal
|
|
20468
|
+
);
|
|
20469
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20470
|
+
return {
|
|
20471
|
+
content: [{
|
|
20472
|
+
type: "text",
|
|
20473
|
+
text: `\u8BF7\u6C42\u5C1D\u8BD5\u5DF2\u8BB0\u5F55\uFF1Arequest ${params.requestId}`
|
|
20474
|
+
}],
|
|
20475
|
+
details
|
|
20476
|
+
};
|
|
20477
|
+
} catch (error) {
|
|
20478
|
+
if (isCorrectableExecuteError(error)) throw error;
|
|
20479
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20480
|
+
}
|
|
20026
20481
|
}
|
|
20027
|
-
}
|
|
20028
|
-
pi.
|
|
20029
|
-
|
|
20030
|
-
|
|
20031
|
-
|
|
20032
|
-
|
|
20482
|
+
});
|
|
20483
|
+
pi.registerTool({
|
|
20484
|
+
name: COLLECTOR_WAIT_TOOL,
|
|
20485
|
+
label: "\u901A\u8FDB\u53F8\u7B49\u5F85",
|
|
20486
|
+
description: "\u518D\u89C2\u5BDF\u524D\u7B49\u5F85\uFF1B\u5355\u6B21\u4E0A\u9650\u4E94\u5206\u949F\u4E14\u4E0D\u8D85\u5269\u4F59\u8D44\u683C\u3002",
|
|
20487
|
+
promptSnippet: "\u8D44\u683C\u622A\u6B62\u524D\u7B49\u5F85",
|
|
20488
|
+
parameters: waitSchema,
|
|
20489
|
+
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
20490
|
+
const activation = getActivation();
|
|
20491
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20492
|
+
try {
|
|
20493
|
+
activation.ledger.beginOperational(COLLECTOR_WAIT_TOOL, toolCallId);
|
|
20494
|
+
const details = await activation.ledger.wait(
|
|
20495
|
+
params,
|
|
20496
|
+
activation.clock,
|
|
20497
|
+
signal
|
|
20498
|
+
);
|
|
20499
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20500
|
+
return {
|
|
20501
|
+
content: [{
|
|
20502
|
+
type: "text",
|
|
20503
|
+
text: `\u5DF2\u7B49\u5F85 ${String(details.effectiveMs)}ms`
|
|
20504
|
+
}],
|
|
20505
|
+
details
|
|
20506
|
+
};
|
|
20507
|
+
} catch (error) {
|
|
20508
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20509
|
+
}
|
|
20033
20510
|
}
|
|
20034
|
-
}
|
|
20035
|
-
|
|
20036
|
-
|
|
20037
|
-
|
|
20511
|
+
});
|
|
20512
|
+
pi.registerTool({
|
|
20513
|
+
name: COLLECTOR_OUTPUT_TOOL,
|
|
20514
|
+
label: "\u901A\u8FDB\u53F8\u8F93\u51FA",
|
|
20515
|
+
description: "\u89C2\u5BDF\u5B8C\u6210\u540E\u63D0\u4EA4\uFF1B\u56DE\u6267\u7531 runtime \u7EC4\u88C5\u3002\u6B63\u5E38\u5B8C\u5DE5\u63D0\u4EA4\u7A7A\u5BF9\u8C61 {}\uFF08\u5982\u9700\u62A5 finding\uFF0C\u586B findings \u6307\u9488\u6570\u7EC4\uFF09\uFF1B\u4EC5\u5728\u57FA\u7840\u8BBE\u65BD\u771F\u5B9E\u5931\u8D25\u65F6\u624D\u53EF\u586B infrastructureFailure\uFF0C\u65E0\u5931\u8D25\u65F6\u5FC5\u987B\u7701\u7565\u8BE5\u5B57\u6BB5\u3002",
|
|
20516
|
+
promptSnippet: "\u63D0\u4EA4\u901A\u8FDB\u53F8\u56DE\u6267",
|
|
20517
|
+
bounceInfrastructureDeclaration(params) {
|
|
20518
|
+
const activation = getActivation();
|
|
20519
|
+
if (activation === void 0) return void 0;
|
|
20520
|
+
try {
|
|
20521
|
+
buildCollectorReceipt(activation.ledger, params, activation.clock);
|
|
20522
|
+
} catch {
|
|
20523
|
+
return void 0;
|
|
20524
|
+
}
|
|
20525
|
+
return new CollectorNormalCompletionDeclarationError();
|
|
20526
|
+
},
|
|
20527
|
+
parameters: outputSchema,
|
|
20528
|
+
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20529
|
+
const activation = getActivation();
|
|
20530
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20531
|
+
try {
|
|
20532
|
+
activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, toolCallId);
|
|
20533
|
+
const receipt = buildCollectorReceipt(
|
|
20534
|
+
activation.ledger,
|
|
20535
|
+
params,
|
|
20536
|
+
activation.clock
|
|
20537
|
+
);
|
|
20538
|
+
activation.ledger.recordOutputCandidate();
|
|
20539
|
+
return {
|
|
20540
|
+
content: [{
|
|
20541
|
+
type: "text",
|
|
20542
|
+
text: COLLECTOR_ACCEPTED_TEXT
|
|
20543
|
+
}],
|
|
20544
|
+
details: receipt,
|
|
20545
|
+
terminate: true
|
|
20546
|
+
};
|
|
20547
|
+
} catch (error) {
|
|
20548
|
+
if (error instanceof Error && error.collectorFatal === true) {
|
|
20549
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20550
|
+
}
|
|
20551
|
+
throw error;
|
|
20552
|
+
} finally {
|
|
20553
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20554
|
+
}
|
|
20038
20555
|
}
|
|
20039
|
-
}
|
|
20040
|
-
const clock = dependencies.createClock?.() ?? createSystemCollectorClock();
|
|
20041
|
-
const transport = dependencies.createTransport();
|
|
20042
|
-
const ledger = dependencies.createLedger(
|
|
20043
|
-
{ repository, prNumber, manifest },
|
|
20044
|
-
clock,
|
|
20045
|
-
ctx
|
|
20046
|
-
);
|
|
20047
|
-
if (ledger.activationRecorded) {
|
|
20048
|
-
firstDispatchDone = true;
|
|
20049
|
-
}
|
|
20050
|
-
activation = {
|
|
20051
|
-
soul,
|
|
20052
|
-
repository,
|
|
20053
|
-
prNumber,
|
|
20054
|
-
manifest,
|
|
20055
|
-
ledger,
|
|
20056
|
-
transport,
|
|
20057
|
-
clock
|
|
20058
|
-
};
|
|
20556
|
+
});
|
|
20059
20557
|
}
|
|
20060
20558
|
};
|
|
20061
20559
|
}
|
|
20062
|
-
var CollectorNormalCompletionDeclarationError, COLLECTOR_REQUIRED_TOOLS, observeSchema, readSchema, requestSchema, waitSchema, outputSchema;
|
|
20560
|
+
var CollectorNormalCompletionDeclarationError, CollectorTargetBindError, COLLECTOR_REQUIRED_TOOLS, COLLECTOR_TRANSPORT_FLAGS, observeSchema, readSchema, requestSchema, waitSchema, bindSchema, outputSchema;
|
|
20063
20561
|
var init_collector_role = __esm({
|
|
20064
20562
|
"src/collector-role.ts"() {
|
|
20065
20563
|
"use strict";
|
|
20066
20564
|
init_collector_config();
|
|
20067
20565
|
init_collector_evidence();
|
|
20566
|
+
init_collector_github();
|
|
20068
20567
|
init_collector_ledger();
|
|
20069
20568
|
init_collector_receipt();
|
|
20070
20569
|
init_collector_tool_schemas();
|
|
@@ -20072,24 +20571,54 @@ var init_collector_role = __esm({
|
|
|
20072
20571
|
init_submission_correctable_error();
|
|
20073
20572
|
init_collector_identity();
|
|
20074
20573
|
init_collector_identity();
|
|
20075
|
-
init_collector_config();
|
|
20076
20574
|
CollectorNormalCompletionDeclarationError = class extends CorrectableSubmissionError {
|
|
20077
20575
|
constructor() {
|
|
20078
20576
|
super("runtime \u5DF2\u6309\u673A\u5668\u72B6\u6001\u6838\u9A8C\u672C\u5C40\u4E3A\u6B63\u5E38\u5B8C\u5DE5\uFF08\u56DE\u6267\u53EF\u5408\u6CD5\u7EC4\u88C5\uFF09\uFF1A\u6B63\u5E38\u5B8C\u5DE5\u7684\u4EA4\u4EF6\u4E0D\u5F97\u586B infrastructureFailure\uFF0C\u8BF7\u7701\u7565\u8BE5\u5B57\u6BB5\u540E\u91CD\u65B0\u63D0\u4EA4\u3002");
|
|
20079
20577
|
this.name = "CollectorNormalCompletionDeclarationError";
|
|
20080
20578
|
}
|
|
20081
20579
|
};
|
|
20580
|
+
CollectorTargetBindError = class extends CorrectableSubmissionError {
|
|
20581
|
+
constructor(message) {
|
|
20582
|
+
super(message);
|
|
20583
|
+
this.name = "CollectorTargetBindError";
|
|
20584
|
+
}
|
|
20585
|
+
};
|
|
20082
20586
|
COLLECTOR_REQUIRED_TOOLS = [
|
|
20587
|
+
COLLECTOR_BIND_TARGET_TOOL,
|
|
20083
20588
|
COLLECTOR_OBSERVE_TOOL,
|
|
20084
20589
|
COLLECTOR_READ_TOOL,
|
|
20085
20590
|
COLLECTOR_REQUEST_TOOL,
|
|
20086
20591
|
COLLECTOR_WAIT_TOOL,
|
|
20087
20592
|
COLLECTOR_OUTPUT_TOOL
|
|
20088
20593
|
];
|
|
20594
|
+
COLLECTOR_TRANSPORT_FLAGS = Object.freeze([
|
|
20595
|
+
Object.freeze({
|
|
20596
|
+
name: "ak-collector-repo",
|
|
20597
|
+
definition: Object.freeze({
|
|
20598
|
+
description: "GitHub owner/repo target for Collector (github.com only; conservative ASCII grammar).",
|
|
20599
|
+
type: "string"
|
|
20600
|
+
})
|
|
20601
|
+
}),
|
|
20602
|
+
Object.freeze({
|
|
20603
|
+
name: "ak-collector-pr",
|
|
20604
|
+
definition: Object.freeze({
|
|
20605
|
+
description: "Optional positive safe-integer pull request number for Collector. Omit when the role will bind from task materials.",
|
|
20606
|
+
type: "string"
|
|
20607
|
+
})
|
|
20608
|
+
}),
|
|
20609
|
+
Object.freeze({
|
|
20610
|
+
name: "ak-collector-request-manifest",
|
|
20611
|
+
definition: Object.freeze({
|
|
20612
|
+
description: "Path to the Collector v1 request manifest JSON file.",
|
|
20613
|
+
type: "string"
|
|
20614
|
+
})
|
|
20615
|
+
})
|
|
20616
|
+
]);
|
|
20089
20617
|
observeSchema = collectorObserveArgsSchema;
|
|
20090
20618
|
readSchema = collectorReadArgsSchema;
|
|
20091
20619
|
requestSchema = collectorRequestArgsSchema;
|
|
20092
20620
|
waitSchema = collectorWaitArgsSchema;
|
|
20621
|
+
bindSchema = collectorBindTargetArgsSchema;
|
|
20093
20622
|
outputSchema = collectorOutputArgsSchema;
|
|
20094
20623
|
}
|
|
20095
20624
|
});
|
|
@@ -21070,11 +21599,11 @@ var init_reviewer_role = __esm({
|
|
|
21070
21599
|
});
|
|
21071
21600
|
|
|
21072
21601
|
// src/worker-submission-gates.ts
|
|
21073
|
-
import { execFileSync as
|
|
21602
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
21074
21603
|
import { existsSync as existsSync10, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, rmdirSync, rmSync } from "node:fs";
|
|
21075
21604
|
import { resolve as resolve18 } from "node:path";
|
|
21076
21605
|
function git2(cwd, args) {
|
|
21077
|
-
return
|
|
21606
|
+
return execFileSync4("git", args, {
|
|
21078
21607
|
cwd,
|
|
21079
21608
|
encoding: "utf8",
|
|
21080
21609
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -21082,7 +21611,7 @@ function git2(cwd, args) {
|
|
|
21082
21611
|
}).trim();
|
|
21083
21612
|
}
|
|
21084
21613
|
function gitFile(file, args) {
|
|
21085
|
-
return
|
|
21614
|
+
return execFileSync4("git", ["config", "--file", file, ...args], {
|
|
21086
21615
|
encoding: "utf8",
|
|
21087
21616
|
stdio: ["ignore", "pipe", "pipe"],
|
|
21088
21617
|
env: { ...process.env, GIT_DIR: void 0, GIT_WORK_TREE: void 0, GIT_COMMON_DIR: void 0 }
|
|
@@ -22310,6 +22839,9 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22310
22839
|
for (const flag of GLEANER_LEFT_TRANSPORT_FLAGS) {
|
|
22311
22840
|
roleHost.registerFlag(flag.name, flag.definition);
|
|
22312
22841
|
}
|
|
22842
|
+
for (const flag of COLLECTOR_TRANSPORT_FLAGS) {
|
|
22843
|
+
roleHost.registerFlag(flag.name, flag.definition);
|
|
22844
|
+
}
|
|
22313
22845
|
let admitted = false;
|
|
22314
22846
|
let selectedRole;
|
|
22315
22847
|
let activeReviewerParent;
|
|
@@ -22440,10 +22972,41 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22440
22972
|
})
|
|
22441
22973
|
};
|
|
22442
22974
|
}
|
|
22975
|
+
if (role === "collector" && activeCollector !== void 0) {
|
|
22976
|
+
const options = event.systemPromptOptions;
|
|
22977
|
+
if (options.skills && options.skills.length > 0) {
|
|
22978
|
+
failInfrastructure(
|
|
22979
|
+
activeCollector.ledger.latchFatal("\u901A\u8FDB\u53F8\u68C0\u6D4B\u5230\u7CFB\u7EDF\u63D0\u793A\u4E2D\u7684\u73AF\u5883 skills"),
|
|
22980
|
+
ctx
|
|
22981
|
+
);
|
|
22982
|
+
}
|
|
22983
|
+
if (options.contextFiles && options.contextFiles.length > 0) {
|
|
22984
|
+
failInfrastructure(
|
|
22985
|
+
activeCollector.ledger.latchFatal("\u901A\u8FDB\u53F8\u68C0\u6D4B\u5230\u7CFB\u7EDF\u63D0\u793A\u4E2D\u7684\u73AF\u5883 context files"),
|
|
22986
|
+
ctx
|
|
22987
|
+
);
|
|
22988
|
+
}
|
|
22989
|
+
if (typeof options.appendSystemPrompt === "string" && options.appendSystemPrompt.trim().length > 0) {
|
|
22990
|
+
failInfrastructure(
|
|
22991
|
+
activeCollector.ledger.latchFatal("\u901A\u8FDB\u53F8\u68C0\u6D4B\u5230 appendSystemPrompt \u6F02\u79FB"),
|
|
22992
|
+
ctx
|
|
22993
|
+
);
|
|
22994
|
+
}
|
|
22995
|
+
if (!collectorFirstDispatchDone) {
|
|
22996
|
+
collectorFirstDispatchDone = true;
|
|
22997
|
+
activeCollector.ledger.recordActivation(activeCollector.clock);
|
|
22998
|
+
}
|
|
22999
|
+
return {
|
|
23000
|
+
systemPrompt: collectorBusiness.assembleMaterials(activeCollector, event.systemPrompt)
|
|
23001
|
+
};
|
|
23002
|
+
}
|
|
22443
23003
|
});
|
|
22444
23004
|
roleHost.on("tool_result", async (event) => {
|
|
22445
23005
|
const role = selectedRole;
|
|
22446
23006
|
if (role === void 0) return;
|
|
23007
|
+
if (role === "collector" && activeCollector !== void 0) {
|
|
23008
|
+
collectorBusiness.onToolResult(activeCollector, event);
|
|
23009
|
+
}
|
|
22447
23010
|
const pendingInfra = pendingInfrastructureFailures.get(event.toolCallId);
|
|
22448
23011
|
const isRoleInfrastructureFailure = pendingInfra !== void 0;
|
|
22449
23012
|
if (pendingInfra !== void 0) pendingInfrastructureFailures.delete(event.toolCallId);
|
|
@@ -22541,6 +23104,11 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22541
23104
|
priorFetch = void 0;
|
|
22542
23105
|
fetchWrapped = false;
|
|
22543
23106
|
}
|
|
23107
|
+
if (selectedRole === "collector" && activeCollector !== void 0 && activeCollector.ledger.fatal) {
|
|
23108
|
+
if (process.exitCode === void 0 || process.exitCode === 0) {
|
|
23109
|
+
process.exitCode = 1;
|
|
23110
|
+
}
|
|
23111
|
+
}
|
|
22544
23112
|
const presentation = pendingNavigatorPresentation;
|
|
22545
23113
|
pendingNavigatorPresentation = void 0;
|
|
22546
23114
|
if (presentation !== void 0) {
|
|
@@ -22742,7 +23310,9 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22742
23310
|
}
|
|
22743
23311
|
}
|
|
22744
23312
|
}, hostActions);
|
|
22745
|
-
|
|
23313
|
+
let activeCollector;
|
|
23314
|
+
let collectorFirstDispatchDone = false;
|
|
23315
|
+
const collectorBusiness = createCollectorRoleRuntime(
|
|
22746
23316
|
roleHost,
|
|
22747
23317
|
{
|
|
22748
23318
|
async loadSoul() {
|
|
@@ -22771,13 +23341,90 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22771
23341
|
dossierEntries: context.sessionManager?.getEntries?.() ?? []
|
|
22772
23342
|
});
|
|
22773
23343
|
},
|
|
22774
|
-
...dependencies.createCollectorClock === void 0 ? {} : { createClock: dependencies.createCollectorClock }
|
|
22775
|
-
...dependencies.collectorPackageExtensionPath === void 0 ? {} : {
|
|
22776
|
-
packageExtensionPath: dependencies.collectorPackageExtensionPath
|
|
22777
|
-
}
|
|
23344
|
+
...dependencies.createCollectorClock === void 0 ? {} : { createClock: dependencies.createCollectorClock }
|
|
22778
23345
|
},
|
|
22779
23346
|
hostActions
|
|
22780
23347
|
);
|
|
23348
|
+
let collectorToolCallRegistered = false;
|
|
23349
|
+
const collector = {
|
|
23350
|
+
async activate(context, event) {
|
|
23351
|
+
activeCollector = void 0;
|
|
23352
|
+
collectorFirstDispatchDone = false;
|
|
23353
|
+
if (context.mode !== "print" && context.mode !== "json") {
|
|
23354
|
+
throw new Error(
|
|
23355
|
+
`Collector supports only print or json mode (got ${context.mode})`
|
|
23356
|
+
);
|
|
23357
|
+
}
|
|
23358
|
+
if (event.reason === "fork" || event.reason === "reload") {
|
|
23359
|
+
throw new Error(
|
|
23360
|
+
`Collector does not support session_start reason ${event.reason}`
|
|
23361
|
+
);
|
|
23362
|
+
}
|
|
23363
|
+
const commands = roleHost.getCommands?.() ?? [];
|
|
23364
|
+
const ambientCommands = commands.filter((command) => {
|
|
23365
|
+
const name = command.name.toLowerCase();
|
|
23366
|
+
return name.includes("skill") || name.includes("prompt") || name.startsWith("template");
|
|
23367
|
+
});
|
|
23368
|
+
if (ambientCommands.length > 0) {
|
|
23369
|
+
throw new Error(
|
|
23370
|
+
`Collector detected ambient instruction commands: ${ambientCommands.map((c) => c.name).join(", ")}`
|
|
23371
|
+
);
|
|
23372
|
+
}
|
|
23373
|
+
const preExisting = roleHost.getAllTools();
|
|
23374
|
+
const alreadyRegistered = COLLECTOR_REQUIRED_TOOLS.every(
|
|
23375
|
+
(required) => preExisting.some((tool) => tool.name === required)
|
|
23376
|
+
);
|
|
23377
|
+
if (!alreadyRegistered) {
|
|
23378
|
+
for (const required of COLLECTOR_REQUIRED_TOOLS) {
|
|
23379
|
+
const prior = preExisting.filter((tool) => tool.name === required);
|
|
23380
|
+
if (prior.length > 0) {
|
|
23381
|
+
throw new Error(`Collector required tool name collision: ${required}`);
|
|
23382
|
+
}
|
|
23383
|
+
}
|
|
23384
|
+
}
|
|
23385
|
+
collectorBusiness.registerBusinessTools(() => activeCollector);
|
|
23386
|
+
const allTools = roleHost.getAllTools();
|
|
23387
|
+
for (const required of COLLECTOR_REQUIRED_TOOLS) {
|
|
23388
|
+
const matches = allTools.filter((tool) => tool.name === required);
|
|
23389
|
+
if (matches.length === 0) {
|
|
23390
|
+
throw new Error(`Collector required tool missing: ${required}`);
|
|
23391
|
+
}
|
|
23392
|
+
if (matches.length > 1) {
|
|
23393
|
+
throw new Error(`Collector required tool name collision: ${required}`);
|
|
23394
|
+
}
|
|
23395
|
+
}
|
|
23396
|
+
roleHost.setActiveTools([...COLLECTOR_REQUIRED_TOOLS]);
|
|
23397
|
+
const active = new Set(roleHost.getActiveTools());
|
|
23398
|
+
for (const required of COLLECTOR_REQUIRED_TOOLS) {
|
|
23399
|
+
if (!active.has(required)) {
|
|
23400
|
+
throw new Error(`Collector failed to activate required tool ${required}`);
|
|
23401
|
+
}
|
|
23402
|
+
}
|
|
23403
|
+
for (const name of active) {
|
|
23404
|
+
if (!COLLECTOR_REQUIRED_TOOLS.includes(name)) {
|
|
23405
|
+
throw new Error(`Collector active tool surface includes unexpected ${name}`);
|
|
23406
|
+
}
|
|
23407
|
+
}
|
|
23408
|
+
if (!collectorToolCallRegistered) {
|
|
23409
|
+
collectorToolCallRegistered = true;
|
|
23410
|
+
roleHost.on("tool_call", (toolEvent) => {
|
|
23411
|
+
if (activeCollector === void 0 || selectedRole !== "collector") return;
|
|
23412
|
+
if (!COLLECTOR_REQUIRED_TOOLS.includes(toolEvent.toolName)) {
|
|
23413
|
+
return {
|
|
23414
|
+
block: true,
|
|
23415
|
+
reason: `\u901A\u8FDB\u53F8\u7981\u7528\u5DE5\u5177 ${toolEvent.toolName}`
|
|
23416
|
+
};
|
|
23417
|
+
}
|
|
23418
|
+
return collectorBusiness.onToolCall(activeCollector, toolEvent);
|
|
23419
|
+
});
|
|
23420
|
+
}
|
|
23421
|
+
const activation = await collectorBusiness.activate(context);
|
|
23422
|
+
if (activation.ledger.activationRecorded) {
|
|
23423
|
+
collectorFirstDispatchDone = true;
|
|
23424
|
+
}
|
|
23425
|
+
activeCollector = activation;
|
|
23426
|
+
}
|
|
23427
|
+
};
|
|
22781
23428
|
const clock = dependencies.activationClock ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
22782
23429
|
const writeTrace = dependencies.activationTraceWriter ?? writeActivationTraceRecord;
|
|
22783
23430
|
const observationFace = createToolExecutionObservationFace({
|
|
@@ -25050,7 +25697,6 @@ ${priorNativePaths.join("\n")}` : prepared.prompt;
|
|
|
25050
25697
|
}
|
|
25051
25698
|
|
|
25052
25699
|
// src/acp-host/role-envelope.ts
|
|
25053
|
-
init_submission_errors();
|
|
25054
25700
|
init_submission_correctable_error();
|
|
25055
25701
|
init_navigator_invocation_identity();
|
|
25056
25702
|
function parseCanonicalSkillInvocation(prompt) {
|
|
@@ -25096,7 +25742,7 @@ function projectAcpActivationFlags(request) {
|
|
|
25096
25742
|
}
|
|
25097
25743
|
if (activation.role === "collector") {
|
|
25098
25744
|
flags.set("ak-collector-repo", activation.repo);
|
|
25099
|
-
flags.set("ak-collector-pr", activation.pr);
|
|
25745
|
+
if (activation.pr !== void 0) flags.set("ak-collector-pr", activation.pr);
|
|
25100
25746
|
if (activation.requestManifestPath !== void 0) flags.set("ak-collector-request-manifest", activation.requestManifestPath);
|
|
25101
25747
|
}
|
|
25102
25748
|
return flags;
|
|
@@ -25438,17 +26084,9 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25438
26084
|
let content;
|
|
25439
26085
|
let details;
|
|
25440
26086
|
if (isCorrectableExecuteError(error)) {
|
|
25441
|
-
const
|
|
25442
|
-
content = [{ type: "text", text: diagnostic }];
|
|
25443
|
-
|
|
25444
|
-
details = { ...error.result };
|
|
25445
|
-
} else if (error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError) {
|
|
25446
|
-
details = { code: error.code };
|
|
25447
|
-
} else if (typeof error.code === "string") {
|
|
25448
|
-
details = { code: error.code };
|
|
25449
|
-
} else {
|
|
25450
|
-
details = { code: error instanceof Error && error.name ? error.name : "correctable-submission-error" };
|
|
25451
|
-
}
|
|
26087
|
+
const projected2 = projectCorrectableExecuteRejection(error);
|
|
26088
|
+
content = [{ type: "text", text: projected2.diagnostic }];
|
|
26089
|
+
details = projected2.details;
|
|
25452
26090
|
} else {
|
|
25453
26091
|
({ content, details } = declareRoundInfrastructureFailure(error));
|
|
25454
26092
|
}
|