@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.
- package/dist/acp-host/production-host.js +5585 -5655
- package/dist/activation-ledger-git.js +2 -2
- package/dist/activation-ledger-topology.js +1 -7
- package/dist/analyst-entry.js +4 -8
- package/dist/analyst-gate-cycles-read.js +3 -11
- package/dist/analyst-index.js +3 -9
- package/dist/analyst-ledger.js +1 -11
- package/dist/analyst-metric-families/acceptance-success-rework.js +1 -3
- package/dist/analyst-metric-families/round-timeline.js +1 -3
- package/dist/analyst-page.js +2 -2
- package/dist/archivist-record-topology.js +2 -2
- package/dist/audit-escalation.js +2 -1
- package/dist/auditor-soul.js +2 -1
- package/dist/collector-config.js +6 -8
- package/dist/compliance-transport.js +2 -1
- package/dist/countersign-contracts.js +2 -1
- package/dist/diarist-contracts.js +3 -2
- package/dist/doctor-contracts.js +1 -3
- package/dist/doctor-evidence.js +7 -8
- package/dist/dossier-resolution.js +1 -3
- package/dist/engine-detour-usage.js +1 -3
- package/dist/gatekeeper-role.js +2 -9
- package/dist/gleaner-left-contracts.js +2 -1
- package/dist/headless-host/description.js +14 -17
- package/dist/headless-host/production-host.js +1665 -1737
- package/dist/host-session-record.js +3 -2
- package/dist/inspector-contracts.js +2 -1
- package/dist/ledger-session-read.js +1 -3
- package/dist/merger-contracts.js +9 -9
- package/dist/migrate-book-topology.js +348 -314
- package/dist/navigator-attendance.js +9 -11
- package/dist/navigator-invocation-identity.js +3 -2
- package/dist/navigator-public-session.js +3 -5
- package/dist/navigator-session-contracts.js +8 -10
- package/dist/navigator-work-base.js +5 -8
- package/dist/notary-contracts.js +3 -5
- package/dist/package-contracts/auditor-output.js +1 -3
- package/dist/package-contracts/fixer-packet.js +3 -6
- package/dist/package-contracts/gatekeeper-output.js +1 -3
- package/dist/package-contracts/navigator-output.js +8 -8
- package/dist/package-contracts/terminating-infrastructure.js +5 -9
- package/dist/package-contracts/terminating-tools.js +4 -3
- package/dist/public-cli/analyst-run.js +3 -2
- package/dist/public-cli/auto-resume.js +4 -9
- package/dist/public-cli/cli.js +66 -64
- package/dist/public-cli/config.js +12 -11
- package/dist/public-cli/countersign-run.js +1 -3
- package/dist/public-cli/host-providers.js +7 -14
- package/dist/public-cli/instruction-seat-run.js +69 -43
- package/dist/public-cli/invocation.js +141 -136
- package/dist/public-cli/main.js +1919 -1968
- package/dist/public-cli/post-admission.js +89 -89
- package/dist/public-cli/role-seat-runtime.js +29 -0
- package/dist/public-cli/run-lifecycle.js +20 -32
- package/dist/public-cli/settlement.js +10 -26
- package/dist/public-cli/turn-request.js +14 -0
- package/dist/public-role-summons.js +23 -35
- package/dist/receipt-delivery-policy.js +1 -3
- package/dist/role-run-placement.js +7 -5
- package/dist/role-run-relocation.js +12 -19
- package/dist/run-terminal-artifacts.js +1 -11
- package/dist/run-ticket-number.js +2 -4
- package/dist/session-assistant-usage.js +2 -1
- package/dist/session-dialogue.js +1 -14
- package/dist/sitian-reader.js +2 -4
- package/dist/submission-correctable-error.js +2 -1
- package/dist/submission-errors.js +2 -1
- package/dist/submission-gate.js +2 -1
- package/dist/submission-ledger.js +4 -5
- package/dist/ticket-provenance-contracts.js +1 -3
- package/dist/ticket-provenance.js +2 -1
- package/dist/typed-provider-http.js +4 -7
- package/dist/unknown-value.js +28 -0
- package/dist/user-dialogue-stdin.js +2 -1
- package/package.json +1 -1
- package/src/acp-host/role-turn-host.ts +4 -2
- package/src/activation-ledger-git.ts +3 -2
- package/src/activation-ledger-topology.ts +4 -12
- package/src/analyst-entry.ts +3 -11
- package/src/analyst-gate-cycles-read.ts +3 -15
- package/src/analyst-index.ts +3 -13
- package/src/analyst-ledger.ts +2 -16
- package/src/analyst-metric-families/acceptance-success-rework.ts +2 -4
- package/src/analyst-metric-families/round-timeline.ts +2 -4
- package/src/analyst-page.ts +2 -2
- package/src/archivist-record-topology.ts +2 -2
- package/src/audit-escalation.ts +2 -1
- package/src/auditor-soul.ts +3 -1
- package/src/book-topology-migration-placement.ts +8 -21
- package/src/book-topology-migrators-t11.ts +16 -15
- package/src/book-topology-mixed-volume-migrators.ts +3 -6
- package/src/book-topology-record-class-migrators.ts +7 -10
- package/src/book-topology-runs-migrator.ts +4 -3
- package/src/collector-config.ts +7 -9
- package/src/compliance-transport.ts +2 -1
- package/src/countersign-contracts.ts +2 -1
- package/src/diarist-contracts.ts +3 -2
- package/src/doctor-contracts.ts +3 -1
- package/src/doctor-evidence.ts +8 -7
- package/src/doctor-role.ts +4 -2
- package/src/dossier-resolution.ts +2 -4
- package/src/engine-detour-tool.ts +0 -2
- package/src/engine-detour-usage.ts +2 -4
- package/src/external-host-turn-loop.ts +3 -1
- package/src/factory-board.ts +1 -8
- package/src/gatekeeper-role.ts +2 -10
- package/src/gleaner-left-contracts.ts +3 -1
- package/src/headless-host/description.ts +15 -18
- package/src/headless-host/role-turn-host.ts +10 -9
- package/src/host-session-record.ts +4 -2
- package/src/inspector-contracts.ts +2 -1
- package/src/ledger-session-read.ts +2 -5
- package/src/merger-contracts.ts +10 -9
- package/src/navigator-attendance.ts +10 -12
- package/src/navigator-invocation-identity.ts +3 -2
- package/src/navigator-public-session.ts +4 -6
- package/src/navigator-session-contracts.ts +8 -11
- package/src/navigator-work-base.ts +5 -8
- package/src/navigator-work-context.ts +2 -1
- package/src/notary-contracts.ts +4 -6
- package/src/oauth-keepalive.ts +5 -18
- package/src/package-contracts/auditor-output.ts +2 -4
- package/src/package-contracts/fixer-packet.ts +4 -6
- package/src/package-contracts/gatekeeper-output.ts +2 -4
- package/src/package-contracts/judge-output.ts +0 -1
- package/src/package-contracts/navigator-output.ts +8 -8
- package/src/package-contracts/terminating-infrastructure.ts +6 -20
- package/src/package-contracts/terminating-tools.ts +8 -12
- package/src/pi/adapter.ts +0 -1
- package/src/pi/role-turn-host.ts +0 -1
- package/src/public-cli/analyst-run.ts +4 -2
- package/src/public-cli/auto-resume.ts +5 -12
- package/src/public-cli/cli.ts +77 -83
- package/src/public-cli/config.ts +16 -27
- package/src/public-cli/countersign-run.ts +2 -4
- package/src/public-cli/host-providers.ts +10 -27
- package/src/public-cli/instruction-seat-run.ts +87 -58
- package/src/public-cli/invocation.ts +159 -172
- package/src/public-cli/post-admission.ts +115 -103
- package/src/public-cli/role-seat-runtime.ts +72 -0
- package/src/public-cli/run-lifecycle.ts +27 -67
- package/src/public-cli/settlement.ts +11 -33
- package/src/public-cli/terminal.ts +2 -17
- package/src/public-cli/turn-request.ts +26 -0
- package/src/public-role-summons.ts +24 -48
- package/src/receipt-delivery-policy.ts +1 -4
- package/src/reviewer-role.ts +0 -1
- package/src/role-envelope.ts +5 -3
- package/src/role-run-placement.ts +9 -10
- package/src/role-run-relocation.ts +13 -23
- package/src/role-runtime.ts +9 -15
- package/src/run-terminal-artifacts.ts +2 -16
- package/src/run-ticket-number.ts +4 -10
- package/src/session-assistant-usage.ts +3 -1
- package/src/session-dialogue.ts +1 -4
- package/src/session-identity.ts +0 -1
- package/src/sitian-reader.ts +2 -4
- package/src/submission-correctable-error.ts +3 -1
- package/src/submission-errors.ts +2 -1
- package/src/submission-gate.ts +3 -1
- package/src/submission-ledger.ts +5 -6
- package/src/ticket-provenance-contracts.ts +1 -4
- package/src/ticket-provenance.ts +3 -1
- package/src/ticket-snapshot.ts +2 -4
- package/src/ticket-trajectory.ts +1 -8
- package/src/typed-provider-http.ts +5 -15
- package/src/unknown-value.ts +34 -0
- package/src/user-dialogue-stdin.ts +3 -1
- package/src/worker-role.ts +2 -5
- package/src/worker-submission-gates.ts +5 -7
|
@@ -41,6 +41,8 @@ import type {
|
|
|
41
41
|
} from "./invocation.ts";
|
|
42
42
|
import { presentControlledFailure, presentStructuralRejection } from "./settlement.ts";
|
|
43
43
|
|
|
44
|
+
import { errorText } from "../unknown-value.ts";
|
|
45
|
+
|
|
44
46
|
export type AnalystRunEnv = {
|
|
45
47
|
readonly home: string;
|
|
46
48
|
};
|
|
@@ -97,7 +99,7 @@ export async function buildAnalystIssueModeInputFromPublicArgv(
|
|
|
97
99
|
|
|
98
100
|
/**
|
|
99
101
|
* Attachment JSON → library AnalystSweepModeInput via the sole schema (#337).
|
|
100
|
-
* No parallel hand shape; rejects missing
|
|
102
|
+
* No parallel hand shape; rejects missing or wrong-type fields only.
|
|
101
103
|
*/
|
|
102
104
|
export function parseAnalystSweepModeInputFromJsonValue(
|
|
103
105
|
value: unknown,
|
|
@@ -141,7 +143,7 @@ export async function buildAnalystSweepModeInputFromAttachmentPaths(
|
|
|
141
143
|
try {
|
|
142
144
|
text = exactUtf8(bytes, "analyst sweep attachment");
|
|
143
145
|
} catch (error) {
|
|
144
|
-
const detail =
|
|
146
|
+
const detail = errorText(error);
|
|
145
147
|
throw new CliUsageError(detail, { cause: error });
|
|
146
148
|
}
|
|
147
149
|
|
|
@@ -42,6 +42,8 @@ import {
|
|
|
42
42
|
import type { CliIo } from "./cli-io.ts";
|
|
43
43
|
import { serializeThrownValue } from "../serialize-thrown-value.ts";
|
|
44
44
|
|
|
45
|
+
import { errorText, isEnoent } from "../unknown-value.ts";
|
|
46
|
+
|
|
45
47
|
const dummyIo: CliIo = { stdout: () => {}, stderr: () => {} };
|
|
46
48
|
|
|
47
49
|
/**
|
|
@@ -132,7 +134,7 @@ export class TurnDispatchedFailure extends Error {
|
|
|
132
134
|
constructor(cause: unknown) {
|
|
133
135
|
super(
|
|
134
136
|
`settlement failed after the host turn genuinely started: ${
|
|
135
|
-
|
|
137
|
+
errorText(cause)
|
|
136
138
|
}`,
|
|
137
139
|
{ cause },
|
|
138
140
|
);
|
|
@@ -164,7 +166,7 @@ export async function ensureRealArtifactsDirectory(runDirectory: string): Promis
|
|
|
164
166
|
throw new Error("run artifact retention: artifacts path is not a real directory");
|
|
165
167
|
}
|
|
166
168
|
} catch (error) {
|
|
167
|
-
if (!
|
|
169
|
+
if (!isEnoent(error)) throw error;
|
|
168
170
|
await mkdir(artifactsDir, { recursive: true });
|
|
169
171
|
const created = await lstat(artifactsDir);
|
|
170
172
|
if (created.isSymbolicLink() || !created.isDirectory()) {
|
|
@@ -174,15 +176,6 @@ export async function ensureRealArtifactsDirectory(runDirectory: string): Promis
|
|
|
174
176
|
return artifactsDir;
|
|
175
177
|
}
|
|
176
178
|
|
|
177
|
-
/** ENOENT identity shared with settlement.ts's hardened audit-artifact path. */
|
|
178
|
-
function isMissingPathError(error: unknown): boolean {
|
|
179
|
-
return (
|
|
180
|
-
error instanceof Error &&
|
|
181
|
-
"code" in error &&
|
|
182
|
-
(error as { code?: unknown }).code === "ENOENT"
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
179
|
/** Cycle- and bigint-safe JSON replacer so serialization itself cannot drop data. */
|
|
187
180
|
function jsonSafeReplacer(): (key: string, value: unknown) => unknown {
|
|
188
181
|
const seen = new WeakSet<object>();
|
|
@@ -210,7 +203,7 @@ function jsonSafeReplacer(): (key: string, value: unknown) => unknown {
|
|
|
210
203
|
* + O_NOFOLLOW where the platform provides it (a planted symlink is never
|
|
211
204
|
* followed) — mirrors settlement.ts's own hardened artifact writers.
|
|
212
205
|
*/
|
|
213
|
-
async function writeHardenedArtifactFile(
|
|
206
|
+
export async function writeHardenedArtifactFile(
|
|
214
207
|
artifactsDir: string,
|
|
215
208
|
namePrefix: string,
|
|
216
209
|
payload: Record<string, unknown>,
|
package/src/public-cli/cli.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { piDurablePrincipalAuthority } from "../pi/durable-principal.ts";
|
|
|
4
4
|
* Public ak-role CLI dispatcher (roles / config / layered help / Judge run).
|
|
5
5
|
*/
|
|
6
6
|
import { realpath } from "node:fs/promises";
|
|
7
|
-
import { join } from "node:path";
|
|
8
7
|
|
|
9
8
|
import { packageMachineHome } from "../activation-ledger-topology.ts";
|
|
10
9
|
import {
|
|
@@ -26,13 +25,13 @@ import {
|
|
|
26
25
|
missingResolvedSeatModelMessage,
|
|
27
26
|
parseModelSpec,
|
|
28
27
|
resolveEffectiveSeat,
|
|
29
|
-
resolvedSeatWithModel,
|
|
30
28
|
savePublicCliConfig,
|
|
31
29
|
setAutoResumeLimit,
|
|
32
30
|
setPersistentSeatConfig,
|
|
33
31
|
setPersistentSeatEngine,
|
|
34
32
|
setPersistentSeatEngineModel,
|
|
35
33
|
setPersistentSeatHost,
|
|
34
|
+
resolvePublicAgentDir,
|
|
36
35
|
validatePublicCliConfigAxes,
|
|
37
36
|
type CredentialProviders,
|
|
38
37
|
type EffectiveSeat,
|
|
@@ -41,7 +40,6 @@ import {
|
|
|
41
40
|
} from "./config.ts";
|
|
42
41
|
import {
|
|
43
42
|
loadHostProvidersTable,
|
|
44
|
-
projectHostFacingProvider,
|
|
45
43
|
renderHostProvidersTable,
|
|
46
44
|
} from "./host-providers.ts";
|
|
47
45
|
import { packagedModelParent } from "../packaged-role-registry.ts";
|
|
@@ -54,11 +52,10 @@ import {
|
|
|
54
52
|
type PostAdmissionEnv,
|
|
55
53
|
} from "./post-admission.ts";
|
|
56
54
|
import { appendPiSessionCustomEntry } from "../pi/role-turn-host.ts";
|
|
55
|
+
import { openRoleSeatRuntime } from "./role-seat-runtime.ts";
|
|
57
56
|
import {
|
|
58
|
-
composeRoleTurnHostAdapters,
|
|
59
57
|
formatHostSelectionFailure,
|
|
60
58
|
HostSelectionError,
|
|
61
|
-
selectRoleTurnHost,
|
|
62
59
|
type HostSelectionFailure,
|
|
63
60
|
type NamedRoleTurnHostAdapter,
|
|
64
61
|
} from "./role-turn-host-resolution.ts";
|
|
@@ -108,6 +105,8 @@ import {
|
|
|
108
105
|
} from "./settlement.ts";
|
|
109
106
|
import type { TerminalResult } from "./terminal.ts";
|
|
110
107
|
|
|
108
|
+
import { errorText } from "../unknown-value.ts";
|
|
109
|
+
|
|
111
110
|
export {
|
|
112
111
|
buildExplicitInternalActivationArgs,
|
|
113
112
|
resolveInternalRoleEntrypoint,
|
|
@@ -240,8 +239,6 @@ export type CliEnv = {
|
|
|
240
239
|
signal?: AbortSignal;
|
|
241
240
|
};
|
|
242
241
|
|
|
243
|
-
|
|
244
|
-
|
|
245
242
|
type RoleEnvironmentOptions = {
|
|
246
243
|
role: PublicCallableRole;
|
|
247
244
|
home: string;
|
|
@@ -258,54 +255,43 @@ function createRoleEnvironment(
|
|
|
258
255
|
/** #178: after host selection, before missing-model — structural argv parse once. */
|
|
259
256
|
afterHost?: () => void,
|
|
260
257
|
) {
|
|
261
|
-
const role = options.role;
|
|
262
258
|
const extraPiArgs = env.extraPiArgs;
|
|
263
259
|
const timeoutMs = env.timeoutMs;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const hostAdapters = composeRoleTurnHostAdapters(
|
|
267
|
-
{
|
|
260
|
+
const opened = openRoleSeatRuntime({
|
|
261
|
+
resolution: {
|
|
268
262
|
packageRoot: env.packageRoot,
|
|
269
263
|
...(env.roleTurnHost === undefined ? {} : { roleTurnHost: env.roleTurnHost }),
|
|
270
264
|
...(env.hostAdapters === undefined ? {} : { hostAdapters: env.hostAdapters }),
|
|
271
265
|
...(extraPiArgs === undefined ? {} : { extraPiArgs }),
|
|
272
266
|
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
273
267
|
},
|
|
274
|
-
env.principalAuthority!,
|
|
275
|
-
|
|
276
|
-
const roleTurnHost = selectRoleTurnHost(hostAdapters, {
|
|
277
|
-
role,
|
|
268
|
+
principalAuthority: env.principalAuthority!,
|
|
269
|
+
role: options.role,
|
|
278
270
|
seat: options.seat,
|
|
271
|
+
home: options.home,
|
|
272
|
+
...(afterHost === undefined ? {} : { afterHost }),
|
|
279
273
|
});
|
|
280
|
-
|
|
281
|
-
afterHost?.();
|
|
282
|
-
const seatWithModel = resolvedSeatWithModel(options.seat);
|
|
283
|
-
if (seatWithModel === undefined) {
|
|
274
|
+
if (!opened.ok) {
|
|
284
275
|
// Direct CLI has --model; dual remediation is intentional here (#178 / #916).
|
|
285
276
|
throw new CliUsageError(
|
|
286
277
|
missingResolvedSeatModelMessage(options.seat.seat, "invocation-or-config"),
|
|
287
278
|
);
|
|
288
279
|
}
|
|
289
|
-
const hostFacingSelection = projectHostFacingProvider(
|
|
290
|
-
seatWithModel.selection,
|
|
291
|
-
seatWithModel.host,
|
|
292
|
-
loadHostProvidersTable(options.home),
|
|
293
|
-
options.home,
|
|
294
|
-
);
|
|
295
280
|
return {
|
|
296
281
|
home: options.home,
|
|
297
282
|
principalAuthority: env.principalAuthority!,
|
|
298
283
|
agentDir: options.agentDir,
|
|
299
284
|
sessionAppender: appendPiSessionCustomEntry,
|
|
300
285
|
packageRoot: env.packageRoot,
|
|
301
|
-
roleTurnHost,
|
|
302
|
-
hostAdapters,
|
|
286
|
+
roleTurnHost: opened.roleTurnHost,
|
|
287
|
+
hostAdapters: opened.hostAdapters,
|
|
303
288
|
cwd: options.cwd,
|
|
304
289
|
...(options.credentials === undefined ? {} : { credentials: options.credentials }),
|
|
305
290
|
...(env.correlationId === undefined ? {} : { correlationId: env.correlationId }),
|
|
306
|
-
...(
|
|
307
|
-
...
|
|
308
|
-
...
|
|
291
|
+
...(opened.model === undefined ? {} : { model: opened.model }),
|
|
292
|
+
...(opened.engine === undefined ? {} : { engine: opened.engine }),
|
|
293
|
+
...(opened.engineModel === undefined ? {} : { engineModel: opened.engineModel }),
|
|
294
|
+
host: opened.host,
|
|
309
295
|
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
310
296
|
...(env.createRunId === undefined ? {} : { createRunId: env.createRunId }),
|
|
311
297
|
...(options.config?.autoResumeLimit === undefined
|
|
@@ -319,6 +305,25 @@ function createRoleEnvironment(
|
|
|
319
305
|
};
|
|
320
306
|
}
|
|
321
307
|
|
|
308
|
+
type PublicRoleDispatchParts = {
|
|
309
|
+
readonly agentDir: string;
|
|
310
|
+
readonly cwd: string;
|
|
311
|
+
readonly config: PublicCliConfig;
|
|
312
|
+
readonly credentials: CredentialProviders;
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
/** Shared preamble for a new public role command and an explicit resume. */
|
|
316
|
+
async function loadPublicRoleDispatchParts(
|
|
317
|
+
env: CliEnv,
|
|
318
|
+
home: string,
|
|
319
|
+
): Promise<PublicRoleDispatchParts> {
|
|
320
|
+
const agentDir = resolvePublicAgentDir(env.agentDir, home);
|
|
321
|
+
const cwd = env.cwd ?? process.cwd();
|
|
322
|
+
const config = await loadAndValidateConfig(home, env.packageRoot);
|
|
323
|
+
const credentials = env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
324
|
+
return { agentDir, cwd, config, credentials };
|
|
325
|
+
}
|
|
326
|
+
|
|
322
327
|
/**
|
|
323
328
|
* #178 single spine: resolve seat → host select → argv parse once → missing-model → run.
|
|
324
329
|
* Keeps host-unregistered ahead of bad argv and missing-model.
|
|
@@ -336,15 +341,11 @@ async function dispatchPublicRoleCommand<TParsed>(
|
|
|
336
341
|
parseOnce: () => TParsed,
|
|
337
342
|
) => Promise<{ exitCode: number; terminal?: TerminalResult }>,
|
|
338
343
|
): Promise<CliResult> {
|
|
339
|
-
const
|
|
340
|
-
const cwd = env.cwd ?? process.cwd();
|
|
341
|
-
const config = await loadAndValidateConfig(home, env.packageRoot);
|
|
342
|
-
const credentials =
|
|
343
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
344
|
+
const parts = await loadPublicRoleDispatchParts(env, home);
|
|
344
345
|
const seat = resolveEffectiveSeat(
|
|
345
|
-
config,
|
|
346
|
+
parts.config,
|
|
346
347
|
role,
|
|
347
|
-
credentials,
|
|
348
|
+
parts.credentials,
|
|
348
349
|
invocationFromParsed(parsed),
|
|
349
350
|
);
|
|
350
351
|
let parsedRoleArgv!: TParsed;
|
|
@@ -352,7 +353,15 @@ async function dispatchPublicRoleCommand<TParsed>(
|
|
|
352
353
|
parsed.args,
|
|
353
354
|
createRoleEnvironment(
|
|
354
355
|
env,
|
|
355
|
-
{
|
|
356
|
+
{
|
|
357
|
+
role,
|
|
358
|
+
home,
|
|
359
|
+
agentDir: parts.agentDir,
|
|
360
|
+
cwd: parts.cwd,
|
|
361
|
+
credentials: parts.credentials,
|
|
362
|
+
seat,
|
|
363
|
+
config: parts.config,
|
|
364
|
+
},
|
|
356
365
|
() => {
|
|
357
366
|
parsedRoleArgv = parse(parsed.args);
|
|
358
367
|
},
|
|
@@ -397,14 +406,6 @@ function resolveHome(env: CliEnv): string {
|
|
|
397
406
|
return env.home ?? packageMachineHome();
|
|
398
407
|
}
|
|
399
408
|
|
|
400
|
-
function resolveAgentDir(env: CliEnv, home: string): string {
|
|
401
|
-
return (
|
|
402
|
-
env.agentDir ??
|
|
403
|
-
process.env.PI_CODING_AGENT_DIR ??
|
|
404
|
-
join(home, ".pi", "agent")
|
|
405
|
-
);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
409
|
type ParsedGlobal = {
|
|
409
410
|
command?: string;
|
|
410
411
|
args: string[];
|
|
@@ -541,7 +542,7 @@ function requireLegalEngineModel(model: string): string {
|
|
|
541
542
|
return assertLegalEngineModel(model);
|
|
542
543
|
} catch (error) {
|
|
543
544
|
throw new CliUsageError(
|
|
544
|
-
|
|
545
|
+
errorText(error),
|
|
545
546
|
{ cause: error },
|
|
546
547
|
);
|
|
547
548
|
}
|
|
@@ -552,7 +553,7 @@ function requireLegalEngineName(name: string): string {
|
|
|
552
553
|
return assertLegalEngineName(name);
|
|
553
554
|
} catch (error) {
|
|
554
555
|
throw new CliUsageError(
|
|
555
|
-
|
|
556
|
+
errorText(error),
|
|
556
557
|
{ cause: error },
|
|
557
558
|
);
|
|
558
559
|
}
|
|
@@ -575,20 +576,6 @@ function requireCallableSeat(
|
|
|
575
576
|
}
|
|
576
577
|
}
|
|
577
578
|
|
|
578
|
-
/** Single seat engine axis → run-options projection (#391 E2 / #883). */
|
|
579
|
-
function projectSeatEngine(
|
|
580
|
-
seat: Readonly<{ engine?: string; engineModel?: string }>,
|
|
581
|
-
): { engine?: string; engineModel?: string } {
|
|
582
|
-
return pickEngineAxis(seat);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
/** Single seat.host → run-options projection (#595 / #617). */
|
|
586
|
-
function projectSeatHost(
|
|
587
|
-
seat: Readonly<{ host: string }>,
|
|
588
|
-
): { host: string } {
|
|
589
|
-
return { host: seat.host };
|
|
590
|
-
}
|
|
591
|
-
|
|
592
579
|
function loadAndValidateConfig(
|
|
593
580
|
home: string,
|
|
594
581
|
packageRoot: string,
|
|
@@ -598,7 +585,7 @@ function loadAndValidateConfig(
|
|
|
598
585
|
validatePublicCliConfigAxes(config, packageRoot);
|
|
599
586
|
} catch (error) {
|
|
600
587
|
throw new CliUsageError(
|
|
601
|
-
|
|
588
|
+
errorText(error),
|
|
602
589
|
{ cause: error },
|
|
603
590
|
);
|
|
604
591
|
}
|
|
@@ -930,7 +917,7 @@ async function runConfigCommand(
|
|
|
930
917
|
try {
|
|
931
918
|
config = setPersistentSeatHost(config, seat, unset ? undefined : args[2]!);
|
|
932
919
|
} catch (error) {
|
|
933
|
-
throw new CliUsageError(
|
|
920
|
+
throw new CliUsageError(errorText(error), { cause: error });
|
|
934
921
|
}
|
|
935
922
|
await savePublicCliConfig(config, home);
|
|
936
923
|
io.stdout(renderConfig(config, home));
|
|
@@ -954,7 +941,7 @@ async function runConfigCommand(
|
|
|
954
941
|
config = setPersistentSeatEngine(config, seat, name, engineModel);
|
|
955
942
|
} catch (error) {
|
|
956
943
|
throw new CliUsageError(
|
|
957
|
-
|
|
944
|
+
errorText(error),
|
|
958
945
|
{ cause: error },
|
|
959
946
|
);
|
|
960
947
|
}
|
|
@@ -976,7 +963,7 @@ async function runConfigCommand(
|
|
|
976
963
|
config = setPersistentSeatEngine(config, seat, undefined);
|
|
977
964
|
} catch (error) {
|
|
978
965
|
throw new CliUsageError(
|
|
979
|
-
|
|
966
|
+
errorText(error),
|
|
980
967
|
{ cause: error },
|
|
981
968
|
);
|
|
982
969
|
}
|
|
@@ -1000,7 +987,7 @@ async function runConfigCommand(
|
|
|
1000
987
|
config = setPersistentSeatEngineModel(config, seat, model);
|
|
1001
988
|
} catch (error) {
|
|
1002
989
|
throw new CliUsageError(
|
|
1003
|
-
|
|
990
|
+
errorText(error),
|
|
1004
991
|
{ cause: error },
|
|
1005
992
|
);
|
|
1006
993
|
}
|
|
@@ -1022,7 +1009,7 @@ async function runConfigCommand(
|
|
|
1022
1009
|
config = setPersistentSeatEngineModel(config, seat, undefined);
|
|
1023
1010
|
} catch (error) {
|
|
1024
1011
|
throw new CliUsageError(
|
|
1025
|
-
|
|
1012
|
+
errorText(error),
|
|
1026
1013
|
{ cause: error },
|
|
1027
1014
|
);
|
|
1028
1015
|
}
|
|
@@ -1170,7 +1157,7 @@ export async function runAkRole(
|
|
|
1170
1157
|
const config = await loadAndValidateConfig(home, env.packageRoot);
|
|
1171
1158
|
const credentials =
|
|
1172
1159
|
env.credentials ??
|
|
1173
|
-
(await loadCredentialProviders(
|
|
1160
|
+
(await loadCredentialProviders(resolvePublicAgentDir(env.agentDir, home)));
|
|
1174
1161
|
const seats = effectiveSeatConfigurations(
|
|
1175
1162
|
config,
|
|
1176
1163
|
credentials,
|
|
@@ -1219,19 +1206,15 @@ export async function runAkRole(
|
|
|
1219
1206
|
runId: resumeRequest.runId,
|
|
1220
1207
|
authority: env.principalAuthority ?? piDurablePrincipalAuthority,
|
|
1221
1208
|
};
|
|
1222
|
-
const
|
|
1223
|
-
const cwd = env.cwd ?? process.cwd();
|
|
1224
|
-
const config = await loadAndValidateConfig(home, env.packageRoot);
|
|
1225
|
-
const credentials =
|
|
1226
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1209
|
+
const parts = await loadPublicRoleDispatchParts(env, home);
|
|
1227
1210
|
const resumeRole = await peekRoleRunRole(home, resumeRequest.runId);
|
|
1228
1211
|
// Missing durable role keeps the judge seat table. The resume entry
|
|
1229
1212
|
// itself is one function; it reads the stored run.
|
|
1230
1213
|
const seatRole = resumeRole ?? "judge";
|
|
1231
1214
|
const seat = resolveEffectiveSeat(
|
|
1232
|
-
config,
|
|
1215
|
+
parts.config,
|
|
1233
1216
|
seatRole,
|
|
1234
|
-
credentials,
|
|
1217
|
+
parts.credentials,
|
|
1235
1218
|
invocationFromParsed(parsed),
|
|
1236
1219
|
);
|
|
1237
1220
|
const result = await runPublicInstructionSeatResume(
|
|
@@ -1239,11 +1222,11 @@ export async function runAkRole(
|
|
|
1239
1222
|
createRoleEnvironment(env, {
|
|
1240
1223
|
role: seatRole,
|
|
1241
1224
|
home,
|
|
1242
|
-
agentDir,
|
|
1243
|
-
cwd,
|
|
1244
|
-
credentials,
|
|
1225
|
+
agentDir: parts.agentDir,
|
|
1226
|
+
cwd: parts.cwd,
|
|
1227
|
+
credentials: parts.credentials,
|
|
1245
1228
|
seat,
|
|
1246
|
-
config,
|
|
1229
|
+
config: parts.config,
|
|
1247
1230
|
}),
|
|
1248
1231
|
io,
|
|
1249
1232
|
);
|
|
@@ -1261,9 +1244,20 @@ export async function runAkRole(
|
|
|
1261
1244
|
};
|
|
1262
1245
|
const parentRole = await peekRoleRunRole(home, parentRunId);
|
|
1263
1246
|
if (parentRole === undefined) break;
|
|
1264
|
-
const parentSeat = resolveEffectiveSeat(
|
|
1247
|
+
const parentSeat = resolveEffectiveSeat(
|
|
1248
|
+
parts.config,
|
|
1249
|
+
parentRole,
|
|
1250
|
+
parts.credentials,
|
|
1251
|
+
invocationFromParsed(parsed),
|
|
1252
|
+
);
|
|
1265
1253
|
const parentEnv = createRoleEnvironment(env, {
|
|
1266
|
-
role: parentRole,
|
|
1254
|
+
role: parentRole,
|
|
1255
|
+
home,
|
|
1256
|
+
agentDir: parts.agentDir,
|
|
1257
|
+
cwd: parts.cwd,
|
|
1258
|
+
credentials: parts.credentials,
|
|
1259
|
+
seat: parentSeat,
|
|
1260
|
+
config: parts.config,
|
|
1267
1261
|
});
|
|
1268
1262
|
current = await continueParentAfterChild(parentRunId, current.admitted, parentEnv, io);
|
|
1269
1263
|
}
|
package/src/public-cli/config.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
type PublicConfigurableSeat,
|
|
28
28
|
type PublicThinkingLevel,
|
|
29
29
|
} from "./registry.ts";
|
|
30
|
+
import { isEnoent, isRecord } from "../unknown-value.ts";
|
|
30
31
|
|
|
31
32
|
/** Province officers that may carry a persistent model override (#453). Registry order. */
|
|
32
33
|
type ProvinceConfigRole = Extract<
|
|
@@ -134,13 +135,7 @@ export async function loadPublicCliConfig(
|
|
|
134
135
|
const raw = await readFile(path, "utf8");
|
|
135
136
|
return parsePublicCliConfig(JSON.parse(raw));
|
|
136
137
|
} catch (error) {
|
|
137
|
-
if (
|
|
138
|
-
error instanceof Error &&
|
|
139
|
-
"code" in error &&
|
|
140
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
141
|
-
) {
|
|
142
|
-
return { seats: {} };
|
|
143
|
-
}
|
|
138
|
+
if (isEnoent(error)) return { seats: {} };
|
|
144
139
|
throw error;
|
|
145
140
|
}
|
|
146
141
|
}
|
|
@@ -481,7 +476,7 @@ function serializePublicCliConfig(config: PublicCliConfig): {
|
|
|
481
476
|
}
|
|
482
477
|
|
|
483
478
|
function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
484
|
-
if (
|
|
479
|
+
if (!isRecord(value)) {
|
|
485
480
|
throw new Error("public CLI config must be an object");
|
|
486
481
|
}
|
|
487
482
|
const record = value as {
|
|
@@ -500,11 +495,7 @@ function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
|
500
495
|
// disk-shaped seats map and a memory-shaped bucket both survive.
|
|
501
496
|
const unknownSeats: Record<string, unknown> = {};
|
|
502
497
|
if (record.unknownSeats !== undefined) {
|
|
503
|
-
if (
|
|
504
|
-
record.unknownSeats === null ||
|
|
505
|
-
typeof record.unknownSeats !== "object" ||
|
|
506
|
-
Array.isArray(record.unknownSeats)
|
|
507
|
-
) {
|
|
498
|
+
if (!isRecord(record.unknownSeats)) {
|
|
508
499
|
throw new Error("public CLI config.unknownSeats must be an object");
|
|
509
500
|
}
|
|
510
501
|
Object.assign(unknownSeats, record.unknownSeats as Record<string, unknown>);
|
|
@@ -517,11 +508,7 @@ function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
|
517
508
|
if (record.seats === undefined) {
|
|
518
509
|
return withOpaque({});
|
|
519
510
|
}
|
|
520
|
-
if (
|
|
521
|
-
record.seats === null ||
|
|
522
|
-
typeof record.seats !== "object" ||
|
|
523
|
-
Array.isArray(record.seats)
|
|
524
|
-
) {
|
|
511
|
+
if (!isRecord(record.seats)) {
|
|
525
512
|
throw new Error("public CLI config.seats must be an object");
|
|
526
513
|
}
|
|
527
514
|
const seats: PublicCliConfig["seats"] = {};
|
|
@@ -542,7 +529,7 @@ function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
|
542
529
|
}
|
|
543
530
|
|
|
544
531
|
function parseSeatModelConfig(value: unknown, seat: string): PersistentSeatConfig {
|
|
545
|
-
if (
|
|
532
|
+
if (!isRecord(value)) {
|
|
546
533
|
throw new Error(`config seat ${seat} must be an object`);
|
|
547
534
|
}
|
|
548
535
|
const raw = value as Record<string, unknown>;
|
|
@@ -825,7 +812,7 @@ export function listRolesForDisplay(
|
|
|
825
812
|
export function credentialProvidersFromAuthData(
|
|
826
813
|
data: unknown,
|
|
827
814
|
): CredentialProviders {
|
|
828
|
-
if (
|
|
815
|
+
if (!isRecord(data)) {
|
|
829
816
|
return { "openai-codex": false, xai: false };
|
|
830
817
|
}
|
|
831
818
|
const record = data as Record<string, unknown>;
|
|
@@ -835,6 +822,14 @@ export function credentialProvidersFromAuthData(
|
|
|
835
822
|
};
|
|
836
823
|
}
|
|
837
824
|
|
|
825
|
+
/**
|
|
826
|
+
* Public entry agent directory: explicit value, else PI_CODING_AGENT_DIR,
|
|
827
|
+
* else `<home>/.pi/agent`. CLI and nested summons share this rule.
|
|
828
|
+
*/
|
|
829
|
+
export function resolvePublicAgentDir(explicit: string | undefined, home: string): string {
|
|
830
|
+
return explicit ?? process.env.PI_CODING_AGENT_DIR ?? join(home, ".pi", "agent");
|
|
831
|
+
}
|
|
832
|
+
|
|
838
833
|
export async function loadCredentialProviders(
|
|
839
834
|
agentDir: string,
|
|
840
835
|
): Promise<CredentialProviders> {
|
|
@@ -842,13 +837,7 @@ export async function loadCredentialProviders(
|
|
|
842
837
|
const raw = await readFile(join(agentDir, "auth.json"), "utf8");
|
|
843
838
|
return credentialProvidersFromAuthData(JSON.parse(raw));
|
|
844
839
|
} catch (error) {
|
|
845
|
-
if (
|
|
846
|
-
error instanceof Error &&
|
|
847
|
-
"code" in error &&
|
|
848
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
849
|
-
) {
|
|
850
|
-
return { "openai-codex": false, xai: false };
|
|
851
|
-
}
|
|
840
|
+
if (isEnoent(error)) return { "openai-codex": false, xai: false };
|
|
852
841
|
throw error;
|
|
853
842
|
}
|
|
854
843
|
}
|
|
@@ -9,6 +9,8 @@ import type { PostAdmissionEnv } from "./post-admission.ts";
|
|
|
9
9
|
import type { CliIo } from "./cli-io.ts";
|
|
10
10
|
import type { TerminalRoleOutcome } from "./terminal.ts";
|
|
11
11
|
|
|
12
|
+
import { isRecord } from "../unknown-value.ts";
|
|
13
|
+
|
|
12
14
|
export type CountersignRunEnv = PostAdmissionEnv & {
|
|
13
15
|
principalAuthority: DurablePrincipalAuthority;
|
|
14
16
|
createRunId?: () => string;
|
|
@@ -51,10 +53,6 @@ export type CourtDiaristInvocationResult = {
|
|
|
51
53
|
readonly failedWithoutEscalate?: { readonly diagnostic: string };
|
|
52
54
|
};
|
|
53
55
|
|
|
54
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
55
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
56
|
function isEscalatePayload(payload: unknown): boolean {
|
|
59
57
|
if (!isRecord(payload)) return false;
|
|
60
58
|
return (
|
|
@@ -12,6 +12,7 @@ import { readFileSync } from "node:fs";
|
|
|
12
12
|
import { join } from "node:path";
|
|
13
13
|
|
|
14
14
|
import type { SeatModelConfig } from "./config.ts";
|
|
15
|
+
import { isEnoent, isRecord } from "../unknown-value.ts";
|
|
15
16
|
|
|
16
17
|
/** host → seat-provider → host-facing provider. */
|
|
17
18
|
export type HostProvidersTable = Readonly<
|
|
@@ -31,25 +32,19 @@ export function hermesProviderModelsCachePath(home: string): string {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export function parseHostProvidersTable(value: unknown): HostProvidersTable {
|
|
34
|
-
if (
|
|
35
|
+
if (!isRecord(value)) {
|
|
35
36
|
throw new Error("host-providers.json must be an object");
|
|
36
37
|
}
|
|
37
38
|
const out: Record<string, Record<string, string>> = {};
|
|
38
|
-
for (const [host, byProvider] of Object.entries(value
|
|
39
|
+
for (const [host, byProvider] of Object.entries(value)) {
|
|
39
40
|
if (host.trim() === "") {
|
|
40
41
|
throw new Error("host-providers.json host key must be non-empty");
|
|
41
42
|
}
|
|
42
|
-
if (
|
|
43
|
-
byProvider === null ||
|
|
44
|
-
typeof byProvider !== "object" ||
|
|
45
|
-
Array.isArray(byProvider)
|
|
46
|
-
) {
|
|
43
|
+
if (!isRecord(byProvider)) {
|
|
47
44
|
throw new Error(`host-providers.json[${host}] must be an object`);
|
|
48
45
|
}
|
|
49
46
|
const providers: Record<string, string> = {};
|
|
50
|
-
for (const [seatProvider, hostProvider] of Object.entries(
|
|
51
|
-
byProvider as Record<string, unknown>,
|
|
52
|
-
)) {
|
|
47
|
+
for (const [seatProvider, hostProvider] of Object.entries(byProvider)) {
|
|
53
48
|
if (seatProvider.trim() === "") {
|
|
54
49
|
throw new Error(
|
|
55
50
|
`host-providers.json[${host}] seat-provider key must be non-empty`,
|
|
@@ -79,13 +74,7 @@ export function loadHostProvidersTable(home: string): HostProvidersTable {
|
|
|
79
74
|
const raw = readFileSync(path, "utf8");
|
|
80
75
|
return parseHostProvidersTable(JSON.parse(raw) as unknown);
|
|
81
76
|
} catch (error) {
|
|
82
|
-
if (
|
|
83
|
-
error instanceof Error &&
|
|
84
|
-
"code" in error &&
|
|
85
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
86
|
-
) {
|
|
87
|
-
return {};
|
|
88
|
-
}
|
|
77
|
+
if (isEnoent(error)) return {};
|
|
89
78
|
throw error;
|
|
90
79
|
}
|
|
91
80
|
}
|
|
@@ -115,24 +104,18 @@ export function listHermesProvidersForModel(
|
|
|
115
104
|
try {
|
|
116
105
|
text = readFileSync(path, "utf8");
|
|
117
106
|
} catch (error) {
|
|
118
|
-
if (
|
|
119
|
-
error instanceof Error &&
|
|
120
|
-
"code" in error &&
|
|
121
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
122
|
-
) {
|
|
123
|
-
return [];
|
|
124
|
-
}
|
|
107
|
+
if (isEnoent(error)) return [];
|
|
125
108
|
throw error;
|
|
126
109
|
}
|
|
127
110
|
const raw: unknown = JSON.parse(text);
|
|
128
|
-
if (
|
|
111
|
+
if (!isRecord(raw)) {
|
|
129
112
|
throw new Error(
|
|
130
113
|
`hermes provider_models_cache.json must be an object: ${path}`,
|
|
131
114
|
);
|
|
132
115
|
}
|
|
133
116
|
const found: string[] = [];
|
|
134
|
-
for (const [provider, entry] of Object.entries(raw
|
|
135
|
-
if (
|
|
117
|
+
for (const [provider, entry] of Object.entries(raw)) {
|
|
118
|
+
if (!isRecord(entry)) {
|
|
136
119
|
continue;
|
|
137
120
|
}
|
|
138
121
|
const models = (entry as { models?: unknown }).models;
|