@akagilnc/pi-workflow-roles 0.1.4243 → 0.1.4274
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 +27 -23
- package/README.zh-CN.md +24 -21
- package/dist/acp-host/production-host.js +4607 -3524
- package/dist/engine-detour-tool.js +64 -5
- package/dist/engine-detour-usage.js +285 -0
- package/dist/headless-host/production-host.js +6057 -4974
- package/dist/navigator-attendance.js +0 -2
- package/dist/navigator-public-session.js +2 -4
- package/dist/navigator-session-contracts.js +6 -13
- package/dist/pi/role-turn-host.js +10 -0
- package/dist/public-cli/config.js +16 -20
- package/dist/public-cli/main.js +935 -613
- package/dist/public-cli/post-admission.js +72 -43
- package/dist/public-cli/registry.js +0 -57
- package/dist/public-cli/settlement.js +80 -24
- package/dist/public-cli/turn-request.js +3 -0
- package/dist/public-role-summons.js +121 -96
- package/package.json +1 -1
- package/src/engine-detour-tool.ts +106 -8
- package/src/engine-detour-usage.ts +373 -0
- package/src/host-contracts.ts +12 -1
- package/src/navigator-attendance.ts +0 -2
- package/src/navigator-public-session.ts +3 -3
- package/src/navigator-session-contracts.ts +8 -14
- package/src/pi/adapter.ts +6 -0
- package/src/pi/role-turn-host.ts +6 -0
- package/src/public-cli/cli.ts +115 -307
- package/src/public-cli/config.ts +35 -23
- package/src/public-cli/post-admission.ts +91 -49
- package/src/public-cli/registry.ts +2 -66
- package/src/public-cli/settlement.ts +148 -23
- package/src/public-cli/turn-request.ts +5 -0
- package/src/public-role-summons.ts +197 -125
- package/src/role-envelope.ts +2 -0
package/src/public-cli/cli.ts
CHANGED
|
@@ -23,8 +23,10 @@ import {
|
|
|
23
23
|
isGateOfficerSeat,
|
|
24
24
|
loadCredentialProviders,
|
|
25
25
|
loadPublicCliConfig,
|
|
26
|
+
missingResolvedSeatModelMessage,
|
|
26
27
|
parseModelSpec,
|
|
27
28
|
resolveEffectiveSeat,
|
|
29
|
+
resolvedSeatWithModel,
|
|
28
30
|
savePublicCliConfig,
|
|
29
31
|
setAutoResumeLimit,
|
|
30
32
|
setPersistentSeatConfig,
|
|
@@ -316,6 +318,8 @@ type RoleEnvironmentOptions = {
|
|
|
316
318
|
function createRoleEnvironment(
|
|
317
319
|
env: CliEnv,
|
|
318
320
|
options: RoleEnvironmentOptions,
|
|
321
|
+
/** #178: after host selection, before missing-model — structural argv parse once. */
|
|
322
|
+
afterHost?: () => void,
|
|
319
323
|
) {
|
|
320
324
|
const role = options.role;
|
|
321
325
|
const extraPiArgs =
|
|
@@ -355,13 +359,7 @@ function createRoleEnvironment(
|
|
|
355
359
|
? env.notaryTimeoutMs
|
|
356
360
|
: undefined;
|
|
357
361
|
|
|
358
|
-
// #617
|
|
359
|
-
// come from the live seat table (invocation flag → persistent → default).
|
|
360
|
-
// #788 expectation 2: select a registered host first; only then project the
|
|
361
|
-
// host-facing provider (table > unique directory > fail). Bad host never
|
|
362
|
-
// reaches model resolution.
|
|
363
|
-
// Nested summons reuse this table and select by the child seat — never the
|
|
364
|
-
// already-selected parent adapter (#840 / ADR 0082: --host 旗标>席位配置>缺省 pi).
|
|
362
|
+
// #617/#178/#788/#840: host first, then model; nested child seat selects own host.
|
|
365
363
|
const hostAdapters = composeRoleTurnHostAdapters(
|
|
366
364
|
{
|
|
367
365
|
packageRoot: env.packageRoot,
|
|
@@ -376,15 +374,21 @@ function createRoleEnvironment(
|
|
|
376
374
|
role,
|
|
377
375
|
seat: options.seat,
|
|
378
376
|
});
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
377
|
+
// #178: host → argv (afterHost) → missing-model → provider projection.
|
|
378
|
+
afterHost?.();
|
|
379
|
+
const seatWithModel = resolvedSeatWithModel(options.seat);
|
|
380
|
+
if (seatWithModel === undefined) {
|
|
381
|
+
// Direct CLI has --model; dual remediation is intentional here (#178 / #916).
|
|
382
|
+
throw new CliUsageError(
|
|
383
|
+
missingResolvedSeatModelMessage(options.seat.seat, "invocation-or-config"),
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
const hostFacingSelection = projectHostFacingProvider(
|
|
387
|
+
seatWithModel.selection,
|
|
388
|
+
seatWithModel.host,
|
|
389
|
+
loadHostProvidersTable(options.home),
|
|
390
|
+
options.home,
|
|
391
|
+
);
|
|
388
392
|
return {
|
|
389
393
|
home: options.home,
|
|
390
394
|
principalAuthority: env.principalAuthority!,
|
|
@@ -408,6 +412,52 @@ function createRoleEnvironment(
|
|
|
408
412
|
};
|
|
409
413
|
}
|
|
410
414
|
|
|
415
|
+
/**
|
|
416
|
+
* #178 single spine: resolve seat → host select → argv parse once → missing-model → run.
|
|
417
|
+
* Keeps host-unregistered ahead of bad argv and missing-model.
|
|
418
|
+
*/
|
|
419
|
+
async function dispatchPublicRoleCommand<TParsed>(
|
|
420
|
+
env: CliEnv,
|
|
421
|
+
home: string,
|
|
422
|
+
io: CliIo,
|
|
423
|
+
parsed: ParsedGlobal,
|
|
424
|
+
role: PublicCallableRole,
|
|
425
|
+
parse: (args: readonly string[]) => TParsed,
|
|
426
|
+
run: (
|
|
427
|
+
args: readonly string[],
|
|
428
|
+
roleEnv: ReturnType<typeof createRoleEnvironment>,
|
|
429
|
+
parseOnce: () => TParsed,
|
|
430
|
+
) => Promise<{ exitCode: number; terminal?: TerminalResult }>,
|
|
431
|
+
): Promise<CliResult> {
|
|
432
|
+
const agentDir = resolveAgentDir(env, home);
|
|
433
|
+
const cwd = env.cwd ?? process.cwd();
|
|
434
|
+
const config = await loadAndValidateConfig(home, env.packageRoot);
|
|
435
|
+
const credentials =
|
|
436
|
+
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
437
|
+
const seat = resolveEffectiveSeat(
|
|
438
|
+
config,
|
|
439
|
+
role,
|
|
440
|
+
credentials,
|
|
441
|
+
invocationFromParsed(parsed),
|
|
442
|
+
);
|
|
443
|
+
let parsedRoleArgv!: TParsed;
|
|
444
|
+
const result = await run(
|
|
445
|
+
parsed.args,
|
|
446
|
+
createRoleEnvironment(
|
|
447
|
+
env,
|
|
448
|
+
{ role, home, agentDir, cwd, credentials, seat, config },
|
|
449
|
+
() => {
|
|
450
|
+
parsedRoleArgv = parse(parsed.args);
|
|
451
|
+
},
|
|
452
|
+
),
|
|
453
|
+
() => parsedRoleArgv,
|
|
454
|
+
);
|
|
455
|
+
return {
|
|
456
|
+
exitCode: result.exitCode,
|
|
457
|
+
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
411
461
|
export type CliResult = {
|
|
412
462
|
exitCode: number;
|
|
413
463
|
/** Settled Terminal when an admitted Role run produced one (programmatic/tests). */
|
|
@@ -744,6 +794,7 @@ function renderHelp(): string {
|
|
|
744
794
|
"Persistent engine (callable roles): ak-role config set-engine <seat> <name> [model] | unset-engine <seat> | set-engine-model <seat> <model> | unset-engine-model <seat>",
|
|
745
795
|
"Persistent host (callable roles): ak-role config set-host <seat> <name> | unset-host <seat>",
|
|
746
796
|
"Host providers: ~/.ak-roles/host-providers.json (owner-edited; table > unique host directory > fail)",
|
|
797
|
+
"Model resolution: --model → persistent seat → officer inherit (#620); still none → error (#178)",
|
|
747
798
|
"Host resolution: --host → persistent seat host → pi (resume uses the same order; #617)",
|
|
748
799
|
"Resume flag position: --model/--thinking/--host/--engine go before <runId> (before `resume` or between `resume` and <runId>); the one argv after <runId> is always the opaque message, never a flag (#471)",
|
|
749
800
|
"Effective seats: ak-role roles",
|
|
@@ -788,7 +839,7 @@ function renderRoles(seats: readonly EffectiveSeat[]): string {
|
|
|
788
839
|
|
|
789
840
|
/**
|
|
790
841
|
* #620 typed config display row. Non-subordinate seats stay on the persistent
|
|
791
|
-
* disk face; notary/inspector may surface inherit-gatekeeper
|
|
842
|
+
* disk face; notary/inspector may surface inherit-gatekeeper.
|
|
792
843
|
* Presentation formats these fields; tests assert the projection, not TSV.
|
|
793
844
|
* source reuses the institutional authority domain — no parallel union.
|
|
794
845
|
*/
|
|
@@ -814,8 +865,8 @@ function diskAxes(disk: PublicCliConfig["seats"][PublicConfigurableSeat]): {
|
|
|
814
865
|
|
|
815
866
|
/**
|
|
816
867
|
* Single-seat config projection (#620).
|
|
817
|
-
* - notary/inspector: institutional authority result (own > gatekeeper)
|
|
818
|
-
* - all other seats: disk model only (persistent face; no
|
|
868
|
+
* - notary/inspector: institutional authority result (own > gatekeeper)
|
|
869
|
+
* - all other seats: disk model only (persistent face; no package fill-in, #178)
|
|
819
870
|
*/
|
|
820
871
|
export function projectConfigSeatDisplay(
|
|
821
872
|
config: PublicCliConfig,
|
|
@@ -1240,9 +1291,10 @@ export async function runAkRole(
|
|
|
1240
1291
|
resumeRole === undefined
|
|
1241
1292
|
? RESUME_SEAT_DISPATCH.judge
|
|
1242
1293
|
: RESUME_SEAT_DISPATCH[resumeRole];
|
|
1243
|
-
// #617 DK-4: resume resolves model/host/engine from the live seat
|
|
1244
|
-
// exactly as a new leg would (flag → persistent →
|
|
1245
|
-
//
|
|
1294
|
+
// #617 DK-4 / #178: resume resolves model/host/engine from the live seat
|
|
1295
|
+
// table exactly as a new leg would (flag → persistent → officer inherit;
|
|
1296
|
+
// model still none → error). Cross-host resume delivers prior native
|
|
1297
|
+
// records as context to the target host.
|
|
1246
1298
|
const seat = resolveEffectiveSeat(
|
|
1247
1299
|
config,
|
|
1248
1300
|
dispatch.seat,
|
|
@@ -1272,333 +1324,89 @@ export async function runAkRole(
|
|
|
1272
1324
|
throw new CliUsageError(`unhandled support command: ${parsed.command}`);
|
|
1273
1325
|
}
|
|
1274
1326
|
|
|
1275
|
-
//
|
|
1327
|
+
// Public LLM role commands share one #178 spine (host → argv once → missing-model → run).
|
|
1276
1328
|
if (parsed.command === "judge") {
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
const credentials =
|
|
1281
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1282
|
-
const seat = resolveEffectiveSeat(
|
|
1283
|
-
config,
|
|
1284
|
-
"judge",
|
|
1285
|
-
credentials,
|
|
1286
|
-
invocationFromParsed(parsed),
|
|
1329
|
+
return await dispatchPublicRoleCommand(
|
|
1330
|
+
env, home, io, parsed, "judge", PUBLIC_ROLE_ARGV.judge.parse,
|
|
1331
|
+
(args, roleEnv, once) => runPublicJudge(args, roleEnv, io, once),
|
|
1287
1332
|
);
|
|
1288
|
-
const result = await runPublicJudge(
|
|
1289
|
-
parsed.args,
|
|
1290
|
-
createRoleEnvironment(env, { role: "judge", home, agentDir, cwd, credentials, seat, config }),
|
|
1291
|
-
io,
|
|
1292
|
-
PUBLIC_ROLE_ARGV.judge.parse,
|
|
1293
|
-
);
|
|
1294
|
-
return {
|
|
1295
|
-
exitCode: result.exitCode,
|
|
1296
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1297
|
-
};
|
|
1298
1333
|
}
|
|
1299
|
-
|
|
1300
|
-
// Countersign ticket-court run path (#572 / ADR 0074); #599 resume allowed.
|
|
1301
1334
|
if (parsed.command === "countersign") {
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
const credentials =
|
|
1306
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1307
|
-
const seat = resolveEffectiveSeat(
|
|
1308
|
-
config,
|
|
1309
|
-
"countersign",
|
|
1310
|
-
credentials,
|
|
1311
|
-
invocationFromParsed(parsed),
|
|
1335
|
+
return await dispatchPublicRoleCommand(
|
|
1336
|
+
env, home, io, parsed, "countersign", PUBLIC_ROLE_ARGV.countersign.parse,
|
|
1337
|
+
(args, roleEnv, once) => runPublicCountersign(args, roleEnv, io, once),
|
|
1312
1338
|
);
|
|
1313
|
-
const result = await runPublicCountersign(
|
|
1314
|
-
parsed.args,
|
|
1315
|
-
createRoleEnvironment(env, { role: "countersign", home, agentDir, cwd, credentials, seat, config }),
|
|
1316
|
-
io,
|
|
1317
|
-
PUBLIC_ROLE_ARGV.countersign.parse,
|
|
1318
|
-
);
|
|
1319
|
-
return {
|
|
1320
|
-
exitCode: result.exitCode,
|
|
1321
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1322
|
-
};
|
|
1323
1339
|
}
|
|
1324
|
-
|
|
1325
|
-
// Gleaner-Left pre-merge memorial run path (#502 / ADR 0067); #599 resume allowed.
|
|
1326
1340
|
if (parsed.command === "gleaner-left") {
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
const credentials =
|
|
1331
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1332
|
-
const seat = resolveEffectiveSeat(
|
|
1333
|
-
config,
|
|
1334
|
-
"gleaner-left",
|
|
1335
|
-
credentials,
|
|
1336
|
-
invocationFromParsed(parsed),
|
|
1337
|
-
);
|
|
1338
|
-
const result = await runPublicGleanerLeft(
|
|
1339
|
-
parsed.args,
|
|
1340
|
-
createRoleEnvironment(env, { role: "gleaner-left", home, agentDir, cwd, credentials, seat, config }),
|
|
1341
|
-
io,
|
|
1342
|
-
PUBLIC_ROLE_ARGV["gleaner-left"].parse,
|
|
1341
|
+
return await dispatchPublicRoleCommand(
|
|
1342
|
+
env, home, io, parsed, "gleaner-left", PUBLIC_ROLE_ARGV["gleaner-left"].parse,
|
|
1343
|
+
(args, roleEnv, once) => runPublicGleanerLeft(args, roleEnv, io, once),
|
|
1343
1344
|
);
|
|
1344
|
-
return {
|
|
1345
|
-
exitCode: result.exitCode,
|
|
1346
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1347
|
-
};
|
|
1348
1345
|
}
|
|
1349
|
-
|
|
1350
|
-
// Diarist public run path (#708): 起居郎 is summoned like any other seat.
|
|
1351
1346
|
if (parsed.command === "diarist") {
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
const credentials =
|
|
1356
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1357
|
-
const seat = resolveEffectiveSeat(
|
|
1358
|
-
config,
|
|
1359
|
-
"diarist",
|
|
1360
|
-
credentials,
|
|
1361
|
-
invocationFromParsed(parsed),
|
|
1347
|
+
return await dispatchPublicRoleCommand(
|
|
1348
|
+
env, home, io, parsed, "diarist", PUBLIC_ROLE_ARGV.diarist.parse,
|
|
1349
|
+
(args, roleEnv, once) => runPublicDiarist(args, roleEnv, io, once),
|
|
1362
1350
|
);
|
|
1363
|
-
const result = await runPublicDiarist(
|
|
1364
|
-
parsed.args,
|
|
1365
|
-
createRoleEnvironment(env, { role: "diarist", home, agentDir, cwd, credentials, seat, config }),
|
|
1366
|
-
io,
|
|
1367
|
-
PUBLIC_ROLE_ARGV.diarist.parse,
|
|
1368
|
-
);
|
|
1369
|
-
return {
|
|
1370
|
-
exitCode: result.exitCode,
|
|
1371
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1372
|
-
};
|
|
1373
1351
|
}
|
|
1374
|
-
|
|
1375
|
-
// Coder public run path with package-owned TDD method (#109).
|
|
1376
1352
|
if (parsed.command === "coder") {
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
const credentials =
|
|
1381
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1382
|
-
const seat = resolveEffectiveSeat(
|
|
1383
|
-
config,
|
|
1384
|
-
"coder",
|
|
1385
|
-
credentials,
|
|
1386
|
-
invocationFromParsed(parsed),
|
|
1387
|
-
);
|
|
1388
|
-
const result = await runPublicCoder(
|
|
1389
|
-
parsed.args,
|
|
1390
|
-
createRoleEnvironment(env, { role: "coder", home, agentDir, cwd, credentials, seat, config }),
|
|
1391
|
-
io,
|
|
1392
|
-
PUBLIC_ROLE_ARGV.coder.parse,
|
|
1353
|
+
return await dispatchPublicRoleCommand(
|
|
1354
|
+
env, home, io, parsed, "coder", PUBLIC_ROLE_ARGV.coder.parse,
|
|
1355
|
+
(args, roleEnv, once) => runPublicCoder(args, roleEnv, io, once),
|
|
1393
1356
|
);
|
|
1394
|
-
return {
|
|
1395
|
-
exitCode: result.exitCode,
|
|
1396
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1397
|
-
};
|
|
1398
1357
|
}
|
|
1399
|
-
|
|
1400
|
-
// Fixer public run path with optional package-owned diagnosing-bugs (#110).
|
|
1401
1358
|
if (parsed.command === "fixer") {
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
const credentials =
|
|
1406
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1407
|
-
const seat = resolveEffectiveSeat(
|
|
1408
|
-
config,
|
|
1409
|
-
"fixer",
|
|
1410
|
-
credentials,
|
|
1411
|
-
invocationFromParsed(parsed),
|
|
1412
|
-
);
|
|
1413
|
-
const result = await runPublicFixer(
|
|
1414
|
-
parsed.args,
|
|
1415
|
-
createRoleEnvironment(env, { role: "fixer", home, agentDir, cwd, credentials, seat, config }),
|
|
1416
|
-
io,
|
|
1417
|
-
PUBLIC_ROLE_ARGV.fixer.parse,
|
|
1359
|
+
return await dispatchPublicRoleCommand(
|
|
1360
|
+
env, home, io, parsed, "fixer", PUBLIC_ROLE_ARGV.fixer.parse,
|
|
1361
|
+
(args, roleEnv, once) => runPublicFixer(args, roleEnv, io, once),
|
|
1418
1362
|
);
|
|
1419
|
-
return {
|
|
1420
|
-
exitCode: result.exitCode,
|
|
1421
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1422
|
-
};
|
|
1423
1363
|
}
|
|
1424
|
-
|
|
1425
|
-
// Collector public run path from explicit PR + leg declarations (#112).
|
|
1426
1364
|
if (parsed.command === "collector") {
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
const credentials =
|
|
1431
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1432
|
-
const seat = resolveEffectiveSeat(
|
|
1433
|
-
config,
|
|
1434
|
-
"collector",
|
|
1435
|
-
credentials,
|
|
1436
|
-
invocationFromParsed(parsed),
|
|
1365
|
+
return await dispatchPublicRoleCommand(
|
|
1366
|
+
env, home, io, parsed, "collector", PUBLIC_ROLE_ARGV.collector.parse,
|
|
1367
|
+
(args, roleEnv, once) => runPublicCollector(args, roleEnv, io, once),
|
|
1437
1368
|
);
|
|
1438
|
-
const result = await runPublicCollector(
|
|
1439
|
-
parsed.args,
|
|
1440
|
-
createRoleEnvironment(env, { role: "collector", home, agentDir, cwd, credentials, seat, config }),
|
|
1441
|
-
io,
|
|
1442
|
-
PUBLIC_ROLE_ARGV.collector.parse,
|
|
1443
|
-
);
|
|
1444
|
-
return {
|
|
1445
|
-
exitCode: result.exitCode,
|
|
1446
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1447
|
-
};
|
|
1448
1369
|
}
|
|
1449
|
-
|
|
1450
|
-
// Reviewer public run path with package-owned adapted code-review (#111).
|
|
1451
1370
|
if (parsed.command === "reviewer") {
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
const credentials =
|
|
1456
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1457
|
-
const seat = resolveEffectiveSeat(
|
|
1458
|
-
config,
|
|
1459
|
-
"reviewer",
|
|
1460
|
-
credentials,
|
|
1461
|
-
invocationFromParsed(parsed),
|
|
1371
|
+
return await dispatchPublicRoleCommand(
|
|
1372
|
+
env, home, io, parsed, "reviewer", PUBLIC_ROLE_ARGV.reviewer.parse,
|
|
1373
|
+
(args, roleEnv, once) => runPublicReviewer(args, roleEnv, io, once),
|
|
1462
1374
|
);
|
|
1463
|
-
const result = await runPublicReviewer(
|
|
1464
|
-
parsed.args,
|
|
1465
|
-
createRoleEnvironment(env, { role: "reviewer", home, agentDir, cwd, credentials, seat, config }),
|
|
1466
|
-
io,
|
|
1467
|
-
PUBLIC_ROLE_ARGV.reviewer.parse,
|
|
1468
|
-
);
|
|
1469
|
-
return {
|
|
1470
|
-
exitCode: result.exitCode,
|
|
1471
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1472
|
-
};
|
|
1473
1375
|
}
|
|
1474
|
-
|
|
1475
|
-
// Doctor public run path from Issue identity + optional confined runs root (#113).
|
|
1476
1376
|
if (parsed.command === "doctor") {
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
const credentials =
|
|
1481
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1482
|
-
const seat = resolveEffectiveSeat(
|
|
1483
|
-
config,
|
|
1484
|
-
"doctor",
|
|
1485
|
-
credentials,
|
|
1486
|
-
invocationFromParsed(parsed),
|
|
1487
|
-
);
|
|
1488
|
-
const result = await runPublicDoctor(
|
|
1489
|
-
parsed.args,
|
|
1490
|
-
createRoleEnvironment(env, { role: "doctor", home, agentDir, cwd, credentials, seat, config }),
|
|
1491
|
-
io,
|
|
1492
|
-
PUBLIC_ROLE_ARGV.doctor.parse,
|
|
1377
|
+
return await dispatchPublicRoleCommand(
|
|
1378
|
+
env, home, io, parsed, "doctor", PUBLIC_ROLE_ARGV.doctor.parse,
|
|
1379
|
+
(args, roleEnv, once) => runPublicDoctor(args, roleEnv, io, once),
|
|
1493
1380
|
);
|
|
1494
|
-
return {
|
|
1495
|
-
exitCode: result.exitCode,
|
|
1496
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1497
|
-
};
|
|
1498
1381
|
}
|
|
1499
|
-
|
|
1500
|
-
// Notary public run path: source-run locator only, direct officer seat (#448).
|
|
1501
1382
|
if (parsed.command === "notary") {
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
const credentials =
|
|
1506
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1507
|
-
const seat = resolveEffectiveSeat(
|
|
1508
|
-
config,
|
|
1509
|
-
"notary",
|
|
1510
|
-
credentials,
|
|
1511
|
-
invocationFromParsed(parsed),
|
|
1383
|
+
return await dispatchPublicRoleCommand(
|
|
1384
|
+
env, home, io, parsed, "notary", PUBLIC_ROLE_ARGV.notary.parse,
|
|
1385
|
+
(args, roleEnv, once) => runPublicNotary(args, roleEnv, io, once),
|
|
1512
1386
|
);
|
|
1513
|
-
const result = await runPublicNotary(
|
|
1514
|
-
parsed.args,
|
|
1515
|
-
createRoleEnvironment(env, { role: "notary", home, agentDir, cwd, credentials, seat, config }),
|
|
1516
|
-
io,
|
|
1517
|
-
PUBLIC_ROLE_ARGV.notary.parse,
|
|
1518
|
-
);
|
|
1519
|
-
return {
|
|
1520
|
-
exitCode: result.exitCode,
|
|
1521
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1522
|
-
};
|
|
1523
1387
|
}
|
|
1524
|
-
|
|
1525
1388
|
if (parsed.command === "inspector") {
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
const credentials =
|
|
1530
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1531
|
-
const seat = resolveEffectiveSeat(
|
|
1532
|
-
config,
|
|
1533
|
-
"inspector",
|
|
1534
|
-
credentials,
|
|
1535
|
-
invocationFromParsed(parsed),
|
|
1536
|
-
);
|
|
1537
|
-
const result = await runPublicInspector(
|
|
1538
|
-
parsed.args,
|
|
1539
|
-
createRoleEnvironment(env, { role: "inspector", home, agentDir, cwd, credentials, seat, config }),
|
|
1540
|
-
io,
|
|
1541
|
-
PUBLIC_ROLE_ARGV.inspector.parse,
|
|
1389
|
+
return await dispatchPublicRoleCommand(
|
|
1390
|
+
env, home, io, parsed, "inspector", PUBLIC_ROLE_ARGV.inspector.parse,
|
|
1391
|
+
(args, roleEnv, once) => runPublicInspector(args, roleEnv, io, once),
|
|
1542
1392
|
);
|
|
1543
|
-
return {
|
|
1544
|
-
exitCode: result.exitCode,
|
|
1545
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1546
|
-
};
|
|
1547
1393
|
}
|
|
1548
|
-
|
|
1549
|
-
// Merger public run path: derive active-merge envelope + forced merge-only method (#114).
|
|
1550
1394
|
if (parsed.command === "merger") {
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
const credentials =
|
|
1555
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1556
|
-
const seat = resolveEffectiveSeat(
|
|
1557
|
-
config,
|
|
1558
|
-
"merger",
|
|
1559
|
-
credentials,
|
|
1560
|
-
invocationFromParsed(parsed),
|
|
1395
|
+
return await dispatchPublicRoleCommand(
|
|
1396
|
+
env, home, io, parsed, "merger", PUBLIC_ROLE_ARGV.merger.parse,
|
|
1397
|
+
(args, roleEnv, once) => runPublicMerger(args, roleEnv, io, once),
|
|
1561
1398
|
);
|
|
1562
|
-
const result = await runPublicMerger(
|
|
1563
|
-
parsed.args,
|
|
1564
|
-
createRoleEnvironment(env, { role: "merger", home, agentDir, cwd, credentials, seat, config }),
|
|
1565
|
-
io,
|
|
1566
|
-
PUBLIC_ROLE_ARGV.merger.parse,
|
|
1567
|
-
);
|
|
1568
|
-
return {
|
|
1569
|
-
exitCode: result.exitCode,
|
|
1570
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1571
|
-
};
|
|
1572
1399
|
}
|
|
1573
|
-
|
|
1574
|
-
// Instruction seats (#639 / #675): gatekeeper / navigator / auditor.
|
|
1575
1400
|
if (
|
|
1576
1401
|
parsed.command === "gatekeeper"
|
|
1577
1402
|
|| parsed.command === "navigator"
|
|
1578
1403
|
|| parsed.command === "auditor"
|
|
1579
1404
|
) {
|
|
1580
|
-
const
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1585
|
-
const seat = resolveEffectiveSeat(
|
|
1586
|
-
config,
|
|
1587
|
-
parsed.command,
|
|
1588
|
-
credentials,
|
|
1589
|
-
invocationFromParsed(parsed),
|
|
1590
|
-
);
|
|
1591
|
-
const result = await runPublicInstructionSeat(
|
|
1592
|
-
parsed.args,
|
|
1593
|
-
createRoleEnvironment(env, { role: parsed.command, home, agentDir, cwd, credentials, seat, config }),
|
|
1594
|
-
io,
|
|
1595
|
-
parsed.command,
|
|
1596
|
-
PUBLIC_ROLE_ARGV[parsed.command].parse,
|
|
1405
|
+
const seat = parsed.command;
|
|
1406
|
+
return await dispatchPublicRoleCommand(
|
|
1407
|
+
env, home, io, parsed, seat, PUBLIC_ROLE_ARGV[seat].parse,
|
|
1408
|
+
(args, roleEnv, once) => runPublicInstructionSeat(args, roleEnv, io, seat, once),
|
|
1597
1409
|
);
|
|
1598
|
-
return {
|
|
1599
|
-
exitCode: result.exitCode,
|
|
1600
|
-
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1601
|
-
};
|
|
1602
1410
|
}
|
|
1603
1411
|
|
|
1604
1412
|
// Analyst public run path: deterministic analysis seat (#336 issue / #337 sweep).
|
package/src/public-cli/config.ts
CHANGED
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
type PublicCallableRole,
|
|
22
22
|
type PublicConfigurableSeat,
|
|
23
23
|
type PublicThinkingLevel,
|
|
24
|
-
publicStartupCandidates,
|
|
25
24
|
} from "./registry.ts";
|
|
26
25
|
|
|
27
26
|
/** Province officers that may carry a persistent model override (#453). */
|
|
@@ -81,7 +80,6 @@ export type PublicCliConfig = {
|
|
|
81
80
|
|
|
82
81
|
export type EffectiveSource =
|
|
83
82
|
| "persistent"
|
|
84
|
-
| "startup"
|
|
85
83
|
| "invocation"
|
|
86
84
|
| "inherit-gatekeeper"
|
|
87
85
|
| "unconfigured";
|
|
@@ -625,16 +623,36 @@ export function missingPublicProviderCredential(
|
|
|
625
623
|
return !providerConfigured(credentials, provider);
|
|
626
624
|
}
|
|
627
625
|
|
|
628
|
-
|
|
626
|
+
/** Effective seat with model axis present (#178). */
|
|
627
|
+
export type EffectiveSeatWithModel = EffectiveSeat & {
|
|
628
|
+
selection: NonNullable<EffectiveSeat["selection"]>;
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
/** #178: narrow seat with model, or undefined — callers own presentation. */
|
|
632
|
+
export function resolvedSeatWithModel(
|
|
633
|
+
seat: EffectiveSeat,
|
|
634
|
+
): EffectiveSeatWithModel | undefined {
|
|
635
|
+
if (seat.selection === undefined) return undefined;
|
|
636
|
+
return seat as EffectiveSeatWithModel;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* #178 shared missing-model wording; throw site stays per entry.
|
|
641
|
+
* Recommend `--model` only when the entry actually has an invocation-model channel
|
|
642
|
+
* (direct public CLI). Nested summons / navigator seat reads do not — config set only.
|
|
643
|
+
*/
|
|
644
|
+
export function missingResolvedSeatModelMessage(
|
|
629
645
|
seat: PublicConfigurableSeat,
|
|
630
|
-
|
|
631
|
-
):
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
646
|
+
remediation: "config" | "invocation-or-config" = "config",
|
|
647
|
+
): string {
|
|
648
|
+
const configSet = `ak-role config set ${seat} <provider/model[:thinking]>`;
|
|
649
|
+
if (remediation === "invocation-or-config") {
|
|
650
|
+
return (
|
|
651
|
+
`seat ${seat} has no model configured; set with --model <provider/model[:thinking]>` +
|
|
652
|
+
` or ${configSet}`
|
|
653
|
+
);
|
|
636
654
|
}
|
|
637
|
-
return
|
|
655
|
+
return `seat ${seat} has no model configured; set with ${configSet}`;
|
|
638
656
|
}
|
|
639
657
|
|
|
640
658
|
type UnhostedEffectiveSeat = Omit<EffectiveSeat, "host" | "hostSource">;
|
|
@@ -695,7 +713,6 @@ function attachEngineAxis(
|
|
|
695
713
|
function resolveBaseSeat(
|
|
696
714
|
config: PublicCliConfig,
|
|
697
715
|
seat: PublicConfigurableSeat,
|
|
698
|
-
credentials: CredentialProviders,
|
|
699
716
|
): UnhostedEffectiveSeat {
|
|
700
717
|
// #620: subordinate officers consume institutional-resolution authority result.
|
|
701
718
|
if (seat === "notary" || seat === "inspector") {
|
|
@@ -708,6 +725,7 @@ function resolveBaseSeat(
|
|
|
708
725
|
};
|
|
709
726
|
}
|
|
710
727
|
// Engine-only residual is not a persistent model source (#453).
|
|
728
|
+
// #178: no package startup candidates — caller specifies via seat table or --model.
|
|
711
729
|
const persistentModel = seatModelOnly(config.seats[seat]);
|
|
712
730
|
if (persistentModel !== undefined) {
|
|
713
731
|
return {
|
|
@@ -717,15 +735,6 @@ function resolveBaseSeat(
|
|
|
717
735
|
engineSource: "unconfigured",
|
|
718
736
|
};
|
|
719
737
|
}
|
|
720
|
-
const startup = pickStartupCandidate(seat, credentials);
|
|
721
|
-
if (startup !== undefined) {
|
|
722
|
-
return {
|
|
723
|
-
seat,
|
|
724
|
-
source: "startup",
|
|
725
|
-
selection: startup,
|
|
726
|
-
engineSource: "unconfigured",
|
|
727
|
-
};
|
|
728
|
-
}
|
|
729
738
|
return { seat, source: "unconfigured", engineSource: "unconfigured" };
|
|
730
739
|
}
|
|
731
740
|
|
|
@@ -739,9 +748,12 @@ export function resolveEffectiveSeat(
|
|
|
739
748
|
invocation !== undefined &&
|
|
740
749
|
(invocation.model !== undefined || invocation.thinking !== undefined);
|
|
741
750
|
|
|
751
|
+
// credentials retained on the public resolve surface for call-site stability;
|
|
752
|
+
// model axis no longer consults them (#178 deleted package startup fallback).
|
|
753
|
+
void credentials;
|
|
742
754
|
let modelSeat: UnhostedEffectiveSeat;
|
|
743
755
|
if (!hasModelInvocation || invocation === undefined) {
|
|
744
|
-
modelSeat = resolveBaseSeat(config, seat
|
|
756
|
+
modelSeat = resolveBaseSeat(config, seat);
|
|
745
757
|
} else if (invocation.model !== undefined) {
|
|
746
758
|
const spec =
|
|
747
759
|
invocation.model.includes(":") || invocation.thinking === undefined
|
|
@@ -754,7 +766,7 @@ export function resolveEffectiveSeat(
|
|
|
754
766
|
engineSource: "unconfigured",
|
|
755
767
|
};
|
|
756
768
|
} else {
|
|
757
|
-
const base = resolveBaseSeat(config, seat
|
|
769
|
+
const base = resolveBaseSeat(config, seat);
|
|
758
770
|
if (base.selection === undefined || invocation.thinking === undefined) {
|
|
759
771
|
modelSeat = {
|
|
760
772
|
seat,
|
|
@@ -801,7 +813,7 @@ export function listRolesForDisplay(
|
|
|
801
813
|
|
|
802
814
|
/**
|
|
803
815
|
* Read configured credential presence from a Pi auth.json document.
|
|
804
|
-
*
|
|
816
|
+
* Presence drives the selected-provider fail-closed seam (public-run-credentials).
|
|
805
817
|
*/
|
|
806
818
|
export function credentialProvidersFromAuthData(
|
|
807
819
|
data: unknown,
|