@akagilnc/pi-workflow-roles 0.1.4641 → 0.1.4649

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 CHANGED
@@ -54,6 +54,16 @@ ak-role config set-auto-resume-limit 3
54
54
 
55
55
  **Host axis (invocation-insensible after default):** `--host` is a global public option on every callable role and on `resume`. Resolution is invocation `--host` → persistent seat host (`config set-host`) → package default (`pi`). After `config set-host <seat> <name>`, the same command face used with Pi runs that seat on the named host with zero extra flags and zero caller-side changes; bare `resume` follows the same table. Public callable roles and their institutional sub-legs (soul audit, doctor audit) share the in-process institutional session seam; Reviewer method Skill delivery is Pi-native `/skill:ak-cross-m-review` today — non-Pi host-native loader remains OPEN ([#922](https://github.com/Akagilnc/ak-pi-workflow-roles/issues/922)).
56
56
 
57
+ **Recommended hosts (token saving, [#971](https://github.com/Akagilnc/ak-pi-workflow-roles/issues/971)):** long legs are capped by each host's own auto-compaction; the threshold lives in that host's own config. This package neither writes those files nor adds a compaction mechanism of its own.
58
+
59
+ | Seat | Recommended host | Where that host's compaction threshold lives (default path; each host's own home override applies) |
60
+ | --- | --- | --- |
61
+ | judge, countersign | `codex` | `~/.codex/config.toml`: `model_auto_compact_token_limit` |
62
+ | coder, fixer | `grok-build` | `~/.grok/config.toml`: `[model."<id>"] auto_compact_threshold_percent` |
63
+ | all other LLM seats (the analyst is deterministic and has no host) | `pi` (package default) | `~/.pi/agent/settings.json`: `compaction.reserveTokens` (trigger = model window − this value; needs pi ≥ 0.85.1) |
64
+
65
+ Set a seat with `ak-role config set-host <seat> <host>`; use `--host` for a one-off. Before moving a seat, make sure its model is one that host can run (for example `codex` only runs OpenAI-family models); otherwise set it first with `ak-role config set <seat> <provider/model[:thinking]>`.
66
+
57
67
  **Host providers (#788):** seat rows keep one provider name. Owner edits `~/.ak-roles/host-providers.json` (`{ "hermes": { "xai": "xai-oauth" } }`); code only reads it. Missing table entries ask the host directory (hermes this ticket): unique match wins, zero or many fail loud. Priority is table > unique > fail — no package discretion. `config show` prints the table as written.
58
68
 
59
69
  **Forced method skills (#922):** Pi uses `--skill`. Claude uses `--plugin-dir` and its native slash command when a role binds exactly one Skill; its current print harness cannot issue multiple slash commands for one turn, so multi-Skill roles such as Fixer have no forced-method call on Claude. Codex discovers the packaged methods through its documented project `.agents/skills` catalog, which is created only when absent and then left in place; existing entries are never replaced, and Codex receives every official `$skill-name` invocation. Hermes ACP and Grok ACP cannot force a Skill call through their current harness interfaces. These gaps are documentation only: the package does not invent an adapter, capability probe, typed failure, catalog, or operator prerequisite for them. The package never changes host trust or configuration.
package/README.zh-CN.md CHANGED
@@ -54,6 +54,16 @@ ak-role config set-auto-resume-limit 3
54
54
 
55
55
  **宿主轴(配置默认 host 后调用无感):** `--host` 为全局公开旗,全部可调用角色与 `resume` 受理。解析序为调用 `--host` → 席位持久 host(`config set-host`)→ 包默认(`pi`)。`config set-host <seat> <name>` 之后,与 Pi 完全相同的命令面即可在该席跑命名宿主——零额外旗、零调用侧改动;裸 `resume` 同序取表。可调用角色及其机构子腿(审刑审计、太医审计)共享进程内机构子会话接缝;御史台方法 Skill 现行仅 Pi 原生 `/skill:ak-cross-m-review` 交付——非 Pi 宿主原生装载仍 OPEN([#922](https://github.com/Akagilnc/ak-pi-workflow-roles/issues/922))。
56
56
 
57
+ **推荐宿主(省 token,[#971](https://github.com/Akagilnc/ak-pi-workflow-roles/issues/971)):** 长腿的上下文靠宿主自带的自动压缩封顶,阈值写在各宿主自己的配置里,本包不代写、不另造压缩机制。
58
+
59
+ | 席位 | 推荐 host | 该宿主的压缩阈值配置(默认路径;宿主自己的家目录覆盖照其约定) |
60
+ | --- | --- | --- |
61
+ | 大理寺(judge)、给事中(countersign) | `codex` | `~/.codex/config.toml`:`model_auto_compact_token_limit` |
62
+ | 将作监(coder)、修内司(fixer) | `grok-build` | `~/.grok/config.toml`:`[model."<id>"] auto_compact_threshold_percent` |
63
+ | 其余 LLM 席位(太史是确定性机制,无宿主) | `pi`(包默认) | `~/.pi/agent/settings.json`:`compaction.reserveTokens`(触发线=模型窗口−该值;需 pi ≥ 0.85.1) |
64
+
65
+ 配席:`ak-role config set-host <seat> <host>`;单次改道仍用 `--host`。换宿主前先确认该席的 model 是该宿主跑得了的(例如 `codex` 只跑 OpenAI 系模型),否则先 `ak-role config set <seat> <provider/model[:thinking]>`。
66
+
57
67
  **宿主 provider 表(#788):** 席位行只写一份 provider 名。owner 手改 `~/.ak-roles/host-providers.json`(形如 `{ "hermes": { "xai": "xai-oauth" } }`);代码只读。表里没有的问宿主目录(本票 hermes):唯一即用,零个或多个响亮失败。优先级:表 > 唯一 > 失败,代码无裁量。`config show` 原样打印该表。
58
68
 
59
69
  **强制方法 Skill(#922):** Pi 使用 `--skill`。角色只绑定一个 Skill 时,Claude 使用 `--plugin-dir` 与原生 slash command;当前 print harness 无法在一轮发出多个 slash command,所以 Fixer 等多 Skill 角色在 Claude 上没有强制方法调用。Codex 通过官方项目 `.agents/skills` 目录发现随包方法:目录缺失时创建常设软链,既有项不覆盖;调用时显式传入每个官方 `$skill-name`。Hermes ACP 与 Grok ACP 当前 harness 无法强制 Skill 调用。这些缺口只在文档说明:本包不为其另造适配、能力探测、typed failure、catalog 或操作员前置,也不改宿主 trust/配置。
@@ -28713,6 +28713,18 @@ function renderSystemPromptOverride(authority) {
28713
28713
  }
28714
28714
 
28715
28715
  // src/acp-host/role-turn-host.ts
28716
+ var GROK_BUILD_HOST = "grok-build";
28717
+ function acpPromptResultHasUsage(result) {
28718
+ const meta = result._meta;
28719
+ if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return false;
28720
+ return Object.prototype.hasOwnProperty.call(meta, "usage");
28721
+ }
28722
+ function isAcpAutoCompactCompletedNotification(method, params) {
28723
+ if (method !== "_x.ai/session_notification") return false;
28724
+ const update = params.update;
28725
+ if (typeof update !== "object" || update === null || Array.isArray(update)) return false;
28726
+ return update.sessionUpdate === "auto_compact_completed";
28727
+ }
28716
28728
  function acpAgentTextChunk(params) {
28717
28729
  let kind;
28718
28730
  let content;
@@ -28915,9 +28927,13 @@ function createAcpRoleTurnHost(config) {
28915
28927
  const rpc = (method, params) => raceAgainstHostAbort(connection.request(method, params), recordAbort.signal, "host-session-record-failed");
28916
28928
  const agentProseChunks = [];
28917
28929
  let collectAgentProse = false;
28930
+ const ledgerGrokBuildObservability = config.hostName === GROK_BUILD_HOST;
28918
28931
  connection.onNotification?.((method, params) => {
28919
- if (method !== "session/update" || hostSessionRecordFailure !== void 0) return;
28920
- if (collectAgentProse) {
28932
+ if (hostSessionRecordFailure !== void 0) return;
28933
+ const isSessionUpdate = method === "session/update";
28934
+ const isAutoCompact = ledgerGrokBuildObservability && isAcpAutoCompactCompletedNotification(method, params);
28935
+ if (!isSessionUpdate && !isAutoCompact) return;
28936
+ if (isSessionUpdate && collectAgentProse) {
28921
28937
  const chunk = acpAgentTextChunk(params);
28922
28938
  if (chunk !== void 0) agentProseChunks.push(chunk);
28923
28939
  }
@@ -29014,6 +29030,23 @@ function createAcpRoleTurnHost(config) {
29014
29030
  throw error;
29015
29031
  }
29016
29032
  collectAgentProse = false;
29033
+ if (ledgerGrokBuildObservability && acpPromptResultHasUsage(result)) {
29034
+ try {
29035
+ reportHostSessionEvent({
29036
+ host: config.hostName,
29037
+ cwd: request.cwd,
29038
+ sessionParent,
29039
+ source: "acp-host",
29040
+ event: { method: "session/prompt", result }
29041
+ });
29042
+ } catch (error) {
29043
+ noteHostSessionRecordFailure(error);
29044
+ return { status: "terminal", result: hostSessionRecordResult() };
29045
+ }
29046
+ }
29047
+ if (hostSessionRecordFailure !== void 0) {
29048
+ return { status: "terminal", result: hostSessionRecordResult() };
29049
+ }
29017
29050
  if (result.stopReason === "refusal") {
29018
29051
  agentProseChunks.length = 0;
29019
29052
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.4641",
3
+ "version": "0.1.4649",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -20,6 +20,30 @@ import {
20
20
  } from "../prepared-role-turn.ts";
21
21
  import { acpModelId, type AcpHostDescription } from "./description.ts";
22
22
 
23
+ /** #971: authorized host for usage + auto_compact ledgering only. */
24
+ const GROK_BUILD_HOST = "grok-build";
25
+
26
+ /** #971: grok-build prompt result carries host usage under `_meta.usage`. */
27
+ function acpPromptResultHasUsage(result: Readonly<Record<string, unknown>>): boolean {
28
+ const meta = result._meta;
29
+ if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return false;
30
+ return Object.prototype.hasOwnProperty.call(meta, "usage");
31
+ }
32
+
33
+ /**
34
+ * #971: ledger only the authorized vendor compaction notice on grok-build.
35
+ * Other `_x.ai/*` notifications stay out of host-session records.
36
+ */
37
+ function isAcpAutoCompactCompletedNotification(
38
+ method: string,
39
+ params: Readonly<Record<string, unknown>>,
40
+ ): boolean {
41
+ if (method !== "_x.ai/session_notification") return false;
42
+ const update = params.update;
43
+ if (typeof update !== "object" || update === null || Array.isArray(update)) return false;
44
+ return (update as { sessionUpdate?: unknown }).sessionUpdate === "auto_compact_completed";
45
+ }
46
+
23
47
  /**
24
48
  * #959: collect free-form agent text from ACP session/update stream.
25
49
  * Used only when the navigator seat spoke prose without calling the output tool.
@@ -294,9 +318,16 @@ export function createAcpRoleTurnHost(config: AcpRoleTurnHostConfig): RoleTurnHo
294
318
  // (resume / set_model load would otherwise prepend prior turns as "this turn" prose).
295
319
  const agentProseChunks: string[] = [];
296
320
  let collectAgentProse = false;
321
+ // #971: usage + auto_compact are grok-build-only; same ACP adapter serves Hermes too.
322
+ const ledgerGrokBuildObservability = config.hostName === GROK_BUILD_HOST;
297
323
  connection.onNotification?.((method, params) => {
298
- if (method !== "session/update" || hostSessionRecordFailure !== undefined) return;
299
- if (collectAgentProse) {
324
+ if (hostSessionRecordFailure !== undefined) return;
325
+ const isSessionUpdate = method === "session/update";
326
+ const isAutoCompact = ledgerGrokBuildObservability
327
+ && isAcpAutoCompactCompletedNotification(method, params);
328
+ // #971: session/update stays; auto_compact_completed is the only vendor notice.
329
+ if (!isSessionUpdate && !isAutoCompact) return;
330
+ if (isSessionUpdate && collectAgentProse) {
300
331
  const chunk = acpAgentTextChunk(params);
301
332
  if (chunk !== undefined) agentProseChunks.push(chunk);
302
333
  }
@@ -409,6 +440,24 @@ export function createAcpRoleTurnHost(config: AcpRoleTurnHostConfig): RoleTurnHo
409
440
  throw error;
410
441
  }
411
442
  collectAgentProse = false;
443
+ // #971: per-round grok-build usage is on the prompt JSON-RPC result, not a notice.
444
+ if (ledgerGrokBuildObservability && acpPromptResultHasUsage(result)) {
445
+ try {
446
+ reportHostSessionEvent({
447
+ host: config.hostName,
448
+ cwd: request.cwd,
449
+ sessionParent,
450
+ source: "acp-host",
451
+ event: { method: "session/prompt", result },
452
+ });
453
+ } catch (error) {
454
+ noteHostSessionRecordFailure(error);
455
+ return { status: "terminal", result: hostSessionRecordResult() };
456
+ }
457
+ }
458
+ if (hostSessionRecordFailure !== undefined) {
459
+ return { status: "terminal", result: hostSessionRecordResult() };
460
+ }
412
461
  if (result.stopReason === "refusal") {
413
462
  agentProseChunks.length = 0;
414
463
  return {