@akagilnc/pi-workflow-roles 0.1.3556 → 0.1.3565

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.
@@ -0,0 +1,21 @@
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
+ /** Absolute agent binary for one operator home. */
8
+ export function resolveAcpBinary(description, operatorHome) {
9
+ return join(operatorHome, ...description.binaryFromHome);
10
+ }
11
+ /** Stdio argv: prefix, optional model/thinking flag pairs, suffix. */
12
+ export function acpStdioArgs(description, model) {
13
+ const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
14
+ const pair = (flag, value) => flag === undefined || value === undefined ? [] : [flag, value];
15
+ return [
16
+ ...prefix,
17
+ ...pair(modelFlag, model?.model),
18
+ ...pair(thinkingFlag, model?.thinking),
19
+ ...suffix,
20
+ ];
21
+ }
@@ -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.AK_GROK_MCP_SOCKET;
6
- const token = process.env.AK_GROK_MCP_TOKEN;
7
- if (!socketPath || !token) throw new Error("AK Grok MCP relay identity is missing");
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 Grok MCP upstream closed"));
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 Grok MCP relay failure");
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);
@@ -1238,9 +1238,8 @@ var init_in_process_session = __esm({
1238
1238
  }
1239
1239
  });
1240
1240
 
1241
- // src/grok/production-host.ts
1241
+ // src/acp-host/production-host.ts
1242
1242
  import { readFile as readFile15 } from "node:fs/promises";
1243
- import { join as join24 } from "node:path";
1244
1243
  import { fileURLToPath as fileURLToPath3 } from "node:url";
1245
1244
 
1246
1245
  // src/canonical-skill-binding.ts
@@ -3696,6 +3695,29 @@ function appendEngineSessionMaterial(lines, engineMaterial) {
3696
3695
  return out;
3697
3696
  }
3698
3697
 
3698
+ // src/host-descriptions.ts
3699
+ var PRIVATE_COMPAT_ENV = Object.fromEntries(
3700
+ ["CLAUDE", "CURSOR", "CODEX"].flatMap((vendor) => ["SKILLS", "RULES", "AGENTS", "MCPS", "HOOKS", "SESSIONS"].map((kind) => [`GROK_${vendor}_${kind}_ENABLED`, "false"]))
3701
+ );
3702
+ var HOST_DESCRIPTIONS = Object.freeze({
3703
+ /** Operator home `~/.grok`, native session/load resume, `agent [--model X] stdio`. */
3704
+ "grok-build": Object.freeze({
3705
+ binaryFromHome: Object.freeze([".grok", "bin", "grok"]),
3706
+ argv: Object.freeze({
3707
+ prefix: Object.freeze(["agent"]),
3708
+ suffix: Object.freeze(["stdio"]),
3709
+ modelFlag: "--model"
3710
+ }),
3711
+ boundResume: "session/load",
3712
+ sessionBindingFile: "grok-acp-session.json",
3713
+ childEnv: Object.freeze({
3714
+ ...PRIVATE_COMPAT_ENV,
3715
+ GROK_MEMORY: "0",
3716
+ GROK_SUBAGENTS: "0"
3717
+ })
3718
+ })
3719
+ });
3720
+
3699
3721
  // src/institutional-resolution.ts
3700
3722
  import { readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
3701
3723
  import { join as join7 } from "node:path";
@@ -13564,14 +13586,30 @@ function createRoleRuntimeExtension(dependencies) {
13564
13586
  };
13565
13587
  }
13566
13588
 
13567
- // src/grok/role-envelope.ts
13589
+ // src/acp-host/description.ts
13590
+ import { join as join22 } from "node:path";
13591
+ function resolveAcpBinary(description, operatorHome) {
13592
+ return join22(operatorHome, ...description.binaryFromHome);
13593
+ }
13594
+ function acpStdioArgs(description, model) {
13595
+ const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
13596
+ const pair = (flag, value) => flag === void 0 || value === void 0 ? [] : [flag, value];
13597
+ return [
13598
+ ...prefix,
13599
+ ...pair(modelFlag, model?.model),
13600
+ ...pair(thinkingFlag, model?.thinking),
13601
+ ...suffix
13602
+ ];
13603
+ }
13604
+
13605
+ // src/acp-host/role-envelope.ts
13568
13606
  import { randomUUID as randomUUID2 } from "node:crypto";
13569
13607
  import { mkdir as mkdir3, readFile as readFile13, writeFile as writeFile7 } from "node:fs/promises";
