@akagilnc/pi-workflow-roles 0.1.3783 → 0.1.3789
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 +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/acp-host/production-host.js +487 -236
- package/dist/atomic-write.js +23 -0
- package/dist/collector-handbook.js +142 -0
- package/dist/collector-ledger.js +39 -47
- package/dist/collector-role.js +103 -14
- package/dist/collector-tool-schemas.js +25 -1
- package/dist/headless-host/production-host.js +488 -237
- package/dist/public-cli/main.js +2 -72
- package/dist/public-cli/option-definitions.js +2 -2
- 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/collector-handbook.ts +194 -0
- package/src/collector-ledger.ts +42 -62
- package/src/collector-role.ts +117 -11
- package/src/collector-tool-schemas.ts +25 -1
- package/src/public-cli/option-definitions.ts +2 -2
- package/src/role-runtime.ts +5 -0
package/src/collector-role.ts
CHANGED
|
@@ -25,8 +25,14 @@ import {
|
|
|
25
25
|
listPullRequestNumbersByTicket,
|
|
26
26
|
type CollectorGitHubTransport,
|
|
27
27
|
} from "./collector-github.ts";
|
|
28
|
+
import {
|
|
29
|
+
createCollectorHandbookStore,
|
|
30
|
+
resolveCollectorHandbookRoot,
|
|
31
|
+
type CollectorHandbookStore,
|
|
32
|
+
} from "./collector-handbook.ts";
|
|
28
33
|
import {
|
|
29
34
|
COLLECTOR_BIND_TARGET_TOOL,
|
|
35
|
+
COLLECTOR_HANDBOOK_WRITE_TOOL,
|
|
30
36
|
COLLECTOR_OBSERVE_TOOL,
|
|
31
37
|
COLLECTOR_OUTPUT_TOOL,
|
|
32
38
|
COLLECTOR_READ_TOOL,
|
|
@@ -42,6 +48,7 @@ import {
|
|
|
42
48
|
} from "./collector-receipt.ts";
|
|
43
49
|
import {
|
|
44
50
|
collectorBindTargetArgsSchema,
|
|
51
|
+
collectorHandbookWriteArgsSchema,
|
|
45
52
|
collectorObserveArgsSchema,
|
|
46
53
|
collectorOutputArgsSchema,
|
|
47
54
|
collectorReadArgsSchema,
|
|
@@ -76,6 +83,7 @@ export class CollectorTargetBindError extends CorrectableSubmissionError {
|
|
|
76
83
|
|
|
77
84
|
export {
|
|
78
85
|
COLLECTOR_BIND_TARGET_TOOL,
|
|
86
|
+
COLLECTOR_HANDBOOK_WRITE_TOOL,
|
|
79
87
|
COLLECTOR_OBSERVE_TOOL,
|
|
80
88
|
COLLECTOR_OUTPUT_TOOL,
|
|
81
89
|
COLLECTOR_READ_TOOL,
|
|
@@ -89,6 +97,7 @@ export const COLLECTOR_REQUIRED_TOOLS = [
|
|
|
89
97
|
COLLECTOR_READ_TOOL,
|
|
90
98
|
COLLECTOR_REQUEST_TOOL,
|
|
91
99
|
COLLECTOR_WAIT_TOOL,
|
|
100
|
+
COLLECTOR_HANDBOOK_WRITE_TOOL,
|
|
92
101
|
COLLECTOR_OUTPUT_TOOL,
|
|
93
102
|
] as const;
|
|
94
103
|
|
|
@@ -125,12 +134,14 @@ const readSchema = collectorReadArgsSchema;
|
|
|
125
134
|
const requestSchema = collectorRequestArgsSchema;
|
|
126
135
|
const waitSchema = collectorWaitArgsSchema;
|
|
127
136
|
const bindSchema = collectorBindTargetArgsSchema;
|
|
137
|
+
const handbookWriteSchema = collectorHandbookWriteArgsSchema;
|
|
128
138
|
const outputSchema = collectorOutputArgsSchema;
|
|
129
139
|
|
|
130
140
|
type RequestParams = Static<typeof requestSchema>;
|
|
131
141
|
type ReadParams = Static<typeof readSchema>;
|
|
132
142
|
type WaitParams = Static<typeof waitSchema>;
|
|
133
143
|
type BindParams = Static<typeof bindSchema>;
|
|
144
|
+
type HandbookWriteParams = Static<typeof handbookWriteSchema>;
|
|
134
145
|
type OutputParams = Static<typeof outputSchema>;
|
|
135
146
|
|
|
136
147
|
export type CollectorRoleDependencies = {
|
|
@@ -138,6 +149,8 @@ export type CollectorRoleDependencies = {
|
|
|
138
149
|
createTransport(): CollectorGitHubTransport;
|
|
139
150
|
createClock?(): CollectorClock;
|
|
140
151
|
createLedger(config: CollectorConfigState, clock: CollectorClock, ctx: HostContext): CollectorLedger;
|
|
152
|
+
/** Optional packaged seed for first-use general handbook (#677). */
|
|
153
|
+
loadHandbookSeed?(): Promise<string>;
|
|
141
154
|
};
|
|
142
155
|
|
|
143
156
|
export type CollectorRoleHostActions = {
|
|
@@ -151,25 +164,51 @@ export type CollectorActivation = {
|
|
|
151
164
|
ledger: CollectorLedger;
|
|
152
165
|
transport: CollectorGitHubTransport;
|
|
153
166
|
clock: CollectorClock;
|
|
167
|
+
handbook: CollectorHandbookStore;
|
|
168
|
+
/** Loaded at activate; refreshed after handbook write for same-session materials. */
|
|
169
|
+
handbookView: {
|
|
170
|
+
general: string;
|
|
171
|
+
repo: string;
|
|
172
|
+
generalSource: "book" | "seed" | "empty";
|
|
173
|
+
repoSource: "book" | "empty";
|
|
174
|
+
generalPath: string;
|
|
175
|
+
repoPath: string;
|
|
176
|
+
};
|
|
154
177
|
};
|
|
155
178
|
|
|
156
179
|
function buildMethodContext(activation: CollectorActivation): string {
|
|
157
180
|
const pr = activation.ledger.config.prNumber;
|
|
158
|
-
|
|
181
|
+
const handbook = activation.handbookView;
|
|
182
|
+
const lines = [
|
|
159
183
|
"<collector_method>",
|
|
160
184
|
`host: github.com`,
|
|
161
185
|
`repository: ${activation.repository.canonical}`,
|
|
162
|
-
`prNumber: ${pr === undefined ? "
|
|
186
|
+
`prNumber: ${pr === undefined ? "未绑定" : String(pr)}`,
|
|
163
187
|
`requests: ${JSON.stringify(activation.manifest.requests.map((request) => ({ id: request.id })))}`,
|
|
188
|
+
`handbookGeneralSource: ${handbook.generalSource}`,
|
|
189
|
+
`handbookRepoSource: ${handbook.repoSource}`,
|
|
164
190
|
"</collector_method>",
|
|
165
|
-
]
|
|
191
|
+
];
|
|
192
|
+
// Opaque working memory only — no directional instructions (ADR 0073).
|
|
193
|
+
// JSON + `<` → \u003c keeps bodies from forging the delivery close tag (#677).
|
|
194
|
+
if (handbook.general.length > 0 || handbook.repo.length > 0) {
|
|
195
|
+
const payload = JSON.stringify({
|
|
196
|
+
general: handbook.general,
|
|
197
|
+
repo: handbook.repo,
|
|
198
|
+
generalSource: handbook.generalSource,
|
|
199
|
+
repoSource: handbook.repoSource,
|
|
200
|
+
repository: activation.repository.canonical,
|
|
201
|
+
}).replaceAll("<", "\\u003c");
|
|
202
|
+
lines.push("", "<collector_handbook>", payload, "</collector_handbook>");
|
|
203
|
+
}
|
|
204
|
+
return lines.join("\n");
|
|
166
205
|
}
|
|
167
206
|
|
|
168
207
|
function parsePositiveTicket(raw: unknown, label: string): number | undefined {
|
|
169
208
|
if (raw === undefined || raw === null) return undefined;
|
|
170
209
|
if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) return raw;
|
|
171
210
|
if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) return Number(raw.trim());
|
|
172
|
-
throw new CollectorTargetBindError(
|
|
211
|
+
throw new CollectorTargetBindError(`通进司绑定 ${label} 须为正安全整数`);
|
|
173
212
|
}
|
|
174
213
|
|
|
175
214
|
/**
|
|
@@ -228,6 +267,26 @@ export function createCollectorRoleRuntime(
|
|
|
228
267
|
ctx,
|
|
229
268
|
);
|
|
230
269
|
|
|
270
|
+
// #677: handbook under admitted book topology (session path → books/<key>/collector-handbook).
|
|
271
|
+
const sessionPath = ctx.sessionManager?.getSessionFile?.()
|
|
272
|
+
?? ctx.sessionManager?.getSessionDir?.();
|
|
273
|
+
if (typeof sessionPath !== "string" || sessionPath.length === 0) {
|
|
274
|
+
throw new Error("通进司手册要求 session 路径位于 books/<bookKey>/");
|
|
275
|
+
}
|
|
276
|
+
const placement = resolveCollectorHandbookRoot(sessionPath);
|
|
277
|
+
const seedGeneral = dependencies.loadHandbookSeed === undefined
|
|
278
|
+
? undefined
|
|
279
|
+
: (await dependencies.loadHandbookSeed()).trim();
|
|
280
|
+
const handbook = createCollectorHandbookStore({
|
|
281
|
+
ledgerHome: placement.ledgerHome,
|
|
282
|
+
handbookRoot: placement.root,
|
|
283
|
+
repositoryCanonical: repository.canonical,
|
|
284
|
+
...(seedGeneral === undefined || seedGeneral.length === 0
|
|
285
|
+
? {}
|
|
286
|
+
: { seedGeneral }),
|
|
287
|
+
});
|
|
288
|
+
const handbookView = await handbook.read();
|
|
289
|
+
|
|
231
290
|
return {
|
|
232
291
|
soul,
|
|
233
292
|
repository,
|
|
@@ -235,6 +294,8 @@ export function createCollectorRoleRuntime(
|
|
|
235
294
|
ledger,
|
|
236
295
|
transport,
|
|
237
296
|
clock,
|
|
297
|
+
handbook,
|
|
298
|
+
handbookView,
|
|
238
299
|
};
|
|
239
300
|
},
|
|
240
301
|
|
|
@@ -297,7 +358,7 @@ export function createCollectorRoleRuntime(
|
|
|
297
358
|
const issueNumber = parsePositiveTicket(params.issueNumber, "issueNumber");
|
|
298
359
|
if (prNumber === undefined && issueNumber === undefined) {
|
|
299
360
|
throw new CollectorTargetBindError(
|
|
300
|
-
"
|
|
361
|
+
"通进司绑定须由角色判定 prNumber 与/或 issueNumber",
|
|
301
362
|
);
|
|
302
363
|
}
|
|
303
364
|
|
|
@@ -310,18 +371,18 @@ export function createCollectorRoleRuntime(
|
|
|
310
371
|
});
|
|
311
372
|
if (associated.length === 0) {
|
|
312
373
|
throw new CollectorTargetBindError(
|
|
313
|
-
|
|
374
|
+
`${activation.repository.canonical} 的 issue #${issueNumber} 无关联 PR;请改用明确 --pr 或其他 issueNumber`,
|
|
314
375
|
);
|
|
315
376
|
}
|
|
316
377
|
if (associated.length > 1) {
|
|
317
378
|
throw new CollectorTargetBindError(
|
|
318
|
-
`
|
|
379
|
+
`issue #${issueNumber} 关联多个 PR:${associated.join("、")};请改用明确 prNumber 或 --pr`,
|
|
319
380
|
);
|
|
320
381
|
}
|
|
321
382
|
const fromIssue = associated[0]!;
|
|
322
383
|
if (prNumber !== undefined && prNumber !== fromIssue) {
|
|
323
384
|
throw new CollectorTargetBindError(
|
|
324
|
-
`prNumber ${prNumber}
|
|
385
|
+
`prNumber ${prNumber} 与 issue #${issueNumber} 关联 PR ${fromIssue} 冲突`,
|
|
325
386
|
);
|
|
326
387
|
}
|
|
327
388
|
bound = fromIssue;
|
|
@@ -422,8 +483,8 @@ export function createCollectorRoleRuntime(
|
|
|
422
483
|
pi.registerTool({
|
|
423
484
|
name: COLLECTOR_REQUEST_TOOL,
|
|
424
485
|
label: "通进司请求",
|
|
425
|
-
description: "
|
|
426
|
-
promptSnippet: "
|
|
486
|
+
description: "在所引最新快照 HEAD 发一次请求。requestId 可取配置清单,或角色依手册/现场判定的稳定 id;后者须同时提供 body。",
|
|
487
|
+
promptSnippet: "发一次评审请求",
|
|
427
488
|
parameters: requestSchema,
|
|
428
489
|
async execute(toolCallId: string, params: RequestParams, signal: AbortSignal | undefined, _onUpdate: unknown, ctx: HostContext) {
|
|
429
490
|
const activation = getActivation();
|
|
@@ -431,7 +492,11 @@ export function createCollectorRoleRuntime(
|
|
|
431
492
|
try {
|
|
432
493
|
activation.ledger.beginOperational(COLLECTOR_REQUEST_TOOL, toolCallId);
|
|
433
494
|
const details = await activation.ledger.request(
|
|
434
|
-
|
|
495
|
+
{
|
|
496
|
+
requestId: params.requestId,
|
|
497
|
+
snapshotId: params.snapshotId,
|
|
498
|
+
...(typeof params.body === "string" ? { body: params.body } : {}),
|
|
499
|
+
},
|
|
435
500
|
activation.transport,
|
|
436
501
|
activation.clock,
|
|
437
502
|
signal,
|
|
@@ -451,6 +516,47 @@ export function createCollectorRoleRuntime(
|
|
|
451
516
|
},
|
|
452
517
|
});
|
|
453
518
|
|
|
519
|
+
pi.registerTool({
|
|
520
|
+
name: COLLECTOR_HANDBOOK_WRITE_TOOL,
|
|
521
|
+
label: "通进司手册写入",
|
|
522
|
+
description: "写入通用手册或当前仓库差异全文(整份替换)。",
|
|
523
|
+
promptSnippet: "更新 bot 手册",
|
|
524
|
+
parameters: handbookWriteSchema,
|
|
525
|
+
async execute(toolCallId: string, params: HandbookWriteParams, _signal: AbortSignal | undefined, _onUpdate: unknown, ctx: HostContext) {
|
|
526
|
+
const activation = getActivation();
|
|
527
|
+
if (activation === undefined) throw new Error("通进司未激活");
|
|
528
|
+
try {
|
|
529
|
+
activation.ledger.beginOperational(COLLECTOR_HANDBOOK_WRITE_TOOL, toolCallId);
|
|
530
|
+
// scope/body shape authority = collectorHandbookWriteArgsSchema (host parameters).
|
|
531
|
+
const details = await activation.handbook.write(params.scope, params.body);
|
|
532
|
+
activation.handbookView = await activation.handbook.read();
|
|
533
|
+
activation.ledger.completeOperational(toolCallId);
|
|
534
|
+
return {
|
|
535
|
+
content: [{
|
|
536
|
+
type: "text" as const,
|
|
537
|
+
text: `手册已写入:${details.scope}`,
|
|
538
|
+
}],
|
|
539
|
+
details: {
|
|
540
|
+
scope: details.scope,
|
|
541
|
+
path: details.path,
|
|
542
|
+
byteLength: details.byteLength,
|
|
543
|
+
generalSource: activation.handbookView.generalSource,
|
|
544
|
+
repoSource: activation.handbookView.repoSource,
|
|
545
|
+
},
|
|
546
|
+
};
|
|
547
|
+
} catch (error) {
|
|
548
|
+
if (isCorrectableExecuteError(error)) throw error;
|
|
549
|
+
hostActions.failInfrastructure(error, ctx, toolCallId);
|
|
550
|
+
} finally {
|
|
551
|
+
try {
|
|
552
|
+
activation.ledger.completeOperational(toolCallId);
|
|
553
|
+
} catch {
|
|
554
|
+
// already completed or not begun
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
},
|
|
558
|
+
});
|
|
559
|
+
|
|
454
560
|
pi.registerTool({
|
|
455
561
|
name: COLLECTOR_WAIT_TOOL,
|
|
456
562
|
label: "通进司等待",
|
|
@@ -4,9 +4,33 @@ import { openToolObject } from "./open-tool-schema.ts";
|
|
|
4
4
|
import { withInfrastructureFailureDeclaration } from "./package-contracts/terminating-infrastructure.ts";
|
|
5
5
|
|
|
6
6
|
export const collectorObserveArgsSchema = Type.Object({}, { additionalProperties: false });
|
|
7
|
+
/**
|
|
8
|
+
* Stable request identity: non-empty after trim, no leading/trailing whitespace.
|
|
9
|
+
* Host schema + ledger identity seam share this contract (#677 / D2 dedup).
|
|
10
|
+
*/
|
|
11
|
+
export const COLLECTOR_REQUEST_ID_PATTERN = /^\S(?:.*\S)?$/;
|
|
7
12
|
export const collectorRequestArgsSchema = Type.Object({
|
|
8
|
-
requestId: Type.String({
|
|
13
|
+
requestId: Type.String({
|
|
14
|
+
minLength: 1,
|
|
15
|
+
pattern: COLLECTOR_REQUEST_ID_PATTERN.source,
|
|
16
|
+
description: "请求身份(配置 id 或角色判定的稳定 id;首尾无空白)",
|
|
17
|
+
}),
|
|
9
18
|
snapshotId: Type.String({ minLength: 1, description: "最新留存观察快照" }),
|
|
19
|
+
body: Type.Optional(Type.String({
|
|
20
|
+
minLength: 1,
|
|
21
|
+
description: "角色判定的请求正文;request-manifest 未收录该 requestId 时必填",
|
|
22
|
+
})),
|
|
23
|
+
}, { additionalProperties: false });
|
|
24
|
+
/** UTF-8 byte ceiling per handbook body — keeps next activation materials inside context budget. */
|
|
25
|
+
export const COLLECTOR_HANDBOOK_MAX_BYTES = 64 * 1024;
|
|
26
|
+
export const collectorHandbookWriteArgsSchema = Type.Object({
|
|
27
|
+
scope: Type.Union([
|
|
28
|
+
Type.Literal("general"),
|
|
29
|
+
Type.Literal("repo"),
|
|
30
|
+
], { description: "general=通用手册;repo=当前仓库差异" }),
|
|
31
|
+
body: Type.String({
|
|
32
|
+
description: `手册全文(opaque 工作记忆;整份替换;UTF-8 至多 ${COLLECTOR_HANDBOOK_MAX_BYTES} 字节)`,
|
|
33
|
+
}),
|
|
10
34
|
}, { additionalProperties: false });
|
|
11
35
|
export const collectorReadArgsSchema = Type.Object({
|
|
12
36
|
evidenceId: Type.String({ minLength: 1, description: "observe 返回的材料证据 id(evidenceId)" }),
|
|
@@ -598,8 +598,8 @@ const COLLECTOR_OPTIONS = [
|
|
|
598
598
|
repeatable: false,
|
|
599
599
|
form: "option",
|
|
600
600
|
description: {
|
|
601
|
-
en: "Optional request manifest JSON path ({requests:[{id,body}]}).",
|
|
602
|
-
zh: "可选 request manifest JSON 路径({requests:[{id,body}]}
|
|
601
|
+
en: "Optional request manifest JSON path ({requests:[{id,body}]}). Role may also decide request bodies from handbook/field activity without this file.",
|
|
602
|
+
zh: "可选 request manifest JSON 路径({requests:[{id,body}]})。角色亦可依手册/现场自行判定请求正文,不必依赖本文件。",
|
|
603
603
|
},
|
|
604
604
|
},
|
|
605
605
|
] as const satisfies readonly PublicOptionDefinition[];
|
package/src/role-runtime.ts
CHANGED
|
@@ -611,6 +611,8 @@ export type RoleRuntimeDependencies = {
|
|
|
611
611
|
/** Shared-seam issue-fetch capability for Reviewer Spec self-fetch (#343). */
|
|
612
612
|
createReviewerIssueFetcher?(): ReviewerIssueFetcher;
|
|
613
613
|
loadCollectorSoul?(): Promise<string>;
|
|
614
|
+
/** #677: optional packaged seed for first-use general bot handbook. */
|
|
615
|
+
loadCollectorHandbookSeed?(): Promise<string>;
|
|
614
616
|
createCollectorTransport?(): CollectorGitHubTransport;
|
|
615
617
|
loadDoctorSoul?(): Promise<string>;
|
|
616
618
|
loadNotarySoul?(): Promise<string>;
|
|
@@ -1717,6 +1719,9 @@ export function createRoleRuntimeExtension(
|
|
|
1717
1719
|
...(dependencies.createCollectorClock === undefined
|
|
1718
1720
|
? {}
|
|
1719
1721
|
: { createClock: dependencies.createCollectorClock }),
|
|
1722
|
+
...(dependencies.loadCollectorHandbookSeed === undefined
|
|
1723
|
+
? {}
|
|
1724
|
+
: { loadHandbookSeed: dependencies.loadCollectorHandbookSeed }),
|
|
1720
1725
|
},
|
|
1721
1726
|
hostActions,
|
|
1722
1727
|
);
|