@akagilnc/pi-workflow-roles 0.1.5845 → 0.1.5855
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 +4 -4
- package/README.zh-CN.md +4 -4
- package/dist/acp-host/production-host.js +348 -1254
- package/dist/acp-host/role-turn-host.js +4 -98
- package/dist/headless-host/production-host.js +15731 -16582
- package/dist/headless-host/role-turn-host.js +6 -31
- package/dist/migrate-book-topology.js +31 -16
- package/dist/navigator-attendance.js +54 -404
- package/dist/navigator-invocation-identity.js +0 -2
- package/dist/navigator-lookup-host.js +41 -0
- package/dist/navigator-lookup.js +68 -0
- package/dist/navigator-route-table.js +42 -0
- package/dist/package-contracts/navigator-output.js +3 -11
- package/dist/packaged-role-registry.js +3 -27
- package/dist/public-cli/instruction-seat-run.js +4 -1
- package/dist/public-cli/invocation.js +13 -26
- package/dist/public-cli/main.js +286 -114
- package/dist/public-cli/option-definitions.js +24 -4
- package/dist/public-cli/post-admission.js +0 -9
- package/dist/public-cli/role-seat-runtime.js +14 -0
- package/dist/public-cli/settlement.js +14 -40
- package/dist/public-cli/terminal.js +1 -8
- package/dist/public-cli/turn-request.js +0 -3
- package/dist/public-role-summons.js +0 -1
- package/dist/receipt-delivery-policy.js +0 -23
- package/dist/role-runtime-dependencies.js +4 -11
- package/dist/role-runtime.js +18 -194
- package/dist/submission-ledger.js +19 -15
- package/dist/ticket-progress.js +23 -5
- package/extensions/role-runtime.ts +0 -16
- package/package.json +1 -1
- package/scripts/build-package.mjs +3 -7
- package/src/acp-host/role-turn-host.ts +8 -97
- package/src/headless-host/description.ts +0 -2
- package/src/headless-host/role-turn-host.ts +7 -32
- package/src/host-contracts.ts +5 -7
- package/src/navigator-attendance.ts +86 -549
- package/src/navigator-invocation-identity.ts +0 -2
- package/src/navigator-lookup-host.ts +45 -0
- package/src/navigator-lookup.ts +98 -0
- package/src/navigator-route-table.ts +92 -0
- package/src/package-contracts/navigator-output.ts +4 -15
- package/src/packaged-role-registry.ts +3 -32
- package/src/public-cli/instruction-seat-run.ts +3 -0
- package/src/public-cli/invocation.ts +18 -30
- package/src/public-cli/option-definitions.ts +25 -4
- package/src/public-cli/post-admission.ts +0 -11
- package/src/public-cli/role-seat-runtime.ts +14 -0
- package/src/public-cli/settlement.ts +23 -51
- package/src/public-cli/terminal.ts +3 -18
- package/src/public-cli/turn-request.ts +0 -5
- package/src/public-role-summons.ts +0 -8
- package/src/receipt-delivery-policy.ts +0 -21
- package/src/role-runtime-dependencies.ts +4 -11
- package/src/role-runtime.ts +19 -210
- package/src/submission-ledger.ts +23 -16
- package/src/ticket-progress.ts +32 -5
- package/dist/navigator-public-session.js +0 -205
- package/dist/navigator-role.js +0 -6
- package/dist/navigator-session-contracts.js +0 -227
- package/dist/navigator-work-context.js +0 -72
- package/resources/navigator-route-playbook.md +0 -33
- package/src/navigator-public-session.ts +0 -305
- package/src/navigator-role.ts +0 -15
- package/src/navigator-session-contracts.ts +0 -320
- package/src/navigator-work-context.ts +0 -97
|
@@ -21,10 +21,6 @@ import {
|
|
|
21
21
|
copyAndRecordHostDossier,
|
|
22
22
|
recordNativeSessionPointer,
|
|
23
23
|
} from "../host-session-record.ts";
|
|
24
|
-
import {
|
|
25
|
-
NAVIGATOR_OUTPUT_TOOL_NAME,
|
|
26
|
-
navigatorProseFromUnknown,
|
|
27
|
-
} from "../package-contracts/navigator-output.ts";
|
|
28
24
|
import {
|
|
29
25
|
renderSystemPromptOverride,
|
|
30
26
|
resolveBoundHostSessionId,
|
|
@@ -33,54 +29,6 @@ import {
|
|
|
33
29
|
} from "../prepared-role-turn.ts";
|
|
34
30
|
import { acpModelId, type AcpHostDescription } from "./description.ts";
|
|
35
31
|
|
|
36
|
-
import { isRecord } from "../unknown-value.ts";
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* #959: collect free-form agent text from ACP session/update stream.
|
|
40
|
-
* Used only when the navigator seat spoke prose without calling the output tool.
|
|
41
|
-
* ACP agent speech is only agent_message / agent_message_chunk — never user,
|
|
42
|
-
* thought, or other *_message kinds (load replay must not poison the bucket).
|
|
43
|
-
*
|
|
44
|
-
* Standard ACP nests under params.update: { sessionUpdate, content }.
|
|
45
|
-
* Flat params.sessionUpdate / string params.update remain accepted for host variants.
|
|
46
|
-
*/
|
|
47
|
-
function acpAgentTextChunk(params: Readonly<Record<string, unknown>>): string | undefined {
|
|
48
|
-
let kind: unknown;
|
|
49
|
-
let content: unknown;
|
|
50
|
-
let textFallback: unknown;
|
|
51
|
-
|
|
52
|
-
const nested = params.update;
|
|
53
|
-
if (isRecord(nested)) {
|
|
54
|
-
const record = nested as Record<string, unknown>;
|
|
55
|
-
kind = record.sessionUpdate;
|
|
56
|
-
content = record.content;
|
|
57
|
-
textFallback = record.text;
|
|
58
|
-
} else {
|
|
59
|
-
kind = params.sessionUpdate ?? nested;
|
|
60
|
-
content = params.content;
|
|
61
|
-
textFallback = params.text;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (kind !== "agent_message_chunk" && kind !== "agent_message") return undefined;
|
|
65
|
-
if (typeof content === "string" && content.length > 0) return content;
|
|
66
|
-
if (isRecord(content)) {
|
|
67
|
-
const record = content as Record<string, unknown>;
|
|
68
|
-
if (typeof record.text === "string" && record.text.length > 0) return record.text;
|
|
69
|
-
}
|
|
70
|
-
if (Array.isArray(content)) {
|
|
71
|
-
const parts: string[] = [];
|
|
72
|
-
for (const part of content) {
|
|
73
|
-
if (typeof part === "string" && part.length > 0) parts.push(part);
|
|
74
|
-
else if (typeof part === "object" && part !== null) {
|
|
75
|
-
const record = part as Record<string, unknown>;
|
|
76
|
-
if (typeof record.text === "string" && record.text.length > 0) parts.push(record.text);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (parts.length > 0) return parts.join("");
|
|
80
|
-
}
|
|
81
|
-
if (typeof textFallback === "string" && textFallback.length > 0) return textFallback;
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
32
|
|
|
85
33
|
/** ACP v1 surface used by the generic ACP adapter. Protocol details stay in this module. */
|
|
86
34
|
export interface AcpConnection {
|
|
@@ -279,20 +227,6 @@ export function createAcpRoleTurnHost(config: AcpRoleTurnHostConfig): RoleTurnHo
|
|
|
279
227
|
params: Readonly<Record<string, unknown>>,
|
|
280
228
|
): Promise<Readonly<Record<string, unknown>>> => connection!.request(method, params);
|
|
281
229
|
|
|
282
|
-
// #959: navigator free-form agent text — only while session/prompt is in flight.
|
|
283
|
-
// session/load replays history via session/update; those must not enter the bucket
|
|
284
|
-
// (resume / set_model load would otherwise prepend prior turns as "this turn" prose).
|
|
285
|
-
const agentProseChunks: string[] = [];
|
|
286
|
-
let collectAgentProse = false;
|
|
287
|
-
connection.onNotification?.((method, params) => {
|
|
288
|
-
const isSessionUpdate = method === "session/update";
|
|
289
|
-
if (!isSessionUpdate) return;
|
|
290
|
-
if (collectAgentProse) {
|
|
291
|
-
const chunk = acpAgentTextChunk(params);
|
|
292
|
-
if (chunk !== undefined) agentProseChunks.push(chunk);
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
|
|
296
230
|
const initialized = await rpc("initialize", {
|
|
297
231
|
protocolVersion: 1,
|
|
298
232
|
clientCapabilities: {},
|
|
@@ -387,26 +321,15 @@ export function createAcpRoleTurnHost(config: AcpRoleTurnHostConfig): RoleTurnHo
|
|
|
387
321
|
outputSchema: deliveredSchema,
|
|
388
322
|
}, "acp-host");
|
|
389
323
|
let result: Readonly<Record<string, unknown>>;
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
}),
|
|
399
|
-
abortSignal,
|
|
400
|
-
"ACP host aborted",
|
|
401
|
-
);
|
|
402
|
-
} catch (error) {
|
|
403
|
-
collectAgentProse = false;
|
|
404
|
-
agentProseChunks.length = 0;
|
|
405
|
-
throw error;
|
|
406
|
-
}
|
|
407
|
-
collectAgentProse = false;
|
|
324
|
+
result = await raceAgainstHostAbort(
|
|
325
|
+
activeConnection.request("session/prompt", {
|
|
326
|
+
sessionId: activeSessionId,
|
|
327
|
+
prompt: [{ type: "text", text: prompt }],
|
|
328
|
+
}),
|
|
329
|
+
abortSignal,
|
|
330
|
+
"ACP host aborted",
|
|
331
|
+
);
|
|
408
332
|
if (result.stopReason === "refusal") {
|
|
409
|
-
agentProseChunks.length = 0;
|
|
410
333
|
reportedFailure = { diagnostic: result.stopReason, details: result };
|
|
411
334
|
return {
|
|
412
335
|
status: "terminal",
|
|
@@ -418,18 +341,6 @@ export function createAcpRoleTurnHost(config: AcpRoleTurnHostConfig): RoleTurnHo
|
|
|
418
341
|
},
|
|
419
342
|
};
|
|
420
343
|
}
|
|
421
|
-
// #959: navigator prose exit when the model spoke without the output tool.
|
|
422
|
-
// Tool path still wins via MCP; ingest is a no-op once the tool already sealed.
|
|
423
|
-
// Emptiness via shared projector; payload keeps original bytes (LLM 原话过手).
|
|
424
|
-
if (prepared.terminatingToolName === NAVIGATOR_OUTPUT_TOOL_NAME) {
|
|
425
|
-
const prose = agentProseChunks.join("");
|
|
426
|
-
agentProseChunks.length = 0;
|
|
427
|
-
if (navigatorProseFromUnknown(prose) !== undefined) {
|
|
428
|
-
await prepared.ingestStructuredOutput({ prose });
|
|
429
|
-
}
|
|
430
|
-
} else {
|
|
431
|
-
agentProseChunks.length = 0;
|
|
432
|
-
}
|
|
433
344
|
return { status: "delivered", stderr: activeConnection.stderr?.() ?? "" };
|
|
434
345
|
},
|
|
435
346
|
async afterAccepted() {
|
|
@@ -433,8 +433,6 @@ export function codexTurnArgs(options: {
|
|
|
433
433
|
/**
|
|
434
434
|
* Absolute path for the native `--output-schema` flag.
|
|
435
435
|
* File holds the Codex-strict transport projection of the open declaration (#1148).
|
|
436
|
-
* Optional: omit for direct navigator prose exit (#959); attendance byStatus
|
|
437
|
-
* prepare mounts it via RoleTurnRequest.navigatorByStatusPrepare (#1160).
|
|
438
436
|
*/
|
|
439
437
|
readonly outputSchemaPath?: string;
|
|
440
438
|
readonly mcpServers: readonly Readonly<Record<string, unknown>>[];
|
|
@@ -46,7 +46,6 @@ import {
|
|
|
46
46
|
isCodexExecDescription,
|
|
47
47
|
type HeadlessHostDescription,
|
|
48
48
|
} from "./description.ts";
|
|
49
|
-
import { NAVIGATOR_OUTPUT_TOOL_NAME } from "../package-contracts/navigator-output.ts";
|
|
50
49
|
|
|
51
50
|
import { errorText, isRecord } from "../unknown-value.ts";
|
|
52
51
|
|
|
@@ -392,7 +391,7 @@ function terminalFromSpawned(
|
|
|
392
391
|
function buildTurnArgs(options: {
|
|
393
392
|
readonly description: HeadlessHostDescription;
|
|
394
393
|
readonly systemPromptPath: string;
|
|
395
|
-
/** Open schema for Claude --json-schema
|
|
394
|
+
/** Open schema for Claude --json-schema. */
|
|
396
395
|
readonly jsonSchema?: Readonly<Record<string, unknown>>;
|
|
397
396
|
readonly mcpServers: readonly Readonly<Record<string, unknown>>[];
|
|
398
397
|
readonly mcpConfigPath?: string;
|
|
@@ -408,7 +407,6 @@ function buildTurnArgs(options: {
|
|
|
408
407
|
if (options.sessionKind === "resume" && !options.sessionId) {
|
|
409
408
|
throw new Error("codex resume requires a bound thread_id");
|
|
410
409
|
}
|
|
411
|
-
// Codex always mounts --output-schema when the path is supplied (incl. navigator byStatus #1160).
|
|
412
410
|
return codexTurnArgs({
|
|
413
411
|
systemPromptPath: options.systemPromptPath,
|
|
414
412
|
...(options.outputSchemaPath === undefined ? {} : { outputSchemaPath: options.outputSchemaPath }),
|
|
@@ -429,7 +427,6 @@ function buildTurnArgs(options: {
|
|
|
429
427
|
return headlessTurnArgs({
|
|
430
428
|
description: options.description,
|
|
431
429
|
systemPromptPath: options.systemPromptPath,
|
|
432
|
-
// #959: navigator omits --json-schema so free-form prose is a lawful exit.
|
|
433
430
|
...(options.jsonSchema === undefined ? {} : { jsonSchema: options.jsonSchema }),
|
|
434
431
|
mcpConfigPath: options.mcpConfigPath,
|
|
435
432
|
...(options.model === undefined ? {} : { model: options.model }),
|
|
@@ -444,11 +441,6 @@ export function createHeadlessRoleTurnHost(config: HeadlessRoleTurnHostConfig):
|
|
|
444
441
|
const prepared = await config.prepare(request);
|
|
445
442
|
const systemPrompt = renderSystemPromptOverride(prepared.systemPrompt);
|
|
446
443
|
const codex = isCodexExecDescription(config.description);
|
|
447
|
-
// #1160: one exit-mode decision per turn — direct navigator free prose vs structured.
|
|
448
|
-
// Attendance sets request.navigatorByStatusPrepare; direct ak-role navigator does not.
|
|
449
|
-
const navigatorProseExit =
|
|
450
|
-
prepared.terminatingToolName === NAVIGATOR_OUTPUT_TOOL_NAME
|
|
451
|
-
&& request.navigatorByStatusPrepare !== true;
|
|
452
444
|
let outcome: RoleTurnResult = failure("session", "HeadlessNoOutcome", "no-outcome");
|
|
453
445
|
try {
|
|
454
446
|
// Claude mints a package UUID for --session-id; codex waits for thread.started.
|
|
@@ -490,11 +482,9 @@ export function createHeadlessRoleTurnHost(config: HeadlessRoleTurnHostConfig):
|
|
|
490
482
|
if (codex) {
|
|
491
483
|
// #1148: Codex --output-schema requires a native strict transport schema.
|
|
492
484
|
// Project from the unique open declaration; do not alter package receipt rules.
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
await writeFile(outputSchemaPath, `${JSON.stringify(deliveredSchema, null, 2)}\n`, "utf8");
|
|
497
|
-
}
|
|
485
|
+
outputSchemaPath = join(inputsDirectory, "output-schema.json");
|
|
486
|
+
deliveredSchema = closeJsonSchemaForCodex(prepared.jsonSchema);
|
|
487
|
+
await writeFile(outputSchemaPath, `${JSON.stringify(deliveredSchema, null, 2)}\n`, "utf8");
|
|
498
488
|
} else {
|
|
499
489
|
mcpConfigPath = join(inputsDirectory, "mcp-config.json");
|
|
500
490
|
await writeFile(
|
|
@@ -502,7 +492,7 @@ export function createHeadlessRoleTurnHost(config: HeadlessRoleTurnHostConfig):
|
|
|
502
492
|
`${JSON.stringify(headlessMcpConfigDocument(prepared.mcpServers), null, 2)}\n`,
|
|
503
493
|
"utf8",
|
|
504
494
|
);
|
|
505
|
-
|
|
495
|
+
deliveredSchema = prepared.jsonSchema;
|
|
506
496
|
}
|
|
507
497
|
startedWithSchema = deliveredSchema;
|
|
508
498
|
} catch (setupError) {
|
|
@@ -530,8 +520,7 @@ export function createHeadlessRoleTurnHost(config: HeadlessRoleTurnHostConfig):
|
|
|
530
520
|
args = buildTurnArgs({
|
|
531
521
|
description: config.description,
|
|
532
522
|
systemPromptPath,
|
|
533
|
-
|
|
534
|
-
...(navigatorProseExit ? {} : { jsonSchema: prepared.jsonSchema }),
|
|
523
|
+
jsonSchema: prepared.jsonSchema,
|
|
535
524
|
mcpServers: prepared.mcpServers,
|
|
536
525
|
...(mcpConfigPath === undefined ? {} : { mcpConfigPath }),
|
|
537
526
|
...(outputSchemaPath === undefined ? {} : { outputSchemaPath }),
|
|
@@ -669,13 +658,7 @@ export function createHeadlessRoleTurnHost(config: HeadlessRoleTurnHostConfig):
|
|
|
669
658
|
|
|
670
659
|
const deliverReply = async (): Promise<ReturnType<typeof deliveredFromSpawned> | undefined> => {
|
|
671
660
|
if (!observation.turnCompleted || observation.finalMessage === undefined) return undefined;
|
|
672
|
-
|
|
673
|
-
// Direct ak-role navigator: free-form agent_message is the prose body.
|
|
674
|
-
if (observation.finalMessage.trim() === "") return undefined;
|
|
675
|
-
await prepared.ingestStructuredOutput({ prose: observation.finalMessage });
|
|
676
|
-
return deliveredFromSpawned(spawned);
|
|
677
|
-
}
|
|
678
|
-
// Structured seats (incl. #1160 byStatus prepare): native JSON receipt.
|
|
661
|
+
// Native JSON receipt.
|
|
679
662
|
let receipt: unknown;
|
|
680
663
|
try {
|
|
681
664
|
receipt = JSON.parse(observation.finalMessage);
|
|
@@ -723,14 +706,6 @@ export function createHeadlessRoleTurnHost(config: HeadlessRoleTurnHostConfig):
|
|
|
723
706
|
|
|
724
707
|
if (envelope.structured_output !== undefined) {
|
|
725
708
|
await prepared.ingestStructuredOutput(envelope.structured_output);
|
|
726
|
-
} else if (
|
|
727
|
-
navigatorProseExit
|
|
728
|
-
&& typeof envelope.result === "string"
|
|
729
|
-
&& envelope.result.trim() !== ""
|
|
730
|
-
) {
|
|
731
|
-
// #959: direct navigator prose exit — free-form result text is the body
|
|
732
|
-
// when structured_output is absent (json-schema omitted).
|
|
733
|
-
await prepared.ingestStructuredOutput({ prose: envelope.result });
|
|
734
709
|
}
|
|
735
710
|
return deliveredFromSpawned(spawned);
|
|
736
711
|
} catch (error) {
|
package/src/host-contracts.ts
CHANGED
|
@@ -134,7 +134,11 @@ export type RoleTurnActivation =
|
|
|
134
134
|
}
|
|
135
135
|
| { readonly role: "inspector"; readonly sourceRun?: string }
|
|
136
136
|
| { readonly role: "gatekeeper" }
|
|
137
|
-
| {
|
|
137
|
+
| {
|
|
138
|
+
readonly role: "navigator";
|
|
139
|
+
/** Structured target seat for the lookup run (#1192); absent = whole table. */
|
|
140
|
+
readonly forRole?: string;
|
|
141
|
+
}
|
|
138
142
|
| { readonly role: "auditor" }
|
|
139
143
|
| { readonly role: "diarist" }
|
|
140
144
|
| { readonly role: "secretariat" };
|
|
@@ -199,12 +203,6 @@ export type RoleTurnRequest = {
|
|
|
199
203
|
readonly host?: string;
|
|
200
204
|
/** Station child role run (#840): omit automatic navigator attendance. */
|
|
201
205
|
readonly stationChild?: boolean;
|
|
202
|
-
/**
|
|
203
|
-
* #1160 attendance auto-prepare: host mounts native structured schema so
|
|
204
|
-
* byStatus returns as structured fields. Direct `ak-role navigator` omits
|
|
205
|
-
* this and keeps the free-form prose exit (#959).
|
|
206
|
-
*/
|
|
207
|
-
readonly navigatorByStatusPrepare?: boolean;
|
|
208
206
|
/**
|
|
209
207
|
* #1132: the effective delivery-request ceiling resolved once by the caller
|
|
210
208
|
* from the single configured `autoResumeLimit` value and projected here, so
|