@akagilnc/pi-workflow-roles 0.1.5365 → 0.1.5375

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.
Files changed (170) hide show
  1. package/dist/acp-host/production-host.js +5585 -5655
  2. package/dist/activation-ledger-git.js +2 -2
  3. package/dist/activation-ledger-topology.js +1 -7
  4. package/dist/analyst-entry.js +4 -8
  5. package/dist/analyst-gate-cycles-read.js +3 -11
  6. package/dist/analyst-index.js +3 -9
  7. package/dist/analyst-ledger.js +1 -11
  8. package/dist/analyst-metric-families/acceptance-success-rework.js +1 -3
  9. package/dist/analyst-metric-families/round-timeline.js +1 -3
  10. package/dist/analyst-page.js +2 -2
  11. package/dist/archivist-record-topology.js +2 -2
  12. package/dist/audit-escalation.js +2 -1
  13. package/dist/auditor-soul.js +2 -1
  14. package/dist/collector-config.js +6 -8
  15. package/dist/compliance-transport.js +2 -1
  16. package/dist/countersign-contracts.js +2 -1
  17. package/dist/diarist-contracts.js +3 -2
  18. package/dist/doctor-contracts.js +1 -3
  19. package/dist/doctor-evidence.js +7 -8
  20. package/dist/dossier-resolution.js +1 -3
  21. package/dist/engine-detour-usage.js +1 -3
  22. package/dist/gatekeeper-role.js +2 -9
  23. package/dist/gleaner-left-contracts.js +2 -1
  24. package/dist/headless-host/description.js +14 -17
  25. package/dist/headless-host/production-host.js +1665 -1737
  26. package/dist/host-session-record.js +3 -2
  27. package/dist/inspector-contracts.js +2 -1
  28. package/dist/ledger-session-read.js +1 -3
  29. package/dist/merger-contracts.js +9 -9
  30. package/dist/migrate-book-topology.js +348 -314
  31. package/dist/navigator-attendance.js +9 -11
  32. package/dist/navigator-invocation-identity.js +3 -2
  33. package/dist/navigator-public-session.js +3 -5
  34. package/dist/navigator-session-contracts.js +8 -10
  35. package/dist/navigator-work-base.js +5 -8
  36. package/dist/notary-contracts.js +3 -5
  37. package/dist/package-contracts/auditor-output.js +1 -3
  38. package/dist/package-contracts/fixer-packet.js +3 -6
  39. package/dist/package-contracts/gatekeeper-output.js +1 -3
  40. package/dist/package-contracts/navigator-output.js +8 -8
  41. package/dist/package-contracts/terminating-infrastructure.js +5 -9
  42. package/dist/package-contracts/terminating-tools.js +4 -3
  43. package/dist/public-cli/analyst-run.js +3 -2
  44. package/dist/public-cli/auto-resume.js +4 -9
  45. package/dist/public-cli/cli.js +66 -64
  46. package/dist/public-cli/config.js +12 -11
  47. package/dist/public-cli/countersign-run.js +1 -3
  48. package/dist/public-cli/host-providers.js +7 -14
  49. package/dist/public-cli/instruction-seat-run.js +69 -43
  50. package/dist/public-cli/invocation.js +141 -136
  51. package/dist/public-cli/main.js +1919 -1968
  52. package/dist/public-cli/post-admission.js +89 -89
  53. package/dist/public-cli/role-seat-runtime.js +29 -0
  54. package/dist/public-cli/run-lifecycle.js +20 -32
  55. package/dist/public-cli/settlement.js +10 -26
  56. package/dist/public-cli/turn-request.js +14 -0
  57. package/dist/public-role-summons.js +23 -35
  58. package/dist/receipt-delivery-policy.js +1 -3
  59. package/dist/role-run-placement.js +7 -5
  60. package/dist/role-run-relocation.js +12 -19
  61. package/dist/run-terminal-artifacts.js +1 -11
  62. package/dist/run-ticket-number.js +2 -4
  63. package/dist/session-assistant-usage.js +2 -1
  64. package/dist/session-dialogue.js +1 -14
  65. package/dist/sitian-reader.js +2 -4
  66. package/dist/submission-correctable-error.js +2 -1
  67. package/dist/submission-errors.js +2 -1
  68. package/dist/submission-gate.js +2 -1
  69. package/dist/submission-ledger.js +4 -5
  70. package/dist/ticket-provenance-contracts.js +1 -3
  71. package/dist/ticket-provenance.js +2 -1
  72. package/dist/typed-provider-http.js +4 -7
  73. package/dist/unknown-value.js +28 -0
  74. package/dist/user-dialogue-stdin.js +2 -1
  75. package/package.json +1 -1
  76. package/src/acp-host/role-turn-host.ts +4 -2
  77. package/src/activation-ledger-git.ts +3 -2
  78. package/src/activation-ledger-topology.ts +4 -12
  79. package/src/analyst-entry.ts +3 -11
  80. package/src/analyst-gate-cycles-read.ts +3 -15
  81. package/src/analyst-index.ts +3 -13
  82. package/src/analyst-ledger.ts +2 -16
  83. package/src/analyst-metric-families/acceptance-success-rework.ts +2 -4
  84. package/src/analyst-metric-families/round-timeline.ts +2 -4
  85. package/src/analyst-page.ts +2 -2
  86. package/src/archivist-record-topology.ts +2 -2
  87. package/src/audit-escalation.ts +2 -1
  88. package/src/auditor-soul.ts +3 -1
  89. package/src/book-topology-migration-placement.ts +8 -21
  90. package/src/book-topology-migrators-t11.ts +16 -15
  91. package/src/book-topology-mixed-volume-migrators.ts +3 -6
  92. package/src/book-topology-record-class-migrators.ts +7 -10
  93. package/src/book-topology-runs-migrator.ts +4 -3
  94. package/src/collector-config.ts +7 -9
  95. package/src/compliance-transport.ts +2 -1
  96. package/src/countersign-contracts.ts +2 -1
  97. package/src/diarist-contracts.ts +3 -2
  98. package/src/doctor-contracts.ts +3 -1
  99. package/src/doctor-evidence.ts +8 -7
  100. package/src/doctor-role.ts +4 -2
  101. package/src/dossier-resolution.ts +2 -4
  102. package/src/engine-detour-tool.ts +0 -2
  103. package/src/engine-detour-usage.ts +2 -4
  104. package/src/external-host-turn-loop.ts +3 -1
  105. package/src/factory-board.ts +1 -8
  106. package/src/gatekeeper-role.ts +2 -10
  107. package/src/gleaner-left-contracts.ts +3 -1
  108. package/src/headless-host/description.ts +15 -18
  109. package/src/headless-host/role-turn-host.ts +10 -9
  110. package/src/host-session-record.ts +4 -2
  111. package/src/inspector-contracts.ts +2 -1
  112. package/src/ledger-session-read.ts +2 -5
  113. package/src/merger-contracts.ts +10 -9
  114. package/src/navigator-attendance.ts +10 -12
  115. package/src/navigator-invocation-identity.ts +3 -2
  116. package/src/navigator-public-session.ts +4 -6
  117. package/src/navigator-session-contracts.ts +8 -11
  118. package/src/navigator-work-base.ts +5 -8
  119. package/src/navigator-work-context.ts +2 -1
  120. package/src/notary-contracts.ts +4 -6
  121. package/src/oauth-keepalive.ts +5 -18
  122. package/src/package-contracts/auditor-output.ts +2 -4
  123. package/src/package-contracts/fixer-packet.ts +4 -6
  124. package/src/package-contracts/gatekeeper-output.ts +2 -4
  125. package/src/package-contracts/judge-output.ts +0 -1
  126. package/src/package-contracts/navigator-output.ts +8 -8
  127. package/src/package-contracts/terminating-infrastructure.ts +6 -20
  128. package/src/package-contracts/terminating-tools.ts +8 -12
  129. package/src/pi/adapter.ts +0 -1
  130. package/src/pi/role-turn-host.ts +0 -1
  131. package/src/public-cli/analyst-run.ts +4 -2
  132. package/src/public-cli/auto-resume.ts +5 -12
  133. package/src/public-cli/cli.ts +77 -83
  134. package/src/public-cli/config.ts +16 -27
  135. package/src/public-cli/countersign-run.ts +2 -4
  136. package/src/public-cli/host-providers.ts +10 -27
  137. package/src/public-cli/instruction-seat-run.ts +87 -58
  138. package/src/public-cli/invocation.ts +159 -172
  139. package/src/public-cli/post-admission.ts +115 -103
  140. package/src/public-cli/role-seat-runtime.ts +72 -0
  141. package/src/public-cli/run-lifecycle.ts +27 -67
  142. package/src/public-cli/settlement.ts +11 -33
  143. package/src/public-cli/terminal.ts +2 -17
  144. package/src/public-cli/turn-request.ts +26 -0
  145. package/src/public-role-summons.ts +24 -48
  146. package/src/receipt-delivery-policy.ts +1 -4
  147. package/src/reviewer-role.ts +0 -1
  148. package/src/role-envelope.ts +5 -3
  149. package/src/role-run-placement.ts +9 -10
  150. package/src/role-run-relocation.ts +13 -23
  151. package/src/role-runtime.ts +9 -15
  152. package/src/run-terminal-artifacts.ts +2 -16
  153. package/src/run-ticket-number.ts +4 -10
  154. package/src/session-assistant-usage.ts +3 -1
  155. package/src/session-dialogue.ts +1 -4
  156. package/src/session-identity.ts +0 -1
  157. package/src/sitian-reader.ts +2 -4
  158. package/src/submission-correctable-error.ts +3 -1
  159. package/src/submission-errors.ts +2 -1
  160. package/src/submission-gate.ts +3 -1
  161. package/src/submission-ledger.ts +5 -6
  162. package/src/ticket-provenance-contracts.ts +1 -4
  163. package/src/ticket-provenance.ts +3 -1
  164. package/src/ticket-snapshot.ts +2 -4
  165. package/src/ticket-trajectory.ts +1 -8
  166. package/src/typed-provider-http.ts +5 -15
  167. package/src/unknown-value.ts +34 -0
  168. package/src/user-dialogue-stdin.ts +3 -1
  169. package/src/worker-role.ts +2 -5
  170. package/src/worker-submission-gates.ts +5 -7
