@akagilnc/pi-workflow-roles 0.1.3558 → 0.1.3572
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 -1
- package/README.zh-CN.md +1 -1
- package/dist/acp-host/description.js +21 -0
- package/dist/{grok → acp-host}/mcp-relay.mjs +5 -5
- package/dist/{grok → acp-host}/production-host.js +860 -162
- package/dist/diarist-contracts.js +72 -0
- package/dist/host-descriptions.js +34 -0
- package/dist/package-contracts/terminating-tools.js +20 -2
- package/dist/packaged-role-registry.js +20 -0
- package/dist/public-cli/config.js +23 -10
- package/dist/public-cli/main.js +622 -671
- package/dist/public-cli/registry.js +4 -1
- package/extensions/role-runtime.ts +1 -0
- package/package.json +1 -1
- package/resources/diarist-collect.md +6 -10
- package/scripts/build-package.mjs +8 -8
- package/souls/diarist.md +9 -0
- package/src/acp-host/description.ts +43 -0
- package/src/{grok → acp-host}/mcp-relay.mjs +5 -5
- package/src/{grok → acp-host}/production-host.ts +31 -37
- package/src/{grok → acp-host}/role-envelope.ts +25 -24
- package/src/{grok → acp-host}/role-turn-host.ts +46 -81
- package/src/{grok → acp-host}/session-identity.ts +7 -7
- package/src/diarist-contracts.ts +88 -0
- package/src/diarist-role.ts +60 -0
- package/src/diarist.ts +253 -179
- package/src/host-contracts.ts +11 -4
- package/src/host-descriptions.ts +51 -0
- package/src/host-transition-prior-native.ts +12 -24
- package/src/package-contracts/terminating-tools.ts +22 -2
- package/src/packaged-role-registry.ts +20 -0
- package/src/pi/role-turn-host.ts +10 -1
- package/src/public-cli/cli.ts +39 -9
- package/src/public-cli/config.ts +24 -11
- package/src/public-cli/countersign-run.ts +9 -129
- package/src/public-cli/diarist-run.ts +312 -0
- package/src/public-cli/invocation.ts +23 -2
- package/src/public-cli/load-production-acp-host.ts +52 -0
- package/src/public-cli/option-definitions.ts +18 -0
- package/src/public-cli/post-admission.ts +3 -3
- package/src/public-cli/registry.ts +3 -0
- package/src/public-cli/run-lifecycle.ts +31 -3
- package/src/public-cli/settlement.ts +50 -2
- package/src/public-cli/terminal.ts +2 -1
- package/src/role-runtime.ts +117 -6
- package/src/ticket-provenance-contracts.ts +1 -0
- package/src/ticket-provenance.ts +0 -23
- package/src/diarist-llm-collector.ts +0 -324
- package/src/public-cli/load-production-grok-host.ts +0 -35
|
@@ -65,7 +65,10 @@ const STARTUP_CANDIDATES = {
|
|
|
65
65
|
navigator: [
|
|
66
66
|
{ provider: "openai-codex", model: "gpt-5.6-luna", thinking: "medium" },
|
|
67
67
|
{ provider: "xai", model: "grok-4.5", thinking: "high" }
|
|
68
|
-
]
|
|
68
|
+
],
|
|
69
|
+
// #708 `diarist-seat-default`: owner-set initial value; changed in the seat
|
|
70
|
+
// table like any other seat. No engine axis, package-default host.
|
|
71
|
+
diarist: [{ provider: "xai", model: "grok-4.5", thinking: "medium" }]
|
|
69
72
|
};
|
|
70
73
|
function publicStartupCandidates(seat) {
|
|
71
74
|
return STARTUP_CANDIDATES[seat];
|
|
@@ -127,6 +127,7 @@ export default function roleRuntime(pi: ExtensionAPI): void {
|
|
|
127
127
|
loadNotarySoul: () => loadMainRoleSessionMaterials("notary"),
|
|
128
128
|
loadCountersignSoul: () => loadMainRoleSessionMaterials("countersign"),
|
|
129
129
|
loadGleanerLeftSoul: () => loadMainRoleSessionMaterials("gleaner-left"),
|
|
130
|
+
loadDiaristSoul: () => loadMainRoleSessionMaterials("diarist"),
|
|
130
131
|
loadInspectorSoul: () => loadMainRoleSessionMaterials("inspector"),
|
|
131
132
|
loadGatekeeperSoul: () => loadGatekeeperSessionMaterials("gatekeeper"),
|
|
132
133
|
loadNavigatorSoul: () => loadMainRoleSessionMaterials("navigator"),
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# 起居郎收集方法(owner-domain)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
本文件是起居郎语义收集的方法真源(ADR 0075 `diarist-llm-collector` / `transcribe-whole-blocks`)。
|
|
4
4
|
|
|
5
5
|
## 任务
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
从本票已冻结的来源块文件中,选出**与本票决策相关**的整块。文件路径见本轮材料中的路径指针,自行读取;不要等别人把正文贴进对话。
|
|
8
8
|
|
|
9
9
|
## 何谓决策相关
|
|
10
10
|
|
|
@@ -14,16 +14,12 @@
|
|
|
14
14
|
- 命名、工序先后、调用面、闸位、存量是否补档等裁决
|
|
15
15
|
- 对既有 ADR / 法源的采纳、修正或明确不适用
|
|
16
16
|
- 陛下(owner)原话、确认、否决、收口条件
|
|
17
|
-
-
|
|
17
|
+
- 为上述裁决提供必要上下文的紧邻块
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
无关闲聊、纯工具噪声、与本票决策无涉的他票材料不选。
|
|
20
20
|
|
|
21
21
|
## 誊录整块
|
|
22
22
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
23
|
+
- 入选即整块保留:指向文件中的完整 transcript,不指针化、不摘要替代正文。
|
|
24
|
+
- 引语必须是该块 transcript 内的**连续原文子串**。拼接、改写、跨段拼贴会在机械反验中失败并拒入录。
|
|
25
25
|
- 宁多勿漏:拿不准是否决策相关时入选,由下游反验与人读面承接。
|
|
26
|
-
|
|
27
|
-
## 输出
|
|
28
|
-
|
|
29
|
-
只输出一个 JSON 对象,形状由机器 prompt 给出的 `selections` 约定。不要输出 JSON 以外的文字。
|
|
@@ -88,16 +88,16 @@ export async function buildPublicAkRoleBin(
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
|
-
* Deferred
|
|
92
|
-
* root selects
|
|
93
|
-
* packages:"external" so optional peers resolve
|
|
91
|
+
* Deferred generic ACP production host artifact. Loaded only when the composition
|
|
92
|
+
* root selects an external host row — keeps role-runtime / peer edges out of the
|
|
93
|
+
* public bin. packages:"external" so optional peers resolve at selection.
|
|
94
94
|
*/
|
|
95
|
-
export async function
|
|
96
|
-
outfile = "dist/
|
|
95
|
+
export async function buildAcpProductionHost(
|
|
96
|
+
outfile = "dist/acp-host/production-host.js",
|
|
97
97
|
) {
|
|
98
98
|
await mkdir(dirname(outfile), { recursive: true });
|
|
99
99
|
await build({
|
|
100
|
-
entryPoints: ["src/
|
|
100
|
+
entryPoints: ["src/acp-host/production-host.ts"],
|
|
101
101
|
outfile,
|
|
102
102
|
format: "esm",
|
|
103
103
|
platform: "node",
|
|
@@ -108,7 +108,7 @@ export async function buildGrokProductionHost(
|
|
|
108
108
|
});
|
|
109
109
|
// role-envelope resolves ./mcp-relay.mjs from import.meta.url — keep it beside the bundle.
|
|
110
110
|
await copyFile(
|
|
111
|
-
resolve("src/
|
|
111
|
+
resolve("src/acp-host/mcp-relay.mjs"),
|
|
112
112
|
join(dirname(outfile), "mcp-relay.mjs"),
|
|
113
113
|
);
|
|
114
114
|
}
|
|
@@ -137,7 +137,7 @@ export async function buildPackageArtifacts() {
|
|
|
137
137
|
);
|
|
138
138
|
}
|
|
139
139
|
await buildPublicAkRoleBin();
|
|
140
|
-
await
|
|
140
|
+
await buildAcpProductionHost();
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
const isMain =
|
package/souls/diarist.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Diarist Soul(起居郎)
|
|
2
|
+
|
|
3
|
+
你为本案找齐并整理决策依据,收进本票已有的起居录。你只记录已经作出的决定,不立法、不批准设计、不指挥施工。
|
|
4
|
+
|
|
5
|
+
- 相关性由你裁决:不把票面已列出的材料当完整候选集合,也不以票号、引语或关键词未命中作为排除依据。
|
|
6
|
+
- 分清身份:陛下(owner)的决定、助手的提议、正式裁决、你自己的整理解释,四者不得混同;建议不得写成授权。
|
|
7
|
+
- 导航而非重写:已有设计与法源以原件指针加简短关系说明引用,不复制成第二份规范。
|
|
8
|
+
- 分清现行与历史:被修订替代的决定保留出处,但不与当前方向并列。
|
|
9
|
+
- 缺录、不可读、引用无法核实时如实说明,不猜成事实,不以缺失充当"没有问题"。
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One ACP host description. Every host-specific value the generic ACP adapter
|
|
3
|
+
* needs — binary location, argv shape, resume verb, binding filename, child env
|
|
4
|
+
* — is data here; the lifecycle in role-turn-host.ts stays one copy (#732).
|
|
5
|
+
*/
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
|
|
8
|
+
export type AcpHostDescription = Readonly<{
|
|
9
|
+
/** Binary path segments relative to the operator home. */
|
|
10
|
+
binaryFromHome: readonly string[];
|
|
11
|
+
argv: Readonly<{
|
|
12
|
+
prefix: readonly string[];
|
|
13
|
+
suffix: readonly string[];
|
|
14
|
+
modelFlag?: string;
|
|
15
|
+
thinkingFlag?: string;
|
|
16
|
+
}>;
|
|
17
|
+
/** Which verb a bound resume uses; "session/new" hosts always mint + bind. */
|
|
18
|
+
boundResume: "session/load" | "session/new";
|
|
19
|
+
/** Durable ACP binding filename written beside the session principal. */
|
|
20
|
+
sessionBindingFile: string;
|
|
21
|
+
childEnv: Readonly<Record<string, string>>;
|
|
22
|
+
}>;
|
|
23
|
+
|
|
24
|
+
/** Absolute agent binary for one operator home. */
|
|
25
|
+
export function resolveAcpBinary(description: AcpHostDescription, operatorHome: string): string {
|
|
26
|
+
return join(operatorHome, ...description.binaryFromHome);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Stdio argv: prefix, optional model/thinking flag pairs, suffix. */
|
|
30
|
+
export function acpStdioArgs(
|
|
31
|
+
description: AcpHostDescription,
|
|
32
|
+
model?: { readonly model?: string; readonly thinking?: string },
|
|
33
|
+
): string[] {
|
|
34
|
+
const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
|
|
35
|
+
const pair = (flag: string | undefined, value: string | undefined): string[] =>
|
|
36
|
+
flag === undefined || value === undefined ? [] : [flag, value];
|
|
37
|
+
return [
|
|
38
|
+
...prefix,
|
|
39
|
+
...pair(modelFlag, model?.model),
|
|
40
|
+
...pair(thinkingFlag, model?.thinking),
|
|
41
|
+
...suffix,
|
|
42
|
+
];
|
|
43
|
+
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { connect } from "node:net";
|
|
3
3
|
import { createInterface } from "node:readline";
|
|
4
4
|
|
|
5
|
-
const socketPath = process.env.
|
|
6
|
-
const token = process.env.
|
|
7
|
-
if (!socketPath || !token) throw new Error("AK
|
|
5
|
+
const socketPath = process.env.AK_ACP_MCP_SOCKET;
|
|
6
|
+
const token = process.env.AK_ACP_MCP_TOKEN;
|
|
7
|
+
if (!socketPath || !token) throw new Error("AK ACP MCP relay identity is missing");
|
|
8
8
|
|
|
9
9
|
const upstream = connect(socketPath);
|
|
10
10
|
const waiters = new Map();
|
|
@@ -45,7 +45,7 @@ upstream.on("error", (error) => settle(error));
|
|
|
45
45
|
upstream.on("close", () => {
|
|
46
46
|
// Shutdown may already be requested (stdin EOF) while an RPC is still
|
|
47
47
|
// in flight. Outstanding waiters must still settle, or drain never ends.
|
|
48
|
-
if (!exiting) settle(new Error("AK
|
|
48
|
+
if (!exiting) settle(new Error("AK ACP MCP upstream closed"));
|
|
49
49
|
maybeExit();
|
|
50
50
|
});
|
|
51
51
|
createInterface({ input: upstream }).on("line", (line) => {
|
|
@@ -56,7 +56,7 @@ createInterface({ input: upstream }).on("line", (line) => {
|
|
|
56
56
|
if (waiter === undefined) return;
|
|
57
57
|
waiters.delete(message.id);
|
|
58
58
|
if (message.error !== undefined) {
|
|
59
|
-
const error = new Error(typeof message.error.message === "string" ? message.error.message : "AK
|
|
59
|
+
const error = new Error(typeof message.error.message === "string" ? message.error.message : "AK ACP MCP relay failure");
|
|
60
60
|
error.code = message.error.code;
|
|
61
61
|
error.cause = message.error;
|
|
62
62
|
waiter.reject(error);
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Production composition for the
|
|
3
|
-
* Owns injectables around the S6 true adapter; does not alter
|
|
2
|
+
* Production composition for the generic ACP RoleTurnHost adapter (#732).
|
|
3
|
+
* Owns injectables around the S6 true adapter; does not alter adapter behavior.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* factory does not create a run-scoped
|
|
7
|
-
* does not copy or scrub
|
|
5
|
+
* The agent runs against the operator home and its credentials in place. The
|
|
6
|
+
* factory does not create a run-scoped agent home, does not rewrite HOME, and
|
|
7
|
+
* does not copy or scrub credentials. Sitian records on the run are the dossier.
|
|
8
8
|
*/
|
|
9
9
|
import { readFile } from "node:fs/promises";
|
|
10
|
-
import { join } from "node:path";
|
|
11
10
|
import { fileURLToPath } from "node:url";
|
|
12
11
|
|
|
13
12
|
import { loadCanonicalSkillBinding as loadHomeCanonicalSkillBinding } from "../canonical-skill-binding.ts";
|
|
@@ -25,35 +24,23 @@ import { createPerDispatchReviewerAgent } from "../reviewer-agent.ts";
|
|
|
25
24
|
import { formatNavigatorRoleHelp, type RoleRuntimeDependencies } from "../role-runtime.ts";
|
|
26
25
|
import { createReviewerPinnedGitReader } from "../reviewer-pinned-git.ts";
|
|
27
26
|
import { loadGatekeeperSessionMaterials, loadMainRoleSessionMaterials } from "../session-opening-materials.ts";
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
} from "./role-turn-host.ts";
|
|
33
|
-
import { createGrokSessionIdentityAuthority } from "./session-identity.ts";
|
|
27
|
+
import { acpStdioArgs, resolveAcpBinary, type AcpHostDescription } from "./description.ts";
|
|
28
|
+
import { createComposedAcpRoleTurnHost } from "./role-envelope.ts";
|
|
29
|
+
import { connectAcpStdio } from "./role-turn-host.ts";
|
|
30
|
+
import { createAcpSessionIdentityAuthority } from "./session-identity.ts";
|
|
34
31
|
|
|
35
|
-
export type
|
|
32
|
+
export type ProductionAcpHostOptions = Readonly<{
|
|
36
33
|
packageRoot: string;
|
|
37
34
|
principalAuthority: DurablePrincipalAuthority;
|
|
35
|
+
description: AcpHostDescription;
|
|
38
36
|
}>;
|
|
39
37
|
|
|
40
|
-
function resolveGrokBinary(operatorHome: string): string {
|
|
41
|
-
return join(operatorHome, ".grok", "bin", "grok");
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function childEnv(packageRoot: string): NodeJS.ProcessEnv {
|
|
45
|
-
return {
|
|
46
|
-
...controlledGrokChildEnv(process.env),
|
|
47
|
-
AK_PACKAGE_ROOT: packageRoot,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
38
|
const navigatorRoutePlaybookPath = fileURLToPath(
|
|
52
39
|
new URL("../../resources/navigator-route-playbook.md", import.meta.url),
|
|
53
40
|
);
|
|
54
41
|
|
|
55
|
-
/** Host-neutral packaged role runtime deps for the
|
|
56
|
-
export function
|
|
42
|
+
/** Host-neutral packaged role runtime deps for the ACP parent-process envelope. */
|
|
43
|
+
export function createAcpRoleRuntimeDependencies(packageRoot: string): RoleRuntimeDependencies {
|
|
57
44
|
const judgeAuditor = createPiJudgeAuditor();
|
|
58
45
|
const doctorAuditor = createPiDoctorAuditor();
|
|
59
46
|
const reviewerAgent = createPerDispatchReviewerAgent({ packageRoot });
|
|
@@ -77,6 +64,7 @@ export function createGrokRoleRuntimeDependencies(packageRoot: string): RoleRunt
|
|
|
77
64
|
loadNotarySoul: () => loadMainRoleSessionMaterials("notary"),
|
|
78
65
|
loadCountersignSoul: () => loadMainRoleSessionMaterials("countersign"),
|
|
79
66
|
loadGleanerLeftSoul: () => loadMainRoleSessionMaterials("gleaner-left"),
|
|
67
|
+
loadDiaristSoul: () => loadMainRoleSessionMaterials("diarist"),
|
|
80
68
|
loadNotarySourceRun: loadNotarySourceRunLocator,
|
|
81
69
|
loadMergerSoul: () => loadMainRoleSessionMaterials("merger"),
|
|
82
70
|
loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
|
|
@@ -119,22 +107,28 @@ export function createGrokRoleRuntimeDependencies(packageRoot: string): RoleRunt
|
|
|
119
107
|
}
|
|
120
108
|
|
|
121
109
|
/**
|
|
122
|
-
* Assemble
|
|
123
|
-
*
|
|
110
|
+
* Assemble a production ACP RoleTurnHost from the S6 true adapter for one host
|
|
111
|
+
* description. Agent subprocesses inherit the operator home; the run directory
|
|
112
|
+
* is sitian-only.
|
|
124
113
|
*/
|
|
125
|
-
export function
|
|
126
|
-
const { packageRoot, principalAuthority } = options;
|
|
127
|
-
const env =
|
|
114
|
+
export function createProductionAcpRoleTurnHost(options: ProductionAcpHostOptions): RoleTurnHost {
|
|
115
|
+
const { packageRoot, principalAuthority, description } = options;
|
|
116
|
+
const env: NodeJS.ProcessEnv = {
|
|
117
|
+
...process.env,
|
|
118
|
+
...description.childEnv,
|
|
119
|
+
AK_PACKAGE_ROOT: packageRoot,
|
|
120
|
+
};
|
|
128
121
|
|
|
129
|
-
return
|
|
130
|
-
sessionIdentity:
|
|
131
|
-
|
|
122
|
+
return createComposedAcpRoleTurnHost({
|
|
123
|
+
sessionIdentity: createAcpSessionIdentityAuthority(principalAuthority, description.sessionBindingFile),
|
|
124
|
+
boundResume: description.boundResume,
|
|
125
|
+
roleRuntimeDependencies: createAcpRoleRuntimeDependencies(packageRoot),
|
|
132
126
|
async connect(request) {
|
|
133
|
-
return
|
|
134
|
-
binary:
|
|
127
|
+
return connectAcpStdio({
|
|
128
|
+
binary: resolveAcpBinary(description, request.home),
|
|
129
|
+
args: acpStdioArgs(description, request.model),
|
|
135
130
|
cwd: request.cwd,
|
|
136
131
|
env,
|
|
137
|
-
...(request.model === undefined ? {} : { model: request.model.model }),
|
|
138
132
|
});
|
|
139
133
|
},
|
|
140
134
|
});
|
|
@@ -22,9 +22,9 @@ import {
|
|
|
22
22
|
type RoleRuntimeDependencies,
|
|
23
23
|
} from "../role-runtime.ts";
|
|
24
24
|
import {
|
|
25
|
-
|
|
26
|
-
type
|
|
27
|
-
type
|
|
25
|
+
createAcpRoleTurnHost,
|
|
26
|
+
type AcpPreparedTurn,
|
|
27
|
+
type AcpRoleTurnHostConfig,
|
|
28
28
|
} from "./role-turn-host.ts";
|
|
29
29
|
import {
|
|
30
30
|
GatekeeperDecisionError,
|
|
@@ -51,7 +51,7 @@ export function parseCanonicalSkillInvocation(prompt: string): { readonly name:
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/** Build host-side Skill expansion evidence from pre-read RoleTurnRequest.methods. */
|
|
54
|
-
export function
|
|
54
|
+
export function buildAcpSkillExpansion(
|
|
55
55
|
methodSkills: ReadonlyMap<string, { readonly path: string; readonly body: string }>,
|
|
56
56
|
prompt: string,
|
|
57
57
|
): HostSkillExpansionEvidence | undefined {
|
|
@@ -67,7 +67,7 @@ export function buildGrokSkillExpansion(
|
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
export function
|
|
70
|
+
export function projectAcpActivationFlags(request: RoleTurnRequest): Map<string, boolean | string> {
|
|
71
71
|
const activation = request.activation;
|
|
72
72
|
const flags = new Map<string, boolean | string>([["ak-role", activation.role]]);
|
|
73
73
|
const inputFlag = packagedRoleInputFlag(activation.role);
|
|
@@ -78,7 +78,8 @@ export function projectGrokActivationFlags(request: RoleTurnRequest): Map<string
|
|
|
78
78
|
: "packetPath" in activation ? activation.packetPath
|
|
79
79
|
: "casePath" in activation ? activation.casePath
|
|
80
80
|
: "inputPath" in activation ? activation.inputPath
|
|
81
|
-
: "sourceRun" in activation ? activation.sourceRun
|
|
81
|
+
: "sourceRun" in activation ? activation.sourceRun
|
|
82
|
+
: "sourcesPath" in activation ? activation.sourcesPath : undefined;
|
|
82
83
|
if (path !== undefined) flags.set(inputFlag, path);
|
|
83
84
|
}
|
|
84
85
|
if (activation.role === "fixer" && activation.prerequisitesPath !== undefined) flags.set("ak-fixer-prerequisites", activation.prerequisitesPath);
|
|
@@ -114,25 +115,25 @@ async function listen(server: Server, path: string): Promise<void> {
|
|
|
114
115
|
* Build one AK-owned MCP projection from the shared eight-seat envelope.
|
|
115
116
|
* The child process is a protocol relay only; all tools execute in this process.
|
|
116
117
|
*/
|
|
117
|
-
export function
|
|
118
|
-
config: Omit<
|
|
118
|
+
export function createComposedAcpRoleTurnHost(
|
|
119
|
+
config: Omit<AcpRoleTurnHostConfig, "prepare"> & {
|
|
119
120
|
readonly roleRuntimeDependencies: RoleRuntimeDependencies;
|
|
120
121
|
readonly socketPath?: (request: RoleTurnRequest) => string;
|
|
121
122
|
},
|
|
122
123
|
) {
|
|
123
|
-
return
|
|
124
|
+
return createAcpRoleTurnHost({
|
|
124
125
|
...config,
|
|
125
|
-
prepare: (request) =>
|
|
126
|
+
prepare: (request) => prepareAcpRoleEnvelope({
|
|
126
127
|
request,
|
|
127
128
|
dependencies: config.roleRuntimeDependencies,
|
|
128
129
|
// Same durable-principal path settlement uses for isAvailable (#617 DK-4 layout).
|
|
129
130
|
sessionFile: config.sessionIdentity.resolveSessionFile(request.principal),
|
|
130
|
-
socketPath: config.socketPath?.(request) ?? `/tmp/ak-
|
|
131
|
+
socketPath: config.socketPath?.(request) ?? `/tmp/ak-acp-mcp-${randomUUID()}.sock`,
|
|
131
132
|
}),
|
|
132
133
|
});
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
export async function
|
|
136
|
+
export async function prepareAcpRoleEnvelope(options: {
|
|
136
137
|
readonly request: RoleTurnRequest;
|
|
137
138
|
readonly dependencies: RoleRuntimeDependencies;
|
|
138
139
|
readonly socketPath: string;
|
|
@@ -142,9 +143,9 @@ export async function prepareGrokRoleEnvelope(options: {
|
|
|
142
143
|
* isAvailable and envelope mint the same file. Tests may omit → runDirectory default.
|
|
143
144
|
*/
|
|
144
145
|
readonly sessionFile?: string;
|
|
145
|
-
}): Promise<
|
|
146
|
+
}): Promise<AcpPreparedTurn> {
|
|
146
147
|
const { request } = options;
|
|
147
|
-
const flags =
|
|
148
|
+
const flags = projectAcpActivationFlags(request);
|
|
148
149
|
const tools = new Map<string, HostToolDefinition>();
|
|
149
150
|
const handlers = new Map<string, Handler[]>();
|
|
150
151
|
const calls: Array<{ toolCallId: string; toolName: string }> = [];
|
|
@@ -169,7 +170,7 @@ export async function prepareGrokRoleEnvelope(options: {
|
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
// Durable principal file for isAvailable / resumable settlement (public-cli).
|
|
172
|
-
// #617 DK-4: header layout only — never
|
|
173
|
+
// #617 DK-4: header layout only — never host conversation/tool writeback into Pi JSONL.
|
|
173
174
|
let sessionFile = options.sessionFile ?? join(request.runDirectory, "session", "session.jsonl");
|
|
174
175
|
await mkdir(dirname(sessionFile), { recursive: true });
|
|
175
176
|
if (request.continuation.kind !== "resume") {
|
|
@@ -235,16 +236,16 @@ export async function prepareGrokRoleEnvelope(options: {
|
|
|
235
236
|
deliverSubmissionRejection(value) { rejection = value; },
|
|
236
237
|
capabilities: {
|
|
237
238
|
skillExpansion(prompt): HostSkillExpansionEvidence | undefined {
|
|
238
|
-
return
|
|
239
|
+
return buildAcpSkillExpansion(methodSkills, prompt);
|
|
239
240
|
},
|
|
240
241
|
},
|
|
241
242
|
registerFlag(name, definition) { if (!flags.has(name) && definition.default !== undefined) flags.set(name, definition.default); },
|
|
242
243
|
getFlag(name) { return flags.get(name); },
|
|
243
244
|
registerTool(tool) { tools.set(tool.name, tool); },
|
|
244
|
-
// The real AK-owned surface only;
|
|
245
|
+
// The real AK-owned surface only; the host builtin surface is host-side and
|
|
245
246
|
// observable after session/new, never echoed back into role-requested names.
|
|
246
247
|
getAllTools() { return [...tools.keys()].map((name) => ({ name })); },
|
|
247
|
-
//
|
|
248
|
+
// The host receives tool choice as role guidance; every tool registered for the
|
|
248
249
|
// seat remains reachable through MCP.
|
|
249
250
|
setActiveTools(names) { preferredTools = [...names]; },
|
|
250
251
|
getActiveTools() { return [...preferredTools]; },
|
|
@@ -580,13 +581,13 @@ export async function prepareGrokRoleEnvelope(options: {
|
|
|
580
581
|
}
|
|
581
582
|
if (cleanupFailures.length === 1) throw cleanupFailures[0];
|
|
582
583
|
if (cleanupFailures.length > 1) {
|
|
583
|
-
throw new AggregateError(cleanupFailures, "
|
|
584
|
+
throw new AggregateError(cleanupFailures, "ACP envelope dispose cleanup failures", {
|
|
584
585
|
cause: cleanupFailures[0],
|
|
585
586
|
});
|
|
586
587
|
}
|
|
587
588
|
};
|
|
588
589
|
|
|
589
|
-
const closeRound:
|
|
590
|
+
const closeRound: AcpPreparedTurn["closeRound"] = async () => {
|
|
590
591
|
// Typed round boundary: hand the complete call list to the shared ledger once.
|
|
591
592
|
if (calls.length > 0) {
|
|
592
593
|
const roundCalls = [...calls];
|
|
@@ -606,7 +607,7 @@ export async function prepareGrokRoleEnvelope(options: {
|
|
|
606
607
|
}
|
|
607
608
|
if (closure !== undefined) {
|
|
608
609
|
// Pi flushes navigator attendance on agent_settled; session/prompt
|
|
609
|
-
// resolution is
|
|
610
|
+
// resolution is the ACP host equivalent round boundary.
|
|
610
611
|
await emit("agent_settled", {});
|
|
611
612
|
return { accepted: true as const };
|
|
612
613
|
}
|
|
@@ -674,8 +675,8 @@ export async function prepareGrokRoleEnvelope(options: {
|
|
|
674
675
|
command: process.execPath,
|
|
675
676
|
args: [relay],
|
|
676
677
|
env: [
|
|
677
|
-
{ name: "
|
|
678
|
-
{ name: "
|
|
678
|
+
{ name: "AK_ACP_MCP_SOCKET", value: options.socketPath },
|
|
679
|
+
{ name: "AK_ACP_MCP_TOKEN", value: token },
|
|
679
680
|
],
|
|
680
681
|
}],
|
|
681
682
|
systemPrompt: { body: systemPromptBody, materials: readingMaterials },
|
|
@@ -693,7 +694,7 @@ export async function prepareGrokRoleEnvelope(options: {
|
|
|
693
694
|
} catch (cleanupFailure) {
|
|
694
695
|
throw new AggregateError(
|
|
695
696
|
[error, cleanupFailure],
|
|
696
|
-
"
|
|
697
|
+
"prepareAcpRoleEnvelope activation failed and its dispose cleanup also failed",
|
|
697
698
|
{ cause: error },
|
|
698
699
|
);
|
|
699
700
|
}
|