@akagilnc/pi-workflow-roles 0.1.3783 → 0.1.3795
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 -1
- package/README.zh-CN.md +3 -1
- package/dist/acp-host/production-host.js +681 -269
- package/dist/atomic-write.js +23 -0
- package/dist/collector-evidence.js +4 -1
- package/dist/collector-github.js +1 -0
- package/dist/collector-handbook.js +142 -0
- package/dist/collector-identity.js +11 -0
- package/dist/collector-ledger.js +109 -63
- package/dist/collector-role.js +182 -18
- package/dist/collector-tool-schemas.js +40 -3
- package/dist/headless-host/production-host.js +682 -270
- package/dist/pi/role-turn-host.js +1 -0
- package/dist/public-cli/invocation.js +15 -0
- package/dist/public-cli/main.js +45 -77
- package/dist/public-cli/option-definitions.js +16 -2
- package/dist/public-cli/run-lifecycle.js +8 -0
- package/dist/role-runtime.js +3 -0
- package/extensions/role-runtime.ts +2 -0
- package/package.json +1 -1
- package/resources/collector-bot-handbook.md +33 -0
- package/src/acp-host/production-host.ts +4 -0
- package/src/acp-host/role-envelope.ts +1 -0
- package/src/collector-evidence.ts +6 -1
- package/src/collector-github.ts +3 -0
- package/src/collector-handbook.ts +194 -0
- package/src/collector-identity.ts +14 -0
- package/src/collector-ledger.ts +132 -80
- package/src/collector-role.ts +198 -14
- package/src/collector-tool-schemas.ts +42 -3
- package/src/host-contracts.ts +2 -0
- package/src/pi/role-turn-host.ts +1 -0
- package/src/public-cli/collector-run.ts +2 -0
- package/src/public-cli/invocation.ts +21 -0
- package/src/public-cli/option-definitions.ts +16 -2
- package/src/public-cli/run-lifecycle.ts +10 -0
- package/src/role-runtime.ts +5 -0
package/dist/collector-role.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { emptyCollectorManifest, loadCollectorManifest, parseCollectorPrNumber, parseCollectorRepository, } from "./collector-config.js";
|
|
2
|
-
import { createSystemCollectorClock, } from "./collector-evidence.js";
|
|
2
|
+
import { COLLECTOR_DEFAULT_WAIT_WINDOW_MS, createSystemCollectorClock, } from "./collector-evidence.js";
|
|
3
3
|
import { createGhApiRunner, listPullRequestNumbersByTicket, } from "./collector-github.js";
|
|
4
|
-
import {
|
|
4
|
+
import { createCollectorHandbookStore, resolveCollectorHandbookRoot, } from "./collector-handbook.js";
|
|
5
|
+
import { COLLECTOR_BIND_TARGET_TOOL, COLLECTOR_HANDBOOK_WRITE_TOOL, COLLECTOR_OBSERVE_TOOL, COLLECTOR_OPEN_WAIT_WINDOW_TOOL, COLLECTOR_OUTPUT_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, projectEvidenceEntryView, } from "./collector-ledger.js";
|
|
5
6
|
import { buildCollectorReceipt, } from "./collector-receipt.js";
|
|
6
|
-
import { collectorBindTargetArgsSchema, collectorObserveArgsSchema, collectorOutputArgsSchema, collectorReadArgsSchema, collectorRequestArgsSchema, collectorWaitArgsSchema, } from "./collector-tool-schemas.js";
|
|
7
|
+
import { collectorBindTargetArgsSchema, collectorHandbookWriteArgsSchema, collectorObserveArgsSchema, collectorOpenWaitWindowArgsSchema, collectorOutputArgsSchema, collectorReadArgsSchema, collectorRequestArgsSchema, collectorWaitArgsSchema, } from "./collector-tool-schemas.js";
|
|
7
8
|
import { COLLECTOR_ACCEPTED_TEXT } from "./package-contracts/collector-output.js";
|
|
8
9
|
import { CorrectableSubmissionError, isCorrectableExecuteError } from "./submission-correctable-error.js";
|
|
9
10
|
import { CollectorUnknownEvidenceError } from "./collector-identity.js";
|
|
@@ -26,13 +27,15 @@ export class CollectorTargetBindError extends CorrectableSubmissionError {
|
|
|
26
27
|
this.name = "CollectorTargetBindError";
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
|
-
export { COLLECTOR_BIND_TARGET_TOOL, COLLECTOR_OBSERVE_TOOL, COLLECTOR_OUTPUT_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, };
|
|
30
|
+
export { COLLECTOR_BIND_TARGET_TOOL, COLLECTOR_HANDBOOK_WRITE_TOOL, COLLECTOR_OBSERVE_TOOL, COLLECTOR_OPEN_WAIT_WINDOW_TOOL, COLLECTOR_OUTPUT_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, };
|
|
30
31
|
export const COLLECTOR_REQUIRED_TOOLS = [
|
|
31
32
|
COLLECTOR_BIND_TARGET_TOOL,
|
|
32
33
|
COLLECTOR_OBSERVE_TOOL,
|
|
33
34
|
COLLECTOR_READ_TOOL,
|
|
34
35
|
COLLECTOR_REQUEST_TOOL,
|
|
36
|
+
COLLECTOR_OPEN_WAIT_WINDOW_TOOL,
|
|
35
37
|
COLLECTOR_WAIT_TOOL,
|
|
38
|
+
COLLECTOR_HANDBOOK_WRITE_TOOL,
|
|
36
39
|
COLLECTOR_OUTPUT_TOOL,
|
|
37
40
|
];
|
|
38
41
|
/** Envelope-owned transport flags (ADR 0018 / #676 E). */
|
|
@@ -58,23 +61,61 @@ export const COLLECTOR_TRANSPORT_FLAGS = Object.freeze([
|
|
|
58
61
|
type: "string",
|
|
59
62
|
}),
|
|
60
63
|
}),
|
|
64
|
+
Object.freeze({
|
|
65
|
+
name: "ak-collector-wait-ms",
|
|
66
|
+
definition: Object.freeze({
|
|
67
|
+
description: `Collector wait-window duration in milliseconds (default ${COLLECTOR_DEFAULT_WAIT_WINDOW_MS}). Caller-configurable; opens at a work step, not session start (#678 D4).`,
|
|
68
|
+
type: "string",
|
|
69
|
+
}),
|
|
70
|
+
}),
|
|
61
71
|
]);
|
|
62
72
|
const observeSchema = collectorObserveArgsSchema;
|
|
63
73
|
const readSchema = collectorReadArgsSchema;
|
|
64
74
|
const requestSchema = collectorRequestArgsSchema;
|
|
75
|
+
const openWaitWindowSchema = collectorOpenWaitWindowArgsSchema;
|
|
65
76
|
const waitSchema = collectorWaitArgsSchema;
|
|
66
77
|
const bindSchema = collectorBindTargetArgsSchema;
|
|
78
|
+
const handbookWriteSchema = collectorHandbookWriteArgsSchema;
|
|
67
79
|
const outputSchema = collectorOutputArgsSchema;
|
|
80
|
+
function parseWaitWindowMsFlag(raw) {
|
|
81
|
+
if (raw === undefined || raw === null || raw === "")
|
|
82
|
+
return COLLECTOR_DEFAULT_WAIT_WINDOW_MS;
|
|
83
|
+
if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1)
|
|
84
|
+
return raw;
|
|
85
|
+
if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) {
|
|
86
|
+
const value = Number(raw.trim());
|
|
87
|
+
if (Number.isSafeInteger(value) && value >= 1)
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
throw new Error("Collector --ak-collector-wait-ms must be a positive safe-integer millisecond string");
|
|
91
|
+
}
|
|
68
92
|
function buildMethodContext(activation) {
|
|
69
93
|
const pr = activation.ledger.config.prNumber;
|
|
70
|
-
|
|
94
|
+
const handbook = activation.handbookView;
|
|
95
|
+
const lines = [
|
|
71
96
|
"<collector_method>",
|
|
72
97
|
`host: github.com`,
|
|
73
98
|
`repository: ${activation.repository.canonical}`,
|
|
74
|
-
`prNumber: ${pr === undefined ? "
|
|
99
|
+
`prNumber: ${pr === undefined ? "未绑定" : String(pr)}`,
|
|
100
|
+
`waitWindowMs: ${String(activation.ledger.config.waitWindowMs)}`,
|
|
75
101
|
`requests: ${JSON.stringify(activation.manifest.requests.map((request) => ({ id: request.id })))}`,
|
|
102
|
+
`handbookGeneralSource: ${handbook.generalSource}`,
|
|
103
|
+
`handbookRepoSource: ${handbook.repoSource}`,
|
|
76
104
|
"</collector_method>",
|
|
77
|
-
]
|
|
105
|
+
];
|
|
106
|
+
// Opaque working memory only — no directional instructions (ADR 0073).
|
|
107
|
+
// JSON + `<` → \u003c keeps bodies from forging the delivery close tag (#677).
|
|
108
|
+
if (handbook.general.length > 0 || handbook.repo.length > 0) {
|
|
109
|
+
const payload = JSON.stringify({
|
|
110
|
+
general: handbook.general,
|
|
111
|
+
repo: handbook.repo,
|
|
112
|
+
generalSource: handbook.generalSource,
|
|
113
|
+
repoSource: handbook.repoSource,
|
|
114
|
+
repository: activation.repository.canonical,
|
|
115
|
+
}).replaceAll("<", "\\u003c");
|
|
116
|
+
lines.push("", "<collector_handbook>", payload, "</collector_handbook>");
|
|
117
|
+
}
|
|
118
|
+
return lines.join("\n");
|
|
78
119
|
}
|
|
79
120
|
function parsePositiveTicket(raw, label) {
|
|
80
121
|
if (raw === undefined || raw === null)
|
|
@@ -83,7 +124,7 @@ function parsePositiveTicket(raw, label) {
|
|
|
83
124
|
return raw;
|
|
84
125
|
if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim()))
|
|
85
126
|
return Number(raw.trim());
|
|
86
|
-
throw new CollectorTargetBindError(
|
|
127
|
+
throw new CollectorTargetBindError(`通进司绑定 ${label} 须为正安全整数`);
|
|
87
128
|
}
|
|
88
129
|
/**
|
|
89
130
|
* Shared envelope installs business tools and material callback after lifecycle gates.
|
|
@@ -100,6 +141,7 @@ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
100
141
|
const repoFlag = pi.getFlag("ak-collector-repo");
|
|
101
142
|
const prFlag = pi.getFlag("ak-collector-pr");
|
|
102
143
|
const requestManifestFlag = pi.getFlag("ak-collector-request-manifest");
|
|
144
|
+
const waitMsFlag = pi.getFlag("ak-collector-wait-ms");
|
|
103
145
|
if (typeof repoFlag !== "string" || repoFlag.trim().length === 0) {
|
|
104
146
|
throw new Error("Collector requires --ak-collector-repo");
|
|
105
147
|
}
|
|
@@ -115,9 +157,29 @@ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
115
157
|
const manifest = typeof requestManifestFlag === "string" && requestManifestFlag.trim().length > 0
|
|
116
158
|
? await loadCollectorManifest(requestManifestFlag)
|
|
117
159
|
: emptyCollectorManifest();
|
|
160
|
+
const waitWindowMs = parseWaitWindowMsFlag(waitMsFlag);
|
|
118
161
|
const clock = dependencies.createClock?.() ?? createSystemCollectorClock();
|
|
119
162
|
const transport = dependencies.createTransport();
|
|
120
|
-
const ledger = dependencies.createLedger({ repository, prNumber, manifest }, clock, ctx);
|
|
163
|
+
const ledger = dependencies.createLedger({ repository, prNumber, manifest, waitWindowMs }, clock, ctx);
|
|
164
|
+
// #677: handbook under admitted book topology (session path → books/<key>/collector-handbook).
|
|
165
|
+
const sessionPath = ctx.sessionManager?.getSessionFile?.()
|
|
166
|
+
?? ctx.sessionManager?.getSessionDir?.();
|
|
167
|
+
if (typeof sessionPath !== "string" || sessionPath.length === 0) {
|
|
168
|
+
throw new Error("通进司手册要求 session 路径位于 books/<bookKey>/");
|
|
169
|
+
}
|
|
170
|
+
const placement = resolveCollectorHandbookRoot(sessionPath);
|
|
171
|
+
const seedGeneral = dependencies.loadHandbookSeed === undefined
|
|
172
|
+
? undefined
|
|
173
|
+
: (await dependencies.loadHandbookSeed()).trim();
|
|
174
|
+
const handbook = createCollectorHandbookStore({
|
|
175
|
+
ledgerHome: placement.ledgerHome,
|
|
176
|
+
handbookRoot: placement.root,
|
|
177
|
+
repositoryCanonical: repository.canonical,
|
|
178
|
+
...(seedGeneral === undefined || seedGeneral.length === 0
|
|
179
|
+
? {}
|
|
180
|
+
: { seedGeneral }),
|
|
181
|
+
});
|
|
182
|
+
const handbookView = await handbook.read();
|
|
121
183
|
return {
|
|
122
184
|
soul,
|
|
123
185
|
repository,
|
|
@@ -125,6 +187,8 @@ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
125
187
|
ledger,
|
|
126
188
|
transport,
|
|
127
189
|
clock,
|
|
190
|
+
handbook,
|
|
191
|
+
handbookView,
|
|
128
192
|
};
|
|
129
193
|
},
|
|
130
194
|
assembleMaterials(activation, baseSystemPrompt) {
|
|
@@ -180,7 +244,7 @@ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
180
244
|
const prNumber = parsePositiveTicket(params.prNumber, "prNumber");
|
|
181
245
|
const issueNumber = parsePositiveTicket(params.issueNumber, "issueNumber");
|
|
182
246
|
if (prNumber === undefined && issueNumber === undefined) {
|
|
183
|
-
throw new CollectorTargetBindError("
|
|
247
|
+
throw new CollectorTargetBindError("通进司绑定须由角色判定 prNumber 与/或 issueNumber");
|
|
184
248
|
}
|
|
185
249
|
let bound = prNumber;
|
|
186
250
|
if (issueNumber !== undefined) {
|
|
@@ -190,14 +254,14 @@ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
190
254
|
ticketNumber: issueNumber,
|
|
191
255
|
});
|
|
192
256
|
if (associated.length === 0) {
|
|
193
|
-
throw new CollectorTargetBindError(
|
|
257
|
+
throw new CollectorTargetBindError(`${activation.repository.canonical} 的 issue #${issueNumber} 无关联 PR;请改用明确 --pr 或其他 issueNumber`);
|
|
194
258
|
}
|
|
195
259
|
if (associated.length > 1) {
|
|
196
|
-
throw new CollectorTargetBindError(`
|
|
260
|
+
throw new CollectorTargetBindError(`issue #${issueNumber} 关联多个 PR:${associated.join("、")};请改用明确 prNumber 或 --pr`);
|
|
197
261
|
}
|
|
198
262
|
const fromIssue = associated[0];
|
|
199
263
|
if (prNumber !== undefined && prNumber !== fromIssue) {
|
|
200
|
-
throw new CollectorTargetBindError(`prNumber ${prNumber}
|
|
264
|
+
throw new CollectorTargetBindError(`prNumber ${prNumber} 与 issue #${issueNumber} 关联 PR ${fromIssue} 冲突`);
|
|
201
265
|
}
|
|
202
266
|
bound = fromIssue;
|
|
203
267
|
}
|
|
@@ -297,8 +361,8 @@ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
297
361
|
pi.registerTool({
|
|
298
362
|
name: COLLECTOR_REQUEST_TOOL,
|
|
299
363
|
label: "通进司请求",
|
|
300
|
-
description: "
|
|
301
|
-
promptSnippet: "
|
|
364
|
+
description: "在所引最新快照 HEAD 发一次请求。requestId 可取配置清单,或角色依手册/现场判定的稳定 id;后者须同时提供 body。",
|
|
365
|
+
promptSnippet: "发一次评审请求",
|
|
302
366
|
parameters: requestSchema,
|
|
303
367
|
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
304
368
|
const activation = getActivation();
|
|
@@ -306,7 +370,11 @@ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
306
370
|
throw new Error("通进司未激活");
|
|
307
371
|
try {
|
|
308
372
|
activation.ledger.beginOperational(COLLECTOR_REQUEST_TOOL, toolCallId);
|
|
309
|
-
const details = await activation.ledger.request(
|
|
373
|
+
const details = await activation.ledger.request({
|
|
374
|
+
requestId: params.requestId,
|
|
375
|
+
snapshotId: params.snapshotId,
|
|
376
|
+
...(typeof params.body === "string" ? { body: params.body } : {}),
|
|
377
|
+
}, activation.transport, activation.clock, signal);
|
|
310
378
|
activation.ledger.completeOperational(toolCallId);
|
|
311
379
|
return {
|
|
312
380
|
content: [{
|
|
@@ -323,11 +391,105 @@ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
323
391
|
}
|
|
324
392
|
},
|
|
325
393
|
});
|
|
394
|
+
pi.registerTool({
|
|
395
|
+
name: COLLECTOR_HANDBOOK_WRITE_TOOL,
|
|
396
|
+
label: "通进司手册写入",
|
|
397
|
+
description: "写入通用手册或当前仓库差异全文(整份替换)。",
|
|
398
|
+
promptSnippet: "更新 bot 手册",
|
|
399
|
+
parameters: handbookWriteSchema,
|
|
400
|
+
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
401
|
+
const activation = getActivation();
|
|
402
|
+
if (activation === undefined)
|
|
403
|
+
throw new Error("通进司未激活");
|
|
404
|
+
try {
|
|
405
|
+
activation.ledger.beginOperational(COLLECTOR_HANDBOOK_WRITE_TOOL, toolCallId);
|
|
406
|
+
// scope/body shape authority = collectorHandbookWriteArgsSchema (host parameters).
|
|
407
|
+
const details = await activation.handbook.write(params.scope, params.body);
|
|
408
|
+
activation.handbookView = await activation.handbook.read();
|
|
409
|
+
activation.ledger.completeOperational(toolCallId);
|
|
410
|
+
return {
|
|
411
|
+
content: [{
|
|
412
|
+
type: "text",
|
|
413
|
+
text: `手册已写入:${details.scope}`,
|
|
414
|
+
}],
|
|
415
|
+
details: {
|
|
416
|
+
scope: details.scope,
|
|
417
|
+
path: details.path,
|
|
418
|
+
byteLength: details.byteLength,
|
|
419
|
+
generalSource: activation.handbookView.generalSource,
|
|
420
|
+
repoSource: activation.handbookView.repoSource,
|
|
421
|
+
},
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
if (isCorrectableExecuteError(error))
|
|
426
|
+
throw error;
|
|
427
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
428
|
+
}
|
|
429
|
+
finally {
|
|
430
|
+
try {
|
|
431
|
+
activation.ledger.completeOperational(toolCallId);
|
|
432
|
+
}
|
|
433
|
+
catch {
|
|
434
|
+
// already completed or not begun
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
});
|
|
439
|
+
pi.registerTool({
|
|
440
|
+
name: COLLECTOR_OPEN_WAIT_WINDOW_TOOL,
|
|
441
|
+
label: "通进司开启等待窗",
|
|
442
|
+
description: "在工作步骤上开启等待窗:新建并自动触发的 PR 传创建成功时刻;已有 PR 在触发阶段结束后省略 startedAt(=现在)。窗长由使用方配置,默认十分钟;开启后不因 PR 更新重置。",
|
|
443
|
+
promptSnippet: "按工作步骤开启等待窗",
|
|
444
|
+
parameters: openWaitWindowSchema,
|
|
445
|
+
async execute(toolCallId, params, _signal, _onUpdate, ctx) {
|
|
446
|
+
const activation = getActivation();
|
|
447
|
+
if (activation === undefined)
|
|
448
|
+
throw new Error("通进司未激活");
|
|
449
|
+
try {
|
|
450
|
+
activation.ledger.beginOperational(COLLECTOR_OPEN_WAIT_WINDOW_TOOL, toolCallId);
|
|
451
|
+
let startedAt;
|
|
452
|
+
if (typeof params.startedAt === "string" && params.startedAt.trim().length > 0) {
|
|
453
|
+
const parsed = new Date(params.startedAt);
|
|
454
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
455
|
+
throw new Error("通进司等待窗 startedAt 须为有效 ISO 时间");
|
|
456
|
+
}
|
|
457
|
+
startedAt = parsed;
|
|
458
|
+
}
|
|
459
|
+
activation.ledger.openWaitWindow(activation.clock, startedAt === undefined ? undefined : { startedAt });
|
|
460
|
+
activation.ledger.completeOperational(toolCallId);
|
|
461
|
+
return {
|
|
462
|
+
content: [{
|
|
463
|
+
type: "text",
|
|
464
|
+
text: "等待窗已开启",
|
|
465
|
+
}],
|
|
466
|
+
details: {
|
|
467
|
+
activationTime: activation.ledger.activationTime?.toISOString(),
|
|
468
|
+
deadlineTime: activation.ledger.deadlineTime?.toISOString(),
|
|
469
|
+
waitWindowMs: activation.ledger.config.waitWindowMs,
|
|
470
|
+
},
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
catch (error) {
|
|
474
|
+
if (isCorrectableExecuteError(error))
|
|
475
|
+
throw error;
|
|
476
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
477
|
+
}
|
|
478
|
+
finally {
|
|
479
|
+
try {
|
|
480
|
+
activation.ledger.completeOperational(toolCallId);
|
|
481
|
+
}
|
|
482
|
+
catch {
|
|
483
|
+
// already completed or not begun
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
});
|
|
326
488
|
pi.registerTool({
|
|
327
489
|
name: COLLECTOR_WAIT_TOOL,
|
|
328
490
|
label: "通进司等待",
|
|
329
|
-
description: "
|
|
330
|
-
promptSnippet: "
|
|
491
|
+
description: "再观察前等待;实际睡眠不超过剩余等待窗。",
|
|
492
|
+
promptSnippet: "等待窗内等待",
|
|
331
493
|
parameters: waitSchema,
|
|
332
494
|
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
333
495
|
const activation = getActivation();
|
|
@@ -346,6 +508,8 @@ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
|
|
|
346
508
|
};
|
|
347
509
|
}
|
|
348
510
|
catch (error) {
|
|
511
|
+
if (isCorrectableExecuteError(error))
|
|
512
|
+
throw error;
|
|
349
513
|
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
350
514
|
}
|
|
351
515
|
},
|
|
@@ -1,17 +1,54 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
|
-
import { COLLECTOR_ELIGIBILITY_MS } from "./collector-evidence.js";
|
|
3
2
|
import { openToolObject } from "./open-tool-schema.js";
|
|
4
3
|
import { withInfrastructureFailureDeclaration } from "./package-contracts/terminating-infrastructure.js";
|
|
5
4
|
export const collectorObserveArgsSchema = Type.Object({}, { additionalProperties: false });
|
|
5
|
+
/**
|
|
6
|
+
* Stable request identity: non-empty after trim, no leading/trailing whitespace.
|
|
7
|
+
* Host schema + ledger identity seam share this contract (#677 / D2 dedup).
|
|
8
|
+
*/
|
|
9
|
+
export const COLLECTOR_REQUEST_ID_PATTERN = /^\S(?:.*\S)?$/;
|
|
6
10
|
export const collectorRequestArgsSchema = Type.Object({
|
|
7
|
-
requestId: Type.String({
|
|
11
|
+
requestId: Type.String({
|
|
12
|
+
minLength: 1,
|
|
13
|
+
pattern: COLLECTOR_REQUEST_ID_PATTERN.source,
|
|
14
|
+
description: "请求身份(配置 id 或角色判定的稳定 id;首尾无空白)",
|
|
15
|
+
}),
|
|
8
16
|
snapshotId: Type.String({ minLength: 1, description: "最新留存观察快照" }),
|
|
17
|
+
body: Type.Optional(Type.String({
|
|
18
|
+
minLength: 1,
|
|
19
|
+
description: "角色判定的请求正文;request-manifest 未收录该 requestId 时必填",
|
|
20
|
+
})),
|
|
21
|
+
}, { additionalProperties: false });
|
|
22
|
+
/** UTF-8 byte ceiling per handbook body — keeps next activation materials inside context budget. */
|
|
23
|
+
export const COLLECTOR_HANDBOOK_MAX_BYTES = 64 * 1024;
|
|
24
|
+
export const collectorHandbookWriteArgsSchema = Type.Object({
|
|
25
|
+
scope: Type.Union([
|
|
26
|
+
Type.Literal("general"),
|
|
27
|
+
Type.Literal("repo"),
|
|
28
|
+
], { description: "general=通用手册;repo=当前仓库差异" }),
|
|
29
|
+
body: Type.String({
|
|
30
|
+
description: `手册全文(opaque 工作记忆;整份替换;UTF-8 至多 ${COLLECTOR_HANDBOOK_MAX_BYTES} 字节)`,
|
|
31
|
+
}),
|
|
9
32
|
}, { additionalProperties: false });
|
|
10
33
|
export const collectorReadArgsSchema = Type.Object({
|
|
11
34
|
evidenceId: Type.String({ minLength: 1, description: "observe 返回的材料证据 id(evidenceId)" }),
|
|
12
35
|
}, { additionalProperties: false });
|
|
13
36
|
export const collectorWaitArgsSchema = Type.Object({
|
|
14
|
-
durationMs: Type.Integer({
|
|
37
|
+
durationMs: Type.Integer({
|
|
38
|
+
minimum: 1,
|
|
39
|
+
description: "等待毫秒;实际睡眠不超过剩余等待窗(#678;无包内单次任意上限)",
|
|
40
|
+
}),
|
|
41
|
+
}, { additionalProperties: false });
|
|
42
|
+
/**
|
|
43
|
+
* #678 D4: open the wait window at a work step.
|
|
44
|
+
* Omit startedAt for existing-PR trigger-phase end (= now).
|
|
45
|
+
* Pass PR creation success time for new-PR auto-trigger rounds.
|
|
46
|
+
*/
|
|
47
|
+
export const collectorOpenWaitWindowArgsSchema = Type.Object({
|
|
48
|
+
startedAt: Type.Optional(Type.String({
|
|
49
|
+
minLength: 1,
|
|
50
|
+
description: "等待窗起点 ISO 时间;新建 PR 用创建成功时刻;省略=现在(触发阶段结束)",
|
|
51
|
+
})),
|
|
15
52
|
}, { additionalProperties: false });
|
|
16
53
|
/**
|
|
17
54
|
* #676 A: role-decided target bind. The model judges task materials and submits
|