@@ -3,19 +3,19 @@ import { piDurablePrincipalAuthority } from "../pi/durable-principal.js";
3
3
  * Public ak-role CLI dispatcher (roles / config / layered help / Judge run).
4
4
  */
5
5
  import { realpath } from "node:fs/promises";
6
- import { join } from "node:path";
7
6
  import { packageMachineHome } from "../activation-ledger-topology.js";
8
7
  import { assertLegalEngineModel, assertLegalEngineName, pickEngineAxis, } from "../package-resources/engine-material.js";
9
8
  import { resolveConfiguredProvinceOfficer, } from "../institutional-resolution.js";
10
- import { clearPersistentSeatConfig, effectiveSeatConfigurations, formatModelSpec, isGateOfficerSeat, loadCredentialProviders, loadPublicCliConfig, missingResolvedSeatModelMessage, parseModelSpec, resolveEffectiveSeat, resolvedSeatWithModel, savePublicCliConfig, setAutoResumeLimit, setPersistentSeatConfig, setPersistentSeatEngine, setPersistentSeatEngineModel, setPersistentSeatHost, validatePublicCliConfigAxes, } from "./config.js";
11
- import { loadHostProvidersTable, projectHostFacingProvider, renderHostProvidersTable, } from "./host-providers.js";
9
+ import { clearPersistentSeatConfig, effectiveSeatConfigurations, formatModelSpec, isGateOfficerSeat, loadCredentialProviders, loadPublicCliConfig, missingResolvedSeatModelMessage, parseModelSpec, resolveEffectiveSeat, savePublicCliConfig, setAutoResumeLimit, setPersistentSeatConfig, setPersistentSeatEngine, setPersistentSeatEngineModel, setPersistentSeatHost, resolvePublicAgentDir, validatePublicCliConfigAxes, } from "./config.js";
10
+ import { loadHostProvidersTable, renderHostProvidersTable, } from "./host-providers.js";
12
11
  import { packagedModelParent } from "../packaged-role-registry.js";
