@akagilnc/pi-workflow-roles 0.1.3412 → 0.1.3439
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/archivist-record-entry.js +21 -12
- package/dist/archivist-record-topology.js +20 -0
- package/dist/auditor-dossier-tool.js +67 -76
- package/dist/canonical-json.js +66 -69
- package/dist/compliance-transport.js +99 -86
- package/dist/countersign-contracts.js +23 -25
- package/dist/doctor-contracts.js +169 -145
- package/dist/engine-detour-tool.js +83 -87
- package/dist/engine-detour.js +148 -183
- package/dist/evidence-child-executor.js +10 -1
- package/dist/exact-utf8.js +11 -10
- package/dist/git-object-id.js +10 -5
- package/dist/gleaner-left-contracts.js +33 -35
- package/dist/grok/production-host.js +229 -118
- package/dist/inspector-contracts.js +28 -31
- package/dist/institutional-resolution.js +101 -104
- package/dist/ledger-session-read.js +241 -0
- package/dist/merger-contracts.js +66 -56
- package/dist/notary-contracts.js +91 -100
- package/dist/open-tool-schema.js +32 -31
- package/dist/package-contracts/collector-output.js +56 -43
- package/dist/package-contracts/fixer-output.js +52 -50
- package/dist/package-contracts/fixer-packet.js +67 -64
- package/dist/package-contracts/gatekeeper-output.js +48 -56
- package/dist/package-contracts/judge-output.js +23 -20
- package/dist/package-contracts/navigator-output.js +35 -40
- package/dist/package-contracts/reviewer-output.js +94 -110
- package/dist/package-contracts/terminating-infrastructure.js +62 -90
- package/dist/package-contracts/worker-output.js +30 -11
- package/dist/package-resources/engine-material.js +58 -94
- package/dist/public-cli/config.js +420 -484
- package/dist/public-cli/main.js +1219 -524
- package/dist/public-cli/registry.js +107 -114
- package/dist/receipt-delivery-policy.js +74 -76
- package/dist/session-opening-materials.js +44 -47
- package/dist/sha256.js +5 -3
- package/dist/sitian-appender.js +204 -210
- package/dist/sitian-contracts.js +15 -19
- package/dist/sitian-facade.js +5 -10
- package/dist/sitian-reader.js +37 -46
- package/dist/stream-idle-guard.js +63 -71
- package/dist/ticket-seat-memory.js +244 -0
- package/package.json +1 -1
- package/scripts/build-package.mjs +41 -0
- package/souls/audit-law.md +4 -0
- package/souls/countersign.md +1 -1
- package/souls/gleaner-left.md +1 -1
- package/souls/inspector.md +1 -1
- package/souls/notary.md +1 -1
- package/souls/reviewer.md +1 -1
- package/src/analyst-gate-cycles-read.ts +152 -83
- package/src/analyst-ledger.ts +170 -43
- package/src/archivist-record-entry.ts +32 -11
- package/src/archivist-record-topology.ts +39 -0
- package/src/evidence-child-executor.ts +14 -1
- package/src/grok/production-host.ts +44 -9
- package/src/host-contracts.ts +18 -0
- package/src/host-transition-prior-native.ts +8 -1
- package/src/ledger-session-read.ts +56 -0
- package/src/pi/durable-principal.ts +6 -0
- package/src/public-cli/inspector-run.ts +21 -10
- package/src/public-cli/invocation.ts +4 -20
- package/src/public-cli/notary-run.ts +21 -4
- package/src/public-cli/post-admission.ts +333 -42
- package/src/public-cli/settlement.ts +266 -81
- package/src/session-opening-materials.ts +4 -2
- package/src/ticket-seat-memory.ts +454 -0
|
@@ -1,532 +1,468 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Persistent and effective per-seat model/thinking configuration for ak-role.
|
|
3
|
-
*/
|
|
4
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
5
2
|
import { dirname, join } from "node:path";
|
|
6
3
|
import { assertLegalEngineName } from "../package-resources/engine-material.js";
|
|
7
4
|
import { resolveConfiguredProvinceOfficer } from "../institutional-resolution.js";
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
import {
|
|
6
|
+
PUBLIC_CALLABLE_ROLES,
|
|
7
|
+
PUBLIC_CONFIGURABLE_SEATS,
|
|
8
|
+
isPublicCallableRole,
|
|
9
|
+
isPublicConfigurableSeat,
|
|
10
|
+
seatModelOnly,
|
|
11
|
+
publicStartupCandidates
|
|
12
|
+
} from "./registry.js";
|
|
13
|
+
const GATE_OFFICER_SEATS = [
|
|
14
|
+
"gatekeeper",
|
|
15
|
+
"inspector",
|
|
16
|
+
"notary"
|
|
14
17
|
];
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
function isGateOfficerSeat(value) {
|
|
19
|
+
return GATE_OFFICER_SEATS.includes(value);
|
|
17
20
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const THINKING_LEVELS = /* @__PURE__ */ new Set([
|
|
22
|
+
"off",
|
|
23
|
+
"minimal",
|
|
24
|
+
"low",
|
|
25
|
+
"medium",
|
|
26
|
+
"high",
|
|
27
|
+
"xhigh",
|
|
28
|
+
"max"
|
|
26
29
|
]);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
function publicCliConfigPath(home) {
|
|
31
|
+
if (typeof home !== "string" || home.trim() === "") {
|
|
32
|
+
throw new Error("home must be explicitly provided");
|
|
33
|
+
}
|
|
34
|
+
return join(home, ".ak-roles", "public-cli.json");
|
|
32
35
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
throw error;
|
|
46
|
-
}
|
|
36
|
+
async function loadPublicCliConfig(home) {
|
|
37
|
+
const path = publicCliConfigPath(home);
|
|
38
|
+
try {
|
|
39
|
+
const raw = await readFile(path, "utf8");
|
|
40
|
+
return parsePublicCliConfig(JSON.parse(raw));
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
43
|
+
return { seats: {} };
|
|
44
|
+
}
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
async function savePublicCliConfig(config, home) {
|
|
49
|
+
const path = publicCliConfigPath(home);
|
|
50
|
+
await mkdir(dirname(path), { recursive: true });
|
|
51
|
+
const normalized = parsePublicCliConfig(config);
|
|
52
|
+
await writeFile(
|
|
53
|
+
path,
|
|
54
|
+
`${JSON.stringify(serializePublicCliConfig(normalized), null, 2)}
|
|
55
|
+
`,
|
|
56
|
+
"utf8"
|
|
57
|
+
);
|
|
55
58
|
}
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
function setPersistentSeatConfig(config, seat, selection) {
|
|
60
|
+
const previous = config.seats[seat];
|
|
61
|
+
return {
|
|
62
|
+
// Spread preserves sibling top-level keys such as autoResumeLimit (#422):
|
|
63
|
+
// a seat write must never silently drop them.
|
|
64
|
+
...config,
|
|
65
|
+
seats: {
|
|
66
|
+
...config.seats,
|
|
67
|
+
[seat]: {
|
|
68
|
+
...selection,
|
|
69
|
+
// Model rewrite preserves a previously configured engine axis.
|
|
70
|
+
...previous?.engine === void 0 ? {} : { engine: previous.engine },
|
|
71
|
+
...previous?.host === void 0 ? {} : { host: previous.host }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function clearPersistentSeatConfig(config, seat) {
|
|
77
|
+
const previous = config.seats[seat];
|
|
78
|
+
if (previous === void 0) return config;
|
|
79
|
+
if ((seat === "notary" || seat === "inspector") && (previous.engine !== void 0 || previous.host !== void 0)) {
|
|
58
80
|
return {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
...config,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
...(previous?.engine === undefined ? {} : { engine: previous.engine }),
|
|
68
|
-
...(previous?.host === undefined ? {} : { host: previous.host }),
|
|
69
|
-
},
|
|
70
|
-
},
|
|
81
|
+
...config,
|
|
82
|
+
seats: {
|
|
83
|
+
...config.seats,
|
|
84
|
+
[seat]: {
|
|
85
|
+
...previous.engine === void 0 ? {} : { engine: previous.engine },
|
|
86
|
+
...previous.host === void 0 ? {} : { host: previous.host }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
71
89
|
};
|
|
90
|
+
}
|
|
91
|
+
const { [seat]: _dropped, ...seats } = config.seats;
|
|
92
|
+
return { ...config, seats };
|
|
72
93
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
(previous.engine !== undefined || previous.host !== undefined)) {
|
|
88
|
-
return {
|
|
89
|
-
...config,
|
|
90
|
-
seats: {
|
|
91
|
-
...config.seats,
|
|
92
|
-
[seat]: {
|
|
93
|
-
...(previous.engine === undefined ? {} : { engine: previous.engine }),
|
|
94
|
-
...(previous.host === undefined ? {} : { host: previous.host }),
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
const { [seat]: _dropped, ...seats } = config.seats;
|
|
100
|
-
return { ...config, seats };
|
|
94
|
+
function setPersistentSeatHost(config, seat, host) {
|
|
95
|
+
const previous = config.seats[seat];
|
|
96
|
+
if (previous === void 0) {
|
|
97
|
+
throw new Error(`config seat ${seat} has no persistent model; set provider/model[:thinking] before host`);
|
|
98
|
+
}
|
|
99
|
+
if (host === void 0) {
|
|
100
|
+
const { host: _dropped, ...rest } = previous;
|
|
101
|
+
if (seatModelOnly(rest) === void 0 && rest.engine === void 0) {
|
|
102
|
+
const { [seat]: _row, ...seats } = config.seats;
|
|
103
|
+
return { ...config, seats };
|
|
104
|
+
}
|
|
105
|
+
return { ...config, seats: { ...config.seats, [seat]: rest } };
|
|
106
|
+
}
|
|
107
|
+
return { ...config, seats: { ...config.seats, [seat]: { ...previous, host } } };
|
|
101
108
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return { ...config, seats: { ...config.seats, [seat]: rest } };
|
|
109
|
+
function setPersistentSeatEngine(config, seat, engine) {
|
|
110
|
+
const previous = config.seats[seat];
|
|
111
|
+
if (previous === void 0) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`config seat ${seat} has no persistent model; set provider/model[:thinking] before engine`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
if (engine === void 0) {
|
|
117
|
+
const { engine: _dropped, ...modelOnly } = previous;
|
|
118
|
+
if (seatModelOnly(modelOnly) === void 0 && modelOnly.host === void 0) {
|
|
119
|
+
const { [seat]: _row, ...seats } = config.seats;
|
|
120
|
+
return { ...config, seats };
|
|
115
121
|
}
|
|
116
|
-
return { ...config, seats: { ...config.seats, [seat]: { ...previous, host } } };
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Set or clear persistent engine on a callable role seat (#356 / #378 / #391 / #453).
|
|
120
|
-
* First engine still requires an existing seat row (model, or residual axes).
|
|
121
|
-
* Clearing engine from an axis-only residual drops the empty row; clearing
|
|
122
|
-
* engine from a model+engine row leaves model-only. Seat type is PublicCallableRole
|
|
123
|
-
* (same as PublicConfigurableSeat; navigator included since #639).
|
|
124
|
-
*/
|
|
125
|
-
export function setPersistentSeatEngine(config, seat, engine) {
|
|
126
|
-
const previous = config.seats[seat];
|
|
127
|
-
if (previous === undefined) {
|
|
128
|
-
throw new Error(`config seat ${seat} has no persistent model; set provider/model[:thinking] before engine`);
|
|
129
|
-
}
|
|
130
|
-
if (engine === undefined) {
|
|
131
|
-
const { engine: _dropped, ...modelOnly } = previous;
|
|
132
|
-
// Drop the row only after the final independent axis is cleared.
|
|
133
|
-
if (seatModelOnly(modelOnly) === undefined && modelOnly.host === undefined) {
|
|
134
|
-
const { [seat]: _row, ...seats } = config.seats;
|
|
135
|
-
return { ...config, seats };
|
|
136
|
-
}
|
|
137
|
-
return {
|
|
138
|
-
...config,
|
|
139
|
-
seats: {
|
|
140
|
-
...config.seats,
|
|
141
|
-
[seat]: modelOnly,
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
// Engine-name path-safety syntax is owned solely by assertLegalEngineName
|
|
146
|
-
// (call-request + config-parse seams). Setter is pure seat mutation.
|
|
147
122
|
return {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
123
|
+
...config,
|
|
124
|
+
seats: {
|
|
125
|
+
...config.seats,
|
|
126
|
+
[seat]: modelOnly
|
|
127
|
+
}
|
|
153
128
|
};
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
...config,
|
|
132
|
+
seats: {
|
|
133
|
+
...config.seats,
|
|
134
|
+
[seat]: { ...previous, engine }
|
|
135
|
+
}
|
|
136
|
+
};
|
|
154
137
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
|
|
163
|
-
throw new Error(`auto-resume limit must be a non-negative integer, got ${JSON.stringify(value)}`);
|
|
164
|
-
}
|
|
165
|
-
return value;
|
|
138
|
+
function parseAutoResumeLimit(value) {
|
|
139
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`auto-resume limit must be a non-negative integer, got ${JSON.stringify(value)}`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
return value;
|
|
166
145
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
* preserves all sibling keys (seats included).
|
|
170
|
-
*/
|
|
171
|
-
export function setAutoResumeLimit(config, limit) {
|
|
172
|
-
return { ...config, autoResumeLimit: parseAutoResumeLimit(limit) };
|
|
146
|
+
function setAutoResumeLimit(config, limit) {
|
|
147
|
+
return { ...config, autoResumeLimit: parseAutoResumeLimit(limit) };
|
|
173
148
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
catch (error) {
|
|
189
|
-
throw new Error(`config seat ${seat} engine is illegal: ${row.engine}`, { cause: error });
|
|
190
|
-
}
|
|
191
|
-
}
|
|
149
|
+
function validatePublicCliConfigAxes(config, _packageRoot) {
|
|
150
|
+
for (const seat of Object.keys(config.seats)) {
|
|
151
|
+
const row = config.seats[seat];
|
|
152
|
+
if (row?.engine === void 0) continue;
|
|
153
|
+
try {
|
|
154
|
+
assertLegalEngineName(row.engine);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`config seat ${seat} engine is illegal: ${row.engine}`,
|
|
158
|
+
{ cause: error }
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
192
162
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
? { provider, model }
|
|
221
|
-
: { provider, model, thinking };
|
|
163
|
+
function parseModelSpec(spec, fallbackThinking) {
|
|
164
|
+
const trimmed = spec.trim();
|
|
165
|
+
if (!trimmed) {
|
|
166
|
+
throw new Error("model specification must be non-empty");
|
|
167
|
+
}
|
|
168
|
+
const thinkingSplit = trimmed.lastIndexOf(":");
|
|
169
|
+
let modelPart = trimmed;
|
|
170
|
+
let thinking = fallbackThinking;
|
|
171
|
+
if (thinkingSplit !== -1) {
|
|
172
|
+
const maybeThinking = trimmed.slice(thinkingSplit + 1);
|
|
173
|
+
if (!THINKING_LEVELS.has(maybeThinking)) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`model specification must be provider/model[:thinking], got ${spec}`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
thinking = maybeThinking;
|
|
179
|
+
modelPart = trimmed.slice(0, thinkingSplit);
|
|
180
|
+
}
|
|
181
|
+
const slash = modelPart.indexOf("/");
|
|
182
|
+
if (slash <= 0 || slash === modelPart.length - 1) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
`model specification must be provider/model[:thinking], got ${spec}`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
const provider = modelPart.slice(0, slash);
|
|
188
|
+
const model = modelPart.slice(slash + 1);
|
|
189
|
+
return thinking === void 0 ? { provider, model } : { provider, model, thinking };
|
|
222
190
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
191
|
+
function formatModelSpec(selection) {
|
|
192
|
+
const base = `${selection.provider}/${selection.model}`;
|
|
193
|
+
return selection.thinking === void 0 ? base : `${base}:${selection.thinking}`;
|
|
226
194
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
model.provider,
|
|
237
|
-
"--model",
|
|
238
|
-
model.model,
|
|
239
|
-
...(model.thinking === undefined ? [] : ["--thinking", model.thinking]),
|
|
240
|
-
];
|
|
195
|
+
function buildSeatModelCliArgs(model) {
|
|
196
|
+
if (model === void 0) return [];
|
|
197
|
+
return [
|
|
198
|
+
"--provider",
|
|
199
|
+
model.provider,
|
|
200
|
+
"--model",
|
|
201
|
+
model.model,
|
|
202
|
+
...model.thinking === void 0 ? [] : ["--thinking", model.thinking]
|
|
203
|
+
];
|
|
241
204
|
}
|
|
242
|
-
/**
|
|
243
|
-
* Disk document shape for public-cli.json. Unknown seat rows live under
|
|
244
|
-
* `seats` (not a parallel top-level key) so every build — old or new — sees
|
|
245
|
-
* one seats map.
|
|
246
|
-
*/
|
|
247
205
|
function serializePublicCliConfig(config) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
: { autoResumeLimit: config.autoResumeLimit }),
|
|
258
|
-
};
|
|
206
|
+
return {
|
|
207
|
+
// Known seats win on any key clash; by construction the two maps are
|
|
208
|
+
// disjoint after parse, but prefer owned rows if a caller stuffed both.
|
|
209
|
+
seats: {
|
|
210
|
+
...config.unknownSeats ?? {},
|
|
211
|
+
...config.seats
|
|
212
|
+
},
|
|
213
|
+
...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit }
|
|
214
|
+
};
|
|
259
215
|
}
|
|
260
216
|
function parsePublicCliConfig(value) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
// #592: shared machine-wide public-cli.json may hold seat rows a newer CLI
|
|
299
|
-
// wrote. Do not consume them (resolve/enum stay owned-seat only), but keep
|
|
300
|
-
// the raw value in the opaque bucket so save can put them back under seats.
|
|
301
|
-
// Unknown field-level keys on known seats keep their existing tolerance.
|
|
302
|
-
if (!isPublicConfigurableSeat(key)) {
|
|
303
|
-
unknownSeats[key] = raw;
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
seats[key] = parseSeatModelConfig(raw, key);
|
|
307
|
-
}
|
|
308
|
-
return withOpaque(seats);
|
|
217
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
218
|
+
throw new Error("public CLI config must be an object");
|
|
219
|
+
}
|
|
220
|
+
const record = value;
|
|
221
|
+
let autoResumeLimit;
|
|
222
|
+
if (record.autoResumeLimit !== void 0) {
|
|
223
|
+
autoResumeLimit = parseAutoResumeLimit(record.autoResumeLimit);
|
|
224
|
+
}
|
|
225
|
+
const unknownSeats = {};
|
|
226
|
+
if (record.unknownSeats !== void 0) {
|
|
227
|
+
if (record.unknownSeats === null || typeof record.unknownSeats !== "object" || Array.isArray(record.unknownSeats)) {
|
|
228
|
+
throw new Error("public CLI config.unknownSeats must be an object");
|
|
229
|
+
}
|
|
230
|
+
Object.assign(unknownSeats, record.unknownSeats);
|
|
231
|
+
}
|
|
232
|
+
const withOpaque = (seats2) => ({
|
|
233
|
+
seats: seats2,
|
|
234
|
+
...autoResumeLimit === void 0 ? {} : { autoResumeLimit },
|
|
235
|
+
...Object.keys(unknownSeats).length === 0 ? {} : { unknownSeats }
|
|
236
|
+
});
|
|
237
|
+
if (record.seats === void 0) {
|
|
238
|
+
return withOpaque({});
|
|
239
|
+
}
|
|
240
|
+
if (record.seats === null || typeof record.seats !== "object" || Array.isArray(record.seats)) {
|
|
241
|
+
throw new Error("public CLI config.seats must be an object");
|
|
242
|
+
}
|
|
243
|
+
const seats = {};
|
|
244
|
+
for (const [key, raw] of Object.entries(
|
|
245
|
+
record.seats
|
|
246
|
+
)) {
|
|
247
|
+
if (!isPublicConfigurableSeat(key)) {
|
|
248
|
+
unknownSeats[key] = raw;
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
seats[key] = parseSeatModelConfig(raw, key);
|
|
252
|
+
}
|
|
253
|
+
return withOpaque(seats);
|
|
309
254
|
}
|
|
310
255
|
function parseSeatModelConfig(value, seat) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
provider: raw.provider,
|
|
358
|
-
model: raw.model,
|
|
359
|
-
...(raw.thinking === undefined
|
|
360
|
-
? {}
|
|
361
|
-
: { thinking: raw.thinking }),
|
|
362
|
-
...(raw.engine === undefined ? {} : { engine: raw.engine }),
|
|
363
|
-
...(raw.host === undefined ? {} : { host: raw.host }),
|
|
364
|
-
};
|
|
365
|
-
return parsed;
|
|
256
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
257
|
+
throw new Error(`config seat ${seat} must be an object`);
|
|
258
|
+
}
|
|
259
|
+
const raw = value;
|
|
260
|
+
const hasProvider = raw.provider !== void 0;
|
|
261
|
+
const hasModel = raw.model !== void 0;
|
|
262
|
+
if (hasProvider !== hasModel) {
|
|
263
|
+
throw new Error(`config seat ${seat} requires both provider and model`);
|
|
264
|
+
}
|
|
265
|
+
if (raw.host !== void 0 && (typeof raw.host !== "string" || raw.host.trim() === "")) {
|
|
266
|
+
throw new Error(`config seat ${seat} host must be a non-empty string`);
|
|
267
|
+
}
|
|
268
|
+
if (raw.engine !== void 0 && typeof raw.engine !== "string") {
|
|
269
|
+
throw new Error(`config seat ${seat} engine must be a string`);
|
|
270
|
+
}
|
|
271
|
+
if (!hasProvider) {
|
|
272
|
+
if ((seat === "notary" || seat === "inspector") && (typeof raw.engine === "string" || typeof raw.host === "string")) {
|
|
273
|
+
if (raw.thinking !== void 0) {
|
|
274
|
+
throw new Error(`config seat ${seat} thinking requires provider/model`);
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
...raw.engine === void 0 ? {} : { engine: raw.engine },
|
|
278
|
+
...raw.host === void 0 ? {} : { host: raw.host }
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
throw new Error(`config seat ${seat} requires provider`);
|
|
282
|
+
}
|
|
283
|
+
if (typeof raw.provider !== "string" || raw.provider.trim() === "") {
|
|
284
|
+
throw new Error(`config seat ${seat} requires provider`);
|
|
285
|
+
}
|
|
286
|
+
if (typeof raw.model !== "string" || raw.model.trim() === "") {
|
|
287
|
+
throw new Error(`config seat ${seat} requires model`);
|
|
288
|
+
}
|
|
289
|
+
if (raw.thinking !== void 0) {
|
|
290
|
+
if (typeof raw.thinking !== "string" || !THINKING_LEVELS.has(raw.thinking)) {
|
|
291
|
+
throw new Error(`config seat ${seat} requires a valid thinking level`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const parsed = {
|
|
295
|
+
provider: raw.provider,
|
|
296
|
+
model: raw.model,
|
|
297
|
+
...raw.thinking === void 0 ? {} : { thinking: raw.thinking },
|
|
298
|
+
...raw.engine === void 0 ? {} : { engine: raw.engine },
|
|
299
|
+
...raw.host === void 0 ? {} : { host: raw.host }
|
|
300
|
+
};
|
|
301
|
+
return parsed;
|
|
366
302
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
return credentials.xai === true;
|
|
372
|
-
return false;
|
|
303
|
+
function providerConfigured(credentials, provider) {
|
|
304
|
+
if (provider === "openai-codex") return credentials["openai-codex"] === true;
|
|
305
|
+
if (provider === "xai") return credentials.xai === true;
|
|
306
|
+
return false;
|
|
373
307
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
* Returns undefined for unknown/custom providers (not this package's credential map).
|
|
378
|
-
*/
|
|
379
|
-
export function missingPublicProviderCredential(provider, credentials) {
|
|
380
|
-
if (provider !== "openai-codex" && provider !== "xai")
|
|
381
|
-
return false;
|
|
382
|
-
return !providerConfigured(credentials, provider);
|
|
308
|
+
function missingPublicProviderCredential(provider, credentials) {
|
|
309
|
+
if (provider !== "openai-codex" && provider !== "xai") return false;
|
|
310
|
+
return !providerConfigured(credentials, provider);
|
|
383
311
|
}
|
|
384
312
|
function pickStartupCandidate(seat, credentials) {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
313
|
+
for (const candidate of publicStartupCandidates(seat)) {
|
|
314
|
+
if (providerConfigured(credentials, candidate.provider)) {
|
|
315
|
+
return { ...candidate };
|
|
389
316
|
}
|
|
390
|
-
|
|
317
|
+
}
|
|
318
|
+
return void 0;
|
|
391
319
|
}
|
|
392
320
|
function attachHostAxis(seat, config, invocation) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return { ...seat, host: persistent, hostSource: "persistent" };
|
|
398
|
-
return { ...seat, host: "pi", hostSource: "default" };
|
|
321
|
+
if (invocation?.host !== void 0) return { ...seat, host: invocation.host, hostSource: "invocation" };
|
|
322
|
+
const persistent = config.seats[seat.seat]?.host;
|
|
323
|
+
if (persistent !== void 0) return { ...seat, host: persistent, hostSource: "persistent" };
|
|
324
|
+
return { ...seat, host: "pi", hostSource: "default" };
|
|
399
325
|
}
|
|
400
326
|
function attachEngineAxis(seat, config, invocation) {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (persistentEngine !== undefined) {
|
|
417
|
-
return {
|
|
418
|
-
...seat,
|
|
419
|
-
engine: persistentEngine,
|
|
420
|
-
engineSource: "persistent",
|
|
421
|
-
};
|
|
422
|
-
}
|
|
327
|
+
if (!isPublicCallableRole(seat.seat)) {
|
|
328
|
+
return {
|
|
329
|
+
...seat,
|
|
330
|
+
engineSource: "unconfigured"
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
const persistentEngine = config.seats[seat.seat]?.engine;
|
|
334
|
+
if (invocation?.engine !== void 0) {
|
|
335
|
+
return {
|
|
336
|
+
...seat,
|
|
337
|
+
engine: invocation.engine,
|
|
338
|
+
engineSource: "invocation"
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
if (persistentEngine !== void 0) {
|
|
423
342
|
return {
|
|
424
|
-
|
|
425
|
-
|
|
343
|
+
...seat,
|
|
344
|
+
engine: persistentEngine,
|
|
345
|
+
engineSource: "persistent"
|
|
426
346
|
};
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
...seat,
|
|
350
|
+
engineSource: "unconfigured"
|
|
351
|
+
};
|
|
427
352
|
}
|
|
428
353
|
function resolveBaseSeat(config, seat, credentials) {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
}
|
|
458
|
-
return { seat, source: "unconfigured", engineSource: "unconfigured" };
|
|
354
|
+
if (seat === "notary" || seat === "inspector") {
|
|
355
|
+
const resolved = resolveConfiguredProvinceOfficer(config, seat);
|
|
356
|
+
return {
|
|
357
|
+
seat,
|
|
358
|
+
source: resolved.source,
|
|
359
|
+
...resolved.selection === void 0 ? {} : { selection: resolved.selection },
|
|
360
|
+
engineSource: "unconfigured"
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
const persistentModel = seatModelOnly(config.seats[seat]);
|
|
364
|
+
if (persistentModel !== void 0) {
|
|
365
|
+
return {
|
|
366
|
+
seat,
|
|
367
|
+
source: "persistent",
|
|
368
|
+
selection: persistentModel,
|
|
369
|
+
engineSource: "unconfigured"
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
const startup = pickStartupCandidate(seat, credentials);
|
|
373
|
+
if (startup !== void 0) {
|
|
374
|
+
return {
|
|
375
|
+
seat,
|
|
376
|
+
source: "startup",
|
|
377
|
+
selection: startup,
|
|
378
|
+
engineSource: "unconfigured"
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
return { seat, source: "unconfigured", engineSource: "unconfigured" };
|
|
459
382
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
selection: { ...base.selection, thinking: invocation.thinking },
|
|
492
|
-
engineSource: "unconfigured",
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
return attachHostAxis(attachEngineAxis(modelSeat, config, invocation), config, invocation);
|
|
383
|
+
function resolveEffectiveSeat(config, seat, credentials, invocation) {
|
|
384
|
+
const hasModelInvocation = invocation !== void 0 && (invocation.model !== void 0 || invocation.thinking !== void 0);
|
|
385
|
+
let modelSeat;
|
|
386
|
+
if (!hasModelInvocation || invocation === void 0) {
|
|
387
|
+
modelSeat = resolveBaseSeat(config, seat, credentials);
|
|
388
|
+
} else if (invocation.model !== void 0) {
|
|
389
|
+
const spec = invocation.model.includes(":") || invocation.thinking === void 0 ? invocation.model : `${invocation.model}:${invocation.thinking}`;
|
|
390
|
+
modelSeat = {
|
|
391
|
+
seat,
|
|
392
|
+
source: "invocation",
|
|
393
|
+
selection: parseModelSpec(spec),
|
|
394
|
+
engineSource: "unconfigured"
|
|
395
|
+
};
|
|
396
|
+
} else {
|
|
397
|
+
const base = resolveBaseSeat(config, seat, credentials);
|
|
398
|
+
if (base.selection === void 0 || invocation.thinking === void 0) {
|
|
399
|
+
modelSeat = {
|
|
400
|
+
seat,
|
|
401
|
+
source: "unconfigured",
|
|
402
|
+
engineSource: "unconfigured"
|
|
403
|
+
};
|
|
404
|
+
} else {
|
|
405
|
+
modelSeat = {
|
|
406
|
+
seat,
|
|
407
|
+
source: "invocation",
|
|
408
|
+
selection: { ...base.selection, thinking: invocation.thinking },
|
|
409
|
+
engineSource: "unconfigured"
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return attachHostAxis(attachEngineAxis(modelSeat, config, invocation), config, invocation);
|
|
497
414
|
}
|
|
498
|
-
|
|
499
|
-
|
|
415
|
+
function effectiveSeatConfigurations(config, credentials, invocation) {
|
|
416
|
+
return PUBLIC_CONFIGURABLE_SEATS.map(
|
|
417
|
+
(seat) => resolveEffectiveSeat(config, seat, credentials, invocation)
|
|
418
|
+
);
|
|
500
419
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
return effectiveSeatConfigurations(config, credentials, invocation);
|
|
420
|
+
function listRolesForDisplay(config, credentials, invocation) {
|
|
421
|
+
return effectiveSeatConfigurations(config, credentials, invocation);
|
|
504
422
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
return {
|
|
515
|
-
"openai-codex": Object.prototype.hasOwnProperty.call(record, "openai-codex"),
|
|
516
|
-
xai: Object.prototype.hasOwnProperty.call(record, "xai"),
|
|
517
|
-
};
|
|
423
|
+
function credentialProvidersFromAuthData(data) {
|
|
424
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
425
|
+
return { "openai-codex": false, xai: false };
|
|
426
|
+
}
|
|
427
|
+
const record = data;
|
|
428
|
+
return {
|
|
429
|
+
"openai-codex": Object.prototype.hasOwnProperty.call(record, "openai-codex"),
|
|
430
|
+
xai: Object.prototype.hasOwnProperty.call(record, "xai")
|
|
431
|
+
};
|
|
518
432
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
}
|
|
530
|
-
throw error;
|
|
531
|
-
}
|
|
433
|
+
async function loadCredentialProviders(agentDir) {
|
|
434
|
+
try {
|
|
435
|
+
const raw = await readFile(join(agentDir, "auth.json"), "utf8");
|
|
436
|
+
return credentialProvidersFromAuthData(JSON.parse(raw));
|
|
437
|
+
} catch (error) {
|
|
438
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
439
|
+
return { "openai-codex": false, xai: false };
|
|
440
|
+
}
|
|
441
|
+
throw error;
|
|
442
|
+
}
|
|
532
443
|
}
|
|
444
|
+
export {
|
|
445
|
+
GATE_OFFICER_SEATS,
|
|
446
|
+
THINKING_LEVELS,
|
|
447
|
+
buildSeatModelCliArgs,
|
|
448
|
+
clearPersistentSeatConfig,
|
|
449
|
+
credentialProvidersFromAuthData,
|
|
450
|
+
effectiveSeatConfigurations,
|
|
451
|
+
formatModelSpec,
|
|
452
|
+
isGateOfficerSeat,
|
|
453
|
+
listRolesForDisplay,
|
|
454
|
+
loadCredentialProviders,
|
|
455
|
+
loadPublicCliConfig,
|
|
456
|
+
missingPublicProviderCredential,
|
|
457
|
+
parseAutoResumeLimit,
|
|
458
|
+
parseModelSpec,
|
|
459
|
+
providerConfigured,
|
|
460
|
+
publicCliConfigPath,
|
|
461
|
+
resolveEffectiveSeat,
|
|
462
|
+
savePublicCliConfig,
|
|
463
|
+
setAutoResumeLimit,
|
|
464
|
+
setPersistentSeatConfig,
|
|
465
|
+
setPersistentSeatEngine,
|
|
466
|
+
setPersistentSeatHost,
|
|
467
|
+
validatePublicCliConfigAxes
|
|
468
|
+
};
|