13570
13608
  import { createServer } from "node:net";
13571
- import { basename as basename7, dirname as dirname15, join as join22 } from "node:path";
13609
+ import { basename as basename7, dirname as dirname15, join as join23 } from "node:path";
13572
13610
  import { fileURLToPath as fileURLToPath2 } from "node:url";
13573
13611
 
13574
- // src/grok/role-turn-host.ts
13612
+ // src/acp-host/role-turn-host.ts
13575
13613
  import { spawn as spawn4 } from "node:child_process";
13576
13614
  import { createInterface } from "node:readline";
13577
13615
 
@@ -13581,8 +13619,8 @@ function renderAgentStartMaterials(body, materials) {
13581
13619
  return [body, ...materials.map((material) => JSON.stringify(material))].join("\n\n");
13582
13620
  }
13583
13621
 
13584
- // src/grok/role-turn-host.ts
13585
- function renderGrokSystemPromptOverride(authority) {
13622
+ // src/acp-host/role-turn-host.ts
13623
+ function renderAcpSystemPromptOverride(authority) {
13586
13624
  return renderAgentStartMaterials(authority.body, authority.materials);
13587
13625
  }
13588
13626
  function failure(cause, name, code, details) {
@@ -13598,19 +13636,13 @@ function failure(cause, name, code, details) {
13598
13636
  };
13599
13637
  }
13600
13638
  function hostAbortedError() {
13601
- return Object.assign(new Error("Grok host aborted"), { code: "host-aborted" });
13639
+ return Object.assign(new Error("ACP host aborted"), { code: "host-aborted" });
13602
13640
  }
13603
13641
  function acpError(code, message, cause) {
13604
13642
  return Object.assign(new Error(message, cause === void 0 ? void 0 : { cause }), { code });
13605
13643
  }
13606
- function connectGrokAcpStdio(options) {
13607
- const args = [
13608
- "agent",
13609
- ...options.model === void 0 ? [] : ["--model", options.model],
13610
- "stdio"
13611
- ];
13612
- const env = options.toolset === void 0 ? options.env : { ...options.env, GROK_CONFIG: JSON.stringify({ toolset: options.toolset }) };
13613
- const child = spawn4(options.binary, args, { cwd: options.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
13644
+ function connectAcpStdio(options) {
13645
+ const child = spawn4(options.binary, [...options.args], { cwd: options.cwd, env: options.env, stdio: ["pipe", "pipe", "pipe"] });
13614
13646
  const pending = /* @__PURE__ */ new Map();
13615
13647
  const notificationHandlers = [];
13616
13648
  if (options.onNotification !== void 0) notificationHandlers.push(options.onNotification);
@@ -13633,13 +13665,13 @@ function connectGrokAcpStdio(options) {
13633
13665
  child.stderr.setEncoding("utf8").on("data", (chunk) => {
13634
13666
  stderr += chunk;
13635
13667
  });
13636
- child.on("error", (error) => settleClosed(acpError("acp-process-error", `Grok ACP process error: ${error.message}`, error)));
13668
+ child.on("error", (error) => settleClosed(acpError("acp-process-error", `ACP process error: ${error.message}`, error)));
13637
13669
  createInterface({ input: child.stdout }).on("line", (line2) => {
13638
13670
  let message;
13639
13671
  try {
13640
13672
  message = JSON.parse(line2);
13641
13673
  } catch (error) {
13642
- terminate(acpError("acp-invalid-json", `Invalid Grok ACP JSON: ${String(error)}`, error));
13674
+ terminate(acpError("acp-invalid-json", `Invalid ACP JSON: ${String(error)}`, error));
13643
13675
  return;
13644
13676
  }
13645
13677
  if (typeof message.method === "string") {
@@ -13647,13 +13679,13 @@ function connectGrokAcpStdio(options) {
13647
13679
  for (const handler of notificationHandlers) handler(message.method, params);
13648
13680
  if (typeof message.id === "number") {
13649
13681
  if (message.method !== "session/request_permission") {
13650
- terminate(acpError("acp-unsupported-client-request", `Unsupported Grok ACP client request: ${message.method}`));
13682
+ terminate(acpError("acp-unsupported-client-request", `Unsupported ACP client request: ${message.method}`));
13651
13683
  return;
13652
13684
  }
13653
13685
  const choices = Array.isArray(params.options) ? params.options : [];
13654
13686
  const selected = choices.find((value) => typeof value === "object" && value !== null && value.kind === "allow_once");
13655
13687
  if (typeof selected?.optionId !== "string") {
13656
- terminate(acpError("acp-permission-missing-allow-once", "Grok ACP permission request omitted allow_once"));
13688
+ terminate(acpError("acp-permission-missing-allow-once", "ACP permission request omitted allow_once"));
13657
13689
  return;
13658
13690
  }
13659
13691
  child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id: message.id, result: { outcome: { outcome: "selected", optionId: selected.optionId } } })}
@@ -13665,13 +13697,13 @@ function connectGrokAcpStdio(options) {
13665
13697
  const waiter = pending.get(message.id);
13666
13698
  if (waiter === void 0) return;
13667
13699
  pending.delete(message.id);
13668
- if (message.error !== void 0) waiter.reject(acpError("acp-upstream-error", `Grok ACP error: ${JSON.stringify(message.error)}`));
13700
+ if (message.error !== void 0) waiter.reject(acpError("acp-upstream-error", `ACP error: ${JSON.stringify(message.error)}`));
13669
13701
  else waiter.resolve(message.result ?? {});
13670
13702
  });
13671
- child.on("close", (code) => settleClosed(acpError("acp-closed", `Grok ACP closed (${String(code)}): ${stderr}`)));
13703
+ child.on("close", (code) => settleClosed(acpError("acp-closed", `ACP closed (${String(code)}): ${stderr}`)));
13672
13704
  return Promise.resolve({
13673
13705
  request(method, params) {
13674
- if (closed) return Promise.reject(terminalError ?? acpError("acp-connection-closed", "Grok ACP connection is closed"));
13706
+ if (closed) return Promise.reject(terminalError ?? acpError("acp-connection-closed", "ACP connection is closed"));
13675
13707
  const id = ++nextId;
13676
13708
  return new Promise((resolve17, reject) => {
13677
13709
  pending.set(id, { resolve: resolve17, reject });
@@ -13681,12 +13713,12 @@ function connectGrokAcpStdio(options) {
13681
13713
  const waiter = pending.get(id);
13682
13714
  if (waiter === void 0) return;
13683
13715
  pending.delete(id);
13684
- waiter.reject(acpError("acp-write-failed", `Grok ACP write failed: ${error.message}`, error));
13716
+ waiter.reject(acpError("acp-write-failed", `ACP write failed: ${error.message}`, error));
13685
13717
  });
13686
13718
  });
13687
13719
  },
13688
13720
  notify(method, params) {
13689
- if (closed) throw terminalError ?? acpError("acp-connection-closed", "Grok ACP connection is closed");
13721
+ if (closed) throw terminalError ?? acpError("acp-connection-closed", "ACP connection is closed");
13690
13722
  child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", method, params })}
13691
13723
  `);
13692
13724
  },
@@ -13695,14 +13727,14 @@ function connectGrokAcpStdio(options) {
13695
13727
  },
13696
13728
  async close() {
13697
13729
  if (closed) return;
13698
- settleClosed(acpError("acp-connection-closed", "Grok ACP connection is closed"));
13730
+ settleClosed(acpError("acp-connection-closed", "ACP connection is closed"));
13699
13731
  child.stdin.end();
13700
13732
  child.kill("SIGTERM");
13701
13733
  await new Promise((resolve17) => child.once("close", () => resolve17()));
13702
13734
  }
13703
13735
  });
13704
13736
  }
13705
- function createGrokRoleTurnHost(config) {
13737
+ function createAcpRoleTurnHost(config) {
13706
13738
  let serial = Promise.resolve();
13707
13739
  return {
13708
13740
  executeTurn(request) {
@@ -13714,7 +13746,7 @@ function createGrokRoleTurnHost(config) {
13714
13746
  let accepted = false;
13715
13747
  try {
13716
13748
  if (prepared.mcpServers.length === 0) {
13717
- return failure("activation", "UncontrolledGrokSession", "ak-config-missing");
13749
+ return failure("activation", "UncontrolledAcpSession", "ak-config-missing");
13718
13750
  }
13719
13751
  connection = await config.connect(request);
13720
13752
  const initialized = await connection.request("initialize", {
@@ -13725,49 +13757,36 @@ function createGrokRoleTurnHost(config) {
13725
13757
  const modelState = initializeMeta?.modelState;
13726
13758
  const availableModels = Array.isArray(modelState?.availableModels) ? modelState.availableModels : void 0;
13727
13759
  if (request.model !== void 0 && availableModels !== void 0 && !availableModels.some((entry) => typeof entry === "object" && entry !== null && entry.modelId === request.model?.model)) {
13728
- return failure("activation", "GrokHostModelMismatch", "host-model-mismatch", {
13760
+ return failure("activation", "AcpHostModelMismatch", "host-model-mismatch", {
13729
13761
  provider: request.model.provider,
13730
13762
  model: request.model.model
13731
13763
  });
13732
13764
  }
13733
- const priorNativePaths = continuation.kind === "resume" && request.hostTransition?.previousHost === "pi" ? request.hostTransition.priorNativePaths : void 0;
13734
- if (continuation.kind === "resume") {
13765
+ const priorNativePaths = continuation.kind === "resume" ? request.hostTransition?.priorNativePaths : void 0;
13766
+ if (continuation.kind === "resume" && config.boundResume === "session/load") {
13735
13767
  const boundSessionId = await config.sessionIdentity.load(request.principal);
13736
13768
  if (boundSessionId !== void 0 && boundSessionId !== "") {
13737
13769
  const loaded = await connection.request("session/load", {
13738
13770
  sessionId: boundSessionId,
13739
13771
  cwd: request.cwd,
13740
13772
  mcpServers: prepared.mcpServers,
13741
- _meta: { systemPromptOverride: renderGrokSystemPromptOverride(prepared.systemPrompt), yoloMode: false }
13773
+ _meta: { systemPromptOverride: renderAcpSystemPromptOverride(prepared.systemPrompt), yoloMode: false }
13742
13774
  });
13743
13775
  sessionId = typeof loaded.sessionId === "string" && loaded.sessionId !== "" ? loaded.sessionId : boundSessionId;
13744
- } else {
13745
- const session = await connection.request(
13746
- "session/new",
13747
- {
13748
- cwd: request.cwd,
13749
- mcpServers: prepared.mcpServers,
13750
- _meta: { systemPromptOverride: renderGrokSystemPromptOverride(prepared.systemPrompt), yoloMode: false }
13751
- }
13752
- );
13753
- sessionId = typeof session.sessionId === "string" ? session.sessionId : void 0;
13754
- if (sessionId === void 0 || sessionId === "") {
13755
- return failure("session", "GrokAcpSessionFailure", "session-id-missing");
13756
- }
13757
- await config.sessionIdentity.bind(request.principal, sessionId);
13758
13776
  }
13759
- } else {
13777
+ }
13778
+ if (sessionId === void 0) {
13760
13779
  const session = await connection.request(
13761
13780
  "session/new",
13762
13781
  {
13763
13782
  cwd: request.cwd,
13764
13783
  mcpServers: prepared.mcpServers,
13765
- _meta: { systemPromptOverride: renderGrokSystemPromptOverride(prepared.systemPrompt), yoloMode: false }
13784
+ _meta: { systemPromptOverride: renderAcpSystemPromptOverride(prepared.systemPrompt), yoloMode: false }
13766
13785
  }
13767
13786
  );
13768
13787
  sessionId = typeof session.sessionId === "string" ? session.sessionId : void 0;
13769
13788
  if (sessionId === void 0 || sessionId === "") {
13770
- return failure("session", "GrokAcpSessionFailure", "session-id-missing");
13789
+ return failure("session", "AcpSessionFailure", "session-id-missing");
13771
13790
  }
13772
13791
  await config.sessionIdentity.bind(request.principal, sessionId);
13773
13792
  }
@@ -13828,7 +13847,7 @@ ${priorNativePaths.join("\n")}` : prepared.prompt;
13828
13847
  throw error;
13829
13848
  }
13830
13849
  if (result2.stopReason === "refusal") {
13831
- return failure("output", "GrokAcpRefusal", "refusal", { sessionId });
13850
+ return failure("output", "AcpRefusal", "refusal", { sessionId });
13832
13851
  }
13833
13852
  const closure = await prepared.closeRound();
13834
13853
  if (closure.accepted) {
@@ -13841,7 +13860,7 @@ ${priorNativePaths.join("\n")}` : prepared.prompt;
13841
13860
  }
13842
13861
  prompt = `The prior terminal submission was rejected (${closure.retry.code}). Resubmit it as the sole terminal tool call. Rejected call ids: ${closure.retry.toolCallIds.join(", ") || "none"}.`;
13843
13862
  }
13844
- return failure("output", "GrokAcpRoundLimit", "round-retry-limit", { sessionId });
13863
+ return failure("output", "AcpRoundLimit", "round-retry-limit", { sessionId });
13845
13864
  } finally {
13846
13865
  if (connection !== void 0) {
13847
13866
  if (sessionId !== void 0 && !accepted) {
@@ -13866,25 +13885,14 @@ ${priorNativePaths.join("\n")}` : prepared.prompt;
13866
13885
  }
13867
13886
  };
13868
13887
  }
13869
- var PRIVATE_COMPAT_ENV = Object.fromEntries(
13870
- ["CLAUDE", "CURSOR", "CODEX"].flatMap((vendor) => ["SKILLS", "RULES", "AGENTS", "MCPS", "HOOKS", "SESSIONS"].map((kind) => [`GROK_${vendor}_${kind}_ENABLED`, "false"]))
13871
- );
13872
- function controlledGrokChildEnv(base) {
13873
- return {
13874
- ...base,
13875
- ...PRIVATE_COMPAT_ENV,
13876
- GROK_MEMORY: "0",
13877
- GROK_SUBAGENTS: "0"
13878
- };
13879
- }
13880
13888
 
13881
- // src/grok/role-envelope.ts
13889
+ // src/acp-host/role-envelope.ts
13882
13890
  function parseCanonicalSkillInvocation(prompt) {
13883
13891
  const match = /^\/skill:([A-Za-z0-9_-]+)(?:\s+([\s\S]*))?$/s.exec(prompt.trim());
13884
13892
  if (match === null) return void 0;
13885
13893
  return { name: match[1], userMessage: (match[2] ?? "").trim() };
13886
13894
  }
13887
- function buildGrokSkillExpansion(methodSkills, prompt) {
13895
+ function buildAcpSkillExpansion(methodSkills, prompt) {
13888
13896
  const parsed = parseCanonicalSkillInvocation(prompt);
13889
13897
  if (parsed === void 0) return void 0;
13890
13898
  const method = methodSkills.get(parsed.name);
@@ -13898,7 +13906,7 @@ ${method.body}`,
13898
13906
  userMessage: parsed.userMessage
13899
13907
  });
13900
13908
  }
13901
- function projectGrokActivationFlags(request) {
13909
+ function projectAcpActivationFlags(request) {
13902
13910
  const activation = request.activation;
13903
13911
  const flags = /* @__PURE__ */ new Map([["ak-role", activation.role]]);
13904
13912
  const inputFlag = packagedRoleInputFlag(activation.role);
@@ -13936,21 +13944,21 @@ async function listen(server, path) {
13936
13944
  });
13937
13945
  });
13938
13946
  }
13939
- function createComposedGrokRoleTurnHost(config) {
13940
- return createGrokRoleTurnHost({
13947
+ function createComposedAcpRoleTurnHost(config) {
13948
+ return createAcpRoleTurnHost({
13941
13949
  ...config,
13942
- prepare: (request) => prepareGrokRoleEnvelope({
13950
+ prepare: (request) => prepareAcpRoleEnvelope({
13943
13951
  request,
13944
13952
  dependencies: config.roleRuntimeDependencies,
13945
13953
  // Same durable-principal path settlement uses for isAvailable (#617 DK-4 layout).
13946
13954
  sessionFile: config.sessionIdentity.resolveSessionFile(request.principal),
13947
- socketPath: config.socketPath?.(request) ?? `/tmp/ak-grok-mcp-${randomUUID2()}.sock`
13955
+ socketPath: config.socketPath?.(request) ?? `/tmp/ak-acp-mcp-${randomUUID2()}.sock`
13948
13956
  })
13949
13957
  });
13950
13958
  }
13951
- async function prepareGrokRoleEnvelope(options) {
13959
+ async function prepareAcpRoleEnvelope(options) {
13952
13960
  const { request } = options;
13953
- const flags = projectGrokActivationFlags(request);
13961
+ const flags = projectAcpActivationFlags(request);
13954
13962
  const tools = /* @__PURE__ */ new Map();
13955
13963
  const handlers = /* @__PURE__ */ new Map();
13956
13964
  const calls = [];
@@ -13969,7 +13977,7 @@ async function prepareGrokRoleEnvelope(options) {
13969
13977
  const raw = await readFile13(method.path, "utf8");
13970
13978
  methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
13971
13979
  }
13972
- let sessionFile = options.sessionFile ?? join22(request.runDirectory, "session", "session.jsonl");
13980
+ let sessionFile = options.sessionFile ?? join23(request.runDirectory, "session", "session.jsonl");
13973
13981
  await mkdir3(dirname15(sessionFile), { recursive: true });
13974
13982
  if (request.continuation.kind !== "resume") {
13975
13983
  try {
@@ -14034,7 +14042,7 @@ async function prepareGrokRoleEnvelope(options) {
14034
14042
  },
14035
14043
  capabilities: {
14036
14044
  skillExpansion(prompt) {
14037
- return buildGrokSkillExpansion(methodSkills, prompt);
14045
+ return buildAcpSkillExpansion(methodSkills, prompt);
14038
14046
  }
14039
14047
  },
14040
14048
  registerFlag(name, definition) {
@@ -14046,12 +14054,12 @@ async function prepareGrokRoleEnvelope(options) {
14046
14054
  registerTool(tool2) {
14047
14055
  tools.set(tool2.name, tool2);
14048
14056
  },
14049
- // The real AK-owned surface only; Grok's builtin surface is host-side and
14057
+ // The real AK-owned surface only; the host builtin surface is host-side and
14050
14058
  // observable after session/new, never echoed back into role-requested names.
14051
14059
  getAllTools() {
14052
14060
  return [...tools.keys()].map((name) => ({ name }));
14053
14061
  },
14054
- // Grok receives tool choice as role guidance; every tool registered for the
14062
+ // The host receives tool choice as role guidance; every tool registered for the
14055
14063
  // seat remains reachable through MCP.
14056
14064
  setActiveTools(names) {
14057
14065
  preferredTools = [...names];
@@ -14333,7 +14341,7 @@ async function prepareGrokRoleEnvelope(options) {
14333
14341
  }
14334
14342
  if (cleanupFailures.length === 1) throw cleanupFailures[0];
14335
14343
  if (cleanupFailures.length > 1) {
14336
- throw new AggregateError(cleanupFailures, "Grok envelope dispose cleanup failures", {
14344
+ throw new AggregateError(cleanupFailures, "ACP envelope dispose cleanup failures", {
14337
14345
  cause: cleanupFailures[0]
14338
14346
  });
14339
14347
  }
@@ -14410,8 +14418,8 @@ async function prepareGrokRoleEnvelope(options) {
14410
14418
  command: process.execPath,
14411
14419
  args: [relay],
14412
14420
  env: [
14413
- { name: "AK_GROK_MCP_SOCKET", value: options.socketPath },
14414
- { name: "AK_GROK_MCP_TOKEN", value: token }
14421
+ { name: "AK_ACP_MCP_SOCKET", value: options.socketPath },
14422
+ { name: "AK_ACP_MCP_TOKEN", value: token }
14415
14423
  ]
14416
14424
  }],
14417
14425
  systemPrompt: { body: systemPromptBody, materials: readingMaterials },
@@ -14426,7 +14434,7 @@ async function prepareGrokRoleEnvelope(options) {
14426
14434
  } catch (cleanupFailure) {
14427
14435
  throw new AggregateError(
14428
14436
  [error, cleanupFailure],
14429
- "prepareGrokRoleEnvelope activation failed and its dispose cleanup also failed",
14437
+ "prepareAcpRoleEnvelope activation failed and its dispose cleanup also failed",
14430
14438
  { cause: error }
14431
14439
  );
14432
14440
  }
@@ -14434,12 +14442,11 @@ async function prepareGrokRoleEnvelope(options) {
14434
14442
  }
14435
14443
  }
14436
14444
 
14437
- // src/grok/session-identity.ts
14445
+ // src/acp-host/session-identity.ts
14438
14446
  import { mkdir as mkdir4, readFile as readFile14, rename, writeFile as writeFile8 } from "node:fs/promises";
14439
- import { dirname as dirname16, join as join23 } from "node:path";
14440
- var GROK_ACP_SESSION_BINDING = "grok-acp-session.json";
14441
- function createGrokSessionIdentityAuthority(authority) {
14442
- const bindingPath = (principal) => join23(authority.decode(principal).sessionDirectory, GROK_ACP_SESSION_BINDING);
14447
+ import { dirname as dirname16, join as join24 } from "node:path";
14448
+ function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
14449
+ const bindingPath = (principal) => join24(authority.decode(principal).sessionDirectory, sessionBindingFile);
14443
14450
  return {
14444
14451
  resolveSessionFile(principal) {
14445
14452
  return authority.decode(principal).sessionFile;
@@ -14448,7 +14455,7 @@ function createGrokSessionIdentityAuthority(authority) {
14448
14455
  try {
14449
14456
  const value = JSON.parse(await readFile14(bindingPath(principal), "utf8"));
14450
14457
  if (typeof value !== "object" || value === null || typeof value.sessionId !== "string") {
14451
- throw new Error("durable Grok ACP session binding is invalid");
14458
+ throw new Error("durable ACP session binding is invalid");
14452
14459
  }
14453
14460
  return value.sessionId;
14454
14461
  } catch (error) {
@@ -14467,20 +14474,11 @@ function createGrokSessionIdentityAuthority(authority) {
14467
14474
  };
14468
14475
  }
14469
14476
 
14470
- // src/grok/production-host.ts
14471
- function resolveGrokBinary(operatorHome) {
14472
- return join24(operatorHome, ".grok", "bin", "grok");
14473
- }
14474
- function childEnv(packageRoot) {
14475
- return {
14476
- ...controlledGrokChildEnv(process.env),
14477
- AK_PACKAGE_ROOT: packageRoot
14478
- };
14479
- }
14477
+ // src/acp-host/production-host.ts
14480
14478
  var navigatorRoutePlaybookPath = fileURLToPath3(
14481
14479
  new URL("../../resources/navigator-route-playbook.md", import.meta.url)
14482
14480
  );
14483
- function createGrokRoleRuntimeDependencies(packageRoot) {
14481
+ function createAcpRoleRuntimeDependencies(packageRoot) {
14484
14482
  const judgeAuditor = createPiJudgeAuditor();
14485
14483
  const doctorAuditor = createPiDoctorAuditor();
14486
14484
  const reviewerAgent = createPerDispatchReviewerAgent({ packageRoot });
@@ -14544,23 +14542,28 @@ function createGrokRoleRuntimeDependencies(packageRoot) {
14544
14542
  })
14545
14543
  };
14546
14544
  }
14547
- function createProductionGrokRoleTurnHost(options) {
14548
- const { packageRoot, principalAuthority } = options;
14549
- const env = childEnv(packageRoot);
14550
- return createComposedGrokRoleTurnHost({
14551
- sessionIdentity: createGrokSessionIdentityAuthority(principalAuthority),
14552
- roleRuntimeDependencies: createGrokRoleRuntimeDependencies(packageRoot),
14545
+ function createProductionAcpRoleTurnHost(options) {
14546
+ const { packageRoot, principalAuthority, description } = options;
14547
+ const env = {
14548
+ ...process.env,
14549
+ ...description.childEnv,
14550
+ AK_PACKAGE_ROOT: packageRoot
14551
+ };
14552
+ return createComposedAcpRoleTurnHost({
14553
+ sessionIdentity: createAcpSessionIdentityAuthority(principalAuthority, description.sessionBindingFile),
14554
+ boundResume: description.boundResume,
14555
+ roleRuntimeDependencies: createAcpRoleRuntimeDependencies(packageRoot),
14553
14556
  async connect(request) {
14554
- return connectGrokAcpStdio({
14555
- binary: resolveGrokBinary(request.home),
14557
+ return connectAcpStdio({
14558
+ binary: resolveAcpBinary(description, request.home),
14559
+ args: acpStdioArgs(description, request.model),
14556
14560
  cwd: request.cwd,
14557
- env,
14558
- ...request.model === void 0 ? {} : { model: request.model.model }
14561
+ env
14559
14562
  });
14560
14563
  }
14561
14564
  });
14562
14565
  }
14563
14566
  export {
14564
- createGrokRoleRuntimeDependencies,
14565
- createProductionGrokRoleTurnHost
14567
+ createAcpRoleRuntimeDependencies,
14568
+ createProductionAcpRoleTurnHost
14566
14569
  };
@@ -0,0 +1,34 @@
1
+ /** Grok CLI reads vendor-private compat surfaces unless each is disabled by name. */
2
+ const PRIVATE_COMPAT_ENV = Object.fromEntries(["CLAUDE", "CURSOR", "CODEX"].flatMap((vendor) => ["SKILLS", "RULES", "AGENTS", "MCPS", "HOOKS", "SESSIONS"].map((kind) => [`GROK_${vendor}_${kind}_ENABLED`, "false"])));
3
+ export const DEFAULT_ROLE_TURN_HOST = "pi";
4
+ export const HOST_DESCRIPTIONS = Object.freeze({
5
+ /** Operator home `~/.grok`, native session/load resume, `agent [--model X] stdio`. */
6
+ "grok-build": Object.freeze({
7
+ binaryFromHome: Object.freeze([".grok", "bin", "grok"]),
8
+ argv: Object.freeze({
9
+ prefix: Object.freeze(["agent"]),
10
+ suffix: Object.freeze(["stdio"]),
11
+ modelFlag: "--model",
12
+ }),
13
+ boundResume: "session/load",
14
+ sessionBindingFile: "grok-acp-session.json",
15
+ childEnv: Object.freeze({
16
+ ...PRIVATE_COMPAT_ENV,
17
+ GROK_MEMORY: "0",
18
+ GROK_SUBAGENTS: "0",
19
+ }),
20
+ }),
21
+ });
22
+ export function lookupHostDescription(host) {
23
+ return Object.hasOwn(HOST_DESCRIPTIONS, host) ? HOST_DESCRIPTIONS[host] : undefined;
24
+ }
25
+ export function packagedExternalHostNames() {
26
+ return Object.keys(HOST_DESCRIPTIONS);
27
+ }
28
+ /** Legal persistent/invocation host: default pi, or a table key. */
29
+ export function assertRegisteredHostName(host) {
30
+ if (host === DEFAULT_ROLE_TURN_HOST || lookupHostDescription(host) !== undefined) {
31
+ return host;
32
+ }
33
+ throw new Error(`unregistered host: ${host}`);
34
+ }
@@ -1,5 +1,6 @@
1
1
  import { mkdir, readFile, writeFile } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
+ import { assertRegisteredHostName, DEFAULT_ROLE_TURN_HOST } from "../host-descriptions.js";
3
4
  import { assertLegalEngineName } from "../package-resources/engine-material.js";
4
5
  import { resolveConfiguredProvinceOfficer } from "../institutional-resolution.js";
5
6
  import {
@@ -95,7 +96,8 @@ function setPersistentSeatHost(config, seat, host) {
95
96
  }
96
97
  return { ...config, seats: { ...config.seats, [seat]: rest } };
97
98
  }
98
- return { ...config, seats: { ...config.seats, [seat]: { ...previous, host } } };
99
+ const registered = assertRegisteredHostName(host);
100
+ return { ...config, seats: { ...config.seats, [seat]: { ...previous, host: registered } } };
99
101
  }
100
102
  function setPersistentSeatEngine(config, seat, engine) {
101
103
  const previous = config.seats[seat];
@@ -140,14 +142,25 @@ function setAutoResumeLimit(config, limit) {
140
142
  function validatePublicCliConfigAxes(config, _packageRoot) {
141
143
  for (const seat of Object.keys(config.seats)) {
142
144
  const row = config.seats[seat];
143
- if (row?.engine === void 0) continue;
144
- try {
145
- assertLegalEngineName(row.engine);
146
- } catch (error) {
147
- throw new Error(
148
- `config seat ${seat} engine is illegal: ${row.engine}`,
149
- { cause: error }
150
- );
145
+ if (row?.engine !== void 0) {
146
+ try {
147
+ assertLegalEngineName(row.engine);
148
+ } catch (error) {
149
+ throw new Error(
150
+ `config seat ${seat} engine is illegal: ${row.engine}`,
151
+ { cause: error }
152
+ );
153
+ }
154
+ }
155
+ if (row?.host !== void 0) {
156
+ try {
157
+ assertRegisteredHostName(row.host);
158
+ } catch (error) {
159
+ throw new Error(
160
+ `config seat ${seat} host is unregistered: ${row.host}`,
161
+ { cause: error }
162
+ );
163
+ }
151
164
  }
152
165
  }
153
166
  }
@@ -304,7 +317,7 @@ function attachHostAxis(seat, config, invocation) {
304
317
  if (invocation?.host !== void 0) return { ...seat, host: invocation.host, hostSource: "invocation" };
305
318
  const persistent = config.seats[seat.seat]?.host;
306
319
  if (persistent !== void 0) return { ...seat, host: persistent, hostSource: "persistent" };
307
- return { ...seat, host: "pi", hostSource: "default" };
320
+ return { ...seat, host: DEFAULT_ROLE_TURN_HOST, hostSource: "default" };
308
321
  }
309
322
  function attachEngineAxis(seat, config, invocation) {
310
323
  if (!isPublicCallableRole(seat.seat)) {