13
12
  import { seatModelOnly } from "./registry.js";
14
13
  import { CliUsageError } from "./cli-errors.js";
15
14
  import { runMachineSkillSetup } from "./machine-method-skills.js";
16
15
  import { presentLocatedResumeFailure, } from "./post-admission.js";
17
16
  import { appendPiSessionCustomEntry } from "../pi/role-turn-host.js";
18
- import { composeRoleTurnHostAdapters, formatHostSelectionFailure, HostSelectionError, selectRoleTurnHost, } from "./role-turn-host-resolution.js";
17
+ import { openRoleSeatRuntime } from "./role-seat-runtime.js";
18
+ import { formatHostSelectionFailure, HostSelectionError, } from "./role-turn-host-resolution.js";
19
19
  import { parseAnalystArgv, parsePublicSeatArgv, } from "./invocation.js";
20
20
  import { createTypedOptionConsumer, optionsForOwner, projectCommandHelp, projectOwnerOptions, PUBLIC_NAVIGATOR_HELP_NOTE, PUBLIC_ROLE_OPTION_OWNERS, renderHumanOwnerOptionLines, } from "./option-definitions.js";
21
21
  import { TurnDispatchedFailure } from "./auto-resume.js";
@@ -25,6 +25,7 @@ import { runPublicAnalyst } from "./analyst-run.js";
25
25
  import { AUTO_RESUME_LIMIT, peekRoleRunRole, } from "./run-lifecycle.js";
