@akagilnc/pi-workflow-roles 0.1.3758 → 0.1.3783
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 +1735 -948
- 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/headless-host/description.js +77 -0
- package/dist/headless-host/mcp-relay.mjs +119 -0
- package/dist/headless-host/production-host.js +26590 -0
- package/dist/host-descriptions.js +44 -3
- 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/load-production-external-host.js +19 -0
- package/dist/public-cli/load-production-headless-host.js +36 -0
- package/dist/public-cli/main.js +857 -310
- 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/public-role-summons.js +40 -5
- 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/scripts/build-package.mjs +28 -0
- package/src/acp-host/role-envelope.ts +146 -103
- package/src/acp-host/role-turn-host.ts +12 -0
- 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/headless-host/description.ts +123 -0
- package/src/headless-host/production-host.ts +75 -0
- package/src/headless-host/role-turn-host.ts +424 -0
- package/src/host-contracts.ts +2 -1
- package/src/host-descriptions.ts +53 -6
- 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 +12 -3
- 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/load-production-external-host.ts +29 -0
- package/src/public-cli/load-production-headless-host.ts +48 -0
- package/src/public-cli/main.ts +5 -0
- 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/public-role-summons.ts +62 -9
- 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,72 +7553,57 @@ 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(
|
|
7167
7574
|
"collector requires a github.com origin remote or an explicit --repo owner/repo"
|
|
7168
|
-
);
|
|
7169
|
-
}
|
|
7170
|
-
const ownerRepo = ownerRepoFromGitHubRemoteUrl(remoteUrl);
|
|
7171
|
-
if (ownerRepo === void 0) {
|
|
7172
|
-
throw new CliUsageError(
|
|
7173
|
-
`collector origin remote must be a github.com owner/repo URL, got ${remoteUrl}`
|
|
7174
|
-
);
|
|
7175
|
-
}
|
|
7176
|
-
try {
|
|
7177
|
-
return parseCollectorRepository(ownerRepo);
|
|
7178
|
-
} catch (error) {
|
|
7179
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
7180
|
-
throw new CliUsageError(detail, { cause: error });
|
|
7181
|
-
}
|
|
7182
|
-
}
|
|
7183
|
-
function ownerRepoFromGitHubRemoteUrl(remoteUrl) {
|
|
7184
|
-
const trimmed = remoteUrl.trim();
|
|
7185
|
-
const scp = /^git@github\.com:([^/\s]+)\/([^/\s]+?)(?:\.git)?$/i.exec(trimmed);
|
|
7186
|
-
if (scp) {
|
|
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])}`;
|
|
7575
|
+
);
|
|
7576
|
+
}
|
|
7577
|
+
const ownerRepo = ownerRepoFromGitHubRemoteUrl(remoteUrl);
|
|
7578
|
+
if (ownerRepo === void 0) {
|
|
7579
|
+
throw new CliUsageError(
|
|
7580
|
+
`collector origin remote must be a github.com owner/repo URL, got ${remoteUrl}`
|
|
7581
|
+
);
|
|
7194
7582
|
}
|
|
7195
|
-
let parsed;
|
|
7196
7583
|
try {
|
|
7197
|
-
|
|
7198
|
-
} catch {
|
|
7199
|
-
|
|
7584
|
+
return parseCollectorRepository(ownerRepo);
|
|
7585
|
+
} catch (error) {
|
|
7586
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
7587
|
+
throw new CliUsageError(detail, { cause: error });
|
|
7200
7588
|
}
|
|
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
7589
|
}
|
|
7207
|
-
function
|
|
7208
|
-
|
|
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();
|
|
@@ -8361,24 +8756,35 @@ var init_invocation = __esm({
|
|
|
8361
8756
|
var host_descriptions_exports = {};
|
|
8362
8757
|
__export(host_descriptions_exports, {
|
|
8363
8758
|
DEFAULT_ROLE_TURN_HOST: () => DEFAULT_ROLE_TURN_HOST,
|
|
8759
|
+
HEADLESS_HOST_DESCRIPTIONS: () => HEADLESS_HOST_DESCRIPTIONS,
|
|
8364
8760
|
HOST_DESCRIPTIONS: () => HOST_DESCRIPTIONS,
|
|
8365
8761
|
assertRegisteredHostName: () => assertRegisteredHostName,
|
|
8762
|
+
lookupHeadlessHostDescription: () => lookupHeadlessHostDescription,
|
|
8366
8763
|
lookupHostDescription: () => lookupHostDescription,
|
|
8764
|
+
lookupHostFamily: () => lookupHostFamily,
|
|
8367
8765
|
packagedExternalHostNames: () => packagedExternalHostNames
|
|
8368
8766
|
});
|
|
8369
8767
|
function lookupHostDescription(host) {
|
|
8370
8768
|
return Object.hasOwn(HOST_DESCRIPTIONS, host) ? HOST_DESCRIPTIONS[host] : void 0;
|
|
8371
8769
|
}
|
|
8770
|
+
function lookupHeadlessHostDescription(host) {
|
|
8771
|
+
return Object.hasOwn(HEADLESS_HOST_DESCRIPTIONS, host) ? HEADLESS_HOST_DESCRIPTIONS[host] : void 0;
|
|
8772
|
+
}
|
|
8773
|
+
function lookupHostFamily(host) {
|
|
8774
|
+
if (lookupHostDescription(host) !== void 0) return "acp";
|
|
8775
|
+
if (lookupHeadlessHostDescription(host) !== void 0) return "headless";
|
|
8776
|
+
return void 0;
|
|
8777
|
+
}
|
|
8372
8778
|
function packagedExternalHostNames() {
|
|
8373
|
-
return Object.keys(HOST_DESCRIPTIONS);
|
|
8779
|
+
return [...Object.keys(HOST_DESCRIPTIONS), ...Object.keys(HEADLESS_HOST_DESCRIPTIONS)];
|
|
8374
8780
|
}
|
|
8375
8781
|
function assertRegisteredHostName(host) {
|
|
8376
|
-
if (host === DEFAULT_ROLE_TURN_HOST ||
|
|
8782
|
+
if (host === DEFAULT_ROLE_TURN_HOST || lookupHostFamily(host) !== void 0) {
|
|
8377
8783
|
return host;
|
|
8378
8784
|
}
|
|
8379
8785
|
throw new Error(`unregistered host: ${host}`);
|
|
8380
8786
|
}
|
|
8381
|
-
var PRIVATE_COMPAT_ENV, DEFAULT_ROLE_TURN_HOST, HOST_DESCRIPTIONS;
|
|
8787
|
+
var PRIVATE_COMPAT_ENV, DEFAULT_ROLE_TURN_HOST, HOST_DESCRIPTIONS, HEADLESS_HOST_DESCRIPTIONS;
|
|
8382
8788
|
var init_host_descriptions = __esm({
|
|
8383
8789
|
"src/host-descriptions.ts"() {
|
|
8384
8790
|
"use strict";
|
|
@@ -8430,14 +8836,37 @@ var init_host_descriptions = __esm({
|
|
|
8430
8836
|
})
|
|
8431
8837
|
})
|
|
8432
8838
|
});
|
|
8839
|
+
HEADLESS_HOST_DESCRIPTIONS = Object.freeze({
|
|
8840
|
+
"claude": Object.freeze({
|
|
8841
|
+
binaryFromHome: Object.freeze([".local", "bin", "claude"]),
|
|
8842
|
+
sessionBindingFile: "claude-headless-session.json",
|
|
8843
|
+
fixedArgs: Object.freeze([
|
|
8844
|
+
// One result envelope (not stream-json): typed receipt only; no event-stream copy.
|
|
8845
|
+
"--output-format",
|
|
8846
|
+
"json",
|
|
8847
|
+
"--permission-mode",
|
|
8848
|
+
"bypassPermissions",
|
|
8849
|
+
// Empty sources: no user/project/local operator surface (envelope owns materials).
|
|
8850
|
+
"--setting-sources",
|
|
8851
|
+
"",
|
|
8852
|
+
// With adapter-supplied --mcp-config only (AK relay); drops operator + claude.ai MCP.
|
|
8853
|
+
"--strict-mcp-config"
|
|
8854
|
+
]),
|
|
8855
|
+
promptFlag: "-p",
|
|
8856
|
+
modelFlag: "--model",
|
|
8857
|
+
effortFlag: "--effort",
|
|
8858
|
+
// File path keeps large role envelopes off ARG_MAX.
|
|
8859
|
+
systemPromptFlag: "--system-prompt-file",
|
|
8860
|
+
jsonSchemaFlag: "--json-schema",
|
|
8861
|
+
mcpConfigFlag: "--mcp-config",
|
|
8862
|
+
sessionIdFlag: "--session-id",
|
|
8863
|
+
resumeFlag: "--resume"
|
|
8864
|
+
})
|
|
8865
|
+
});
|
|
8433
8866
|
}
|
|
8434
8867
|
});
|
|
8435
8868
|
|
|
8436
8869
|
// src/public-cli/load-production-acp-host.ts
|
|
8437
|
-
var load_production_acp_host_exports = {};
|
|
8438
|
-
__export(load_production_acp_host_exports, {
|
|
8439
|
-
loadProductionAcpHostFactory: () => loadProductionAcpHostFactory
|
|
8440
|
-
});
|
|
8441
8870
|
import { existsSync as existsSync5 } from "node:fs";
|
|
8442
8871
|
import { join as join14 } from "node:path";
|
|
8443
8872
|
import { pathToFileURL } from "node:url";
|
|
@@ -8461,6 +8890,54 @@ var init_load_production_acp_host = __esm({
|
|
|
8461
8890
|
}
|
|
8462
8891
|
});
|
|
8463
8892
|
|
|
8893
|
+
// src/public-cli/load-production-headless-host.ts
|
|
8894
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
8895
|
+
import { join as join15 } from "node:path";
|
|
8896
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
8897
|
+
async function loadProductionHeadlessHostFactory(packageRoot, host) {
|
|
8898
|
+
const description = lookupHeadlessHostDescription(host);
|
|
8899
|
+
if (description === void 0) {
|
|
8900
|
+
throw new Error(`unregistered headless host: ${host}`);
|
|
8901
|
+
}
|
|
8902
|
+
const built = join15(packageRoot, "dist/headless-host/production-host.js");
|
|
8903
|
+
const source = join15(packageRoot, "src/headless-host/production-host.ts");
|
|
8904
|
+
const target = existsSync6(built) ? built : source;
|
|
8905
|
+
const href = pathToFileURL2(target).href;
|
|
8906
|
+
const mod = await import(href);
|
|
8907
|
+
const create = mod.createProductionHeadlessRoleTurnHost;
|
|
8908
|
+
return (options) => create({ ...options, description });
|
|
8909
|
+
}
|
|
8910
|
+
var init_load_production_headless_host = __esm({
|
|
8911
|
+
"src/public-cli/load-production-headless-host.ts"() {
|
|
8912
|
+
"use strict";
|
|
8913
|
+
init_host_descriptions();
|
|
8914
|
+
}
|
|
8915
|
+
});
|
|
8916
|
+
|
|
8917
|
+
// src/public-cli/load-production-external-host.ts
|
|
8918
|
+
var load_production_external_host_exports = {};
|
|
8919
|
+
__export(load_production_external_host_exports, {
|
|
8920
|
+
loadProductionExternalHostFactory: () => loadProductionExternalHostFactory
|
|
8921
|
+
});
|
|
8922
|
+
async function loadProductionExternalHostFactory(packageRoot, host) {
|
|
8923
|
+
const family = lookupHostFamily(host);
|
|
8924
|
+
if (family === "acp") {
|
|
8925
|
+
return loadProductionAcpHostFactory(packageRoot, host);
|
|
8926
|
+
}
|
|
8927
|
+
if (family === "headless") {
|
|
8928
|
+
return loadProductionHeadlessHostFactory(packageRoot, host);
|
|
8929
|
+
}
|
|
8930
|
+
throw new Error(`unregistered host: ${host}`);
|
|
8931
|
+
}
|
|
8932
|
+
var init_load_production_external_host = __esm({
|
|
8933
|
+
"src/public-cli/load-production-external-host.ts"() {
|
|
8934
|
+
"use strict";
|
|
8935
|
+
init_host_descriptions();
|
|
8936
|
+
init_load_production_acp_host();
|
|
8937
|
+
init_load_production_headless_host();
|
|
8938
|
+
}
|
|
8939
|
+
});
|
|
8940
|
+
|
|
8464
8941
|
// src/public-cli/host-providers.ts
|
|
8465
8942
|
var host_providers_exports = {};
|
|
8466
8943
|
__export(host_providers_exports, {
|
|
@@ -8475,15 +8952,15 @@ __export(host_providers_exports, {
|
|
|
8475
8952
|
renderHostProvidersTable: () => renderHostProvidersTable
|
|
8476
8953
|
});
|
|
8477
8954
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
8478
|
-
import { join as
|
|
8955
|
+
import { join as join16 } from "node:path";
|
|
8479
8956
|
function hostProvidersPath(home) {
|
|
8480
8957
|
if (typeof home !== "string" || home.trim() === "") {
|
|
8481
8958
|
throw new Error("home must be explicitly provided");
|
|
8482
8959
|
}
|
|
8483
|
-
return
|
|
8960
|
+
return join16(home, ".ak-roles", "host-providers.json");
|
|
8484
8961
|
}
|
|
8485
8962
|
function hermesProviderModelsCachePath(home) {
|
|
8486
|
-
return
|
|
8963
|
+
return join16(home, ".hermes", "provider_models_cache.json");
|
|
8487
8964
|
}
|
|
8488
8965
|
function parseHostProvidersTable(value) {
|
|
8489
8966
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -9050,7 +9527,7 @@ __export(config_exports, {
|
|
|
9050
9527
|
validatePublicCliConfigAxes: () => validatePublicCliConfigAxes
|
|
9051
9528
|
});
|
|
9052
9529
|
import { mkdir as mkdir2, readFile as readFile10, writeFile as writeFile5 } from "node:fs/promises";
|
|
9053
|
-
import { dirname as dirname8, join as
|
|
9530
|
+
import { dirname as dirname8, join as join17 } from "node:path";
|
|
9054
9531
|
function isGateOfficerSeat(value) {
|
|
9055
9532
|
return GATE_OFFICER_SEATS.includes(value);
|
|
9056
9533
|
}
|
|
@@ -9058,7 +9535,7 @@ function publicCliConfigPath(home) {
|
|
|
9058
9535
|
if (typeof home !== "string" || home.trim() === "") {
|
|
9059
9536
|
throw new Error("home must be explicitly provided");
|
|
9060
9537
|
}
|
|
9061
|
-
return
|
|
9538
|
+
return join17(home, ".ak-roles", "public-cli.json");
|
|
9062
9539
|
}
|
|
9063
9540
|
async function loadPublicCliConfig(home) {
|
|
9064
9541
|
const path = publicCliConfigPath(home);
|
|
@@ -9467,7 +9944,7 @@ function credentialProvidersFromAuthData(data) {
|
|
|
9467
9944
|
}
|
|
9468
9945
|
async function loadCredentialProviders(agentDir) {
|
|
9469
9946
|
try {
|
|
9470
|
-
const raw = await readFile10(
|
|
9947
|
+
const raw = await readFile10(join17(agentDir, "auth.json"), "utf8");
|
|
9471
9948
|
return credentialProvidersFromAuthData(JSON.parse(raw));
|
|
9472
9949
|
} catch (error) {
|
|
9473
9950
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -9609,7 +10086,7 @@ var init_ticket_provenance_contracts = __esm({
|
|
|
9609
10086
|
// src/ticket-provenance.ts
|
|
9610
10087
|
import { createHash as createHash5 } from "node:crypto";
|
|
9611
10088
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
9612
|
-
import { join as
|
|
10089
|
+
import { join as join18 } from "node:path";
|
|
9613
10090
|
function ticketProvenanceSubject(ticketNumber) {
|
|
9614
10091
|
if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
|
|
9615
10092
|
throw new Error(`ticket-provenance subject requires a positive ticket number, got ${String(ticketNumber)}`);
|
|
@@ -9667,7 +10144,7 @@ function resolveTicketProvenanceVolume(ticketNumber, cwd, home) {
|
|
|
9667
10144
|
return {
|
|
9668
10145
|
recordFile: path.recordFile,
|
|
9669
10146
|
volumeDir: path.sessionDir,
|
|
9670
|
-
humanViewFile:
|
|
10147
|
+
humanViewFile: join18(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW)
|
|
9671
10148
|
};
|
|
9672
10149
|
}
|
|
9673
10150
|
async function readTicketProvenance(ticketNumber, cwd, home) {
|
|
@@ -9811,7 +10288,7 @@ var init_case_dossier_delivery = __esm({
|
|
|
9811
10288
|
|
|
9812
10289
|
// src/host-transition-prior-native.ts
|
|
9813
10290
|
import { access as access2, readdir as readdir3 } from "node:fs/promises";
|
|
9814
|
-
import { dirname as dirname9, join as
|
|
10291
|
+
import { dirname as dirname9, join as join19 } from "node:path";
|
|
9815
10292
|
function isEnoent2(error) {
|
|
9816
10293
|
return typeof error === "object" && error !== null && error.code === "ENOENT";
|
|
9817
10294
|
}
|
|
@@ -9836,7 +10313,7 @@ async function listSitianRecordPaths(sessionParent) {
|
|
|
9836
10313
|
const recordPaths = [];
|
|
9837
10314
|
for (const entry of entries) {
|
|
9838
10315
|
if (!entry.isDirectory()) continue;
|
|
9839
|
-
const recordFile =
|
|
10316
|
+
const recordFile = join19(sessionRoot, entry.name, "records.jsonl");
|
|
9840
10317
|
try {
|
|
9841
10318
|
await access2(recordFile);
|
|
9842
10319
|
recordPaths.push(recordFile);
|
|
@@ -9903,7 +10380,7 @@ var init_public_run_credentials = __esm({
|
|
|
9903
10380
|
});
|
|
9904
10381
|
|
|
9905
10382
|
// src/run-terminal-artifacts.ts
|
|
9906
|
-
import { basename as basename6, dirname as dirname10, join as
|
|
10383
|
+
import { basename as basename6, dirname as dirname10, join as join20 } from "node:path";
|
|
9907
10384
|
function runIdFromRunDirectory(runDirectory) {
|
|
9908
10385
|
const name = basename6(runDirectory);
|
|
9909
10386
|
const at = name.lastIndexOf("@");
|
|
@@ -10307,7 +10784,7 @@ var init_ledger_session_read = __esm({
|
|
|
10307
10784
|
|
|
10308
10785
|
// src/analyst-gate-cycles-read.ts
|
|
10309
10786
|
import { readdir as readdir4 } from "node:fs/promises";
|
|
10310
|
-
import { join as
|
|
10787
|
+
import { join as join21 } from "node:path";
|
|
10311
10788
|
function isRecord13(value) {
|
|
10312
10789
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10313
10790
|
}
|
|
@@ -10569,7 +11046,7 @@ async function readAnalystGateCyclesFromAuditorRoles(auditorRolesDirectory, opti
|
|
|
10569
11046
|
throw error;
|
|
10570
11047
|
}
|
|
10571
11048
|
for (const name of names) {
|
|
10572
|
-
const path =
|
|
11049
|
+
const path = join21(directory, name);
|
|
10573
11050
|
const fromPointer = name.endsWith(".pointer.json");
|
|
10574
11051
|
const sessionPath = fromPointer ? await resolveOfficerSessionFromPointerFile(path) : path;
|
|
10575
11052
|
if (sessionPath === void 0) continue;
|
|
@@ -10611,14 +11088,14 @@ var init_analyst_gate_cycles_read = __esm({
|
|
|
10611
11088
|
});
|
|
10612
11089
|
|
|
10613
11090
|
// src/session-opening-materials.ts
|
|
10614
|
-
import { existsSync as
|
|
11091
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
10615
11092
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
10616
|
-
import { dirname as dirname11, join as
|
|
10617
|
-
import { fileURLToPath, pathToFileURL as
|
|
11093
|
+
import { dirname as dirname11, join as join22 } from "node:path";
|
|
11094
|
+
import { fileURLToPath, pathToFileURL as pathToFileURL3 } from "node:url";
|
|
10618
11095
|
function resolvePackageRootDir(moduleUrl = import.meta.url) {
|
|
10619
11096
|
let dir = dirname11(fileURLToPath(moduleUrl));
|
|
10620
11097
|
for (let i = 0; i < 8; i += 1) {
|
|
10621
|
-
if (
|
|
11098
|
+
if (existsSync7(join22(dir, "package.json")) && existsSync7(join22(dir, "souls"))) {
|
|
10622
11099
|
return dir;
|
|
10623
11100
|
}
|
|
10624
11101
|
const parent = dirname11(dir);
|
|
@@ -10648,7 +11125,7 @@ var init_session_opening_materials = __esm({
|
|
|
10648
11125
|
"src/session-opening-materials.ts"() {
|
|
10649
11126
|
"use strict";
|
|
10650
11127
|
init_packaged_role_registry();
|
|
10651
|
-
packageRootUrl =
|
|
11128
|
+
packageRootUrl = pathToFileURL3(resolvePackageRootDir() + "/").href;
|
|
10652
11129
|
MAIN_ROLE_SESSION_MATERIALS = {
|
|
10653
11130
|
...Object.fromEntries(
|
|
10654
11131
|
PUBLIC_ROLE_RECORDS.map((record4) => [record4.role, record4.sessionMaterials])
|
|
@@ -10924,19 +11401,19 @@ function branchNamesAtPinnedHead(pin) {
|
|
|
10924
11401
|
}
|
|
10925
11402
|
return Object.freeze([...names]);
|
|
10926
11403
|
}
|
|
10927
|
-
async function
|
|
11404
|
+
async function gitText2(root, args) {
|
|
10928
11405
|
const { stdout } = await execGit(["-C", root, ...args], { encoding: "utf8" });
|
|
10929
11406
|
return stdout.trim();
|
|
10930
11407
|
}
|
|
10931
11408
|
async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
10932
|
-
const discoveredRoot = await
|
|
11409
|
+
const discoveredRoot = await gitText2(root, ["rev-parse", "--show-toplevel"]);
|
|
10933
11410
|
const repositoryRoot = await realpath6(discoveredRoot);
|
|
10934
|
-
const objectFormat = await
|
|
11411
|
+
const objectFormat = await gitText2(repositoryRoot, ["rev-parse", "--show-object-format"]);
|
|
10935
11412
|
if (objectFormat !== "sha1" && objectFormat !== "sha256") throw new Error("Unsupported Git object format");
|
|
10936
11413
|
const oidWidth = objectFormat === "sha1" ? 40 : 64;
|
|
10937
|
-
const targetHead = await
|
|
10938
|
-
const reachableCommitIds = Object.freeze((await
|
|
10939
|
-
const refs = parseReviewerRefSnapshot(await
|
|
11414
|
+
const targetHead = await gitText2(repositoryRoot, ["rev-parse", "HEAD^{commit}"]);
|
|
11415
|
+
const reachableCommitIds = Object.freeze((await gitText2(repositoryRoot, ["rev-list", targetHead])).split("\n").filter(Boolean));
|
|
11416
|
+
const refs = parseReviewerRefSnapshot(await gitText2(repositoryRoot, reviewerRefSnapshotArgs()));
|
|
10940
11417
|
const pin = immutableReviewerPin({ repositoryRoot, objectFormat, targetHead, refs });
|
|
10941
11418
|
const invalid = (code, diagnostic, cause) => {
|
|
10942
11419
|
throw new ReviewerCorrectablePreflightError(code, diagnostic, cause === void 0 ? void 0 : { cause });
|
|
@@ -10955,9 +11432,9 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
10955
11432
|
return Object.freeze({
|
|
10956
11433
|
pin,
|
|
10957
11434
|
async snapshot() {
|
|
10958
|
-
const liveObjectFormat = await
|
|
11435
|
+
const liveObjectFormat = await gitText2(repositoryRoot, ["rev-parse", "--show-object-format"]);
|
|
10959
11436
|
if (liveObjectFormat !== "sha1" && liveObjectFormat !== "sha256") throw new Error("Unsupported Git object format");
|
|
10960
|
-
return immutableReviewerPin({ repositoryRoot, objectFormat: liveObjectFormat, targetHead: await
|
|
11437
|
+
return immutableReviewerPin({ repositoryRoot, objectFormat: liveObjectFormat, targetHead: await gitText2(repositoryRoot, ["rev-parse", "HEAD^{commit}"]), refs: parseReviewerRefSnapshot(await gitText2(repositoryRoot, reviewerRefSnapshotArgs())) });
|
|
10961
11438
|
},
|
|
10962
11439
|
async resolve(base) {
|
|
10963
11440
|
if (!/^[A-Za-z0-9._/~^+-]+$/.test(base) || base.startsWith("-") || base.includes("..") || base.includes("@{")) {
|
|
@@ -10967,7 +11444,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
10967
11444
|
const headExpression = /^HEAD((?:~[0-9]+|\^[0-9]+)*)$/.exec(base);
|
|
10968
11445
|
if (headExpression) {
|
|
10969
11446
|
try {
|
|
10970
|
-
commit = await
|
|
11447
|
+
commit = await gitText2(repositoryRoot, ["rev-parse", "--verify", `${targetHead}${headExpression[1]}^{commit}`]);
|
|
10971
11448
|
} catch (error) {
|
|
10972
11449
|
if (exitCode(error) === 128) {
|
|
10973
11450
|
const repository = await repositoryIsAvailable(repositoryRoot);
|
|
@@ -10983,7 +11460,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
10983
11460
|
} else commit = symbolic(base);
|
|
10984
11461
|
if (commit === void 0) invalid("base-invalid", "base revision must name an existing pinned ref or reachable commit");
|
|
10985
11462
|
try {
|
|
10986
|
-
commit = await
|
|
11463
|
+
commit = await gitText2(repositoryRoot, ["rev-parse", "--verify", `${commit}^{commit}`]);
|
|
10987
11464
|
} catch (error) {
|
|
10988
11465
|
if (exitCode(error) === 128) {
|
|
10989
11466
|
const repository = await repositoryIsAvailable(repositoryRoot);
|
|
@@ -10992,7 +11469,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
10992
11469
|
throw error;
|
|
10993
11470
|
}
|
|
10994
11471
|
try {
|
|
10995
|
-
await
|
|
11472
|
+
await gitText2(repositoryRoot, ["merge-base", "--is-ancestor", commit, targetHead]);
|
|
10996
11473
|
} catch (error) {
|
|
10997
11474
|
if (exitCode(error) === 1) invalid("base-invalid", "base revision must be an ancestor of the pinned target", error);
|
|
10998
11475
|
throw error;
|
|
@@ -11002,7 +11479,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11002
11479
|
async range(base) {
|
|
11003
11480
|
let mergeBase;
|
|
11004
11481
|
try {
|
|
11005
|
-
mergeBase = await
|
|
11482
|
+
mergeBase = await gitText2(repositoryRoot, ["merge-base", base, targetHead]);
|
|
11006
11483
|
} catch (error) {
|
|
11007
11484
|
if (exitCode(error) === 1) {
|
|
11008
11485
|
invalid("range-invalid", "review range requires a common ancestor for base and pinned target", error);
|
|
@@ -11013,7 +11490,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11013
11490
|
const diffCommand = `git diff ${mergeBase}...${targetHead}`;
|
|
11014
11491
|
const [{ stdout: diff }, commitsText] = await Promise.all([
|
|
11015
11492
|
execGit(["-C", repositoryRoot, "diff", `${mergeBase}...${targetHead}`], { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 }),
|
|
11016
|
-
|
|
11493
|
+
gitText2(repositoryRoot, ["rev-list", "--reverse", `${mergeBase}..${targetHead}`])
|
|
11017
11494
|
]);
|
|
11018
11495
|
if (diff.length === 0) invalid("range-invalid", "review range must contain a non-empty diff between base and pinned target");
|
|
11019
11496
|
return Object.freeze({ base: mergeBase, target: targetHead, diffCommand, diffSha256: sha256Hex(Uint8Array.from(diff)), commits: Object.freeze(commitsText ? commitsText.split("\n") : []) });
|
|
@@ -11029,7 +11506,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11029
11506
|
},
|
|
11030
11507
|
async listSpecCandidatePaths() {
|
|
11031
11508
|
const roots = ["docs", "specs", ".scratch"];
|
|
11032
|
-
const text = await
|
|
11509
|
+
const text = await gitText2(repositoryRoot, [
|
|
11033
11510
|
"ls-tree",
|
|
11034
11511
|
"-r",
|
|
11035
11512
|
"--name-only",
|
|
@@ -11042,7 +11519,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11042
11519
|
async originRepository() {
|
|
11043
11520
|
let remoteUrl;
|
|
11044
11521
|
try {
|
|
11045
|
-
remoteUrl = await
|
|
11522
|
+
remoteUrl = await gitText2(repositoryRoot, ["remote", "get-url", "origin"]);
|
|
11046
11523
|
} catch (error) {
|
|
11047
11524
|
if (isConfirmedMissingOriginRemote(error)) return void 0;
|
|
11048
11525
|
throw error;
|
|
@@ -11050,7 +11527,7 @@ async function createReviewerPinnedGitReader(root = process.cwd()) {
|
|
|
11050
11527
|
return parseGitHubOriginRemote(remoteUrl);
|
|
11051
11528
|
},
|
|
11052
11529
|
async commitMessagesNewestFirst(base) {
|
|
11053
|
-
const text = await
|
|
11530
|
+
const text = await gitText2(repositoryRoot, [
|
|
11054
11531
|
"log",
|
|
11055
11532
|
"--format=%s",
|
|
11056
11533
|
`${base}..${targetHead}`
|
|
@@ -11490,12 +11967,12 @@ var init_reviewer_dispatch = __esm({
|
|
|
11490
11967
|
// src/public-cli/reviewer-dispatch-rejection.ts
|
|
11491
11968
|
import { writeFileSync as writeFileSync4 } from "node:fs";
|
|
11492
11969
|
import { readFile as readFile13, unlink as unlink3 } from "node:fs/promises";
|
|
11493
|
-
import { join as
|
|
11970
|
+
import { join as join23 } from "node:path";
|
|
11494
11971
|
function isReviewerPreflightViolation(value) {
|
|
11495
11972
|
return typeof value === "string" && REVIEWER_PREFLIGHT_VIOLATIONS.includes(value);
|
|
11496
11973
|
}
|
|
11497
11974
|
function reviewerDispatchRejectionPath(runDirectory) {
|
|
11498
|
-
return
|
|
11975
|
+
return join23(runDirectory, REVIEWER_DISPATCH_REJECTION_FILE);
|
|
11499
11976
|
}
|
|
11500
11977
|
function recordReviewerDispatchRejectionSync(runDirectory, rejection) {
|
|
11501
11978
|
writeFileSync4(
|
|
@@ -11835,13 +12312,206 @@ var init_collector_evidence = __esm({
|
|
|
11835
12312
|
}
|
|
11836
12313
|
});
|
|
11837
12314
|
|
|
12315
|
+
// src/collector-identity.ts
|
|
12316
|
+
function identityKey(identity) {
|
|
12317
|
+
if (identity === null) return "unassigned";
|
|
12318
|
+
return String(identity.userId);
|
|
12319
|
+
}
|
|
12320
|
+
function mergeMachineIdentity(current, observed) {
|
|
12321
|
+
if (current === null) return observed;
|
|
12322
|
+
if (observed === null) return current;
|
|
12323
|
+
if (current.appId === void 0 && observed.appId !== void 0) return observed;
|
|
12324
|
+
if (current.appId !== void 0 && observed.appId === void 0) return current;
|
|
12325
|
+
return observed.userType < current.userType ? observed : current;
|
|
12326
|
+
}
|
|
12327
|
+
function headRelationFor(record4, targetHead) {
|
|
12328
|
+
return record4.commitOid === void 0 || record4.commitOid === null ? "unbound" : record4.commitOid === targetHead ? "current" : "prior";
|
|
12329
|
+
}
|
|
12330
|
+
function extractCollectorEvidenceIdentityGroups(records2, targetHead) {
|
|
12331
|
+
const groups = /* @__PURE__ */ new Map();
|
|
12332
|
+
for (const record4 of records2) {
|
|
12333
|
+
if (record4.kind !== "review" && record4.kind !== "issue_comment" && record4.kind !== "review_comment" && record4.kind !== "reaction") continue;
|
|
12334
|
+
if (record4.githubId === void 0) continue;
|
|
12335
|
+
const identity = record4.machineIdentity ?? null;
|
|
12336
|
+
const kind = record4.kind;
|
|
12337
|
+
const source = {
|
|
12338
|
+
kind,
|
|
12339
|
+
id: record4.githubId,
|
|
12340
|
+
evidenceId: record4.evidenceId,
|
|
12341
|
+
headRelation: headRelationFor(record4, targetHead)
|
|
12342
|
+
};
|
|
12343
|
+
const key = identityKey(identity);
|
|
12344
|
+
let group = groups.get(key);
|
|
12345
|
+
if (group === void 0) {
|
|
12346
|
+
group = {
|
|
12347
|
+
identity,
|
|
12348
|
+
...record4.authorLogin === void 0 ? {} : { displayLogin: record4.authorLogin },
|
|
12349
|
+
attendance: true,
|
|
12350
|
+
findings: [],
|
|
12351
|
+
materials: []
|
|
12352
|
+
};
|
|
12353
|
+
groups.set(key, group);
|
|
12354
|
+
} else {
|
|
12355
|
+
group.identity = mergeMachineIdentity(group.identity, identity);
|
|
12356
|
+
}
|
|
12357
|
+
group.materials.push(source);
|
|
12358
|
+
}
|
|
12359
|
+
return [...groups.values()];
|
|
12360
|
+
}
|
|
12361
|
+
function candidateRecord(candidate) {
|
|
12362
|
+
if (candidate === void 0 || candidate === null || typeof candidate !== "object" || Array.isArray(candidate)) {
|
|
12363
|
+
return void 0;
|
|
12364
|
+
}
|
|
12365
|
+
return candidate;
|
|
12366
|
+
}
|
|
12367
|
+
function hasNonCanonicalOwnKeys(record4) {
|
|
12368
|
+
for (const key of Object.keys(record4)) {
|
|
12369
|
+
if (!COLLECTOR_OUTPUT_CANONICAL_KEYS.has(key)) return true;
|
|
12370
|
+
}
|
|
12371
|
+
return false;
|
|
12372
|
+
}
|
|
12373
|
+
function enrichCollectorFindings(input) {
|
|
12374
|
+
if (input.candidate !== void 0 && input.candidate !== null && candidateRecord(input.candidate) === void 0) {
|
|
12375
|
+
return { findingsSource: "unreadable", findingsProjectedCount: 0, findingsUnprojected: true };
|
|
12376
|
+
}
|
|
12377
|
+
const record4 = candidateRecord(input.candidate);
|
|
12378
|
+
if (record4 === void 0) {
|
|
12379
|
+
return { findingsSource: "absent", findingsProjectedCount: 0, findingsUnprojected: false };
|
|
12380
|
+
}
|
|
12381
|
+
if (!Object.hasOwn(record4, "findings")) {
|
|
12382
|
+
if (hasNonCanonicalOwnKeys(record4)) {
|
|
12383
|
+
return { findingsSource: "unreadable", findingsProjectedCount: 0, findingsUnprojected: true };
|
|
12384
|
+
}
|
|
12385
|
+
return { findingsSource: "absent", findingsProjectedCount: 0, findingsUnprojected: false };
|
|
12386
|
+
}
|
|
12387
|
+
const rawFindings = record4["findings"];
|
|
12388
|
+
if (!Array.isArray(rawFindings)) {
|
|
12389
|
+
return { findingsSource: "unreadable", findingsProjectedCount: 0, findingsUnprojected: true };
|
|
12390
|
+
}
|
|
12391
|
+
const byEvidenceId = new Map(input.records.map((evidence) => [evidence.evidenceId, evidence]));
|
|
12392
|
+
let projected = 0;
|
|
12393
|
+
let unprojected = false;
|
|
12394
|
+
for (const raw of rawFindings) {
|
|
12395
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
12396
|
+
unprojected = true;
|
|
12397
|
+
continue;
|
|
12398
|
+
}
|
|
12399
|
+
const item = raw;
|
|
12400
|
+
const evidenceId = item.evidenceId;
|
|
12401
|
+
if (typeof evidenceId !== "string" || evidenceId.length === 0) {
|
|
12402
|
+
unprojected = true;
|
|
12403
|
+
continue;
|
|
12404
|
+
}
|
|
12405
|
+
const evidence = byEvidenceId.get(evidenceId);
|
|
12406
|
+
if (evidence === void 0) {
|
|
12407
|
+
throw new CollectorUnknownEvidenceError(evidenceId);
|
|
12408
|
+
}
|
|
12409
|
+
if (evidence.kind !== "review" && evidence.kind !== "issue_comment" && evidence.kind !== "review_comment") {
|
|
12410
|
+
throw new CollectorFindingsValidationError(`\u901A\u8FDB\u53F8 finding \u6307\u9488\u6307\u5411\u4E0D\u53EF\u627F finding \u7684\u8BC1\u636E\u79CD\u7C7B ${evidence.kind}`);
|
|
12411
|
+
}
|
|
12412
|
+
if (evidence.githubId === void 0) {
|
|
12413
|
+
throw new CollectorFindingsValidationError(`\u901A\u8FDB\u53F8 finding \u6307\u9488\u8BC1\u636E ${evidenceId} \u7F3A\u5C11 GitHub id`);
|
|
12414
|
+
}
|
|
12415
|
+
const identity = evidence.machineIdentity ?? null;
|
|
12416
|
+
const group = input.groups.find((candidateGroup) => identityKey(candidateGroup.identity) === identityKey(identity));
|
|
12417
|
+
if (group === void 0) {
|
|
12418
|
+
throw new CollectorFindingsValidationError(`\u901A\u8FDB\u53F8 finding \u6307\u9488\u8BC1\u636E ${evidenceId} \u65E0\u5F52\u5C5E\u8EAB\u4EFD\u7EC4`);
|
|
12419
|
+
}
|
|
12420
|
+
const category = item.category;
|
|
12421
|
+
const summary = item.summary;
|
|
12422
|
+
if (Object.hasOwn(item, "category") && typeof category !== "string") unprojected = true;
|
|
12423
|
+
if (Object.hasOwn(item, "summary") && typeof summary !== "string") unprojected = true;
|
|
12424
|
+
group.findings.push({
|
|
12425
|
+
identity,
|
|
12426
|
+
source: {
|
|
12427
|
+
kind: evidence.kind,
|
|
12428
|
+
id: evidence.githubId,
|
|
12429
|
+
evidenceId: evidence.evidenceId,
|
|
12430
|
+
headRelation: headRelationFor(evidence, input.targetHead)
|
|
12431
|
+
},
|
|
12432
|
+
...typeof category === "string" ? { category } : {},
|
|
12433
|
+
...typeof summary === "string" ? { summary } : {},
|
|
12434
|
+
pointer: {
|
|
12435
|
+
repository: input.repository,
|
|
12436
|
+
prNumber: input.prNumber,
|
|
12437
|
+
commentId: evidence.githubId,
|
|
12438
|
+
...evidence.htmlUrl === void 0 ? {} : { htmlUrl: evidence.htmlUrl },
|
|
12439
|
+
...evidence.authorLogin === void 0 ? {} : { authorLogin: evidence.authorLogin },
|
|
12440
|
+
kind: evidence.kind,
|
|
12441
|
+
authoritativeTime: evidence.authoritativeTime ?? null,
|
|
12442
|
+
...evidence.commitOid === void 0 ? {} : { commitOid: evidence.commitOid }
|
|
12443
|
+
}
|
|
12444
|
+
});
|
|
12445
|
+
projected += 1;
|
|
12446
|
+
}
|
|
12447
|
+
return {
|
|
12448
|
+
findingsSource: "array",
|
|
12449
|
+
findingsProjectedCount: projected,
|
|
12450
|
+
findingsUnprojected: unprojected
|
|
12451
|
+
};
|
|
12452
|
+
}
|
|
12453
|
+
function extractCollectorUnfinishedReasons(candidate) {
|
|
12454
|
+
if (candidate !== void 0 && candidate !== null && candidateRecord(candidate) === void 0) {
|
|
12455
|
+
return { reasons: void 0, source: "unreadable", unprojected: true };
|
|
12456
|
+
}
|
|
12457
|
+
const record4 = candidateRecord(candidate);
|
|
12458
|
+
if (record4 === void 0) {
|
|
12459
|
+
return { reasons: void 0, source: "absent", unprojected: false };
|
|
12460
|
+
}
|
|
12461
|
+
if (!Object.hasOwn(record4, "unfinishedReasons")) {
|
|
12462
|
+
return { reasons: void 0, source: "absent", unprojected: false };
|
|
12463
|
+
}
|
|
12464
|
+
const raw = record4["unfinishedReasons"];
|
|
12465
|
+
if (!Array.isArray(raw)) {
|
|
12466
|
+
return { reasons: void 0, source: "unreadable", unprojected: true };
|
|
12467
|
+
}
|
|
12468
|
+
const reasons = raw.filter((item) => typeof item === "string");
|
|
12469
|
+
const unprojected = reasons.length !== raw.length;
|
|
12470
|
+
return {
|
|
12471
|
+
reasons: reasons.length > 0 ? reasons : void 0,
|
|
12472
|
+
source: "array",
|
|
12473
|
+
unprojected
|
|
12474
|
+
};
|
|
12475
|
+
}
|
|
12476
|
+
var CollectorUnknownEvidenceError, CollectorFindingsValidationError, CollectorNonOpenRequestError, COLLECTOR_OUTPUT_CANONICAL_KEYS;
|
|
12477
|
+
var init_collector_identity = __esm({
|
|
12478
|
+
"src/collector-identity.ts"() {
|
|
12479
|
+
"use strict";
|
|
12480
|
+
init_submission_correctable_error();
|
|
12481
|
+
CollectorUnknownEvidenceError = class extends CorrectableSubmissionError {
|
|
12482
|
+
constructor(evidenceId) {
|
|
12483
|
+
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`);
|
|
12484
|
+
this.name = "CollectorUnknownEvidenceError";
|
|
12485
|
+
}
|
|
12486
|
+
};
|
|
12487
|
+
CollectorFindingsValidationError = class extends CorrectableSubmissionError {
|
|
12488
|
+
constructor(message) {
|
|
12489
|
+
super(message);
|
|
12490
|
+
this.name = "CollectorFindingsValidationError";
|
|
12491
|
+
}
|
|
12492
|
+
};
|
|
12493
|
+
CollectorNonOpenRequestError = class extends CorrectableSubmissionError {
|
|
12494
|
+
constructor(prState) {
|
|
12495
|
+
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`);
|
|
12496
|
+
this.name = "CollectorNonOpenRequestError";
|
|
12497
|
+
}
|
|
12498
|
+
};
|
|
12499
|
+
COLLECTOR_OUTPUT_CANONICAL_KEYS = /* @__PURE__ */ new Set([
|
|
12500
|
+
"findings",
|
|
12501
|
+
"unfinishedReasons",
|
|
12502
|
+
"infrastructureFailure"
|
|
12503
|
+
]);
|
|
12504
|
+
}
|
|
12505
|
+
});
|
|
12506
|
+
|
|
11838
12507
|
// src/collector-tool-schemas.ts
|
|
11839
12508
|
import { Type as Type13 } from "typebox";
|
|
11840
|
-
var collectorObserveArgsSchema, collectorRequestArgsSchema, collectorReadArgsSchema, collectorWaitArgsSchema,
|
|
12509
|
+
var collectorObserveArgsSchema, collectorRequestArgsSchema, collectorReadArgsSchema, collectorWaitArgsSchema, collectorBindTargetArgsSchema, collectorFindingItemDeclaration, collectorOutputBaseSchema, collectorOutputArgsSchema;
|
|
11841
12510
|
var init_collector_tool_schemas = __esm({
|
|
11842
12511
|
"src/collector-tool-schemas.ts"() {
|
|
11843
12512
|
"use strict";
|
|
11844
12513
|
init_collector_evidence();
|
|
12514
|
+
init_open_tool_schema();
|
|
11845
12515
|
init_terminating_infrastructure();
|
|
11846
12516
|
collectorObserveArgsSchema = Type13.Object({}, { additionalProperties: false });
|
|
11847
12517
|
collectorRequestArgsSchema = Type13.Object({
|
|
@@ -11854,19 +12524,51 @@ var init_collector_tool_schemas = __esm({
|
|
|
11854
12524
|
collectorWaitArgsSchema = Type13.Object({
|
|
11855
12525
|
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
12526
|
}, { 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"
|
|
12527
|
+
collectorBindTargetArgsSchema = Type13.Object({
|
|
12528
|
+
prNumber: Type13.Optional(Type13.Unknown({
|
|
12529
|
+
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"
|
|
12530
|
+
})),
|
|
12531
|
+
issueNumber: Type13.Optional(Type13.Unknown({
|
|
12532
|
+
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
12533
|
}))
|
|
11865
|
-
}, { additionalProperties: true
|
|
12534
|
+
}, { additionalProperties: true });
|
|
12535
|
+
collectorFindingItemDeclaration = (() => {
|
|
12536
|
+
const item = Type13.Object(
|
|
12537
|
+
{
|
|
12538
|
+
evidenceId: Type13.Unknown({
|
|
12539
|
+
description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u6307\u9488\uFF08\u5FC5\u586B\u8BED\u4E49\uFF09"
|
|
12540
|
+
}),
|
|
12541
|
+
category: Type13.Unknown({
|
|
12542
|
+
description: "\u7B80\u77ED\u5F52\u7C7B\u6807\u7B7E\uFF0C\u4E0D\u662F\u6458\u8981"
|
|
12543
|
+
}),
|
|
12544
|
+
summary: Type13.Unknown({
|
|
12545
|
+
description: "\u54EA\u4E2A bot\u3001\u4EC0\u4E48\u95EE\u9898\u7684\u6458\u8981\uFF1B\u4E0D\u8A8A\u6284\u6B63\u6587"
|
|
12546
|
+
})
|
|
12547
|
+
},
|
|
12548
|
+
{
|
|
12549
|
+
additionalProperties: true,
|
|
12550
|
+
description: "\u5355\u6761 finding \u6307\u9488\uFF1AevidenceId + \u53EF\u9009 category/summary\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
|
|
12551
|
+
}
|
|
12552
|
+
);
|
|
12553
|
+
item.required = [];
|
|
12554
|
+
return item;
|
|
12555
|
+
})();
|
|
12556
|
+
collectorOutputBaseSchema = openToolObject(
|
|
12557
|
+
Type13.Object({
|
|
12558
|
+
// No root type:array — host must not shape-reject non-array findings (#676 C).
|
|
12559
|
+
// Nested item declarations ride `items` for registration preservation (ADR 0057).
|
|
12560
|
+
findings: Type13.Unsafe({
|
|
12561
|
+
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",
|
|
12562
|
+
items: collectorFindingItemDeclaration
|
|
12563
|
+
}),
|
|
12564
|
+
unfinishedReasons: Type13.Unknown({
|
|
12565
|
+
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"
|
|
12566
|
+
})
|
|
12567
|
+
})
|
|
12568
|
+
);
|
|
11866
12569
|
collectorOutputArgsSchema = withInfrastructureFailureDeclaration(
|
|
11867
12570
|
collectorOutputBaseSchema
|
|
11868
12571
|
);
|
|
11869
|
-
collectorOutputArgsSchema.required = [];
|
|
11870
12572
|
}
|
|
11871
12573
|
});
|
|
11872
12574
|
|
|
@@ -11942,10 +12644,18 @@ function createCollectorLedger(config, options) {
|
|
|
11942
12644
|
return Math.max(0, deadlineMono - monoNowOrThrow(clock2));
|
|
11943
12645
|
};
|
|
11944
12646
|
const prIdentity = (pr) => `${pr.state}|${pr.headOid}|${pr.updatedAt ?? ""}`;
|
|
12647
|
+
const requireBoundPr = () => {
|
|
12648
|
+
if (config.prNumber === void 0) {
|
|
12649
|
+
throw new Error(
|
|
12650
|
+
"Collector PR target is unbound; call ak_collector_bind_target with the role-decided issue/PR or pass --pr"
|
|
12651
|
+
);
|
|
12652
|
+
}
|
|
12653
|
+
return config.prNumber;
|
|
12654
|
+
};
|
|
11945
12655
|
const fetchObserveSurfaces = async (transport, observedAt, signal) => {
|
|
11946
12656
|
const owner = config.repository.owner;
|
|
11947
12657
|
const repo = config.repository.repo;
|
|
11948
|
-
const prNumber =
|
|
12658
|
+
const prNumber = requireBoundPr();
|
|
11949
12659
|
const signalOpt = signal === void 0 ? {} : { signal };
|
|
11950
12660
|
const user = await transport.getAuthenticatedUser(signalOpt);
|
|
11951
12661
|
const prInitial = await transport.getPullRequest({
|
|
@@ -12214,6 +12924,25 @@ function createCollectorLedger(config, options) {
|
|
|
12214
12924
|
assertNotFatal();
|
|
12215
12925
|
outputCandidate = true;
|
|
12216
12926
|
},
|
|
12927
|
+
bindTarget(prNumber) {
|
|
12928
|
+
assertNotFatal();
|
|
12929
|
+
if (outputCandidate || pendingOutputCallId !== void 0) {
|
|
12930
|
+
throw new Error("\u901A\u8FDB\u53F8\u5DF2\u4EA7\u51FA\u8F93\u51FA\u5019\u9009\uFF0C\u672C\u5C40\u4E0D\u518D\u53D7\u7406\u76EE\u6807\u7ED1\u5B9A");
|
|
12931
|
+
}
|
|
12932
|
+
if (!Number.isSafeInteger(prNumber) || prNumber < 1) {
|
|
12933
|
+
throw new Error("Collector bind target requires a positive safe-integer PR number");
|
|
12934
|
+
}
|
|
12935
|
+
if (config.prNumber !== void 0 && config.prNumber !== prNumber) {
|
|
12936
|
+
throw new Error(
|
|
12937
|
+
`Collector target already bound to PR ${config.prNumber}; cannot rebind to ${prNumber}`
|
|
12938
|
+
);
|
|
12939
|
+
}
|
|
12940
|
+
config.prNumber = prNumber;
|
|
12941
|
+
appendJournal("ak-collector-target-bound", {
|
|
12942
|
+
prNumber,
|
|
12943
|
+
repository: config.repository.canonical
|
|
12944
|
+
});
|
|
12945
|
+
},
|
|
12217
12946
|
beginOperational(toolName, toolCallId) {
|
|
12218
12947
|
assertNotFatal();
|
|
12219
12948
|
if (toolName !== COLLECTOR_OUTPUT_TOOL && (outputCandidate || pendingOutputCallId !== void 0)) {
|
|
@@ -12360,7 +13089,7 @@ function createCollectorLedger(config, options) {
|
|
|
12360
13089
|
completedMono,
|
|
12361
13090
|
host: "github.com",
|
|
12362
13091
|
repository: config.repository.canonical,
|
|
12363
|
-
prNumber:
|
|
13092
|
+
prNumber: requireBoundPr(),
|
|
12364
13093
|
prState: pr.state,
|
|
12365
13094
|
headOid: pr.headOid,
|
|
12366
13095
|
complete: true,
|
|
@@ -12399,10 +13128,6 @@ function createCollectorLedger(config, options) {
|
|
|
12399
13128
|
if (activationTime === void 0 || deadlineTime === void 0) {
|
|
12400
13129
|
throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u9700\u8981\u6FC0\u6D3B");
|
|
12401
13130
|
}
|
|
12402
|
-
if (pastCutoff(clock2)) {
|
|
12403
|
-
finalObservationRequired = true;
|
|
12404
|
-
throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u4E0D\u5728\u8D44\u683C\u622A\u6B62\u524D");
|
|
12405
|
-
}
|
|
12406
13131
|
if (ledger.unresolvedTransportFailure) {
|
|
12407
13132
|
throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u65F6\u5B58\u5728\u672A\u6062\u590D\u7684\u4F20\u8F93\u5931\u8D25");
|
|
12408
13133
|
}
|
|
@@ -12418,7 +13143,11 @@ function createCollectorLedger(config, options) {
|
|
|
12418
13143
|
throw new Error("\u901A\u8FDB\u53F8\u8BF7\u6C42\u8981\u6C42\u6700\u65B0\u5B8C\u6574\u5FEB\u7167");
|
|
12419
13144
|
}
|
|
12420
13145
|
if (snapshot.prState !== "OPEN") {
|
|
12421
|
-
throw
|
|
13146
|
+
throw new CollectorNonOpenRequestError(snapshot.prState);
|
|
13147
|
+
}
|
|
13148
|
+
if (pastCutoff(clock2)) {
|
|
13149
|
+
finalObservationRequired = true;
|
|
13150
|
+
throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u4E0D\u5728\u8D44\u683C\u622A\u6B62\u524D");
|
|
12422
13151
|
}
|
|
12423
13152
|
const { body, marker } = buildCollectorRequestBody({
|
|
12424
13153
|
configuredBody: request.requestBody,
|
|
@@ -12435,9 +13164,10 @@ function createCollectorLedger(config, options) {
|
|
|
12435
13164
|
`\u901A\u8FDB\u53F8\u5728\u6B64 HEAD \u5DF2\u6709\u540C marker \u7684\u5DF2\u8BA4\u8BC1\u8BF7\u6C42 "${input.requestId}"`
|
|
12436
13165
|
);
|
|
12437
13166
|
}
|
|
13167
|
+
const boundPr = requireBoundPr();
|
|
12438
13168
|
const attemptKey = [
|
|
12439
13169
|
config.repository.canonical,
|
|
12440
|
-
String(
|
|
13170
|
+
String(boundPr),
|
|
12441
13171
|
snapshot.headOid,
|
|
12442
13172
|
request.id
|
|
12443
13173
|
].join("|");
|
|
@@ -12466,7 +13196,7 @@ function createCollectorLedger(config, options) {
|
|
|
12466
13196
|
const result = await transport.createIssueComment({
|
|
12467
13197
|
owner: config.repository.owner,
|
|
12468
13198
|
repo: config.repository.repo,
|
|
12469
|
-
prNumber:
|
|
13199
|
+
prNumber: boundPr,
|
|
12470
13200
|
body,
|
|
12471
13201
|
...signal === void 0 ? {} : { signal }
|
|
12472
13202
|
});
|
|
@@ -12632,19 +13362,22 @@ function buildObserveModelView(input) {
|
|
|
12632
13362
|
}))
|
|
12633
13363
|
};
|
|
12634
13364
|
}
|
|
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;
|
|
13365
|
+
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
13366
|
var init_collector_ledger = __esm({
|
|
12637
13367
|
"src/collector-ledger.ts"() {
|
|
12638
13368
|
"use strict";
|
|
12639
13369
|
init_collector_evidence();
|
|
12640
13370
|
init_collector_github();
|
|
13371
|
+
init_collector_identity();
|
|
12641
13372
|
init_collector_tool_schemas();
|
|
12642
13373
|
init_collector_output();
|
|
12643
13374
|
COLLECTOR_OBSERVE_TOOL = "ak_collector_observe";
|
|
12644
13375
|
COLLECTOR_READ_TOOL = "ak_collector_read";
|
|
12645
13376
|
COLLECTOR_REQUEST_TOOL = "ak_collector_request";
|
|
12646
13377
|
COLLECTOR_WAIT_TOOL = "ak_collector_wait";
|
|
13378
|
+
COLLECTOR_BIND_TARGET_TOOL = "ak_collector_bind_target";
|
|
12647
13379
|
COLLECTOR_OPERATIONAL_TOOLS = [
|
|
13380
|
+
COLLECTOR_BIND_TARGET_TOOL,
|
|
12648
13381
|
COLLECTOR_OBSERVE_TOOL,
|
|
12649
13382
|
COLLECTOR_READ_TOOL,
|
|
12650
13383
|
COLLECTOR_REQUEST_TOOL,
|
|
@@ -12661,7 +13394,7 @@ var init_collector_ledger = __esm({
|
|
|
12661
13394
|
// src/package-resources/method-skill.ts
|
|
12662
13395
|
import { createHash as createHash7 } from "node:crypto";
|
|
12663
13396
|
import { readFile as readFile14, realpath as realpath7 } from "node:fs/promises";
|
|
12664
|
-
import { join as
|
|
13397
|
+
import { join as join24 } from "node:path";
|
|
12665
13398
|
function gitBlobOid(bytes) {
|
|
12666
13399
|
const body = typeof bytes === "string" ? Buffer.from(bytes, "utf8") : Buffer.from(bytes);
|
|
12667
13400
|
const header = Buffer.from(`blob ${body.byteLength}\0`, "utf8");
|
|
@@ -12678,10 +13411,10 @@ function packagedMethodSkillRelativeDirectory(name) {
|
|
|
12678
13411
|
return `${METHOD_SKILL_RELATIVE_ROOT}/${name}`;
|
|
12679
13412
|
}
|
|
12680
13413
|
function resolvePackagedMethodSkillRoot(packageRoot, name) {
|
|
12681
|
-
return
|
|
13414
|
+
return join24(packageRoot, packagedMethodSkillRelativeDirectory(name));
|
|
12682
13415
|
}
|
|
12683
13416
|
function resolvePackagedMethodSkillPath(packageRoot, name) {
|
|
12684
|
-
return
|
|
13417
|
+
return join24(resolvePackagedMethodSkillRoot(packageRoot, name), "SKILL.md");
|
|
12685
13418
|
}
|
|
12686
13419
|
function isRecord14(value) {
|
|
12687
13420
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -12775,8 +13508,8 @@ function parseProvenance(raw, expectedName) {
|
|
|
12775
13508
|
}
|
|
12776
13509
|
async function loadPackagedMethodSkillMaterial(packageRoot, name) {
|
|
12777
13510
|
const rootDirectory = resolvePackagedMethodSkillRoot(packageRoot, name);
|
|
12778
|
-
const skillPathConfigured =
|
|
12779
|
-
const provenancePath =
|
|
13511
|
+
const skillPathConfigured = join24(rootDirectory, "SKILL.md");
|
|
13512
|
+
const provenancePath = join24(rootDirectory, "provenance.json");
|
|
12780
13513
|
let provenanceRaw;
|
|
12781
13514
|
try {
|
|
12782
13515
|
provenanceRaw = await readFile14(provenancePath, "utf8");
|
|
@@ -12793,7 +13526,7 @@ async function loadPackagedMethodSkillMaterial(packageRoot, name) {
|
|
|
12793
13526
|
}
|
|
12794
13527
|
const provenance = parseProvenance(provenanceJson, name);
|
|
12795
13528
|
for (const [rel, expected] of Object.entries(provenance.files)) {
|
|
12796
|
-
const absolute =
|
|
13529
|
+
const absolute = join24(rootDirectory, rel);
|
|
12797
13530
|
let bytes;
|
|
12798
13531
|
try {
|
|
12799
13532
|
bytes = await readFile14(absolute);
|
|
@@ -13309,7 +14042,7 @@ var init_terminal = __esm({
|
|
|
13309
14042
|
// src/public-cli/settlement.ts
|
|
13310
14043
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
13311
14044
|
import { appendFile as appendFile2, readFile as readFile15, readdir as readdir5, writeFile as writeFile6 } from "node:fs/promises";
|
|
13312
|
-
import { dirname as dirname12, join as
|
|
14045
|
+
import { dirname as dirname12, join as join25 } from "node:path";
|
|
13313
14046
|
function sealedLedgerHome(admitted) {
|
|
13314
14047
|
return homeFromRunDirectory(admitted.runDirectory);
|
|
13315
14048
|
}
|
|
@@ -13397,8 +14130,27 @@ function formatFailureStderrDiagnostic(failure2) {
|
|
|
13397
14130
|
const oneLine2 = selected.split(/\r?\n/).map((line2) => line2.trim()).find((line2) => line2.length > 0) ?? "failure";
|
|
13398
14131
|
return formatCliDiagnostic(boundConciseDiagnostic(oneLine2));
|
|
13399
14132
|
}
|
|
14133
|
+
function formatErrorCauseDetail(cause) {
|
|
14134
|
+
if (cause instanceof Error) return cause.message;
|
|
14135
|
+
if (typeof cause === "object" && cause !== null) {
|
|
14136
|
+
try {
|
|
14137
|
+
return JSON.stringify(cause);
|
|
14138
|
+
} catch {
|
|
14139
|
+
return String(cause);
|
|
14140
|
+
}
|
|
14141
|
+
}
|
|
14142
|
+
return String(cause);
|
|
14143
|
+
}
|
|
13400
14144
|
function presentStructuralRejection(error, io) {
|
|
13401
|
-
|
|
14145
|
+
let message = error.message;
|
|
14146
|
+
const cause = error.cause;
|
|
14147
|
+
if (cause !== void 0) {
|
|
14148
|
+
const detail = formatErrorCauseDetail(cause);
|
|
14149
|
+
if (detail.trim().length > 0) {
|
|
14150
|
+
message = `${message}; cause: ${detail}`;
|
|
14151
|
+
}
|
|
14152
|
+
}
|
|
14153
|
+
io.stderr(formatCliDiagnostic(message));
|
|
13402
14154
|
}
|
|
13403
14155
|
async function inspectJudgeSession(sessionFile) {
|
|
13404
14156
|
try {
|
|
@@ -13705,7 +14457,7 @@ async function readSessionProviderStop(sessionFile) {
|
|
|
13705
14457
|
}
|
|
13706
14458
|
}
|
|
13707
14459
|
async function readBoundEvidenceChildKnownFailure(sessionFile) {
|
|
13708
|
-
const childDirectory =
|
|
14460
|
+
const childDirectory = join25(dirname12(sessionFile), "evidence-children");
|
|
13709
14461
|
let names;
|
|
13710
14462
|
try {
|
|
13711
14463
|
names = await readdir5(childDirectory);
|
|
@@ -13716,7 +14468,7 @@ async function readBoundEvidenceChildKnownFailure(sessionFile) {
|
|
|
13716
14468
|
for (const file of names.filter((name) => name.endsWith(".jsonl")).sort().reverse()) {
|
|
13717
14469
|
let entries;
|
|
13718
14470
|
try {
|
|
13719
|
-
entries = await readBoundSessionEntries(
|
|
14471
|
+
entries = await readBoundSessionEntries(join25(childDirectory, file));
|
|
13720
14472
|
} catch (error) {
|
|
13721
14473
|
throw sessionReadFailure(error, "failed to read discovered evidence-child session");
|
|
13722
14474
|
}
|
|
@@ -13770,7 +14522,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
|
|
|
13770
14522
|
latestParentUserIndex = i;
|
|
13771
14523
|
break;
|
|
13772
14524
|
}
|
|
13773
|
-
const childDirectories = [
|
|
14525
|
+
const childDirectories = [join25(dirname12(sessionFile), "auditor-roles")];
|
|
13774
14526
|
const valid = [];
|
|
13775
14527
|
let sawAnyDirectory = false;
|
|
13776
14528
|
for (const childDirectory of childDirectories) {
|
|
@@ -13785,7 +14537,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
|
|
|
13785
14537
|
for (const file of names.filter((name) => name.endsWith(".jsonl")).sort().reverse()) {
|
|
13786
14538
|
let entries;
|
|
13787
14539
|
try {
|
|
13788
|
-
entries = await readBoundSessionEntries(
|
|
14540
|
+
entries = await readBoundSessionEntries(join25(childDirectory, file));
|
|
13789
14541
|
} catch (error) {
|
|
13790
14542
|
throw sessionReadFailure(error, "failed to read discovered auditor session");
|
|
13791
14543
|
}
|
|
@@ -14086,6 +14838,22 @@ function toolResultText(message) {
|
|
|
14086
14838
|
return "";
|
|
14087
14839
|
}).join("").trim();
|
|
14088
14840
|
}
|
|
14841
|
+
function extractCollectorTargetBindRejection(entries) {
|
|
14842
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
14843
|
+
const entry = entries[i];
|
|
14844
|
+
if (entry?.type !== "message") continue;
|
|
14845
|
+
const message = entry.message;
|
|
14846
|
+
if (message?.role !== "toolResult") continue;
|
|
14847
|
+
if (message.toolName !== COLLECTOR_BIND_TARGET_TOOL) continue;
|
|
14848
|
+
if (message.isError !== true) return void 0;
|
|
14849
|
+
const diagnostic = toolResultText(message);
|
|
14850
|
+
if (diagnostic.length === 0) return void 0;
|
|
14851
|
+
const details = message.details;
|
|
14852
|
+
const code = isRecord16(details) && typeof details.code === "string" && details.code.trim() !== "" ? details.code : void 0;
|
|
14853
|
+
return code === void 0 ? { diagnostic } : { diagnostic, code };
|
|
14854
|
+
}
|
|
14855
|
+
return void 0;
|
|
14856
|
+
}
|
|
14089
14857
|
function boundErroredToolCandidate(entries, resultIndex, message, toolName) {
|
|
14090
14858
|
if (message.toolName !== toolName || message.isError !== true) return void 0;
|
|
14091
14859
|
const bound = boundRoleToolCallForResult(entries, resultIndex, message, toolName);
|
|
@@ -14285,8 +15053,8 @@ function projectTerminalGateFact(rounds) {
|
|
|
14285
15053
|
};
|
|
14286
15054
|
}
|
|
14287
15055
|
async function extractGateFactFromSessionDirectory(sessionDirectory, options = {}) {
|
|
14288
|
-
const directories = [
|
|
14289
|
-
const parentSessionFile = options.parentSessionFile ??
|
|
15056
|
+
const directories = [join25(sessionDirectory, "auditor-roles")];
|
|
15057
|
+
const parentSessionFile = options.parentSessionFile ?? join25(sessionDirectory, "session.jsonl");
|
|
14290
15058
|
const rounds = await readAnalystGateCyclesFromAuditorRoles(directories, {
|
|
14291
15059
|
parentSessionFile
|
|
14292
15060
|
});
|
|
@@ -14384,8 +15152,8 @@ async function extractNavigatorFactFromAdmittedSession(sessionFile) {
|
|
|
14384
15152
|
async function publishJudgeArtifacts(admitted, roleOutcome, coordinates) {
|
|
14385
15153
|
await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
|
|
14386
15154
|
const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
|
|
14387
|
-
const reportPath =
|
|
14388
|
-
const evidencePath =
|
|
15155
|
+
const reportPath = join25(artifactsDir, "report.json");
|
|
15156
|
+
const evidencePath = join25(artifactsDir, "evidence.json");
|
|
14389
15157
|
await writeFile6(
|
|
14390
15158
|
reportPath,
|
|
14391
15159
|
`${JSON.stringify(
|
|
@@ -14475,8 +15243,8 @@ async function trySettleJudgeTerminalResult(admitted, authority) {
|
|
|
14475
15243
|
async function publishDoctorArtifacts(admitted, roleOutcome, coordinates, options = {}) {
|
|
14476
15244
|
await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
|
|
14477
15245
|
const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
|
|
14478
|
-
const reportPath =
|
|
14479
|
-
const evidencePath =
|
|
15246
|
+
const reportPath = join25(artifactsDir, "report.json");
|
|
15247
|
+
const evidencePath = join25(artifactsDir, "evidence.json");
|
|
14480
15248
|
await writeFile6(
|
|
14481
15249
|
reportPath,
|
|
14482
15250
|
`${JSON.stringify(
|
|
@@ -14709,7 +15477,7 @@ function uniqueFailureFallbackDirs(runDirectory, baseDir) {
|
|
|
14709
15477
|
return dirs;
|
|
14710
15478
|
}
|
|
14711
15479
|
async function resolveFailureArtifactsBase(runDirectory) {
|
|
14712
|
-
const artifactsDir =
|
|
15480
|
+
const artifactsDir = join25(runDirectory, "artifacts");
|
|
14713
15481
|
try {
|
|
14714
15482
|
await ensureRunArtifactsDir(runDirectory);
|
|
14715
15483
|
return { baseDir: artifactsDir };
|
|
@@ -14725,7 +15493,7 @@ async function writeFailureJsonRetainingCause(preferredCandidates, uniqueFallbac
|
|
|
14725
15493
|
const candidates = [
|
|
14726
15494
|
...preferredCandidates,
|
|
14727
15495
|
// One unique name per fallback dir — collisions on fixed names cannot exhaust this.
|
|
14728
|
-
...uniqueFallbackDirs.map((dir) =>
|
|
15496
|
+
...uniqueFallbackDirs.map((dir) => join25(dir, `${stem}.${randomUUID3()}.json`))
|
|
14729
15497
|
];
|
|
14730
15498
|
for (let i = 0; i < candidates.length; i += 1) {
|
|
14731
15499
|
const path = candidates[i];
|
|
@@ -14770,26 +15538,26 @@ async function publishFailureArtifacts(admitted, failure2, authority) {
|
|
|
14770
15538
|
} catch (error) {
|
|
14771
15539
|
priorIssues.push(publicationAttemptFromError(sessionFile, error));
|
|
14772
15540
|
}
|
|
14773
|
-
const underArtifacts = baseDir ===
|
|
15541
|
+
const underArtifacts = baseDir === join25(admitted.runDirectory, "artifacts");
|
|
14774
15542
|
const uniqueFallbackDirs = uniqueFailureFallbackDirs(
|
|
14775
15543
|
admitted.runDirectory,
|
|
14776
15544
|
baseDir
|
|
14777
15545
|
);
|
|
14778
15546
|
const errorCandidates = underArtifacts ? [
|
|
14779
|
-
|
|
14780
|
-
|
|
14781
|
-
|
|
15547
|
+
join25(baseDir, "error.json"),
|
|
15548
|
+
join25(baseDir, "error.settlement.json"),
|
|
15549
|
+
join25(admitted.runDirectory, "error.settlement.json")
|
|
14782
15550
|
] : [
|
|
14783
|
-
|
|
14784
|
-
|
|
15551
|
+
join25(baseDir, "error.settlement.json"),
|
|
15552
|
+
join25(baseDir, "error.json")
|
|
14785
15553
|
];
|
|
14786
15554
|
const evidenceCandidates = underArtifacts ? [
|
|
14787
|
-
|
|
14788
|
-
|
|
14789
|
-
|
|
15555
|
+
join25(baseDir, "evidence.json"),
|
|
15556
|
+
join25(baseDir, "evidence.settlement.json"),
|
|
15557
|
+
join25(admitted.runDirectory, "evidence.settlement.json")
|
|
14790
15558
|
] : [
|
|
14791
|
-
|
|
14792
|
-
|
|
15559
|
+
join25(baseDir, "evidence.settlement.json"),
|
|
15560
|
+
join25(baseDir, "evidence.json")
|
|
14793
15561
|
];
|
|
14794
15562
|
const errorPayloadBase = {
|
|
14795
15563
|
kind: "error",
|
|
@@ -14891,7 +15659,18 @@ async function settleFailureTerminalResult(admitted, failure2, authority, option
|
|
|
14891
15659
|
try {
|
|
14892
15660
|
const facts = parseNoReceiptLifecycleFacts(raw);
|
|
14893
15661
|
if (facts.runPointer === admitted.runDirectory && facts.attemptPointer === `current:${admitted.runDirectory}`) {
|
|
14894
|
-
|
|
15662
|
+
let decisiveFacts2 = facts;
|
|
15663
|
+
if (admitted.role === "collector") {
|
|
15664
|
+
const bindRejection = extractCollectorTargetBindRejection(entries.slice(attemptStart));
|
|
15665
|
+
if (bindRejection !== void 0) {
|
|
15666
|
+
decisiveFacts2 = {
|
|
15667
|
+
...facts,
|
|
15668
|
+
targetBindRejected: true,
|
|
15669
|
+
targetBindDiagnostic: bindRejection.diagnostic,
|
|
15670
|
+
...bindRejection.code === void 0 ? {} : { targetBindCode: bindRejection.code }
|
|
15671
|
+
};
|
|
15672
|
+
}
|
|
15673
|
+
}
|
|
14895
15674
|
return withOptionalGateProjection(
|
|
14896
15675
|
{
|
|
14897
15676
|
roleOutcome: { kind: "no_receipt", role: admitted.role, status: "no-accepted-receipt", ...facts, decisiveFacts: decisiveFacts2 },
|
|
@@ -14969,8 +15748,16 @@ function presentFailureTerminal(terminal, io) {
|
|
|
14969
15748
|
io.stdout(formatTerminalResult(terminal));
|
|
14970
15749
|
if (terminal.roleOutcome.kind === "failure") {
|
|
14971
15750
|
io.stderr(formatFailureStderrDiagnostic({
|
|
14972
|
-
cause: terminal.roleOutcome.cause,
|
|
14973
|
-
diagnostic: terminal.roleOutcome.diagnostic
|
|
15751
|
+
cause: terminal.roleOutcome.cause,
|
|
15752
|
+
diagnostic: terminal.roleOutcome.diagnostic
|
|
15753
|
+
}));
|
|
15754
|
+
return;
|
|
15755
|
+
}
|
|
15756
|
+
const bindDiagnostic = terminal.roleOutcome.decisiveFacts.targetBindDiagnostic;
|
|
15757
|
+
if (typeof bindDiagnostic === "string" && bindDiagnostic.trim() !== "") {
|
|
15758
|
+
io.stderr(formatFailureStderrDiagnostic({
|
|
15759
|
+
cause: "output",
|
|
15760
|
+
diagnostic: bindDiagnostic
|
|
14974
15761
|
}));
|
|
14975
15762
|
}
|
|
14976
15763
|
}
|
|
@@ -15060,7 +15847,7 @@ var init_settlement = __esm({
|
|
|
15060
15847
|
import { constants as fsConstants } from "node:fs";
|
|
15061
15848
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
15062
15849
|
import { lstat as lstat5, mkdir as mkdir4, open as open2 } from "node:fs/promises";
|
|
15063
|
-
import { join as
|
|
15850
|
+
import { join as join26 } from "node:path";
|
|
15064
15851
|
function presentTerminal(terminal, io) {
|
|
15065
15852
|
if (terminal.roleOutcome.kind === "failure" || terminal.roleOutcome.kind === "no_receipt") {
|
|
15066
15853
|
presentFailureTerminal(terminal, io);
|
|
@@ -15079,7 +15866,7 @@ async function finalizeExceptionRunBestEffort(runDirectory, io) {
|
|
|
15079
15866
|
}
|
|
15080
15867
|
}
|
|
15081
15868
|
function runArtifactsDirectory(runDirectory) {
|
|
15082
|
-
return
|
|
15869
|
+
return join26(runDirectory, "artifacts");
|
|
15083
15870
|
}
|
|
15084
15871
|
async function ensureRealArtifactsDirectory(runDirectory) {
|
|
15085
15872
|
const runStat = await lstat5(runDirectory);
|
|
@@ -15162,7 +15949,7 @@ function jsonSafeReplacer() {
|
|
|
15162
15949
|
}
|
|
15163
15950
|
async function retainDispatchError(admitted, principalAuthority, sessionAppender, attempt, error) {
|
|
15164
15951
|
const artifactsDir = await ensureRealArtifactsDirectory(admitted.runDirectory);
|
|
15165
|
-
const filePath =
|
|
15952
|
+
const filePath = join26(
|
|
15166
15953
|
artifactsDir,
|
|
15167
15954
|
`dispatch-error-attempt-${attempt}-${randomUUID4()}.json`
|
|
15168
15955
|
);
|
|
@@ -15411,7 +16198,7 @@ var init_auto_resume = __esm({
|
|
|
15411
16198
|
// src/public-cli/post-admission.ts
|
|
15412
16199
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
15413
16200
|
import { readFile as readFile16, writeFile as writeFile7 } from "node:fs/promises";
|
|
15414
|
-
import { isAbsolute as isAbsolute7, join as
|
|
16201
|
+
import { isAbsolute as isAbsolute7, join as join27, resolve as resolve11 } from "node:path";
|
|
15415
16202
|
function appendContinuationSection(continuation, section) {
|
|
15416
16203
|
const prompt = `${continuation.prompt}
|
|
15417
16204
|
|
|
@@ -15420,7 +16207,7 @@ ${section}`;
|
|
|
15420
16207
|
}
|
|
15421
16208
|
async function readInvocationHost(runDirectory) {
|
|
15422
16209
|
try {
|
|
15423
|
-
const raw = JSON.parse(await readFile16(
|
|
16210
|
+
const raw = JSON.parse(await readFile16(join27(runDirectory, "invocation.json"), "utf8"));
|
|
15424
16211
|
return typeof raw.host === "string" && raw.host.trim() !== "" ? raw.host : void 0;
|
|
15425
16212
|
} catch (error) {
|
|
15426
16213
|
if (error.code === "ENOENT") return void 0;
|
|
@@ -15574,7 +16361,7 @@ async function dispatchPostAdmissionTurn(input) {
|
|
|
15574
16361
|
}
|
|
15575
16362
|
try {
|
|
15576
16363
|
await writeFile7(
|
|
15577
|
-
|
|
16364
|
+
join27(admitted.runDirectory, "stderr.log"),
|
|
15578
16365
|
result.stderr,
|
|
15579
16366
|
"utf8"
|
|
15580
16367
|
);
|
|
@@ -15683,7 +16470,7 @@ function resumeTurnRequestProjectionOptions(admitted, request, env, summonsPrepa
|
|
|
15683
16470
|
}
|
|
15684
16471
|
function isAlreadyFrozenSummonsAttachment(runDirectory, attachmentPath) {
|
|
15685
16472
|
const absolute = isAbsolute7(attachmentPath) ? attachmentPath : resolve11(attachmentPath);
|
|
15686
|
-
return pathContainedIn(
|
|
16473
|
+
return pathContainedIn(join27(runDirectory, "attachments"), absolute);
|
|
15687
16474
|
}
|
|
15688
16475
|
async function prepareSummonsResumeMaterials(runDirectory, summons) {
|
|
15689
16476
|
if (summons === void 0) return void 0;
|
|
@@ -16868,8 +17655,8 @@ __export(public_role_summons_exports, {
|
|
|
16868
17655
|
summonGateOfficer: () => summonGateOfficer,
|
|
16869
17656
|
summonPublicRole: () => summonPublicRole
|
|
16870
17657
|
});
|
|
16871
|
-
import { existsSync as
|
|
16872
|
-
import { join as
|
|
17658
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
17659
|
+
import { join as join28 } from "node:path";
|
|
16873
17660
|
function createCapturingIo() {
|
|
16874
17661
|
const chunks = [];
|
|
16875
17662
|
return {
|
|
@@ -16892,7 +17679,7 @@ function parentDir(path) {
|
|
|
16892
17679
|
function walkPackageRoot(start) {
|
|
16893
17680
|
let dir = start;
|
|
16894
17681
|
for (let i = 0; i < 12; i += 1) {
|
|
16895
|
-
if (
|
|
17682
|
+
if (existsSync8(join28(dir, "package.json")) && existsSync8(join28(dir, "souls"))) {
|
|
16896
17683
|
return dir;
|
|
16897
17684
|
}
|
|
16898
17685
|
const parent = parentDir(dir);
|
|
@@ -16968,9 +17755,9 @@ async function createSummonEnv(options) {
|
|
|
16968
17755
|
const hostName = options.seat.host ?? "pi";
|
|
16969
17756
|
let roleTurnHost = piHost;
|
|
16970
17757
|
if (hostName !== "pi") {
|
|
16971
|
-
const {
|
|
16972
|
-
const {
|
|
16973
|
-
if (
|
|
17758
|
+
const { lookupHostFamily: lookupHostFamily2 } = await Promise.resolve().then(() => (init_host_descriptions(), host_descriptions_exports));
|
|
17759
|
+
const { loadProductionExternalHostFactory: loadProductionExternalHostFactory2 } = await Promise.resolve().then(() => (init_load_production_external_host(), load_production_external_host_exports));
|
|
17760
|
+
if (lookupHostFamily2(hostName) === void 0) {
|
|
16974
17761
|
throw new Error(
|
|
16975
17762
|
`public role summons host unregistered: host=${hostName} seat=${options.role}`
|
|
16976
17763
|
);
|
|
@@ -16978,7 +17765,7 @@ async function createSummonEnv(options) {
|
|
|
16978
17765
|
let hostPromise;
|
|
16979
17766
|
roleTurnHost = {
|
|
16980
17767
|
executeTurn: async (request) => {
|
|
16981
|
-
hostPromise ??=
|
|
17768
|
+
hostPromise ??= loadProductionExternalHostFactory2(options.packageRoot, hostName).then(
|
|
16982
17769
|
(create) => create({
|
|
16983
17770
|
packageRoot: options.packageRoot,
|
|
16984
17771
|
principalAuthority
|
|
@@ -17012,7 +17799,7 @@ async function createSummonEnv(options) {
|
|
|
17012
17799
|
async function summonPublicRole(options) {
|
|
17013
17800
|
const packageRoot = resolveSummonsPackageRoot(options.packageRoot);
|
|
17014
17801
|
const home = await resolveSummonHome(options);
|
|
17015
|
-
const agentDir = options.agentDir ?? process.env.PI_CODING_AGENT_DIR ??
|
|
17802
|
+
const agentDir = options.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join28(home, ".pi", "agent");
|
|
17016
17803
|
const {
|
|
17017
17804
|
loadCredentialProviders: loadCredentialProviders2,
|
|
17018
17805
|
loadPublicCliConfig: loadPublicCliConfig2,
|
|
@@ -17020,7 +17807,8 @@ async function summonPublicRole(options) {
|
|
|
17020
17807
|
} = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
17021
17808
|
const credentials = options.credentials ?? await loadCredentialProviders2(agentDir);
|
|
17022
17809
|
const config = await loadPublicCliConfig2(home);
|
|
17023
|
-
const
|
|
17810
|
+
const invocation = options.host === void 0 ? void 0 : { host: options.host };
|
|
17811
|
+
const seat = resolveEffectiveSeat2(config, options.role, credentials, invocation);
|
|
17024
17812
|
const env = {
|
|
17025
17813
|
...await createSummonEnv({
|
|
17026
17814
|
role: options.role,
|
|
@@ -17132,6 +17920,38 @@ async function summonPublicRole(options) {
|
|
|
17132
17920
|
...stderr === void 0 || stderr === "" ? {} : { stderr }
|
|
17133
17921
|
};
|
|
17134
17922
|
}
|
|
17923
|
+
async function parentInvocationHost(sourceRunDirectory) {
|
|
17924
|
+
const { readFile: readFile21 } = await import("node:fs/promises");
|
|
17925
|
+
const path = join28(sourceRunDirectory, "invocation.json");
|
|
17926
|
+
let text;
|
|
17927
|
+
try {
|
|
17928
|
+
text = await readFile21(path, "utf8");
|
|
17929
|
+
} catch (error) {
|
|
17930
|
+
const code = error instanceof Error && "code" in error ? error.code : void 0;
|
|
17931
|
+
throw new Error(
|
|
17932
|
+
`parent invocation.json required for gate source run at ${path}: ${code ?? (error instanceof Error ? error.message : String(error))}`,
|
|
17933
|
+
{ cause: error }
|
|
17934
|
+
);
|
|
17935
|
+
}
|
|
17936
|
+
let raw;
|
|
17937
|
+
try {
|
|
17938
|
+
raw = JSON.parse(text);
|
|
17939
|
+
} catch (error) {
|
|
17940
|
+
throw new Error(
|
|
17941
|
+
`parent invocation.json unreadable at ${path}: ${error instanceof Error ? error.message : String(error)}`,
|
|
17942
|
+
{ cause: error }
|
|
17943
|
+
);
|
|
17944
|
+
}
|
|
17945
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
17946
|
+
throw new Error(`parent invocation.json has non-object shape at ${path}`);
|
|
17947
|
+
}
|
|
17948
|
+
const host = raw.host;
|
|
17949
|
+
if (host === void 0) return void 0;
|
|
17950
|
+
if (typeof host !== "string" || host.trim() === "") {
|
|
17951
|
+
throw new Error(`parent invocation.json host must be a non-empty string at ${path}`);
|
|
17952
|
+
}
|
|
17953
|
+
return host;
|
|
17954
|
+
}
|
|
17135
17955
|
async function summonGateOfficer(options) {
|
|
17136
17956
|
let home = options.home;
|
|
17137
17957
|
if (home === void 0) {
|
|
@@ -17145,6 +17965,7 @@ async function summonGateOfficer(options) {
|
|
|
17145
17965
|
submission: options.submission
|
|
17146
17966
|
});
|
|
17147
17967
|
}
|
|
17968
|
+
const parentHost = await parentInvocationHost(options.sourceRunDirectory);
|
|
17148
17969
|
const common = {
|
|
17149
17970
|
cwd: options.cwd,
|
|
17150
17971
|
...home === void 0 ? {} : { home },
|
|
@@ -17153,6 +17974,7 @@ async function summonGateOfficer(options) {
|
|
|
17153
17974
|
...options.signal === void 0 ? {} : { signal: options.signal },
|
|
17154
17975
|
...options.reask === void 0 ? {} : { reviewReask: options.reask },
|
|
17155
17976
|
...gateReviewInstruction === void 0 ? {} : { gateReviewInstruction },
|
|
17977
|
+
...parentHost === void 0 ? {} : { host: parentHost },
|
|
17156
17978
|
...options.roleTurnHost === void 0 ? {} : { roleTurnHost: options.roleTurnHost },
|
|
17157
17979
|
...options.createRunId === void 0 ? {} : { createRunId: options.createRunId }
|
|
17158
17980
|
};
|
|
@@ -17318,7 +18140,7 @@ var init_compliance_transport = __esm({
|
|
|
17318
18140
|
});
|
|
17319
18141
|
|
|
17320
18142
|
// src/dossier-resolution.ts
|
|
17321
|
-
import { existsSync as
|
|
18143
|
+
import { existsSync as existsSync9, statSync as statSync2 } from "node:fs";
|
|
17322
18144
|
import { resolve as resolve12 } from "node:path";
|
|
17323
18145
|
function resolveAuditDossier(env = process.env) {
|
|
17324
18146
|
const raw = env[AUDIT_RUN_DIR_ENV];
|
|
@@ -17327,7 +18149,7 @@ function resolveAuditDossier(env = process.env) {
|
|
|
17327
18149
|
}
|
|
17328
18150
|
const runDirectory = resolve12(raw);
|
|
17329
18151
|
try {
|
|
17330
|
-
if (!
|
|
18152
|
+
if (!existsSync9(runDirectory) || !statSync2(runDirectory).isDirectory()) {
|
|
17331
18153
|
return { status: "incomplete", observation: { kind: "missing-dossier" } };
|
|
17332
18154
|
}
|
|
17333
18155
|
} catch {
|
|
@@ -17577,11 +18399,11 @@ var init_navigator_session_contracts = __esm({
|
|
|
17577
18399
|
|
|
17578
18400
|
// src/archivist-record-topology.ts
|
|
17579
18401
|
import { createHash as createHash8 } from "node:crypto";
|
|
17580
|
-
import { join as
|
|
18402
|
+
import { join as join29 } from "node:path";
|
|
17581
18403
|
function subjectKeyedRecordDirectory(input) {
|
|
17582
18404
|
const ledgerHome = input.parentSessionFile !== void 0 && input.parentSessionFile.length > 0 ? resolveActivationLedgerHomeForPath(input.parentSessionFile) : resolveActivationLedgerHome(input.home);
|
|
17583
18405
|
const digest = createHash8("sha256").update(input.subject).digest("hex").slice(0, 32);
|
|
17584
|
-
return
|
|
18406
|
+
return join29(
|
|
17585
18407
|
activationBookDirectory(ledgerHome, resolveBookKeyFromGit(input.cwd)),
|
|
17586
18408
|
input.kind,
|
|
17587
18409
|
digest
|
|
@@ -17605,11 +18427,11 @@ __export(archivist_record_entry_exports, {
|
|
|
17605
18427
|
createRecordSessionOpen: () => createRecordSessionOpen,
|
|
17606
18428
|
subjectKeyedRecordDirectory: () => subjectKeyedRecordDirectory
|
|
17607
18429
|
});
|
|
17608
|
-
import { existsSync as
|
|
17609
|
-
import { dirname as dirname13, resolve as resolve13, join as
|
|
18430
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
18431
|
+
import { dirname as dirname13, resolve as resolve13, join as join30 } from "node:path";
|
|
17610
18432
|
import { SessionManager } from "@earendil-works/pi-coding-agent";
|
|
17611
18433
|
function readCurrentSession(sessionDir) {
|
|
17612
|
-
const ledger =
|
|
18434
|
+
const ledger = join30(sessionDir, CURRENT_SESSION_LEDGER);
|
|
17613
18435
|
try {
|
|
17614
18436
|
const value = JSON.parse(readFileSync3(ledger, "utf8"));
|
|
17615
18437
|
if (typeof value !== "object" || value === null || typeof value.sessionFile !== "string" || value.sessionFile.length === 0) {
|
|
@@ -17624,7 +18446,7 @@ function readCurrentSession(sessionDir) {
|
|
|
17624
18446
|
}
|
|
17625
18447
|
}
|
|
17626
18448
|
function writeCurrentSession(sessionDir, sessionFile) {
|
|
17627
|
-
const ledger =
|
|
18449
|
+
const ledger = join30(sessionDir, CURRENT_SESSION_LEDGER);
|
|
17628
18450
|
try {
|
|
17629
18451
|
writeFileSync5(ledger, `${JSON.stringify({ sessionFile })}
|
|
17630
18452
|
`, { flag: "wx" });
|
|
@@ -17685,10 +18507,10 @@ function createRecordSessionOpen(options) {
|
|
|
17685
18507
|
return { session: SessionManager.inMemory(cwd), resumed: false };
|
|
17686
18508
|
} else {
|
|
17687
18509
|
const parentResolved = resolve13(parentFile);
|
|
17688
|
-
sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ?
|
|
18510
|
+
sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join30(dirname13(parentResolved), options.kind) : join30(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
|
|
17689
18511
|
parentSession = parentFile;
|
|
17690
18512
|
}
|
|
17691
|
-
const nestAlreadyExists =
|
|
18513
|
+
const nestAlreadyExists = existsSync10(sessionDir);
|
|
17692
18514
|
ensureRealDirectoryTree(ledgerHome, sessionDir);
|
|
17693
18515
|
const mayResumeSameNest = options.subject !== void 0 || options.kind === WORKER_SUBMISSION_GATE_KIND;
|
|
17694
18516
|
if (mayResumeSameNest && nestAlreadyExists) {
|
|
@@ -17706,7 +18528,7 @@ function createRecordSessionOpen(options) {
|
|
|
17706
18528
|
);
|
|
17707
18529
|
if (session.isPersisted()) {
|
|
17708
18530
|
const file = session.getSessionFile();
|
|
17709
|
-
if (file !== void 0 && !
|
|
18531
|
+
if (file !== void 0 && !existsSync10(file)) {
|
|
17710
18532
|
const header = session.getHeader();
|
|
17711
18533
|
if (header !== null && header.type === "session") {
|
|
17712
18534
|
writeFileSync5(file, `${JSON.stringify(header)}
|
|
@@ -17724,7 +18546,7 @@ function createRecordSession(options) {
|
|
|
17724
18546
|
return createRecordSessionOpen(options).session;
|
|
17725
18547
|
}
|
|
17726
18548
|
function bookDirectOfficerRunPointer(options) {
|
|
17727
|
-
const nest =
|
|
18549
|
+
const nest = join30(dirname13(options.parentSessionFile), "auditor-roles");
|
|
17728
18550
|
mkdirSync4(nest, { recursive: true });
|
|
17729
18551
|
const pointer = {
|
|
17730
18552
|
version: 1,
|
|
@@ -17734,7 +18556,7 @@ function bookDirectOfficerRunPointer(options) {
|
|
|
17734
18556
|
...options.runDirectory !== void 0 && options.runDirectory.trim() !== "" ? { runDirectory: options.runDirectory } : {}
|
|
17735
18557
|
};
|
|
17736
18558
|
writeFileSync5(
|
|
17737
|
-
|
|
18559
|
+
join30(nest, `${options.officer}.pointer.json`),
|
|
17738
18560
|
`${JSON.stringify(pointer)}
|
|
17739
18561
|
`,
|
|
17740
18562
|
"utf8"
|
|
@@ -19432,132 +20254,6 @@ var init_tool_execution_observation = __esm({
|
|
|
19432
20254
|
}
|
|
19433
20255
|
});
|
|
19434
20256
|
|
|
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
20257
|
// src/collector-receipt.ts
|
|
19562
20258
|
function fail4(message) {
|
|
19563
20259
|
throw new Error(message);
|
|
@@ -19567,13 +20263,15 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19567
20263
|
if (ledger.unresolvedTransportFailure) fail4("Collector cannot output while a transport failure is unrecovered");
|
|
19568
20264
|
if (ledger.latestCompleteSnapshotId === void 0) fail4("Collector output requires a complete final snapshot");
|
|
19569
20265
|
if (ledger.activationTime === void 0 || ledger.deadlineTime === void 0) fail4("Collector output requires activation timeline");
|
|
20266
|
+
if (ledger.config.prNumber === void 0) {
|
|
20267
|
+
fail4("Collector output requires a bound PR target; call ak_collector_bind_target first or pass --pr");
|
|
20268
|
+
}
|
|
19570
20269
|
if (clock !== void 0) ledger.assertOutputObservationLaw(clock);
|
|
19571
20270
|
else if (ledger.observedGeneration !== ledger.mutationGeneration || ledger.finalObservationRequired && !ledger.finalObservationCompleted) {
|
|
19572
20271
|
fail4("Collector output requires a complete observe after the latest request/wait mutation");
|
|
19573
20272
|
}
|
|
19574
20273
|
const finalSnapshot = ledger.getSnapshot(ledger.latestCompleteSnapshotId);
|
|
19575
20274
|
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
20275
|
const evidenceRecords = [...ledger.allEvidence()];
|
|
19578
20276
|
const snapshots = [...ledger.allSnapshots()];
|
|
19579
20277
|
const evidenceIndex = new Map(evidenceRecords.map((record4) => [record4.evidenceId, record4]));
|
|
@@ -19586,7 +20284,7 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19586
20284
|
for (const id of snapshot.evidenceIds) if (!evidenceIndex.has(id)) fail4(`Collector snapshot ref "${id}" does not resolve`);
|
|
19587
20285
|
}
|
|
19588
20286
|
const groups = extractCollectorEvidenceIdentityGroups(evidenceRecords, finalSnapshot.headOid);
|
|
19589
|
-
enrichCollectorFindings({
|
|
20287
|
+
const findingsProjection = enrichCollectorFindings({
|
|
19590
20288
|
candidate: candidateRaw,
|
|
19591
20289
|
records: evidenceRecords,
|
|
19592
20290
|
groups,
|
|
@@ -19595,7 +20293,6 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19595
20293
|
prNumber: ledger.config.prNumber
|
|
19596
20294
|
});
|
|
19597
20295
|
for (const group of groups) {
|
|
19598
|
-
if (group.attendance !== true) fail4("Collector group lacks attendance");
|
|
19599
20296
|
for (const material of group.materials) {
|
|
19600
20297
|
if (material.evidenceId === void 0 || !evidenceIndex.has(material.evidenceId)) fail4("Collector material lacks a receipt-local evidence ref");
|
|
19601
20298
|
}
|
|
@@ -19603,10 +20300,20 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19603
20300
|
if (finding2.source.evidenceId === void 0 || !evidenceIndex.has(finding2.source.evidenceId)) fail4("Collector finding lacks a receipt-local evidence ref");
|
|
19604
20301
|
}
|
|
19605
20302
|
}
|
|
20303
|
+
const unfinished = extractCollectorUnfinishedReasons(candidateRaw);
|
|
20304
|
+
const submissionProjection = {
|
|
20305
|
+
findingsSource: findingsProjection.findingsSource,
|
|
20306
|
+
findingsProjectedCount: findingsProjection.findingsProjectedCount,
|
|
20307
|
+
findingsUnprojected: findingsProjection.findingsUnprojected,
|
|
20308
|
+
unfinishedReasonsSource: unfinished.source,
|
|
20309
|
+
unfinishedReasonsProjectedCount: unfinished.reasons?.length ?? 0,
|
|
20310
|
+
unfinishedReasonsUnprojected: unfinished.unprojected
|
|
20311
|
+
};
|
|
19606
20312
|
return {
|
|
19607
20313
|
host: COLLECTOR_HOST,
|
|
19608
20314
|
repository: ledger.config.repository.canonical,
|
|
19609
20315
|
prNumber: ledger.config.prNumber,
|
|
20316
|
+
prState: finalSnapshot.prState,
|
|
19610
20317
|
manifestDigest: ledger.config.manifest.digest,
|
|
19611
20318
|
activationTime: ledger.activationTime.toISOString(),
|
|
19612
20319
|
deadlineTime: ledger.deadlineTime.toISOString(),
|
|
@@ -19614,6 +20321,8 @@ function buildCollectorReceipt(ledger, candidateRaw, clock) {
|
|
|
19614
20321
|
finalSnapshotId: finalSnapshot.snapshotId,
|
|
19615
20322
|
targetHead: finalSnapshot.headOid,
|
|
19616
20323
|
groups,
|
|
20324
|
+
...unfinished.reasons === void 0 ? {} : { unfinishedReasons: unfinished.reasons },
|
|
20325
|
+
submissionProjection,
|
|
19617
20326
|
requestAttempts: [...ledger.requestAttempts()],
|
|
19618
20327
|
snapshots,
|
|
19619
20328
|
evidenceRecords: evidenceRecords.map(toReceiptEvidenceRecord)
|
|
@@ -19643,340 +20352,26 @@ var init_collector_receipt = __esm({
|
|
|
19643
20352
|
|
|
19644
20353
|
// src/collector-role.ts
|
|
19645
20354
|
function buildMethodContext(activation) {
|
|
20355
|
+
const pr = activation.ledger.config.prNumber;
|
|
19646
20356
|
return [
|
|
19647
20357
|
"<collector_method>",
|
|
19648
20358
|
`host: github.com`,
|
|
19649
20359
|
`repository: ${activation.repository.canonical}`,
|
|
19650
|
-
`prNumber: ${
|
|
20360
|
+
`prNumber: ${pr === void 0 ? "unbound \u2014 call ak_collector_bind_target with the role-decided issue/PR before observe" : String(pr)}`,
|
|
19651
20361
|
`requests: ${JSON.stringify(activation.manifest.requests.map((request) => ({ id: request.id })))}`,
|
|
19652
20362
|
"</collector_method>"
|
|
19653
20363
|
].join("\n");
|
|
19654
20364
|
}
|
|
19655
|
-
function
|
|
19656
|
-
|
|
19657
|
-
|
|
19658
|
-
|
|
19659
|
-
|
|
19660
|
-
|
|
19661
|
-
|
|
19662
|
-
|
|
19663
|
-
|
|
19664
|
-
|
|
19665
|
-
pi.registerFlag("ak-collector-pr", {
|
|
19666
|
-
description: "Positive safe-integer pull request number for Collector. Supported profile: --no-skills, --no-extensions with only the explicit Collector package extension, no prompt templates/context files, one print/JSON prompt",
|
|
19667
|
-
type: "string"
|
|
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
|
-
);
|
|
19729
|
-
}
|
|
19730
|
-
if (!firstDispatchDone) {
|
|
19731
|
-
firstDispatchDone = true;
|
|
19732
|
-
activation.ledger.recordActivation(activation.clock);
|
|
19733
|
-
}
|
|
19734
|
-
return {
|
|
19735
|
-
systemPrompt: [
|
|
19736
|
-
event.systemPrompt,
|
|
19737
|
-
"",
|
|
19738
|
-
"<collector_soul>",
|
|
19739
|
-
activation.soul,
|
|
19740
|
-
"</collector_soul>",
|
|
19741
|
-
"",
|
|
19742
|
-
buildMethodContext(activation)
|
|
19743
|
-
].join("\n")
|
|
19744
|
-
};
|
|
19745
|
-
});
|
|
19746
|
-
pi.on("tool_call", (event) => {
|
|
19747
|
-
if (activation === void 0) return;
|
|
19748
|
-
if (activation.ledger.fatal) {
|
|
19749
|
-
return {
|
|
19750
|
-
block: true,
|
|
19751
|
-
reason: activation.ledger.fatalReason ?? "\u901A\u8FDB\u53F8\u81F4\u547D\u72B6\u6001"
|
|
19752
|
-
};
|
|
19753
|
-
}
|
|
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
|
-
if (event.toolName === COLLECTOR_OUTPUT_TOOL) {
|
|
19761
|
-
activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, event.toolCallId);
|
|
19762
|
-
}
|
|
19763
|
-
if (activation.ledger.outputCandidate && event.toolName !== COLLECTOR_OUTPUT_TOOL) {
|
|
19764
|
-
return {
|
|
19765
|
-
block: true,
|
|
19766
|
-
reason: "\u901A\u8FDB\u53F8\u5DF2\u4EA7\u51FA\u8F93\u51FA\u5019\u9009\uFF0C\u672C\u5C40\u4E0D\u518D\u53D7\u7406\u64CD\u4F5C"
|
|
19767
|
-
};
|
|
19768
|
-
}
|
|
19769
|
-
return void 0;
|
|
19770
|
-
});
|
|
19771
|
-
pi.on("tool_result", (event) => {
|
|
19772
|
-
if (activation === void 0) return;
|
|
19773
|
-
activation.ledger.completeOperational(event.toolCallId);
|
|
19774
|
-
});
|
|
19775
|
-
pi.on("session_shutdown", () => {
|
|
19776
|
-
if (activation === void 0) return;
|
|
19777
|
-
if (activation.ledger.fatal) {
|
|
19778
|
-
if (process.exitCode === void 0 || process.exitCode === 0) {
|
|
19779
|
-
process.exitCode = 1;
|
|
19780
|
-
}
|
|
19781
|
-
}
|
|
19782
|
-
});
|
|
19783
|
-
};
|
|
19784
|
-
const registerTools = () => {
|
|
19785
|
-
if (toolsRegistered) return;
|
|
19786
|
-
toolsRegistered = true;
|
|
19787
|
-
pi.registerTool({
|
|
19788
|
-
name: COLLECTOR_OBSERVE_TOOL,
|
|
19789
|
-
label: "\u901A\u8FDB\u53F8\u89C2\u5BDF",
|
|
19790
|
-
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",
|
|
19791
|
-
promptSnippet: "\u6293\u53D6\u914D\u7F6E\u76EE\u6807 PR \u8BC1\u636E",
|
|
19792
|
-
parameters: observeSchema,
|
|
19793
|
-
async execute(toolCallId, _params, signal, _onUpdate, ctx) {
|
|
19794
|
-
if (activation === void 0) {
|
|
19795
|
-
throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
19796
|
-
}
|
|
19797
|
-
try {
|
|
19798
|
-
activation.ledger.beginOperational(COLLECTOR_OBSERVE_TOOL, toolCallId);
|
|
19799
|
-
const { snapshot, contextView } = await activation.ledger.observe(
|
|
19800
|
-
activation.transport,
|
|
19801
|
-
activation.clock,
|
|
19802
|
-
signal
|
|
19803
|
-
);
|
|
19804
|
-
activation.ledger.completeOperational(toolCallId);
|
|
19805
|
-
if (snapshot.prState !== "OPEN") {
|
|
19806
|
-
}
|
|
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
|
-
}
|
|
19821
|
-
}
|
|
19822
|
-
});
|
|
19823
|
-
pi.registerTool({
|
|
19824
|
-
name: COLLECTOR_READ_TOOL,
|
|
19825
|
-
label: "\u901A\u8FDB\u53F8\u5F00\u5377",
|
|
19826
|
-
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",
|
|
19827
|
-
promptSnippet: "\u6309\u6307\u9488\u5F00\u5377\u8BFB\u6750\u6599",
|
|
19828
|
-
parameters: readSchema,
|
|
19829
|
-
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
19830
|
-
if (activation === void 0) {
|
|
19831
|
-
throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
19832
|
-
}
|
|
19833
|
-
try {
|
|
19834
|
-
activation.ledger.beginOperational(COLLECTOR_READ_TOOL, toolCallId);
|
|
19835
|
-
const record4 = activation.ledger.getEvidence(params.evidenceId);
|
|
19836
|
-
if (record4 === void 0 || record4.kind !== "review" && record4.kind !== "issue_comment" && record4.kind !== "review_comment" && record4.kind !== "reaction" || typeof record4.body !== "string") {
|
|
19837
|
-
throw new CollectorUnknownEvidenceError(params.evidenceId);
|
|
19838
|
-
}
|
|
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
|
-
}
|
|
19938
|
-
try {
|
|
19939
|
-
activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, toolCallId);
|
|
19940
|
-
const receipt = buildCollectorReceipt(
|
|
19941
|
-
activation.ledger,
|
|
19942
|
-
params,
|
|
19943
|
-
activation.clock
|
|
19944
|
-
);
|
|
19945
|
-
activation.ledger.recordOutputCandidate();
|
|
19946
|
-
const acceptedDetails = receipt;
|
|
19947
|
-
return {
|
|
19948
|
-
content: [{
|
|
19949
|
-
type: "text",
|
|
19950
|
-
text: COLLECTOR_ACCEPTED_TEXT
|
|
19951
|
-
}],
|
|
19952
|
-
details: acceptedDetails,
|
|
19953
|
-
terminate: true
|
|
19954
|
-
};
|
|
19955
|
-
} catch (error) {
|
|
19956
|
-
if (error instanceof Error && error.collectorFatal === true) {
|
|
19957
|
-
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
19958
|
-
}
|
|
19959
|
-
throw error;
|
|
19960
|
-
} finally {
|
|
19961
|
-
activation.ledger.completeOperational(toolCallId);
|
|
19962
|
-
}
|
|
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
|
-
}
|
|
20365
|
+
function parsePositiveTicket(raw, label) {
|
|
20366
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
20367
|
+
if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) return raw;
|
|
20368
|
+
if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) return Number(raw.trim());
|
|
20369
|
+
throw new CollectorTargetBindError(`ak_collector_bind_target ${label} must be a positive safe integer`);
|
|
20370
|
+
}
|
|
20371
|
+
function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
20372
|
+
let toolsRegistered = false;
|
|
20373
|
+
return {
|
|
20374
|
+
async activate(ctx) {
|
|
19980
20375
|
const soul = (await dependencies.loadSoul()).trim();
|
|
19981
20376
|
if (soul.length === 0) throw new Error("Collector soul is empty");
|
|
19982
20377
|
const repoFlag = pi.getFlag("ak-collector-repo");
|
|
@@ -19985,58 +20380,14 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
19985
20380
|
if (typeof repoFlag !== "string" || repoFlag.trim().length === 0) {
|
|
19986
20381
|
throw new Error("Collector requires --ak-collector-repo");
|
|
19987
20382
|
}
|
|
19988
|
-
if (typeof prFlag !== "string" && typeof prFlag !== "number") {
|
|
19989
|
-
throw new Error("Collector requires --ak-collector-pr");
|
|
19990
|
-
}
|
|
19991
20383
|
const repository = parseCollectorRepository(repoFlag);
|
|
19992
|
-
|
|
19993
|
-
|
|
19994
|
-
|
|
19995
|
-
|
|
19996
|
-
|
|
19997
|
-
return name.includes("skill") || name.includes("prompt") || name.startsWith("template");
|
|
19998
|
-
});
|
|
19999
|
-
if (ambientCommands.length > 0) {
|
|
20000
|
-
throw new Error(
|
|
20001
|
-
`Collector detected ambient instruction commands: ${ambientCommands.map((c) => c.name).join(", ")}`
|
|
20002
|
-
);
|
|
20003
|
-
}
|
|
20004
|
-
const preExisting = pi.getAllTools();
|
|
20005
|
-
for (const required of COLLECTOR_REQUIRED_TOOLS) {
|
|
20006
|
-
const prior = preExisting.filter((tool) => tool.name === required);
|
|
20007
|
-
if (prior.length > 0) {
|
|
20008
|
-
throw new Error(`Collector required tool name collision: ${required}`);
|
|
20009
|
-
}
|
|
20010
|
-
}
|
|
20011
|
-
registerTools();
|
|
20012
|
-
const allTools = pi.getAllTools();
|
|
20013
|
-
for (const required of COLLECTOR_REQUIRED_TOOLS) {
|
|
20014
|
-
const matches = allTools.filter((tool2) => tool2.name === required);
|
|
20015
|
-
if (matches.length === 0) {
|
|
20016
|
-
throw new Error(`Collector required tool missing: ${required}`);
|
|
20017
|
-
}
|
|
20018
|
-
if (matches.length > 1) {
|
|
20019
|
-
throw new Error(`Collector required tool name collision: ${required}`);
|
|
20020
|
-
}
|
|
20021
|
-
const tool = matches[0];
|
|
20022
|
-
if (dependencies.packageExtensionPath !== void 0 && tool.sourceInfo?.path !== void 0 && tool.sourceInfo.path !== dependencies.packageExtensionPath && !tool.sourceInfo.path.includes("role-runtime")) {
|
|
20023
|
-
throw new Error(
|
|
20024
|
-
`Collector required tool ${required} is overridden by ${tool.sourceInfo.path}`
|
|
20025
|
-
);
|
|
20026
|
-
}
|
|
20027
|
-
}
|
|
20028
|
-
pi.setActiveTools([...COLLECTOR_REQUIRED_TOOLS]);
|
|
20029
|
-
const active = new Set(pi.getActiveTools());
|
|
20030
|
-
for (const required of COLLECTOR_REQUIRED_TOOLS) {
|
|
20031
|
-
if (!active.has(required)) {
|
|
20032
|
-
throw new Error(`Collector failed to activate required tool ${required}`);
|
|
20033
|
-
}
|
|
20034
|
-
}
|
|
20035
|
-
for (const name of active) {
|
|
20036
|
-
if (!COLLECTOR_REQUIRED_TOOLS.includes(name)) {
|
|
20037
|
-
throw new Error(`Collector active tool surface includes unexpected ${name}`);
|
|
20038
|
-
}
|
|
20384
|
+
let prNumber;
|
|
20385
|
+
if (typeof prFlag === "string" && prFlag.trim().length > 0) {
|
|
20386
|
+
prNumber = parseCollectorPrNumber(prFlag);
|
|
20387
|
+
} else if (typeof prFlag === "number") {
|
|
20388
|
+
prNumber = parseCollectorPrNumber(prFlag);
|
|
20039
20389
|
}
|
|
20390
|
+
const manifest = typeof requestManifestFlag === "string" && requestManifestFlag.trim().length > 0 ? await loadCollectorManifest(requestManifestFlag) : emptyCollectorManifest();
|
|
20040
20391
|
const clock = dependencies.createClock?.() ?? createSystemCollectorClock();
|
|
20041
20392
|
const transport = dependencies.createTransport();
|
|
20042
20393
|
const ledger = dependencies.createLedger(
|
|
@@ -20044,27 +20395,292 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
20044
20395
|
clock,
|
|
20045
20396
|
ctx
|
|
20046
20397
|
);
|
|
20047
|
-
|
|
20048
|
-
firstDispatchDone = true;
|
|
20049
|
-
}
|
|
20050
|
-
activation = {
|
|
20398
|
+
return {
|
|
20051
20399
|
soul,
|
|
20052
20400
|
repository,
|
|
20053
|
-
prNumber,
|
|
20054
20401
|
manifest,
|
|
20055
20402
|
ledger,
|
|
20056
20403
|
transport,
|
|
20057
20404
|
clock
|
|
20058
20405
|
};
|
|
20406
|
+
},
|
|
20407
|
+
assembleMaterials(activation, baseSystemPrompt) {
|
|
20408
|
+
return [
|
|
20409
|
+
baseSystemPrompt,
|
|
20410
|
+
"",
|
|
20411
|
+
"<collector_soul>",
|
|
20412
|
+
activation.soul,
|
|
20413
|
+
"</collector_soul>",
|
|
20414
|
+
"",
|
|
20415
|
+
buildMethodContext(activation)
|
|
20416
|
+
].join("\n");
|
|
20417
|
+
},
|
|
20418
|
+
onToolCall(activation, event) {
|
|
20419
|
+
if (activation.ledger.fatal) {
|
|
20420
|
+
return {
|
|
20421
|
+
block: true,
|
|
20422
|
+
reason: activation.ledger.fatalReason ?? "\u901A\u8FDB\u53F8\u81F4\u547D\u72B6\u6001"
|
|
20423
|
+
};
|
|
20424
|
+
}
|
|
20425
|
+
if (event.toolName === COLLECTOR_OUTPUT_TOOL) {
|
|
20426
|
+
activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, event.toolCallId);
|
|
20427
|
+
}
|
|
20428
|
+
if (activation.ledger.outputCandidate && event.toolName !== COLLECTOR_OUTPUT_TOOL) {
|
|
20429
|
+
return {
|
|
20430
|
+
block: true,
|
|
20431
|
+
reason: "\u901A\u8FDB\u53F8\u5DF2\u4EA7\u51FA\u8F93\u51FA\u5019\u9009\uFF0C\u672C\u5C40\u4E0D\u518D\u53D7\u7406\u64CD\u4F5C"
|
|
20432
|
+
};
|
|
20433
|
+
}
|
|
20434
|
+
return void 0;
|
|
20435
|
+
},
|
|
20436
|
+
onToolResult(activation, event) {
|
|
20437
|
+
activation.ledger.completeOperational(event.toolCallId);
|
|
20438
|
+
},
|
|
20439
|
+
registerBusinessTools(getActivation) {
|
|
20440
|
+
if (toolsRegistered) return;
|
|
20441
|
+
toolsRegistered = true;
|
|
20442
|
+
pi.registerTool({
|
|
20443
|
+
name: COLLECTOR_BIND_TARGET_TOOL,
|
|
20444
|
+
label: "\u901A\u8FDB\u53F8\u8BA4\u7968\u7ED1\u5B9A",
|
|
20445
|
+
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",
|
|
20446
|
+
promptSnippet: "\u7ED1\u5B9A\u89D2\u8272\u5224\u5B9A\u7684 issue/PR \u76EE\u6807",
|
|
20447
|
+
parameters: bindSchema,
|
|
20448
|
+
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20449
|
+
const activation = getActivation();
|
|
20450
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20451
|
+
try {
|
|
20452
|
+
activation.ledger.beginOperational(COLLECTOR_BIND_TARGET_TOOL, toolCallId);
|
|
20453
|
+
const prNumber = parsePositiveTicket(params.prNumber, "prNumber");
|
|
20454
|
+
const issueNumber = parsePositiveTicket(params.issueNumber, "issueNumber");
|
|
20455
|
+
if (prNumber === void 0 && issueNumber === void 0) {
|
|
20456
|
+
throw new CollectorTargetBindError(
|
|
20457
|
+
"ak_collector_bind_target requires role-decided prNumber and/or issueNumber"
|
|
20458
|
+
);
|
|
20459
|
+
}
|
|
20460
|
+
let bound = prNumber;
|
|
20461
|
+
if (issueNumber !== void 0) {
|
|
20462
|
+
const associated = await listPullRequestNumbersByTicket(createGhApiRunner(), {
|
|
20463
|
+
owner: activation.repository.owner,
|
|
20464
|
+
repo: activation.repository.repo,
|
|
20465
|
+
ticketNumber: issueNumber
|
|
20466
|
+
});
|
|
20467
|
+
if (associated.length === 0) {
|
|
20468
|
+
throw new CollectorTargetBindError(
|
|
20469
|
+
`no PR associated with issue #${issueNumber} in ${activation.repository.canonical}; pass an explicit --pr or a different issueNumber`
|
|
20470
|
+
);
|
|
20471
|
+
}
|
|
20472
|
+
if (associated.length > 1) {
|
|
20473
|
+
throw new CollectorTargetBindError(
|
|
20474
|
+
`multiple PRs associated with issue #${issueNumber}: ${associated.join(", ")}; pass an explicit prNumber or --pr`
|
|
20475
|
+
);
|
|
20476
|
+
}
|
|
20477
|
+
const fromIssue = associated[0];
|
|
20478
|
+
if (prNumber !== void 0 && prNumber !== fromIssue) {
|
|
20479
|
+
throw new CollectorTargetBindError(
|
|
20480
|
+
`prNumber ${prNumber} conflicts with issue #${issueNumber} association PR ${fromIssue}`
|
|
20481
|
+
);
|
|
20482
|
+
}
|
|
20483
|
+
bound = fromIssue;
|
|
20484
|
+
}
|
|
20485
|
+
activation.ledger.bindTarget(bound);
|
|
20486
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20487
|
+
return {
|
|
20488
|
+
content: [{
|
|
20489
|
+
type: "text",
|
|
20490
|
+
text: `\u76EE\u6807\u5DF2\u7ED1\u5B9A\uFF1A${activation.repository.canonical}#${bound}`
|
|
20491
|
+
}],
|
|
20492
|
+
details: {
|
|
20493
|
+
repository: activation.repository.canonical,
|
|
20494
|
+
prNumber: bound,
|
|
20495
|
+
...issueNumber === void 0 ? {} : { issueNumber }
|
|
20496
|
+
}
|
|
20497
|
+
};
|
|
20498
|
+
} catch (error) {
|
|
20499
|
+
if (isCorrectableExecuteError(error)) throw error;
|
|
20500
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20501
|
+
} finally {
|
|
20502
|
+
try {
|
|
20503
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20504
|
+
} catch {
|
|
20505
|
+
}
|
|
20506
|
+
}
|
|
20507
|
+
}
|
|
20508
|
+
});
|
|
20509
|
+
pi.registerTool({
|
|
20510
|
+
name: COLLECTOR_OBSERVE_TOOL,
|
|
20511
|
+
label: "\u901A\u8FDB\u53F8\u89C2\u5BDF",
|
|
20512
|
+
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",
|
|
20513
|
+
promptSnippet: "\u6293\u53D6\u914D\u7F6E\u76EE\u6807 PR \u8BC1\u636E",
|
|
20514
|
+
parameters: observeSchema,
|
|
20515
|
+
async execute(toolCallId, _params, signal, _onUpdate, ctx) {
|
|
20516
|
+
const activation = getActivation();
|
|
20517
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20518
|
+
try {
|
|
20519
|
+
activation.ledger.beginOperational(COLLECTOR_OBSERVE_TOOL, toolCallId);
|
|
20520
|
+
const { snapshot, contextView } = await activation.ledger.observe(
|
|
20521
|
+
activation.transport,
|
|
20522
|
+
activation.clock,
|
|
20523
|
+
signal
|
|
20524
|
+
);
|
|
20525
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20526
|
+
return {
|
|
20527
|
+
content: [{
|
|
20528
|
+
type: "text",
|
|
20529
|
+
text: JSON.stringify(contextView)
|
|
20530
|
+
}],
|
|
20531
|
+
details: contextView
|
|
20532
|
+
};
|
|
20533
|
+
} catch (error) {
|
|
20534
|
+
if (isCorrectableExecuteError(error)) throw error;
|
|
20535
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20536
|
+
}
|
|
20537
|
+
}
|
|
20538
|
+
});
|
|
20539
|
+
pi.registerTool({
|
|
20540
|
+
name: COLLECTOR_READ_TOOL,
|
|
20541
|
+
label: "\u901A\u8FDB\u53F8\u5F00\u5377",
|
|
20542
|
+
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",
|
|
20543
|
+
promptSnippet: "\u6309\u6307\u9488\u5F00\u5377\u8BFB\u6750\u6599",
|
|
20544
|
+
parameters: readSchema,
|
|
20545
|
+
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20546
|
+
const activation = getActivation();
|
|
20547
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20548
|
+
try {
|
|
20549
|
+
activation.ledger.beginOperational(COLLECTOR_READ_TOOL, toolCallId);
|
|
20550
|
+
const record4 = activation.ledger.getEvidence(params.evidenceId);
|
|
20551
|
+
if (record4 === void 0 || record4.kind !== "review" && record4.kind !== "issue_comment" && record4.kind !== "review_comment" && record4.kind !== "reaction" || typeof record4.body !== "string") {
|
|
20552
|
+
throw new CollectorUnknownEvidenceError(params.evidenceId);
|
|
20553
|
+
}
|
|
20554
|
+
const material = projectEvidenceEntryView(record4);
|
|
20555
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20556
|
+
return {
|
|
20557
|
+
content: [{
|
|
20558
|
+
type: "text",
|
|
20559
|
+
text: JSON.stringify(material)
|
|
20560
|
+
}],
|
|
20561
|
+
details: material
|
|
20562
|
+
};
|
|
20563
|
+
} catch (error) {
|
|
20564
|
+
if (isCorrectableExecuteError(error)) throw error;
|
|
20565
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20566
|
+
}
|
|
20567
|
+
}
|
|
20568
|
+
});
|
|
20569
|
+
pi.registerTool({
|
|
20570
|
+
name: COLLECTOR_REQUEST_TOOL,
|
|
20571
|
+
label: "\u901A\u8FDB\u53F8\u8BF7\u6C42",
|
|
20572
|
+
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",
|
|
20573
|
+
promptSnippet: "\u6309\u914D\u7F6E\u53D1\u4E00\u6B21\u8BF7\u6C42",
|
|
20574
|
+
parameters: requestSchema,
|
|
20575
|
+
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
20576
|
+
const activation = getActivation();
|
|
20577
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20578
|
+
try {
|
|
20579
|
+
activation.ledger.beginOperational(COLLECTOR_REQUEST_TOOL, toolCallId);
|
|
20580
|
+
const details = await activation.ledger.request(
|
|
20581
|
+
params,
|
|
20582
|
+
activation.transport,
|
|
20583
|
+
activation.clock,
|
|
20584
|
+
signal
|
|
20585
|
+
);
|
|
20586
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20587
|
+
return {
|
|
20588
|
+
content: [{
|
|
20589
|
+
type: "text",
|
|
20590
|
+
text: `\u8BF7\u6C42\u5C1D\u8BD5\u5DF2\u8BB0\u5F55\uFF1Arequest ${params.requestId}`
|
|
20591
|
+
}],
|
|
20592
|
+
details
|
|
20593
|
+
};
|
|
20594
|
+
} catch (error) {
|
|
20595
|
+
if (isCorrectableExecuteError(error)) throw error;
|
|
20596
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20597
|
+
}
|
|
20598
|
+
}
|
|
20599
|
+
});
|
|
20600
|
+
pi.registerTool({
|
|
20601
|
+
name: COLLECTOR_WAIT_TOOL,
|
|
20602
|
+
label: "\u901A\u8FDB\u53F8\u7B49\u5F85",
|
|
20603
|
+
description: "\u518D\u89C2\u5BDF\u524D\u7B49\u5F85\uFF1B\u5355\u6B21\u4E0A\u9650\u4E94\u5206\u949F\u4E14\u4E0D\u8D85\u5269\u4F59\u8D44\u683C\u3002",
|
|
20604
|
+
promptSnippet: "\u8D44\u683C\u622A\u6B62\u524D\u7B49\u5F85",
|
|
20605
|
+
parameters: waitSchema,
|
|
20606
|
+
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
20607
|
+
const activation = getActivation();
|
|
20608
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20609
|
+
try {
|
|
20610
|
+
activation.ledger.beginOperational(COLLECTOR_WAIT_TOOL, toolCallId);
|
|
20611
|
+
const details = await activation.ledger.wait(
|
|
20612
|
+
params,
|
|
20613
|
+
activation.clock,
|
|
20614
|
+
signal
|
|
20615
|
+
);
|
|
20616
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20617
|
+
return {
|
|
20618
|
+
content: [{
|
|
20619
|
+
type: "text",
|
|
20620
|
+
text: `\u5DF2\u7B49\u5F85 ${String(details.effectiveMs)}ms`
|
|
20621
|
+
}],
|
|
20622
|
+
details
|
|
20623
|
+
};
|
|
20624
|
+
} catch (error) {
|
|
20625
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20626
|
+
}
|
|
20627
|
+
}
|
|
20628
|
+
});
|
|
20629
|
+
pi.registerTool({
|
|
20630
|
+
name: COLLECTOR_OUTPUT_TOOL,
|
|
20631
|
+
label: "\u901A\u8FDB\u53F8\u8F93\u51FA",
|
|
20632
|
+
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",
|
|
20633
|
+
promptSnippet: "\u63D0\u4EA4\u901A\u8FDB\u53F8\u56DE\u6267",
|
|
20634
|
+
bounceInfrastructureDeclaration(params) {
|
|
20635
|
+
const activation = getActivation();
|
|
20636
|
+
if (activation === void 0) return void 0;
|
|
20637
|
+
try {
|
|
20638
|
+
buildCollectorReceipt(activation.ledger, params, activation.clock);
|
|
20639
|
+
} catch {
|
|
20640
|
+
return void 0;
|
|
20641
|
+
}
|
|
20642
|
+
return new CollectorNormalCompletionDeclarationError();
|
|
20643
|
+
},
|
|
20644
|
+
parameters: outputSchema,
|
|
20645
|
+
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20646
|
+
const activation = getActivation();
|
|
20647
|
+
if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
|
|
20648
|
+
try {
|
|
20649
|
+
activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, toolCallId);
|
|
20650
|
+
const receipt = buildCollectorReceipt(
|
|
20651
|
+
activation.ledger,
|
|
20652
|
+
params,
|
|
20653
|
+
activation.clock
|
|
20654
|
+
);
|
|
20655
|
+
activation.ledger.recordOutputCandidate();
|
|
20656
|
+
return {
|
|
20657
|
+
content: [{
|
|
20658
|
+
type: "text",
|
|
20659
|
+
text: COLLECTOR_ACCEPTED_TEXT
|
|
20660
|
+
}],
|
|
20661
|
+
details: receipt,
|
|
20662
|
+
terminate: true
|
|
20663
|
+
};
|
|
20664
|
+
} catch (error) {
|
|
20665
|
+
if (error instanceof Error && error.collectorFatal === true) {
|
|
20666
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
20667
|
+
}
|
|
20668
|
+
throw error;
|
|
20669
|
+
} finally {
|
|
20670
|
+
activation.ledger.completeOperational(toolCallId);
|
|
20671
|
+
}
|
|
20672
|
+
}
|
|
20673
|
+
});
|
|
20059
20674
|
}
|
|
20060
20675
|
};
|
|
20061
20676
|
}
|
|
20062
|
-
var CollectorNormalCompletionDeclarationError, COLLECTOR_REQUIRED_TOOLS, observeSchema, readSchema, requestSchema, waitSchema, outputSchema;
|
|
20677
|
+
var CollectorNormalCompletionDeclarationError, CollectorTargetBindError, COLLECTOR_REQUIRED_TOOLS, COLLECTOR_TRANSPORT_FLAGS, observeSchema, readSchema, requestSchema, waitSchema, bindSchema, outputSchema;
|
|
20063
20678
|
var init_collector_role = __esm({
|
|
20064
20679
|
"src/collector-role.ts"() {
|
|
20065
20680
|
"use strict";
|
|
20066
20681
|
init_collector_config();
|
|
20067
20682
|
init_collector_evidence();
|
|
20683
|
+
init_collector_github();
|
|
20068
20684
|
init_collector_ledger();
|
|
20069
20685
|
init_collector_receipt();
|
|
20070
20686
|
init_collector_tool_schemas();
|
|
@@ -20072,24 +20688,54 @@ var init_collector_role = __esm({
|
|
|
20072
20688
|
init_submission_correctable_error();
|
|
20073
20689
|
init_collector_identity();
|
|
20074
20690
|
init_collector_identity();
|
|
20075
|
-
init_collector_config();
|
|
20076
20691
|
CollectorNormalCompletionDeclarationError = class extends CorrectableSubmissionError {
|
|
20077
20692
|
constructor() {
|
|
20078
20693
|
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
20694
|
this.name = "CollectorNormalCompletionDeclarationError";
|
|
20080
20695
|
}
|
|
20081
20696
|
};
|
|
20697
|
+
CollectorTargetBindError = class extends CorrectableSubmissionError {
|
|
20698
|
+
constructor(message) {
|
|
20699
|
+
super(message);
|
|
20700
|
+
this.name = "CollectorTargetBindError";
|
|
20701
|
+
}
|
|
20702
|
+
};
|
|
20082
20703
|
COLLECTOR_REQUIRED_TOOLS = [
|
|
20704
|
+
COLLECTOR_BIND_TARGET_TOOL,
|
|
20083
20705
|
COLLECTOR_OBSERVE_TOOL,
|
|
20084
20706
|
COLLECTOR_READ_TOOL,
|
|
20085
20707
|
COLLECTOR_REQUEST_TOOL,
|
|
20086
20708
|
COLLECTOR_WAIT_TOOL,
|
|
20087
20709
|
COLLECTOR_OUTPUT_TOOL
|
|
20088
20710
|
];
|
|
20711
|
+
COLLECTOR_TRANSPORT_FLAGS = Object.freeze([
|
|
20712
|
+
Object.freeze({
|
|
20713
|
+
name: "ak-collector-repo",
|
|
20714
|
+
definition: Object.freeze({
|
|
20715
|
+
description: "GitHub owner/repo target for Collector (github.com only; conservative ASCII grammar).",
|
|
20716
|
+
type: "string"
|
|
20717
|
+
})
|
|
20718
|
+
}),
|
|
20719
|
+
Object.freeze({
|
|
20720
|
+
name: "ak-collector-pr",
|
|
20721
|
+
definition: Object.freeze({
|
|
20722
|
+
description: "Optional positive safe-integer pull request number for Collector. Omit when the role will bind from task materials.",
|
|
20723
|
+
type: "string"
|
|
20724
|
+
})
|
|
20725
|
+
}),
|
|
20726
|
+
Object.freeze({
|
|
20727
|
+
name: "ak-collector-request-manifest",
|
|
20728
|
+
definition: Object.freeze({
|
|
20729
|
+
description: "Path to the Collector v1 request manifest JSON file.",
|
|
20730
|
+
type: "string"
|
|
20731
|
+
})
|
|
20732
|
+
})
|
|
20733
|
+
]);
|
|
20089
20734
|
observeSchema = collectorObserveArgsSchema;
|
|
20090
20735
|
readSchema = collectorReadArgsSchema;
|
|
20091
20736
|
requestSchema = collectorRequestArgsSchema;
|
|
20092
20737
|
waitSchema = collectorWaitArgsSchema;
|
|
20738
|
+
bindSchema = collectorBindTargetArgsSchema;
|
|
20093
20739
|
outputSchema = collectorOutputArgsSchema;
|
|
20094
20740
|
}
|
|
20095
20741
|
});
|
|
@@ -21070,11 +21716,11 @@ var init_reviewer_role = __esm({
|
|
|
21070
21716
|
});
|
|
21071
21717
|
|
|
21072
21718
|
// src/worker-submission-gates.ts
|
|
21073
|
-
import { execFileSync as
|
|
21074
|
-
import { existsSync as
|
|
21719
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
21720
|
+
import { existsSync as existsSync11, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, rmdirSync, rmSync } from "node:fs";
|
|
21075
21721
|
import { resolve as resolve18 } from "node:path";
|
|
21076
21722
|
function git2(cwd, args) {
|
|
21077
|
-
return
|
|
21723
|
+
return execFileSync4("git", args, {
|
|
21078
21724
|
cwd,
|
|
21079
21725
|
encoding: "utf8",
|
|
21080
21726
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -21082,7 +21728,7 @@ function git2(cwd, args) {
|
|
|
21082
21728
|
}).trim();
|
|
21083
21729
|
}
|
|
21084
21730
|
function gitFile(file, args) {
|
|
21085
|
-
return
|
|
21731
|
+
return execFileSync4("git", ["config", "--file", file, ...args], {
|
|
21086
21732
|
encoding: "utf8",
|
|
21087
21733
|
stdio: ["ignore", "pipe", "pipe"],
|
|
21088
21734
|
env: { ...process.env, GIT_DIR: void 0, GIT_WORK_TREE: void 0, GIT_COMMON_DIR: void 0 }
|
|
@@ -21092,7 +21738,7 @@ function statusOf(error) {
|
|
|
21092
21738
|
return typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
|
|
21093
21739
|
}
|
|
21094
21740
|
function tryGetAll(file, key) {
|
|
21095
|
-
if (!
|
|
21741
|
+
if (!existsSync11(file)) return [];
|
|
21096
21742
|
try {
|
|
21097
21743
|
const out = gitFile(file, ["--get-all", key]);
|
|
21098
21744
|
return out.length === 0 ? [] : out.split("\n");
|
|
@@ -21102,7 +21748,7 @@ function tryGetAll(file, key) {
|
|
|
21102
21748
|
}
|
|
21103
21749
|
}
|
|
21104
21750
|
function ownedHook(path) {
|
|
21105
|
-
if (!
|
|
21751
|
+
if (!existsSync11(path)) return false;
|
|
21106
21752
|
return readFileSync4(path, "utf8").includes(HOOK_MARKER);
|
|
21107
21753
|
}
|
|
21108
21754
|
function escapeGitConfigValueRegex(value) {
|
|
@@ -21129,11 +21775,11 @@ function rmOwnedDir(dir) {
|
|
|
21129
21775
|
const hookPath = resolve18(dir, HOOK_FILE);
|
|
21130
21776
|
if (!ownedHook(hookPath)) return;
|
|
21131
21777
|
rmSync(hookPath, { force: true });
|
|
21132
|
-
if (
|
|
21778
|
+
if (existsSync11(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
|
|
21133
21779
|
}
|
|
21134
21780
|
function linkedGitDirs(commonDir) {
|
|
21135
21781
|
const root = resolve18(commonDir, "worktrees");
|
|
21136
|
-
if (!
|
|
21782
|
+
if (!existsSync11(root)) return [];
|
|
21137
21783
|
return readdirSync2(root).map((name) => resolve18(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
|
|
21138
21784
|
}
|
|
21139
21785
|
function uninstallPackageWorkerHooks(cwd) {
|
|
@@ -21822,7 +22468,7 @@ var init_activation_reconciliation = __esm({
|
|
|
21822
22468
|
|
|
21823
22469
|
// src/role-runtime.ts
|
|
21824
22470
|
import { readFileSync as readFileSync5, writeSync as writeSync4 } from "node:fs";
|
|
21825
|
-
import { join as
|
|
22471
|
+
import { join as join32 } from "node:path";
|
|
21826
22472
|
import { Value as Value5 } from "typebox/value";
|
|
21827
22473
|
function decodeReviewerAdmittedInputs(getFlag) {
|
|
21828
22474
|
let reviewScopeKeys;
|
|
@@ -22194,7 +22840,7 @@ function readDiaristRunCoordinates() {
|
|
|
22194
22840
|
if (typeof runDirectory !== "string" || runDirectory.trim() === "") {
|
|
22195
22841
|
throw new Error("diarist accept requires AK_ROLE_RUN_DIR");
|
|
22196
22842
|
}
|
|
22197
|
-
const admittedPath =
|
|
22843
|
+
const admittedPath = join32(runDirectory, "admitted-request.json");
|
|
22198
22844
|
const admitted = JSON.parse(readFileSync5(admittedPath, "utf8"));
|
|
22199
22845
|
if (typeof admitted.projectRoot !== "string" || admitted.projectRoot.trim() === "") {
|
|
22200
22846
|
throw new Error(`diarist admitted-request missing projectRoot (${admittedPath})`);
|
|
@@ -22310,6 +22956,9 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22310
22956
|
for (const flag of GLEANER_LEFT_TRANSPORT_FLAGS) {
|
|
22311
22957
|
roleHost.registerFlag(flag.name, flag.definition);
|
|
22312
22958
|
}
|
|
22959
|
+
for (const flag of COLLECTOR_TRANSPORT_FLAGS) {
|
|
22960
|
+
roleHost.registerFlag(flag.name, flag.definition);
|
|
22961
|
+
}
|
|
22313
22962
|
let admitted = false;
|
|
22314
22963
|
let selectedRole;
|
|
22315
22964
|
let activeReviewerParent;
|
|
@@ -22440,10 +23089,41 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22440
23089
|
})
|
|
22441
23090
|
};
|
|
22442
23091
|
}
|
|
23092
|
+
if (role === "collector" && activeCollector !== void 0) {
|
|
23093
|
+
const options = event.systemPromptOptions;
|
|
23094
|
+
if (options.skills && options.skills.length > 0) {
|
|
23095
|
+
failInfrastructure(
|
|
23096
|
+
activeCollector.ledger.latchFatal("\u901A\u8FDB\u53F8\u68C0\u6D4B\u5230\u7CFB\u7EDF\u63D0\u793A\u4E2D\u7684\u73AF\u5883 skills"),
|
|
23097
|
+
ctx
|
|
23098
|
+
);
|
|
23099
|
+
}
|
|
23100
|
+
if (options.contextFiles && options.contextFiles.length > 0) {
|
|
23101
|
+
failInfrastructure(
|
|
23102
|
+
activeCollector.ledger.latchFatal("\u901A\u8FDB\u53F8\u68C0\u6D4B\u5230\u7CFB\u7EDF\u63D0\u793A\u4E2D\u7684\u73AF\u5883 context files"),
|
|
23103
|
+
ctx
|
|
23104
|
+
);
|
|
23105
|
+
}
|
|
23106
|
+
if (typeof options.appendSystemPrompt === "string" && options.appendSystemPrompt.trim().length > 0) {
|
|
23107
|
+
failInfrastructure(
|
|
23108
|
+
activeCollector.ledger.latchFatal("\u901A\u8FDB\u53F8\u68C0\u6D4B\u5230 appendSystemPrompt \u6F02\u79FB"),
|
|
23109
|
+
ctx
|
|
23110
|
+
);
|
|
23111
|
+
}
|
|
23112
|
+
if (!collectorFirstDispatchDone) {
|
|
23113
|
+
collectorFirstDispatchDone = true;
|
|
23114
|
+
activeCollector.ledger.recordActivation(activeCollector.clock);
|
|
23115
|
+
}
|
|
23116
|
+
return {
|
|
23117
|
+
systemPrompt: collectorBusiness.assembleMaterials(activeCollector, event.systemPrompt)
|
|
23118
|
+
};
|
|
23119
|
+
}
|
|
22443
23120
|
});
|
|
22444
23121
|
roleHost.on("tool_result", async (event) => {
|
|
22445
23122
|
const role = selectedRole;
|
|
22446
23123
|
if (role === void 0) return;
|
|
23124
|
+
if (role === "collector" && activeCollector !== void 0) {
|
|
23125
|
+
collectorBusiness.onToolResult(activeCollector, event);
|
|
23126
|
+
}
|
|
22447
23127
|
const pendingInfra = pendingInfrastructureFailures.get(event.toolCallId);
|
|
22448
23128
|
const isRoleInfrastructureFailure = pendingInfra !== void 0;
|
|
22449
23129
|
if (pendingInfra !== void 0) pendingInfrastructureFailures.delete(event.toolCallId);
|
|
@@ -22541,6 +23221,11 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22541
23221
|
priorFetch = void 0;
|
|
22542
23222
|
fetchWrapped = false;
|
|
22543
23223
|
}
|
|
23224
|
+
if (selectedRole === "collector" && activeCollector !== void 0 && activeCollector.ledger.fatal) {
|
|
23225
|
+
if (process.exitCode === void 0 || process.exitCode === 0) {
|
|
23226
|
+
process.exitCode = 1;
|
|
23227
|
+
}
|
|
23228
|
+
}
|
|
22544
23229
|
const presentation = pendingNavigatorPresentation;
|
|
22545
23230
|
pendingNavigatorPresentation = void 0;
|
|
22546
23231
|
if (presentation !== void 0) {
|
|
@@ -22742,7 +23427,9 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22742
23427
|
}
|
|
22743
23428
|
}
|
|
22744
23429
|
}, hostActions);
|
|
22745
|
-
|
|
23430
|
+
let activeCollector;
|
|
23431
|
+
let collectorFirstDispatchDone = false;
|
|
23432
|
+
const collectorBusiness = createCollectorRoleRuntime(
|
|
22746
23433
|
roleHost,
|
|
22747
23434
|
{
|
|
22748
23435
|
async loadSoul() {
|
|
@@ -22771,13 +23458,90 @@ function createRoleRuntimeExtension(dependencies) {
|
|
|
22771
23458
|
dossierEntries: context.sessionManager?.getEntries?.() ?? []
|
|
22772
23459
|
});
|
|
22773
23460
|
},
|
|
22774
|
-
...dependencies.createCollectorClock === void 0 ? {} : { createClock: dependencies.createCollectorClock }
|
|
22775
|
-
...dependencies.collectorPackageExtensionPath === void 0 ? {} : {
|
|
22776
|
-
packageExtensionPath: dependencies.collectorPackageExtensionPath
|
|
22777
|
-
}
|
|
23461
|
+
...dependencies.createCollectorClock === void 0 ? {} : { createClock: dependencies.createCollectorClock }
|
|
22778
23462
|
},
|
|
22779
23463
|
hostActions
|
|
22780
23464
|
);
|
|
23465
|
+
let collectorToolCallRegistered = false;
|
|
23466
|
+
const collector = {
|
|
23467
|
+
async activate(context, event) {
|
|
23468
|
+
activeCollector = void 0;
|
|
23469
|
+
collectorFirstDispatchDone = false;
|
|
23470
|
+
if (context.mode !== "print" && context.mode !== "json") {
|
|
23471
|
+
throw new Error(
|
|
23472
|
+
`Collector supports only print or json mode (got ${context.mode})`
|
|
23473
|
+
);
|
|
23474
|
+
}
|
|
23475
|
+
if (event.reason === "fork" || event.reason === "reload") {
|
|
23476
|
+
throw new Error(
|
|
23477
|
+
`Collector does not support session_start reason ${event.reason}`
|
|
23478
|
+
);
|
|
23479
|
+
}
|
|
23480
|
+
const commands = roleHost.getCommands?.() ?? [];
|
|
23481
|
+
const ambientCommands = commands.filter((command) => {
|
|
23482
|
+
const name = command.name.toLowerCase();
|
|
23483
|
+
return name.includes("skill") || name.includes("prompt") || name.startsWith("template");
|
|
23484
|
+
});
|
|
23485
|
+
if (ambientCommands.length > 0) {
|
|
23486
|
+
throw new Error(
|
|
23487
|
+
`Collector detected ambient instruction commands: ${ambientCommands.map((c) => c.name).join(", ")}`
|
|
23488
|
+
);
|
|
23489
|
+
}
|
|
23490
|
+
const preExisting = roleHost.getAllTools();
|
|
23491
|
+
const alreadyRegistered = COLLECTOR_REQUIRED_TOOLS.every(
|
|
23492
|
+
(required) => preExisting.some((tool) => tool.name === required)
|
|
23493
|
+
);
|
|
23494
|
+
if (!alreadyRegistered) {
|
|
23495
|
+
for (const required of COLLECTOR_REQUIRED_TOOLS) {
|
|
23496
|
+
const prior = preExisting.filter((tool) => tool.name === required);
|
|
23497
|
+
if (prior.length > 0) {
|
|
23498
|
+
throw new Error(`Collector required tool name collision: ${required}`);
|
|
23499
|
+
}
|
|
23500
|
+
}
|
|
23501
|
+
}
|
|
23502
|
+
collectorBusiness.registerBusinessTools(() => activeCollector);
|
|
23503
|
+
const allTools = roleHost.getAllTools();
|
|
23504
|
+
for (const required of COLLECTOR_REQUIRED_TOOLS) {
|
|
23505
|
+
const matches = allTools.filter((tool) => tool.name === required);
|
|
23506
|
+
if (matches.length === 0) {
|
|
23507
|
+
throw new Error(`Collector required tool missing: ${required}`);
|
|
23508
|
+
}
|
|
23509
|
+
if (matches.length > 1) {
|
|
23510
|
+
throw new Error(`Collector required tool name collision: ${required}`);
|
|
23511
|
+
}
|
|
23512
|
+
}
|
|
23513
|
+
roleHost.setActiveTools([...COLLECTOR_REQUIRED_TOOLS]);
|
|
23514
|
+
const active = new Set(roleHost.getActiveTools());
|
|
23515
|
+
for (const required of COLLECTOR_REQUIRED_TOOLS) {
|
|
23516
|
+
if (!active.has(required)) {
|
|
23517
|
+
throw new Error(`Collector failed to activate required tool ${required}`);
|
|
23518
|
+
}
|
|
23519
|
+
}
|
|
23520
|
+
for (const name of active) {
|
|
23521
|
+
if (!COLLECTOR_REQUIRED_TOOLS.includes(name)) {
|
|
23522
|
+
throw new Error(`Collector active tool surface includes unexpected ${name}`);
|
|
23523
|
+
}
|
|
23524
|
+
}
|
|
23525
|
+
if (!collectorToolCallRegistered) {
|
|
23526
|
+
collectorToolCallRegistered = true;
|
|
23527
|
+
roleHost.on("tool_call", (toolEvent) => {
|
|
23528
|
+
if (activeCollector === void 0 || selectedRole !== "collector") return;
|
|
23529
|
+
if (!COLLECTOR_REQUIRED_TOOLS.includes(toolEvent.toolName)) {
|
|
23530
|
+
return {
|
|
23531
|
+
block: true,
|
|
23532
|
+
reason: `\u901A\u8FDB\u53F8\u7981\u7528\u5DE5\u5177 ${toolEvent.toolName}`
|
|
23533
|
+
};
|
|
23534
|
+
}
|
|
23535
|
+
return collectorBusiness.onToolCall(activeCollector, toolEvent);
|
|
23536
|
+
});
|
|
23537
|
+
}
|
|
23538
|
+
const activation = await collectorBusiness.activate(context);
|
|
23539
|
+
if (activation.ledger.activationRecorded) {
|
|
23540
|
+
collectorFirstDispatchDone = true;
|
|
23541
|
+
}
|
|
23542
|
+
activeCollector = activation;
|
|
23543
|
+
}
|
|
23544
|
+
};
|
|
22781
23545
|
const clock = dependencies.activationClock ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
22782
23546
|
const writeTrace = dependencies.activationTraceWriter ?? writeActivationTraceRecord;
|
|
22783
23547
|
const observationFace = createToolExecutionObservationFace({
|
|
@@ -23437,7 +24201,7 @@ __export(in_process_session_exports, {
|
|
|
23437
24201
|
});
|
|
23438
24202
|
import { mkdtemp as mkdtemp2, rm as rm2 } from "node:fs/promises";
|
|
23439
24203
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
23440
|
-
import { join as
|
|
24204
|
+
import { join as join33 } from "node:path";
|
|
23441
24205
|
import {
|
|
23442
24206
|
createAgentSession,
|
|
23443
24207
|
DefaultResourceLoader,
|
|
@@ -23560,7 +24324,7 @@ async function openPiInProcessSession(options) {
|
|
|
23560
24324
|
let scratchDir;
|
|
23561
24325
|
let resolvedAgentDir = options.agentDir;
|
|
23562
24326
|
if (resolvedAgentDir === void 0) {
|
|
23563
|
-
scratchDir = await mkdtemp2(
|
|
24327
|
+
scratchDir = await mkdtemp2(join33(options.credentialScratchParent ?? tmpdir2(), "ak-institutional-"));
|
|
23564
24328
|
resolvedAgentDir = scratchDir;
|
|
23565
24329
|
}
|
|
23566
24330
|
try {
|
|
@@ -24256,7 +25020,7 @@ var init_reviewer_child_executor = __esm({
|
|
|
24256
25020
|
import { spawn as spawn4 } from "node:child_process";
|
|
24257
25021
|
import { mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
|
|
24258
25022
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
24259
|
-
import { join as
|
|
25023
|
+
import { join as join34 } from "node:path";
|
|
24260
25024
|
async function runCommand(command, args, options = {}) {
|
|
24261
25025
|
return await new Promise((resolve20, reject) => {
|
|
24262
25026
|
const child = spawn4(command, args, { ...options.cwd === void 0 ? {} : { cwd: options.cwd }, stdio: ["ignore", "pipe", "pipe"], signal: options.signal });
|
|
@@ -24305,8 +25069,8 @@ async function prepareSnapshot(accepted, signal, dependencies) {
|
|
|
24305
25069
|
if (!sameReviewerPinnedTarget({ repositoryRoot: accepted.repositoryRoot, objectFormat, targetHead }, accepted)) throw new Error("Accepted Reviewer target identity no longer matches the repository");
|
|
24306
25070
|
await git3(accepted.repositoryRoot, ["cat-file", "-e", `${targetHead}^{commit}`], signal);
|
|
24307
25071
|
dependencies.fault?.("mirror.before-create");
|
|
24308
|
-
mirrorRoot = await mkdtemp3(
|
|
24309
|
-
const mirrorPath =
|
|
25072
|
+
mirrorRoot = await mkdtemp3(join34(tmpdir3(), "ak-reviewer-snapshot-"));
|
|
25073
|
+
const mirrorPath = join34(mirrorRoot, "repository.git");
|
|
24310
25074
|
dependencies.fault?.("mirror.create");
|
|
24311
25075
|
await runCommand("git", ["init", "--bare", `--object-format=${accepted.objectFormat}`, mirrorPath], signal === void 0 ? {} : { signal });
|
|
24312
25076
|
await git3(mirrorPath, ["fetch", "--no-tags", accepted.repositoryRoot, targetHead], signal);
|
|
@@ -24323,7 +25087,7 @@ async function prepareClone(snapshot, signal, dependencies) {
|
|
|
24323
25087
|
const target = { repositoryRoot: snapshot.repositoryRoot, objectFormat: snapshot.objectFormat, targetHead: snapshot.targetHead, refs: { ...snapshot.refs } };
|
|
24324
25088
|
try {
|
|
24325
25089
|
dependencies.fault?.("workspace.before-create");
|
|
24326
|
-
workspace = await mkdtemp3(
|
|
25090
|
+
workspace = await mkdtemp3(join34(tmpdir3(), "ak-reviewer-leg-"));
|
|
24327
25091
|
dependencies.fault?.("workspace.init");
|
|
24328
25092
|
await git3(workspace, ["init", `--object-format=${snapshot.objectFormat}`, "--initial-branch=ak-reviewer-unborn"], signal);
|
|
24329
25093
|
dependencies.fault?.("workspace.fetch");
|
|
@@ -24738,9 +25502,9 @@ init_auditor_soul();
|
|
|
24738
25502
|
init_session_opening_materials();
|
|
24739
25503
|
|
|
24740
25504
|
// src/acp-host/description.ts
|
|
24741
|
-
import { join as
|
|
25505
|
+
import { join as join35 } from "node:path";
|
|
24742
25506
|
function resolveAcpBinary(description, operatorHome) {
|
|
24743
|
-
return
|
|
25507
|
+
return join35(operatorHome, ...description.binaryFromHome);
|
|
24744
25508
|
}
|
|
24745
25509
|
function acpStdioArgs(description, model, seat) {
|
|
24746
25510
|
const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
|
|
@@ -24766,7 +25530,7 @@ init_role_runtime();
|
|
|
24766
25530
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
24767
25531
|
import { mkdir as mkdir5, readFile as readFile18, writeFile as writeFile8 } from "node:fs/promises";
|
|
24768
25532
|
import { createServer } from "node:net";
|
|
24769
|
-
import { basename as basename7, dirname as dirname17, join as
|
|
25533
|
+
import { basename as basename7, dirname as dirname17, join as join36 } from "node:path";
|
|
24770
25534
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
24771
25535
|
|
|
24772
25536
|
// src/acp-host/role-turn-host.ts
|
|
@@ -25050,7 +25814,6 @@ ${priorNativePaths.join("\n")}` : prepared.prompt;
|
|
|
25050
25814
|
}
|
|
25051
25815
|
|
|
25052
25816
|
// src/acp-host/role-envelope.ts
|
|
25053
|
-
init_submission_errors();
|
|
25054
25817
|
init_submission_correctable_error();
|
|
25055
25818
|
init_navigator_invocation_identity();
|
|
25056
25819
|
function parseCanonicalSkillInvocation(prompt) {
|
|
@@ -25096,7 +25859,7 @@ function projectAcpActivationFlags(request) {
|
|
|
25096
25859
|
}
|
|
25097
25860
|
if (activation.role === "collector") {
|
|
25098
25861
|
flags.set("ak-collector-repo", activation.repo);
|
|
25099
|
-
flags.set("ak-collector-pr", activation.pr);
|
|
25862
|
+
if (activation.pr !== void 0) flags.set("ak-collector-pr", activation.pr);
|
|
25100
25863
|
if (activation.requestManifestPath !== void 0) flags.set("ak-collector-request-manifest", activation.requestManifestPath);
|
|
25101
25864
|
}
|
|
25102
25865
|
return flags;
|
|
@@ -25122,8 +25885,23 @@ function createComposedAcpRoleTurnHost(config) {
|
|
|
25122
25885
|
})
|
|
25123
25886
|
});
|
|
25124
25887
|
}
|
|
25888
|
+
function terminatingToolJsonSchema(parameters) {
|
|
25889
|
+
const cloned = JSON.parse(JSON.stringify(parameters));
|
|
25890
|
+
return Object.freeze({
|
|
25891
|
+
...cloned,
|
|
25892
|
+
$schema: "http://json-schema.org/draft-07/schema#"
|
|
25893
|
+
});
|
|
25894
|
+
}
|
|
25125
25895
|
async function prepareAcpRoleEnvelope(options) {
|
|
25126
25896
|
const { request } = options;
|
|
25897
|
+
if (options.socketPath === "") {
|
|
25898
|
+
throw new Error("prepareAcpRoleEnvelope requires socketPath");
|
|
25899
|
+
}
|
|
25900
|
+
const listTerminatingToolOnMcp = options.listTerminatingToolOnMcp !== false;
|
|
25901
|
+
const earlyTerminatingTool = packagedRoleOutputTool(request.activation.role);
|
|
25902
|
+
if (earlyTerminatingTool === void 0) {
|
|
25903
|
+
throw new Error(`role has no terminating tool: ${request.activation.role}`);
|
|
25904
|
+
}
|
|
25127
25905
|
const flags = projectAcpActivationFlags(request);
|
|
25128
25906
|
const tools = /* @__PURE__ */ new Map();
|
|
25129
25907
|
const handlers = /* @__PURE__ */ new Map();
|
|
@@ -25143,7 +25921,7 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25143
25921
|
const raw = await readFile18(method.path, "utf8");
|
|
25144
25922
|
methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
|
|
25145
25923
|
}
|
|
25146
|
-
let sessionFile = options.sessionFile ??
|
|
25924
|
+
let sessionFile = options.sessionFile ?? join36(request.runDirectory, "session", "session.jsonl");
|
|
25147
25925
|
await mkdir5(dirname17(sessionFile), { recursive: true });
|
|
25148
25926
|
if (request.continuation.kind !== "resume") {
|
|
25149
25927
|
try {
|
|
@@ -25346,6 +26124,68 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25346
26124
|
await emit("tool_execution_end", { toolCallId, toolName, isError: projected.isError });
|
|
25347
26125
|
return projected;
|
|
25348
26126
|
}
|
|
26127
|
+
async function invokeAkTool(name, args) {
|
|
26128
|
+
const tool = tools.get(name);
|
|
26129
|
+
if (tool === void 0) throw new Error(`Unknown AK tool: ${name}`);
|
|
26130
|
+
const toolCallId = randomUUID6();
|
|
26131
|
+
calls.push({ toolCallId, toolName: name });
|
|
26132
|
+
sessionEntries.push({
|
|
26133
|
+
type: "message",
|
|
26134
|
+
message: {
|
|
26135
|
+
role: "assistant",
|
|
26136
|
+
content: [{
|
|
26137
|
+
type: "toolCall",
|
|
26138
|
+
id: toolCallId,
|
|
26139
|
+
name,
|
|
26140
|
+
arguments: args ?? {}
|
|
26141
|
+
}]
|
|
26142
|
+
}
|
|
26143
|
+
});
|
|
26144
|
+
try {
|
|
26145
|
+
await emit("tool_execution_start", { toolCallId, toolName: name });
|
|
26146
|
+
const blocked = (await emit("tool_call", { toolCallId, toolName: name, input: args ?? {} })).some((value) => typeof value === "object" && value !== null && "block" in value && value.block === true);
|
|
26147
|
+
if (blocked) {
|
|
26148
|
+
return { content: [{ type: "text", text: `AK tool blocked: ${name}` }], isError: true, blocked: true };
|
|
26149
|
+
}
|
|
26150
|
+
} catch (error) {
|
|
26151
|
+
const declared = declareRoundInfrastructureFailure(error);
|
|
26152
|
+
try {
|
|
26153
|
+
const projected = await projectToolResult(toolCallId, name, {
|
|
26154
|
+
content: declared.content,
|
|
26155
|
+
details: declared.details,
|
|
26156
|
+
isError: true
|
|
26157
|
+
});
|
|
26158
|
+
return { content: projected.content, isError: true };
|
|
26159
|
+
} catch {
|
|
26160
|
+
return { content: declared.content, isError: true };
|
|
26161
|
+
}
|
|
26162
|
+
}
|
|
26163
|
+
try {
|
|
26164
|
+
const result = await tool.execute(toolCallId, args ?? {}, void 0, void 0, context);
|
|
26165
|
+
const projected = await projectToolResult(toolCallId, name, {
|
|
26166
|
+
content: result.content,
|
|
26167
|
+
details: result.details,
|
|
26168
|
+
isError: false
|
|
26169
|
+
});
|
|
26170
|
+
return { content: projected.content, isError: projected.isError };
|
|
26171
|
+
} catch (error) {
|
|
26172
|
+
let content;
|
|
26173
|
+
let details;
|
|
26174
|
+
if (isCorrectableExecuteError(error)) {
|
|
26175
|
+
const projected2 = projectCorrectableExecuteRejection(error);
|
|
26176
|
+
content = [{ type: "text", text: projected2.diagnostic }];
|
|
26177
|
+
details = projected2.details;
|
|
26178
|
+
} else {
|
|
26179
|
+
({ content, details } = declareRoundInfrastructureFailure(error));
|
|
26180
|
+
}
|
|
26181
|
+
const projected = await projectToolResult(toolCallId, name, {
|
|
26182
|
+
content,
|
|
26183
|
+
details,
|
|
26184
|
+
isError: true
|
|
26185
|
+
});
|
|
26186
|
+
return { content: projected.content, isError: projected.isError };
|
|
26187
|
+
}
|
|
26188
|
+
}
|
|
25349
26189
|
function reply(socket, id, result, error) {
|
|
25350
26190
|
const rpcError = error instanceof Error ? { code: "ak-relay-failure", name: error.name, message: error.message } : { code: "ak-relay-failure", name: "RelayFailure", message: String(error) };
|
|
25351
26191
|
socket.write(`${JSON.stringify({ id, ...error === void 0 ? { result } : { error: rpcError } })}
|
|
@@ -25374,8 +26214,9 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25374
26214
|
}
|
|
25375
26215
|
try {
|
|
25376
26216
|
if (rpc.method === "tools/list") {
|
|
25377
|
-
|
|
25378
|
-
|
|
26217
|
+
const listed = [...tools.values()].filter((tool) => listTerminatingToolOnMcp || tool.name !== earlyTerminatingTool);
|
|
26218
|
+
reply(socket, rpc.id, { tools: listed.map((tool) => {
|
|
26219
|
+
return { name: tool.name, description: tool.description, inputSchema: tool.parameters };
|
|
25379
26220
|
}) });
|
|
25380
26221
|
return;
|
|
25381
26222
|
}
|
|
@@ -25383,82 +26224,15 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25383
26224
|
const params = rpc.params;
|
|
25384
26225
|
const name = params?.name;
|
|
25385
26226
|
if (typeof name !== "string") throw new Error("MCP tool name is missing");
|
|
25386
|
-
|
|
25387
|
-
|
|
25388
|
-
const toolCallId = randomUUID6();
|
|
25389
|
-
calls.push({ toolCallId, toolName: name });
|
|
25390
|
-
{
|
|
25391
|
-
const message = {
|
|
25392
|
-
role: "assistant",
|
|
25393
|
-
content: [{
|
|
25394
|
-
type: "toolCall",
|
|
25395
|
-
id: toolCallId,
|
|
25396
|
-
name,
|
|
25397
|
-
arguments: params?.arguments ?? {}
|
|
25398
|
-
}]
|
|
25399
|
-
};
|
|
25400
|
-
sessionEntries.push({ type: "message", message });
|
|
26227
|
+
if (!listTerminatingToolOnMcp && name === earlyTerminatingTool) {
|
|
26228
|
+
throw new Error(`terminating tool ${name} is schema-channel only on this host`);
|
|
25401
26229
|
}
|
|
25402
|
-
|
|
25403
|
-
|
|
25404
|
-
|
|
25405
|
-
if (blocked) {
|
|
25406
|
-
reply(socket, rpc.id, void 0, new Error(`AK tool blocked: ${name}`));
|
|
25407
|
-
return;
|
|
25408
|
-
}
|
|
25409
|
-
} catch (error) {
|
|
25410
|
-
const declared = declareRoundInfrastructureFailure(error);
|
|
25411
|
-
try {
|
|
25412
|
-
const projected = await projectToolResult(toolCallId, name, {
|
|
25413
|
-
content: declared.content,
|
|
25414
|
-
details: declared.details,
|
|
25415
|
-
isError: true
|
|
25416
|
-
});
|
|
25417
|
-
reply(socket, rpc.id, {
|
|
25418
|
-
content: projected.content,
|
|
25419
|
-
isError: true
|
|
25420
|
-
});
|
|
25421
|
-
} catch {
|
|
25422
|
-
reply(socket, rpc.id, {
|
|
25423
|
-
content: declared.content,
|
|
25424
|
-
isError: true
|
|
25425
|
-
});
|
|
25426
|
-
}
|
|
26230
|
+
const outcome = await invokeAkTool(name, params?.arguments ?? {});
|
|
26231
|
+
if (outcome.blocked === true) {
|
|
26232
|
+
reply(socket, rpc.id, void 0, new Error(outcome.content.map((p) => p.type === "text" ? p.text : "").join("")));
|
|
25427
26233
|
return;
|
|
25428
26234
|
}
|
|
25429
|
-
|
|
25430
|
-
const result = await tool.execute(toolCallId, params?.arguments ?? {}, void 0, void 0, context);
|
|
25431
|
-
const projected = await projectToolResult(toolCallId, name, {
|
|
25432
|
-
content: result.content,
|
|
25433
|
-
details: result.details,
|
|
25434
|
-
isError: false
|
|
25435
|
-
});
|
|
25436
|
-
reply(socket, rpc.id, { content: projected.content, ...projected.isError ? { isError: true } : {} });
|
|
25437
|
-
} catch (error) {
|
|
25438
|
-
let content;
|
|
25439
|
-
let details;
|
|
25440
|
-
if (isCorrectableExecuteError(error)) {
|
|
25441
|
-
const diagnostic = error instanceof Error ? error.message : String(error);
|
|
25442
|
-
content = [{ type: "text", text: diagnostic }];
|
|
25443
|
-
if (error instanceof GatekeeperDecisionError) {
|
|
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
|
-
}
|
|
25452
|
-
} else {
|
|
25453
|
-
({ content, details } = declareRoundInfrastructureFailure(error));
|
|
25454
|
-
}
|
|
25455
|
-
const projected = await projectToolResult(toolCallId, name, {
|
|
25456
|
-
content,
|
|
25457
|
-
details,
|
|
25458
|
-
isError: true
|
|
25459
|
-
});
|
|
25460
|
-
reply(socket, rpc.id, { content: projected.content, ...projected.isError ? { isError: true } : {} });
|
|
25461
|
-
}
|
|
26235
|
+
reply(socket, rpc.id, { content: outcome.content, ...outcome.isError ? { isError: true } : {} });
|
|
25462
26236
|
} catch (error) {
|
|
25463
26237
|
reply(socket, rpc.id, void 0, error);
|
|
25464
26238
|
}
|
|
@@ -25466,8 +26240,8 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25466
26240
|
}
|
|
25467
26241
|
});
|
|
25468
26242
|
}
|
|
25469
|
-
await listen(server, options.socketPath);
|
|
25470
26243
|
const relay = fileURLToPath2(new URL("./mcp-relay.mjs", import.meta.url));
|
|
26244
|
+
await listen(server, options.socketPath);
|
|
25471
26245
|
let disposed = false;
|
|
25472
26246
|
let priorAkRoleRunDir;
|
|
25473
26247
|
let priorAkRoleCourtAttempt;
|
|
@@ -25510,6 +26284,11 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25510
26284
|
});
|
|
25511
26285
|
}
|
|
25512
26286
|
};
|
|
26287
|
+
const terminatingToolName = earlyTerminatingTool;
|
|
26288
|
+
async function ingestStructuredOutput(params) {
|
|
26289
|
+
if (calls.some((call) => call.toolName === terminatingToolName)) return;
|
|
26290
|
+
await invokeAkTool(terminatingToolName, params ?? {});
|
|
26291
|
+
}
|
|
25513
26292
|
const closeRound = async () => {
|
|
25514
26293
|
if (calls.length > 0) {
|
|
25515
26294
|
const roundCalls = [...calls];
|
|
@@ -25576,6 +26355,11 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25576
26355
|
if (request.courtAttemptId === void 0) delete process.env.AK_ROLE_COURT_ATTEMPT;
|
|
25577
26356
|
else process.env.AK_ROLE_COURT_ATTEMPT = request.courtAttemptId;
|
|
25578
26357
|
runDirInjected = true;
|
|
26358
|
+
const terminating = tools.get(terminatingToolName);
|
|
26359
|
+
if (terminating === void 0) {
|
|
26360
|
+
throw new Error(`terminating tool not registered after activation: ${terminatingToolName}`);
|
|
26361
|
+
}
|
|
26362
|
+
const jsonSchema = terminatingToolJsonSchema(terminating.parameters);
|
|
25579
26363
|
return {
|
|
25580
26364
|
mcpServers: [{
|
|
25581
26365
|
name: `ak-${request.activation.role}`,
|
|
@@ -25590,7 +26374,10 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25590
26374
|
prompt,
|
|
25591
26375
|
abortSignal: hostAbort.signal,
|
|
25592
26376
|
closeRound,
|
|
25593
|
-
dispose
|
|
26377
|
+
dispose,
|
|
26378
|
+
jsonSchema,
|
|
26379
|
+
terminatingToolName,
|
|
26380
|
+
ingestStructuredOutput
|
|
25594
26381
|
};
|
|
25595
26382
|
} catch (error) {
|
|
25596
26383
|
try {
|
|
@@ -25609,12 +26396,12 @@ async function prepareAcpRoleEnvelope(options) {
|
|
|
25609
26396
|
// src/acp-host/seat-profile-soul.ts
|
|
25610
26397
|
import { constants as constants3 } from "node:fs";
|
|
25611
26398
|
import { access as access4, copyFile, lstat as lstat6, mkdir as mkdir6, readlink, symlink, unlink as unlink4 } from "node:fs/promises";
|
|
25612
|
-
import { dirname as dirname18, join as
|
|
26399
|
+
import { dirname as dirname18, join as join37, relative as relative3, resolve as resolve19 } from "node:path";
|
|
25613
26400
|
function seatProfileName(spec, role) {
|
|
25614
26401
|
return `${spec.namePrefix}${role}`;
|
|
25615
26402
|
}
|
|
25616
26403
|
function packageRoleSoulPath(packageRoot, role) {
|
|
25617
|
-
return
|
|
26404
|
+
return join37(packageRoot, "souls", `${role}.md`);
|
|
25618
26405
|
}
|
|
25619
26406
|
async function pathExists(path) {
|
|
25620
26407
|
try {
|
|
@@ -25631,16 +26418,16 @@ async function ensureSeatProfileSoul(options) {
|
|
|
25631
26418
|
if (!await pathExists(soulTarget)) {
|
|
25632
26419
|
throw new Error(`packaged role soul missing: ${soulTarget}`);
|
|
25633
26420
|
}
|
|
25634
|
-
const profilesRoot =
|
|
25635
|
-
const profileDir =
|
|
26421
|
+
const profilesRoot = join37(operatorHome, ...spec.profilesRootFromHome);
|
|
26422
|
+
const profileDir = join37(profilesRoot, profileName);
|
|
25636
26423
|
const hostRoot = dirname18(profilesRoot);
|
|
25637
|
-
const soulPath =
|
|
26424
|
+
const soulPath = join37(profileDir, spec.soulFileName);
|
|
25638
26425
|
if (!await pathExists(profileDir)) {
|
|
25639
26426
|
await mkdir6(profileDir, { recursive: true });
|
|
25640
26427
|
for (const name of ["auth.json", ".env", "config.yaml"]) {
|
|
25641
|
-
const source =
|
|
26428
|
+
const source = join37(hostRoot, name);
|
|
25642
26429
|
if (!await pathExists(source)) continue;
|
|
25643
|
-
await copyFile(source,
|
|
26430
|
+
await copyFile(source, join37(profileDir, name));
|
|
25644
26431
|
}
|
|
25645
26432
|
} else {
|
|
25646
26433
|
await mkdir6(profileDir, { recursive: true });
|
|
@@ -25667,9 +26454,9 @@ async function ensureSeatProfileSoul(options) {
|
|
|
25667
26454
|
|
|
25668
26455
|
// src/acp-host/session-identity.ts
|
|
25669
26456
|
import { mkdir as mkdir7, readFile as readFile19, rename, writeFile as writeFile9 } from "node:fs/promises";
|
|
25670
|
-
import { dirname as dirname19, join as
|
|
26457
|
+
import { dirname as dirname19, join as join38 } from "node:path";
|
|
25671
26458
|
function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
|
|
25672
|
-
const bindingPath = (principal) =>
|
|
26459
|
+
const bindingPath = (principal) => join38(authority.decode(principal).sessionDirectory, sessionBindingFile);
|
|
25673
26460
|
return {
|
|
25674
26461
|
resolveSessionFile(principal) {
|
|
25675
26462
|
return authority.decode(principal).sessionFile;
|