@akagilnc/pi-workflow-roles 0.1.3262 → 0.1.3280
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 +8 -122
- package/README.zh-CN.md +9 -123
- package/dist/gatekeeper-role.js +22 -16
- package/dist/grok/production-host.js +745 -571
- package/dist/package-contracts/gatekeeper-output.js +71 -0
- package/dist/package-contracts/navigator-output.js +48 -0
- package/dist/package-contracts/terminating-tools.js +18 -2
- package/dist/packaged-role-registry.js +24 -0
- package/dist/public-cli/config.js +7 -21
- package/dist/public-cli/main.js +689 -365
- package/dist/public-cli/registry.js +2 -14
- package/dist/session-opening-materials.js +6 -11
- package/extensions/role-runtime.ts +3 -1
- package/package.json +1 -1
- package/resources/navigator-route-playbook.md +1 -1
- package/src/gatekeeper-role.ts +32 -17
- package/src/grok/production-host.ts +3 -1
- package/src/host-contracts.ts +3 -1
- package/src/navigator-role.ts +17 -0
- package/src/package-contracts/gatekeeper-output.ts +89 -0
- package/src/package-contracts/navigator-output.ts +59 -0
- package/src/package-contracts/terminating-tools.ts +24 -2
- package/src/packaged-role-registry.ts +25 -2
- package/src/pi/role-turn-host.ts +4 -0
- package/src/public-cli/cli.ts +37 -10
- package/src/public-cli/config.ts +6 -30
- package/src/public-cli/instruction-seat-run.ts +147 -0
- package/src/public-cli/invocation.ts +47 -3
- package/src/public-cli/option-definitions.ts +36 -3
- package/src/public-cli/registry.ts +3 -26
- package/src/public-cli/run-lifecycle.ts +8 -2
- package/src/public-cli/settlement.ts +115 -3
- package/src/public-cli/terminal.ts +3 -1
- package/src/role-runtime.ts +64 -1
- package/src/session-opening-materials.ts +6 -11
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public Gatekeeper (门下省) terminating receipt contracts (#639).
|
|
3
|
+
* Direct public seat shares the province decision shape: dispatch | pass.
|
|
4
|
+
* No usable result is infrastructure failure via public settlement, not a judgment status (#475).
|
|
5
|
+
*/
|
|
6
|
+
import { Type } from "typebox";
|
|
7
|
+
import { openToolObject } from "../open-tool-schema.js";
|
|
8
|
+
import { withInfrastructureFailureDeclaration } from "./terminating-infrastructure.js";
|
|
9
|
+
export const GATEKEEPER_OUTPUT_TOOL_NAME = "ak_gatekeeper_output";
|
|
10
|
+
export const GATEKEEPER_ACCEPTED_TEXT = "门下省决议已受理";
|
|
11
|
+
/** Same open decision shape the province uses inside audit sessions. */
|
|
12
|
+
export const gatekeeperDecisionSchema = openToolObject(Type.Object({
|
|
13
|
+
status: Type.Unknown({
|
|
14
|
+
description: "dispatch | pass — 形状指引,非 schema 闸",
|
|
15
|
+
}),
|
|
16
|
+
officer: Type.Unknown({
|
|
17
|
+
description: "status 为 dispatch 时为 inspector | notary",
|
|
18
|
+
}),
|
|
19
|
+
findings: Type.Unknown({
|
|
20
|
+
description: "status 为 pass 时可选 string[] findings",
|
|
21
|
+
}),
|
|
22
|
+
}));
|
|
23
|
+
export const gatekeeperOutputSchema = withInfrastructureFailureDeclaration(gatekeeperDecisionSchema);
|
|
24
|
+
function isRecord(value) {
|
|
25
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26
|
+
}
|
|
27
|
+
function asStringArray(value) {
|
|
28
|
+
if (!Array.isArray(value))
|
|
29
|
+
return [];
|
|
30
|
+
return value.filter((item) => typeof item === "string");
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Project one lawful explicit Gatekeeper decision (dispatch | pass).
|
|
34
|
+
* No throw on shape — ADR 0055 / 第 0 条: already-submitted params are retained as-is;
|
|
35
|
+
* public-terminal projects non-usable releases via typed failure cause.
|
|
36
|
+
*/
|
|
37
|
+
export function projectLawfulGatekeeperOutput(value) {
|
|
38
|
+
if (!isRecord(value))
|
|
39
|
+
return undefined;
|
|
40
|
+
if (value.status === "pass") {
|
|
41
|
+
return Array.isArray(value.findings)
|
|
42
|
+
? { status: "pass", findings: asStringArray(value.findings) }
|
|
43
|
+
: { status: "pass" };
|
|
44
|
+
}
|
|
45
|
+
if (value.status === "dispatch" &&
|
|
46
|
+
(value.officer === "inspector" || value.officer === "notary")) {
|
|
47
|
+
return { status: "dispatch", officer: value.officer };
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Settlement/recording path: only lawful recorded dispatch/pass.
|
|
53
|
+
* Does not gate role admission — callers must not use this to reject a submission.
|
|
54
|
+
*/
|
|
55
|
+
export function validateRecordedGatekeeperOutput(value) {
|
|
56
|
+
const projected = projectLawfulGatekeeperOutput(value);
|
|
57
|
+
if (projected === undefined) {
|
|
58
|
+
throw new Error("Gatekeeper output has no recognized execution discriminator");
|
|
59
|
+
}
|
|
60
|
+
return projected;
|
|
61
|
+
}
|
|
62
|
+
export function gatekeeperDecisiveFacts(output) {
|
|
63
|
+
const facts = { status: output.status };
|
|
64
|
+
if (output.status === "dispatch") {
|
|
65
|
+
facts.officer = output.officer;
|
|
66
|
+
}
|
|
67
|
+
else if (Array.isArray(output.findings)) {
|
|
68
|
+
facts.findingsCount = output.findings.length;
|
|
69
|
+
}
|
|
70
|
+
return facts;
|
|
71
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public Navigator (游奕使) terminating receipt contracts (#639).
|
|
3
|
+
* Direct public seat submits route advice with the same candidate shape the
|
|
4
|
+
* attendance prepare tool owns — one shape authority for navigator advice.
|
|
5
|
+
* No usable result is infrastructure failure via public settlement, not a judgment status (#475).
|
|
6
|
+
*/
|
|
7
|
+
import { Type } from "typebox";
|
|
8
|
+
import { openToolObject } from "../open-tool-schema.js";
|
|
9
|
+
import { withInfrastructureFailureDeclaration } from "./terminating-infrastructure.js";
|
|
10
|
+
export const NAVIGATOR_OUTPUT_TOOL_NAME = "ak_navigator_output";
|
|
11
|
+
export const NAVIGATOR_ACCEPTED_TEXT = "游奕使建议已受理";
|
|
12
|
+
export const navigatorOutputSchema = withInfrastructureFailureDeclaration(openToolObject(Type.Object({
|
|
13
|
+
status: Type.Unknown({
|
|
14
|
+
description: "advice — 形状指引,非 schema 闸",
|
|
15
|
+
}),
|
|
16
|
+
candidates: Type.Unknown({
|
|
17
|
+
description: "排好序的路线建议数组,元素含 next/phase/reason — 形状指引,非 schema 闸",
|
|
18
|
+
}),
|
|
19
|
+
})));
|
|
20
|
+
function isRecord(value) {
|
|
21
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Project one lawful explicit Navigator advice receipt: candidates array,
|
|
25
|
+
* each candidate a record. Broken ancillary fields are preserved as submitted —
|
|
26
|
+
* shape is not an admission gate (ADR 0055 / 第 0 条).
|
|
27
|
+
*/
|
|
28
|
+
export function projectLawfulNavigatorOutput(value) {
|
|
29
|
+
if (!isRecord(value) || !Array.isArray(value.candidates))
|
|
30
|
+
return undefined;
|
|
31
|
+
if (value.status !== "advice")
|
|
32
|
+
return undefined;
|
|
33
|
+
return { status: "advice", candidates: value.candidates.filter(isRecord) };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Settlement/recording path: only lawful recorded candidate arrays.
|
|
37
|
+
* Does not gate role admission — callers must not use this to reject a submission.
|
|
38
|
+
*/
|
|
39
|
+
export function validateRecordedNavigatorOutput(value) {
|
|
40
|
+
const projected = projectLawfulNavigatorOutput(value);
|
|
41
|
+
if (projected === undefined) {
|
|
42
|
+
throw new Error("Navigator output has no recognized execution discriminator");
|
|
43
|
+
}
|
|
44
|
+
return projected;
|
|
45
|
+
}
|
|
46
|
+
export function navigatorDecisiveFacts(output) {
|
|
47
|
+
return { status: "advice", candidates: output.candidates };
|
|
48
|
+
}
|
|
@@ -8,13 +8,15 @@ import { REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, projectReviewerInten
|
|
|
8
8
|
import { isAuditEscalationResult } from "../audit-escalation.js";
|
|
9
9
|
import { CorrectableSubmissionError } from "../submission-correctable-error.js";
|
|
10
10
|
import { DOCTOR_ACCEPTED_TEXT, DOCTOR_OUTPUT_TOOL_NAME, validateDoctorSubmissionShape, validateRecordedDoctorOutput } from "../doctor-contracts.js";
|
|
11
|
+
import { GATEKEEPER_ACCEPTED_TEXT, GATEKEEPER_OUTPUT_TOOL_NAME, validateRecordedGatekeeperOutput } from "./gatekeeper-output.js";
|
|
12
|
+
import { NAVIGATOR_ACCEPTED_TEXT, NAVIGATOR_OUTPUT_TOOL_NAME, validateRecordedNavigatorOutput } from "./navigator-output.js";
|
|
11
13
|
import { MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateMergerOutput } from "../merger-contracts.js";
|
|
12
14
|
import { NOTARY_ACCEPTED_TEXT, NOTARY_OUTPUT_TOOL_NAME, validateRecordedNotaryOutput } from "../notary-contracts.js";
|
|
13
15
|
import { COUNTERSIGN_ACCEPTED_TEXT, COUNTERSIGN_OUTPUT_TOOL_NAME, validateRecordedCountersignOutput } from "../countersign-contracts.js";
|
|
14
16
|
import { GLEANER_LEFT_ACCEPTED_TEXT, GLEANER_LEFT_OUTPUT_TOOL_NAME, validateRecordedGleanerLeftOutput } from "../gleaner-left-contracts.js";
|
|
15
17
|
import { INSPECTOR_ACCEPTED_TEXT, INSPECTOR_OUTPUT_TOOL_NAME, validateRecordedInspectorOutput } from "../inspector-contracts.js";
|
|
16
18
|
import { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, validateAcceptedWorkerDetails, } from "./worker-output.js";
|
|
17
|
-
export { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, COLLECTOR_ACCEPTED_TEXT, COLLECTOR_OUTPUT_TOOL, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, JUDGE_ACCEPTED_TEXT, JUDGE_OUTPUT_TOOL_NAME, REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateAcceptedCollectorReceipt, validateAcceptedJudgeDetails, projectReviewerIntentToReceipt, validateReviewerIntent, validateRuntimeReviewerReceipt, validateAcceptedWorkerDetails, validateDoctorSubmissionShape, validateRecordedDoctorOutput, validateMergerOutput, validateRecordedNotaryOutput, validateRecordedCountersignOutput, validateRecordedGleanerLeftOutput, validateRecordedInspectorOutput, };
|
|
19
|
+
export { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, COLLECTOR_ACCEPTED_TEXT, COLLECTOR_OUTPUT_TOOL, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, JUDGE_ACCEPTED_TEXT, JUDGE_OUTPUT_TOOL_NAME, REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateAcceptedCollectorReceipt, validateAcceptedJudgeDetails, projectReviewerIntentToReceipt, validateReviewerIntent, validateRuntimeReviewerReceipt, validateAcceptedWorkerDetails, validateDoctorSubmissionShape, validateRecordedDoctorOutput, validateMergerOutput, validateRecordedNotaryOutput, validateRecordedCountersignOutput, validateRecordedGleanerLeftOutput, validateRecordedInspectorOutput, validateRecordedGatekeeperOutput, validateRecordedNavigatorOutput, };
|
|
18
20
|
export const TERMINATING_TOOL_NAMES = [
|
|
19
21
|
CODER_OUTPUT_TOOL_NAME,
|
|
20
22
|
FIXER_OUTPUT_TOOL_NAME,
|
|
@@ -27,6 +29,8 @@ export const TERMINATING_TOOL_NAMES = [
|
|
|
27
29
|
COUNTERSIGN_OUTPUT_TOOL_NAME,
|
|
28
30
|
GLEANER_LEFT_OUTPUT_TOOL_NAME,
|
|
29
31
|
INSPECTOR_OUTPUT_TOOL_NAME,
|
|
32
|
+
GATEKEEPER_OUTPUT_TOOL_NAME,
|
|
33
|
+
NAVIGATOR_OUTPUT_TOOL_NAME,
|
|
30
34
|
];
|
|
31
35
|
export function isTerminatingToolName(name) {
|
|
32
36
|
return TERMINATING_TOOL_NAMES.includes(name);
|
|
@@ -55,6 +59,10 @@ export function acceptedTextFor(toolName) {
|
|
|
55
59
|
return GLEANER_LEFT_ACCEPTED_TEXT;
|
|
56
60
|
case INSPECTOR_OUTPUT_TOOL_NAME:
|
|
57
61
|
return INSPECTOR_ACCEPTED_TEXT;
|
|
62
|
+
case GATEKEEPER_OUTPUT_TOOL_NAME:
|
|
63
|
+
return GATEKEEPER_ACCEPTED_TEXT;
|
|
64
|
+
case NAVIGATOR_OUTPUT_TOOL_NAME:
|
|
65
|
+
return NAVIGATOR_ACCEPTED_TEXT;
|
|
58
66
|
}
|
|
59
67
|
}
|
|
60
68
|
export class AcceptedDetailsContractError extends CorrectableSubmissionError {
|
|
@@ -104,6 +112,8 @@ export function validateAcceptedDetails(toolName, details) {
|
|
|
104
112
|
[COUNTERSIGN_OUTPUT_TOOL_NAME]: ["converged", "continue", "escalate"],
|
|
105
113
|
[GLEANER_LEFT_OUTPUT_TOOL_NAME]: ["completed"],
|
|
106
114
|
[INSPECTOR_OUTPUT_TOOL_NAME]: ["pass", "bounce"],
|
|
115
|
+
[GATEKEEPER_OUTPUT_TOOL_NAME]: ["dispatch", "pass"],
|
|
116
|
+
[NAVIGATOR_OUTPUT_TOOL_NAME]: ["advice"],
|
|
107
117
|
};
|
|
108
118
|
const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
|
|
109
119
|
const baseDiscriminator = discriminator;
|
|
@@ -137,6 +147,10 @@ export function validateAcceptedDetails(toolName, details) {
|
|
|
137
147
|
return validateRecordedGleanerLeftOutput(details);
|
|
138
148
|
case INSPECTOR_OUTPUT_TOOL_NAME:
|
|
139
149
|
return validateRecordedInspectorOutput(details);
|
|
150
|
+
case GATEKEEPER_OUTPUT_TOOL_NAME:
|
|
151
|
+
return validateRecordedGatekeeperOutput(details);
|
|
152
|
+
case NAVIGATOR_OUTPUT_TOOL_NAME:
|
|
153
|
+
return validateRecordedNavigatorOutput(details);
|
|
140
154
|
}
|
|
141
155
|
}
|
|
142
156
|
catch (error) {
|
|
@@ -176,7 +190,9 @@ export function acceptedFacts(toolName, details) {
|
|
|
176
190
|
case DOCTOR_OUTPUT_TOOL_NAME:
|
|
177
191
|
case NOTARY_OUTPUT_TOOL_NAME:
|
|
178
192
|
case GLEANER_LEFT_OUTPUT_TOOL_NAME:
|
|
179
|
-
case INSPECTOR_OUTPUT_TOOL_NAME:
|
|
193
|
+
case INSPECTOR_OUTPUT_TOOL_NAME:
|
|
194
|
+
case GATEKEEPER_OUTPUT_TOOL_NAME:
|
|
195
|
+
case NAVIGATOR_OUTPUT_TOOL_NAME: return { status: details.status };
|
|
180
196
|
case JUDGE_OUTPUT_TOOL_NAME: return { status: details.judgeStatus };
|
|
181
197
|
case COUNTERSIGN_OUTPUT_TOOL_NAME: return { status: details.countersignStatus };
|
|
182
198
|
case MERGER_OUTPUT_TOOL_NAME: {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { COLLECTOR_OUTPUT_TOOL } from "./package-contracts/collector-output.js";
|
|
2
|
+
import { GATEKEEPER_OUTPUT_TOOL_NAME } from "./package-contracts/gatekeeper-output.js";
|
|
3
|
+
import { NAVIGATOR_OUTPUT_TOOL_NAME } from "./package-contracts/navigator-output.js";
|
|
2
4
|
import { JUDGE_OUTPUT_TOOL_NAME } from "./package-contracts/judge-output.js";
|
|
3
5
|
import { REVIEWER_OUTPUT_TOOL_NAME } from "./package-contracts/reviewer-output.js";
|
|
4
6
|
import { CODER_OUTPUT_TOOL_NAME, FIXER_OUTPUT_TOOL_NAME } from "./package-contracts/worker-output.js";
|
|
@@ -151,6 +153,28 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
151
153
|
phaseFlag: void 0,
|
|
152
154
|
activationStage: "load-and-install",
|
|
153
155
|
sessionMaterials: INSPECTOR_SESSION_MATERIALS
|
|
156
|
+
},
|
|
157
|
+
// #639: gatekeeper and navigator are roles like any other — public ak-role
|
|
158
|
+
// entries; automatic attendance (province dispatch, navigator sidecar) is
|
|
159
|
+
// unchanged and orthogonal to callability.
|
|
160
|
+
{
|
|
161
|
+
role: "gatekeeper",
|
|
162
|
+
phases: [null],
|
|
163
|
+
outputTool: GATEKEEPER_OUTPUT_TOOL_NAME,
|
|
164
|
+
inputFlag: void 0,
|
|
165
|
+
phaseFlag: void 0,
|
|
166
|
+
activationStage: "load-and-install",
|
|
167
|
+
// Province materials; officers reuse their own public records below.
|
|
168
|
+
sessionMaterials: ["CLAUDE.md", "souls/gatekeeper.md", "souls/quality-law.md", "souls/gate-output-guide.md"]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
role: "navigator",
|
|
172
|
+
phases: [null],
|
|
173
|
+
outputTool: NAVIGATOR_OUTPUT_TOOL_NAME,
|
|
174
|
+
inputFlag: void 0,
|
|
175
|
+
phaseFlag: void 0,
|
|
176
|
+
activationStage: "load-and-install",
|
|
177
|
+
sessionMaterials: ["CLAUDE.md", "souls/navigator.md"]
|
|
154
178
|
}
|
|
155
179
|
];
|
|
156
180
|
const ONE_SHOT_ROLES = [
|
|
@@ -5,7 +5,7 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
import { assertLegalEngineName } from "../package-resources/engine-material.js";
|
|
7
7
|
import { resolveConfiguredProvinceOfficer } from "../institutional-resolution.js";
|
|
8
|
-
import {
|
|
8
|
+
import { PUBLIC_CALLABLE_ROLES, PUBLIC_CONFIGURABLE_SEATS, isPublicCallableRole, isPublicConfigurableSeat, seatModelOnly, publicStartupCandidates, } from "./registry.js";
|
|
9
9
|
/** Province officers that may carry a persistent model override (#453). */
|
|
10
10
|
export const GATE_OFFICER_SEATS = [
|
|
11
11
|
"gatekeeper",
|
|
@@ -120,7 +120,7 @@ export function setPersistentSeatHost(config, seat, host) {
|
|
|
120
120
|
* First engine still requires an existing seat row (model, or residual axes).
|
|
121
121
|
* Clearing engine from an axis-only residual drops the empty row; clearing
|
|
122
122
|
* engine from a model+engine row leaves model-only. Seat type is PublicCallableRole
|
|
123
|
-
* (
|
|
123
|
+
* (same as PublicConfigurableSeat; navigator included since #639).
|
|
124
124
|
*/
|
|
125
125
|
export function setPersistentSeatEngine(config, seat, engine) {
|
|
126
126
|
const previous = config.seats[seat];
|
|
@@ -174,15 +174,12 @@ export function setAutoResumeLimit(config, limit) {
|
|
|
174
174
|
/**
|
|
175
175
|
* Config-parse seam: persistent call axes belong to PUBLIC_CALLABLE_ROLES;
|
|
176
176
|
* engine names need only path-safety syntax (no closed material catalog;
|
|
177
|
-
* #376 / #378 / #391 / ADR 0069).
|
|
178
|
-
*
|
|
177
|
+
* #376 / #378 / #391 / ADR 0069). Syntax authority = assertLegalEngineName
|
|
178
|
+
* (no injected duplicate).
|
|
179
179
|
*/
|
|
180
180
|
export function validatePublicCliConfigAxes(config, _packageRoot) {
|
|
181
181
|
for (const seat of Object.keys(config.seats)) {
|
|
182
182
|
const row = config.seats[seat];
|
|
183
|
-
if ((row?.engine !== undefined || row?.host !== undefined) && !isPublicCallableRole(seat)) {
|
|
184
|
-
throw new Error(`config seat ${seat} cannot persist call axes: no independent activation path; storing would be silently ineffective`);
|
|
185
|
-
}
|
|
186
183
|
if (row?.engine === undefined)
|
|
187
184
|
continue;
|
|
188
185
|
try {
|
|
@@ -429,13 +426,11 @@ function attachEngineAxis(seat, config, invocation) {
|
|
|
429
426
|
};
|
|
430
427
|
}
|
|
431
428
|
function resolveBaseSeat(config, seat, credentials) {
|
|
432
|
-
const automatic = isAutomaticConfigurableSeat(seat);
|
|
433
429
|
// #620: subordinate officers consume institutional-resolution authority result.
|
|
434
430
|
if (seat === "notary" || seat === "inspector") {
|
|
435
431
|
const resolved = resolveConfiguredProvinceOfficer(config, seat);
|
|
436
432
|
return {
|
|
437
433
|
seat,
|
|
438
|
-
automatic,
|
|
439
434
|
source: resolved.source,
|
|
440
435
|
...(resolved.selection === undefined ? {} : { selection: resolved.selection }),
|
|
441
436
|
engineSource: "unconfigured",
|
|
@@ -446,7 +441,6 @@ function resolveBaseSeat(config, seat, credentials) {
|
|
|
446
441
|
if (persistentModel !== undefined) {
|
|
447
442
|
return {
|
|
448
443
|
seat,
|
|
449
|
-
automatic,
|
|
450
444
|
source: "persistent",
|
|
451
445
|
selection: persistentModel,
|
|
452
446
|
engineSource: "unconfigured",
|
|
@@ -456,16 +450,14 @@ function resolveBaseSeat(config, seat, credentials) {
|
|
|
456
450
|
if (startup !== undefined) {
|
|
457
451
|
return {
|
|
458
452
|
seat,
|
|
459
|
-
automatic,
|
|
460
453
|
source: "startup",
|
|
461
454
|
selection: startup,
|
|
462
455
|
engineSource: "unconfigured",
|
|
463
456
|
};
|
|
464
457
|
}
|
|
465
|
-
return { seat,
|
|
458
|
+
return { seat, source: "unconfigured", engineSource: "unconfigured" };
|
|
466
459
|
}
|
|
467
460
|
export function resolveEffectiveSeat(config, seat, credentials, invocation) {
|
|
468
|
-
const automatic = isAutomaticConfigurableSeat(seat);
|
|
469
461
|
const hasModelInvocation = invocation !== undefined &&
|
|
470
462
|
(invocation.model !== undefined || invocation.thinking !== undefined);
|
|
471
463
|
let modelSeat;
|
|
@@ -478,7 +470,6 @@ export function resolveEffectiveSeat(config, seat, credentials, invocation) {
|
|
|
478
470
|
: `${invocation.model}:${invocation.thinking}`;
|
|
479
471
|
modelSeat = {
|
|
480
472
|
seat,
|
|
481
|
-
automatic,
|
|
482
473
|
source: "invocation",
|
|
483
474
|
selection: parseModelSpec(spec),
|
|
484
475
|
engineSource: "unconfigured",
|
|
@@ -489,7 +480,6 @@ export function resolveEffectiveSeat(config, seat, credentials, invocation) {
|
|
|
489
480
|
if (base.selection === undefined || invocation.thinking === undefined) {
|
|
490
481
|
modelSeat = {
|
|
491
482
|
seat,
|
|
492
|
-
automatic,
|
|
493
483
|
source: "unconfigured",
|
|
494
484
|
engineSource: "unconfigured",
|
|
495
485
|
};
|
|
@@ -497,7 +487,6 @@ export function resolveEffectiveSeat(config, seat, credentials, invocation) {
|
|
|
497
487
|
else {
|
|
498
488
|
modelSeat = {
|
|
499
489
|
seat,
|
|
500
|
-
automatic,
|
|
501
490
|
source: "invocation",
|
|
502
491
|
selection: { ...base.selection, thinking: invocation.thinking },
|
|
503
492
|
engineSource: "unconfigured",
|
|
@@ -509,12 +498,9 @@ export function resolveEffectiveSeat(config, seat, credentials, invocation) {
|
|
|
509
498
|
export function effectiveSeatConfigurations(config, credentials, invocation) {
|
|
510
499
|
return PUBLIC_CONFIGURABLE_SEATS.map((seat) => resolveEffectiveSeat(config, seat, credentials, invocation));
|
|
511
500
|
}
|
|
512
|
-
/** Callable roles
|
|
501
|
+
/** Callable roles in package order. */
|
|
513
502
|
export function listRolesForDisplay(config, credentials, invocation) {
|
|
514
|
-
|
|
515
|
-
const callable = PUBLIC_CALLABLE_ROLES.map((role) => all.find((entry) => entry.seat === role));
|
|
516
|
-
const automatic = AUTOMATIC_CONFIGURABLE_SEATS.map((seat) => all.find((entry) => entry.seat === seat));
|
|
517
|
-
return [...callable, ...automatic];
|
|
503
|
+
return effectiveSeatConfigurations(config, credentials, invocation);
|
|
518
504
|
}
|
|
519
505
|
/**
|
|
520
506
|
* Read configured credential presence from a Pi auth.json document.
|