26
26
  import { INTERNAL_ROLE_ENTRYPOINT_RELATIVE, PUBLIC_CALLABLE_ROLES, isPublicCallableRole, isPublicCliSupportCommand, isPublicConfigurableSeat, listHelpCapabilities, } from "./registry.js";
27
27
  import { formatCliDiagnostic, formatErrorCauseDetail, presentStructuralRejection, } from "./settlement.js";
28
+ import { errorText } from "../unknown-value.js";
28
29
  export { buildExplicitInternalActivationArgs, resolveInternalRoleEntrypoint, } from "../pi/role-turn-host.js";
29
30
  export { CliUsageError } from "./cli-errors.js";
30
31
  /**
@@ -89,43 +90,41 @@ function takePublicGlobalFlag(argv, index, options) {
89
90
  function createRoleEnvironment(env, options,
90
91
  /** #178: after host selection, before missing-model — structural argv parse once. */
91
92
  afterHost) {
92
- const role = options.role;
93
93
  const extraPiArgs = env.extraPiArgs;
94
94
  const timeoutMs = env.timeoutMs;
95
- // #617/#178/#788/#840: host first, then model; nested child seat selects own host.
96
- const hostAdapters = composeRoleTurnHostAdapters({
97
- packageRoot: env.packageRoot,
98
- ...(env.roleTurnHost === undefined ? {} : { roleTurnHost: env.roleTurnHost }),
99
- ...(env.hostAdapters === undefined ? {} : { hostAdapters: env.hostAdapters }),
100
- ...(extraPiArgs === undefined ? {} : { extraPiArgs }),
101
- ...(timeoutMs === undefined ? {} : { timeoutMs }),
102
- }, env.principalAuthority);
103
- const roleTurnHost = selectRoleTurnHost(hostAdapters, {
104
- role,
95
+ const opened = openRoleSeatRuntime({
96
+ resolution: {
97
+ packageRoot: env.packageRoot,
98
+ ...(env.roleTurnHost === undefined ? {} : { roleTurnHost: env.roleTurnHost }),
99
+ ...(env.hostAdapters === undefined ? {} : { hostAdapters: env.hostAdapters }),
100
+ ...(extraPiArgs === undefined ? {} : { extraPiArgs }),
101
+ ...(timeoutMs === undefined ? {} : { timeoutMs }),
102
+ },
103
+ principalAuthority: env.principalAuthority,
104
+ role: options.role,
105
105
  seat: options.seat,
106
+ home: options.home,
107
+ ...(afterHost === undefined ? {} : { afterHost }),
106
108
  });
107
- // #178: host → argv (afterHost) → missing-model → provider projection.
108
- afterHost?.();
109
- const seatWithModel = resolvedSeatWithModel(options.seat);
110
- if (seatWithModel === undefined) {
109
+ if (!opened.ok) {
111
110
  // Direct CLI has --model; dual remediation is intentional here (#178 / #916).
112
111
  throw new CliUsageError(missingResolvedSeatModelMessage(options.seat.seat, "invocation-or-config"));
113
112
  }
114
- const hostFacingSelection = projectHostFacingProvider(seatWithModel.selection, seatWithModel.host, loadHostProvidersTable(options.home), options.home);
115
113
  return {
116
114
  home: options.home,
117
115
  principalAuthority: env.principalAuthority,
118
116
  agentDir: options.agentDir,
119
117
  sessionAppender: appendPiSessionCustomEntry,
120
118
  packageRoot: env.packageRoot,
121
- roleTurnHost,
122
- hostAdapters,
119
+ roleTurnHost: opened.roleTurnHost,
120
+ hostAdapters: opened.hostAdapters,
123
121
  cwd: options.cwd,
124
122
  ...(options.credentials === undefined ? {} : { credentials: options.credentials }),
125
123
  ...(env.correlationId === undefined ? {} : { correlationId: env.correlationId }),
126
- ...(hostFacingSelection === undefined ? {} : { model: hostFacingSelection }),
127
- ...projectSeatEngine(options.seat),
128
- ...projectSeatHost(options.seat),
124
+ ...(opened.model === undefined ? {} : { model: opened.model }),
125
+ ...(opened.engine === undefined ? {} : { engine: opened.engine }),
126
+ ...(opened.engineModel === undefined ? {} : { engineModel: opened.engineModel }),
127
+ host: opened.host,
129
128
  ...(timeoutMs === undefined ? {} : { timeoutMs }),
130
129
  ...(env.createRunId === undefined ? {} : { createRunId: env.createRunId }),
131
130
  ...(options.config?.autoResumeLimit === undefined
@@ -138,18 +137,31 @@ afterHost) {
138
137
  ...(env.signal === undefined ? {} : { signal: env.signal }),
139
138
  };
140
139
  }
140
+ /** Shared preamble for a new public role command and an explicit resume. */
141
+ async function loadPublicRoleDispatchParts(env, home) {
142
+ const agentDir = resolvePublicAgentDir(env.agentDir, home);
143
+ const cwd = env.cwd ?? process.cwd();
144
+ const config = await loadAndValidateConfig(home, env.packageRoot);
145
+ const credentials = env.credentials ?? (await loadCredentialProviders(agentDir));
146
+ return { agentDir, cwd, config, credentials };
147
+ }
141
148
  /**
142
149
  * #178 single spine: resolve seat → host select → argv parse once → missing-model → run.
143
150
  * Keeps host-unregistered ahead of bad argv and missing-model.
144
151
  */
145
152
  async function dispatchPublicRoleCommand(env, home, io, parsed, role, parse, run) {
146
- const agentDir = resolveAgentDir(env, home);
147
- const cwd = env.cwd ?? process.cwd();
148
- const config = await loadAndValidateConfig(home, env.packageRoot);
149
- const credentials = env.credentials ?? (await loadCredentialProviders(agentDir));
150
- const seat = resolveEffectiveSeat(config, role, credentials, invocationFromParsed(parsed));
153
+ const parts = await loadPublicRoleDispatchParts(env, home);
154
+ const seat = resolveEffectiveSeat(parts.config, role, parts.credentials, invocationFromParsed(parsed));
151
155
  let parsedRoleArgv;
152
- const result = await run(parsed.args, createRoleEnvironment(env, { role, home, agentDir, cwd, credentials, seat, config }, () => {
156
+ const result = await run(parsed.args, createRoleEnvironment(env, {
157
+ role,
158
+ home,
159
+ agentDir: parts.agentDir,
160
+ cwd: parts.cwd,
161
+ credentials: parts.credentials,
162
+ seat,
163
+ config: parts.config,
164
+ }, () => {
153
165
  parsedRoleArgv = parse(parsed.args);
154
166
  }), () => parsedRoleArgv);
155
167
  return {
@@ -176,11 +188,6 @@ function defaultIo() {
176
188
  function resolveHome(env) {
177
189
  return env.home ?? packageMachineHome();
178
190
  }
179
- function resolveAgentDir(env, home) {
180
- return (env.agentDir ??
181
- process.env.PI_CODING_AGENT_DIR ??
182
- join(home, ".pi", "agent"));
183
- }
184
191
  function parseThinking(value) {
185
192
  // #683: opaque pass-through — no local whitelist.
186
193
  return value;
@@ -299,7 +306,7 @@ function requireLegalEngineModel(model) {
299
306
  return assertLegalEngineModel(model);
300
307
  }
301
308
  catch (error) {
302
- throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
309
+ throw new CliUsageError(errorText(error), { cause: error });
303
310
  }
304
311
  }
305
312
  function requireLegalEngineName(name) {
@@ -307,7 +314,7 @@ function requireLegalEngineName(name) {
307
314
  return assertLegalEngineName(name);
308
315
  }
309
316
  catch (error) {
310
- throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
317
+ throw new CliUsageError(errorText(error), { cause: error });
311
318
  }
312
319
  }
313
320
  /** Callable seats own persistent call axes (checked against the callable predicate). */
@@ -316,21 +323,13 @@ function requireCallableSeat(seat, axis, verb) {
316
323
  throw new CliUsageError(`unknown ${axis}-axis seat: ${seat}`);
317
324
  }
318
325
  }
319
- /** Single seat engine axis → run-options projection (#391 E2 / #883). */
320
- function projectSeatEngine(seat) {
321
- return pickEngineAxis(seat);
322
- }
323
- /** Single seat.host → run-options projection (#595 / #617). */
324
- function projectSeatHost(seat) {
325
- return { host: seat.host };
326
- }
327
326
  function loadAndValidateConfig(home, packageRoot) {
328
327
  return loadPublicCliConfig(home).then((config) => {
329
328
  try {
330
329
  validatePublicCliConfigAxes(config, packageRoot);
331
330
  }
332
331
  catch (error) {
333
- throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
332
+ throw new CliUsageError(errorText(error), { cause: error });
334
333
  }
335
334
  return config;
336
335
  });
@@ -592,7 +591,7 @@ async function runConfigCommand(args, home, packageRoot, io) {
592
591
  config = setPersistentSeatHost(config, seat, unset ? undefined : args[2]);
593
592
  }
594
593
  catch (error) {
595
- throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
594
+ throw new CliUsageError(errorText(error), { cause: error });
596
595
  }
597
596
  await savePublicCliConfig(config, home);
598
597
  io.stdout(renderConfig(config, home));
@@ -614,7 +613,7 @@ async function runConfigCommand(args, home, packageRoot, io) {
614
613
  config = setPersistentSeatEngine(config, seat, name, engineModel);
615
614
  }
616
615
  catch (error) {
617
- throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
616
+ throw new CliUsageError(errorText(error), { cause: error });
618
617
  }
619
618
  await savePublicCliConfig(config, home);
620
619
  io.stdout(renderConfig(config, home));
@@ -631,7 +630,7 @@ async function runConfigCommand(args, home, packageRoot, io) {
631
630
  config = setPersistentSeatEngine(config, seat, undefined);
632
631
  }
633
632
  catch (error) {
634
- throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
633
+ throw new CliUsageError(errorText(error), { cause: error });
635
634
  }
636
635
  await savePublicCliConfig(config, home);
637
636
  io.stdout(renderConfig(config, home));
@@ -650,7 +649,7 @@ async function runConfigCommand(args, home, packageRoot, io) {
650
649
  config = setPersistentSeatEngineModel(config, seat, model);
651
650
  }
652
651
  catch (error) {
653
- throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
652
+ throw new CliUsageError(errorText(error), { cause: error });
654
653
  }
655
654
  await savePublicCliConfig(config, home);
656
655
  io.stdout(renderConfig(config, home));
@@ -667,7 +666,7 @@ async function runConfigCommand(args, home, packageRoot, io) {
667
666
  config = setPersistentSeatEngineModel(config, seat, undefined);
668
667
  }
669
668
  catch (error) {
670
- throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
669
+ throw new CliUsageError(errorText(error), { cause: error });
671
670
  }
672
671
  await savePublicCliConfig(config, home);
673
672
  io.stdout(renderConfig(config, home));
@@ -787,7 +786,7 @@ export async function runAkRole(argv, env) {
787
786
  }
788
787
  const config = await loadAndValidateConfig(home, env.packageRoot);
789
788
  const credentials = env.credentials ??
790
- (await loadCredentialProviders(resolveAgentDir(env, home)));
789
+ (await loadCredentialProviders(resolvePublicAgentDir(env.agentDir, home)));
791
790
  const seats = effectiveSeatConfigurations(config, credentials, invocationFromParsed(parsed));
792
791
  io.stdout(renderRoles(seats));
793
792
  return { exitCode: 0 };
@@ -829,23 +828,20 @@ export async function runAkRole(argv, env) {
829
828
  runId: resumeRequest.runId,
830
829
  authority: env.principalAuthority ?? piDurablePrincipalAuthority,
831
830
  };
832
- const agentDir = resolveAgentDir(env, home);
833
- const cwd = env.cwd ?? process.cwd();
834
- const config = await loadAndValidateConfig(home, env.packageRoot);
835
- const credentials = env.credentials ?? (await loadCredentialProviders(agentDir));
831
+ const parts = await loadPublicRoleDispatchParts(env, home);
836
832
  const resumeRole = await peekRoleRunRole(home, resumeRequest.runId);
837
833
  // Missing durable role keeps the judge seat table. The resume entry
838
834
  // itself is one function; it reads the stored run.
839
835
  const seatRole = resumeRole ?? "judge";
840
- const seat = resolveEffectiveSeat(config, seatRole, credentials, invocationFromParsed(parsed));
836
+ const seat = resolveEffectiveSeat(parts.config, seatRole, parts.credentials, invocationFromParsed(parsed));
841
837
  const result = await runPublicInstructionSeatResume(resumeRequest, createRoleEnvironment(env, {
842
838
  role: seatRole,
843
839
  home,
844
- agentDir,
845
- cwd,
846
- credentials,
840
+ agentDir: parts.agentDir,
841
+ cwd: parts.cwd,
842
+ credentials: parts.credentials,
847
843
  seat,
848
- config,
844
+ config: parts.config,
849
845
  }), io);
850
846
  let current = result;
851
847
  while (current.exitCode === 0 && current.admitted?.correlationId !== undefined
@@ -860,9 +856,15 @@ export async function runAkRole(argv, env) {
860
856
  const parentRole = await peekRoleRunRole(home, parentRunId);
861
857
  if (parentRole === undefined)
862
858
  break;
863
- const parentSeat = resolveEffectiveSeat(config, parentRole, credentials, invocationFromParsed(parsed));
859
+ const parentSeat = resolveEffectiveSeat(parts.config, parentRole, parts.credentials, invocationFromParsed(parsed));
864
860
  const parentEnv = createRoleEnvironment(env, {
865
- role: parentRole, home, agentDir, cwd, credentials, seat: parentSeat, config,
861
+ role: parentRole,
862
+ home,
863
+ agentDir: parts.agentDir,
864
+ cwd: parts.cwd,
865
+ credentials: parts.credentials,
866
+ seat: parentSeat,
867
+ config: parts.config,
866
868
  });
867
869
  current = await continueParentAfterChild(parentRunId, current.admitted, parentEnv, io);
868
870
  }
@@ -19,6 +19,7 @@ import {
19
19
  isPublicConfigurableSeat,
20
20
  seatModelOnly
21
21
  } from "./registry.js";
22
+ import { isEnoent, isRecord } from "../unknown-value.js";
22
23
  const GATE_OFFICER_SEATS = PUBLIC_ROLE_RECORDS.flatMap(
23
24
  (record) => "provinceConfig" in record && record.provinceConfig === true ? [record.role] : []
24
25
  );
@@ -37,9 +38,7 @@ async function loadPublicCliConfig(home) {
37
38
  const raw = await readFile(path, "utf8");
38
39
  return parsePublicCliConfig(JSON.parse(raw));
39
40
  } catch (error) {
40
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
41
- return { seats: {} };
42
- }
41
+ if (isEnoent(error)) return { seats: {} };
43
42
  throw error;
44
43
  }
45
44
  }
@@ -260,7 +259,7 @@ function serializePublicCliConfig(config) {
260
259
  };
261
260
  }
262
261
  function parsePublicCliConfig(value) {
263
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
262
+ if (!isRecord(value)) {
264
263
  throw new Error("public CLI config must be an object");
265
264
  }
266
265
  const record = value;
@@ -270,7 +269,7 @@ function parsePublicCliConfig(value) {
270
269
  }
271
270
  const unknownSeats = {};
272
271
  if (record.unknownSeats !== void 0) {
273
- if (record.unknownSeats === null || typeof record.unknownSeats !== "object" || Array.isArray(record.unknownSeats)) {
272
+ if (!isRecord(record.unknownSeats)) {
274
273
  throw new Error("public CLI config.unknownSeats must be an object");
275
274
  }
276
275
  Object.assign(unknownSeats, record.unknownSeats);
@@ -283,7 +282,7 @@ function parsePublicCliConfig(value) {
283
282
  if (record.seats === void 0) {
284
283
  return withOpaque({});
285
284
  }
286
- if (record.seats === null || typeof record.seats !== "object" || Array.isArray(record.seats)) {
285
+ if (!isRecord(record.seats)) {
287
286
  throw new Error("public CLI config.seats must be an object");
288
287
  }
289
288
  const seats = {};
@@ -299,7 +298,7 @@ function parsePublicCliConfig(value) {
299
298
  return withOpaque(seats);
300
299
  }
301
300
  function parseSeatModelConfig(value, seat) {
302
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
301
+ if (!isRecord(value)) {
303
302
  throw new Error(`config seat ${seat} must be an object`);
304
303
  }
305
304
  const raw = value;
@@ -481,7 +480,7 @@ function listRolesForDisplay(config, credentials, invocation) {
481
480
  return effectiveSeatConfigurations(config, credentials, invocation);
482
481
  }
483
482
  function credentialProvidersFromAuthData(data) {
484
- if (data === null || typeof data !== "object" || Array.isArray(data)) {
483
+ if (!isRecord(data)) {
485
484
  return { "openai-codex": false, xai: false };
486
485
  }
487
486
  const record = data;
@@ -490,14 +489,15 @@ function credentialProvidersFromAuthData(data) {
490
489
  xai: Object.prototype.hasOwnProperty.call(record, "xai")
491
490
  };
492
491
  }
492
+ function resolvePublicAgentDir(explicit, home) {
493
+ return explicit ?? process.env.PI_CODING_AGENT_DIR ?? join(home, ".pi", "agent");
494
+ }
493
495
  async function loadCredentialProviders(agentDir) {
494
496
  try {
495
497
  const raw = await readFile(join(agentDir, "auth.json"), "utf8");
496
498
  return credentialProvidersFromAuthData(JSON.parse(raw));
497
499
  } catch (error) {
498
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
499
- return { "openai-codex": false, xai: false };
500
- }
500
+ if (isEnoent(error)) return { "openai-codex": false, xai: false };
501
501
  throw error;
502
502
  }
503
503
  }
@@ -519,6 +519,7 @@ export {
519
519
  providerConfigured,
520
520
  publicCliConfigPath,
521
521
  resolveEffectiveSeat,
522
+ resolvePublicAgentDir,
522
523
  resolvedSeatWithModel,
523
524
  savePublicCliConfig,
524
525
  setAutoResumeLimit,
@@ -1,7 +1,5 @@
1
1
  import { readableGateItem } from "../readable-gate-item.js";
2
- function isRecord(value) {
3
- return typeof value === "object" && value !== null && !Array.isArray(value);
4
- }
2
+ import { isRecord } from "../unknown-value.js";
5
3
  function isEscalatePayload(payload) {
6
4
  if (!isRecord(payload))
7
5
  return false;
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import { readFileSync } from "node:fs";
12
12
  import { join } from "node:path";
13
+ import { isEnoent, isRecord } from "../unknown-value.js";
13
14
  export function hostProvidersPath(home) {
14
15
  if (typeof home !== "string" || home.trim() === "") {
15
16
  throw new Error("home must be explicitly provided");
@@ -21,7 +22,7 @@ export function hermesProviderModelsCachePath(home) {
21
22
  return join(home, ".hermes", "provider_models_cache.json");
22
23
  }
23
24
  export function parseHostProvidersTable(value) {
24
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
25
+ if (!isRecord(value)) {
25
26
  throw new Error("host-providers.json must be an object");
26
27
  }
27
28
  const out = {};
@@ -29,9 +30,7 @@ export function parseHostProvidersTable(value) {
29
30
  if (host.trim() === "") {
30
31
  throw new Error("host-providers.json host key must be non-empty");
31
32
  }
32
- if (byProvider === null ||
33
- typeof byProvider !== "object" ||
34
- Array.isArray(byProvider)) {
33
+ if (!isRecord(byProvider)) {
35
34
  throw new Error(`host-providers.json[${host}] must be an object`);
36
35
  }
37
36
  const providers = {};
@@ -61,11 +60,8 @@ export function loadHostProvidersTable(home) {
61
60
  return parseHostProvidersTable(JSON.parse(raw));
62
61
  }
63
62
  catch (error) {
64
- if (error instanceof Error &&
65
- "code" in error &&
66
- error.code === "ENOENT") {
63
+ if (isEnoent(error))
67
64
  return {};
68
- }
69
65
  throw error;
70
66
  }
71
67
  }
@@ -86,20 +82,17 @@ export function listHermesProvidersForModel(home, seatModel) {
86
82
  text = readFileSync(path, "utf8");
87
83
  }
88
84
  catch (error) {
89
- if (error instanceof Error &&
90
- "code" in error &&
91
- error.code === "ENOENT") {
85
+ if (isEnoent(error))
92
86
  return [];
93
- }
94
87
  throw error;
95
88
  }
96
89
  const raw = JSON.parse(text);
97
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
90
+ if (!isRecord(raw)) {
98
91
  throw new Error(`hermes provider_models_cache.json must be an object: ${path}`);
99
92
  }
100
93
  const found = [];
101
94
  for (const [provider, entry] of Object.entries(raw)) {
102
- if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
95
+ if (!isRecord(entry)) {
103
96
  continue;
104
97
  }
105
98
  const models = entry.models;