@akagilnc/pi-workflow-roles 0.1.3712 → 0.1.3718
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 +4 -0
- package/README.zh-CN.md +4 -0
- package/dist/acp-host/production-host.js +111 -4
- package/dist/public-cli/config.js +106 -2
- package/dist/public-cli/main.js +156 -4
- package/dist/public-cli/option-definitions.js +3 -0
- package/package.json +1 -1
- package/souls/countersign.md +8 -11
- package/src/public-cli/cli.ts +54 -0
- package/src/public-cli/config.ts +157 -1
- package/src/public-cli/option-definitions.ts +3 -0
package/README.md
CHANGED
|
@@ -59,10 +59,14 @@ ak-role config unset-engine judge
|
|
|
59
59
|
ak-role config set-host judge grok-build
|
|
60
60
|
ak-role config unset-host judge
|
|
61
61
|
ak-role config set-auto-resume-limit 3
|
|
62
|
+
ak-role config set-provider-alias xai hermes xai-oauth
|
|
63
|
+
ak-role config unset-provider-alias xai hermes
|
|
62
64
|
```
|
|
63
65
|
|
|
64
66
|
**Host axis (invocation-insensible after default):** `--host` is a global public option on every callable role and on `resume`. Resolution is invocation `--host` → persistent seat host (`config set-host`) → package default (`pi`). After `config set-host <seat> <name>`, the same command face used with Pi runs that seat on the named host with zero extra flags and zero caller-side changes; bare `resume` follows the same table. All public callable roles and their institutional sub-legs (soul audit, doctor audit, navigator, reviewer evidence children) are host-neutral on the shared in-process institutional session seam.
|
|
65
67
|
|
|
68
|
+
**Provider host alias (#778):** seat rows keep one provider name; `config set-provider-alias <provider> <host> <alias>` registers an owner map so the same row hands the host the name it recognizes. Unregistered pairs pass the seat provider through unchanged — the package never invents pairs.
|
|
69
|
+
|
|
66
70
|
For Gate officers (`gatekeeper` / `inspector` / `notary`) resolution is officer pin → province (`gatekeeper`) pin → inherit parent session; an explicit selection that fails is loud and does not fall back. Configuration usage and refusal text are owned by `ak-role config` / `ak-role help config`. The persistent file is machine-wide and shared across CLI builds: seat keys this build does not know are skipped on read (not an error); unknown field-level keys on known seats keep their existing tolerance.
|
|
67
71
|
|
|
68
72
|
Receipts are typed, so callers compose roles without parsing prose; ordering and stopping stay caller-owned ([ADR 0010](docs/adr/0010-callers-own-role-composition-and-repetition.md)). Programmatic consumers derive contracts from the exported schemas in `src/package-contracts/`, not from this guide.
|
package/README.zh-CN.md
CHANGED
|
@@ -59,10 +59,14 @@ ak-role config unset-engine judge
|
|
|
59
59
|
ak-role config set-host judge grok-build
|
|
60
60
|
ak-role config unset-host judge
|
|
61
61
|
ak-role config set-auto-resume-limit 3
|
|
62
|
+
ak-role config set-provider-alias xai hermes xai-oauth
|
|
63
|
+
ak-role config unset-provider-alias xai hermes
|
|
62
64
|
```
|
|
63
65
|
|
|
64
66
|
**宿主轴(配置默认 host 后调用无感):** `--host` 为全局公开旗,全部可调用角色与 `resume` 受理。解析序为调用 `--host` → 席位持久 host(`config set-host`)→ 包默认(`pi`)。`config set-host <seat> <name>` 之后,与 Pi 完全相同的命令面即可在该席跑命名宿主——零额外旗、零调用侧改动;裸 `resume` 同序取表。全部 public callable 角色及其机构子腿(审刑审计、太医审计、游奕使、御史台证据子腿)在共享进程内机构子会话接缝上均为宿主中立。
|
|
65
67
|
|
|
68
|
+
**Provider 宿主别名(#778):** 席位行只写一份 provider 名;`config set-provider-alias <provider> <host> <alias>` 由 owner 在席位表登记映射,使同一行在指定宿主下交出该宿主认得的名。未登记的 (provider, host) 原样透传——包内不内置任何对照。
|
|
69
|
+
|
|
66
70
|
门下省官席解析顺序:官自钉 → 省钉(`gatekeeper`)→ 继承父 session;显式指定失败响亮、不回退。配置用法与拒绝文案以 `ak-role config`/`ak-role help config` 为准。持久配置是全机共享单文件、多 CLI 版本同读:本构建不认识的席位键读时跳过(不报错);已知席位上的未知字段沿用现行容忍。
|
|
67
71
|
|
|
68
72
|
回执是 typed 的,调用者不必解析散文即可组合角色;顺序与停止归调用者([ADR 0010](docs/adr/0010-callers-own-role-composition-and-repetition.md))。编程消费者从 `src/package-contracts/` 导出推导契约,不从本文。
|
|
@@ -6074,14 +6074,17 @@ var init_option_definitions = __esm({
|
|
|
6074
6074
|
"ak-role config unset-engine <seat>",
|
|
6075
6075
|
"ak-role config set-host <seat> <name>",
|
|
6076
6076
|
"ak-role config unset-host <seat>",
|
|
6077
|
-
"ak-role config set-auto-resume-limit <N>"
|
|
6077
|
+
"ak-role config set-auto-resume-limit <N>",
|
|
6078
|
+
"ak-role config set-provider-alias <provider> <host> <alias>",
|
|
6079
|
+
"ak-role config unset-provider-alias <provider> <host>"
|
|
6078
6080
|
],
|
|
6079
6081
|
examples: [
|
|
6080
6082
|
"ak-role config set judge openai-codex/gpt-5.6-sol:high",
|
|
6081
6083
|
"ak-role config unset gatekeeper",
|
|
6082
6084
|
"ak-role config set-engine judge opus",
|
|
6083
6085
|
"ak-role config set-host judge grok-build",
|
|
6084
|
-
"ak-role config set-auto-resume-limit 3"
|
|
6086
|
+
"ak-role config set-auto-resume-limit 3",
|
|
6087
|
+
"ak-role config set-provider-alias xai hermes xai-oauth"
|
|
6085
6088
|
]
|
|
6086
6089
|
},
|
|
6087
6090
|
help: {
|
|
@@ -8819,6 +8822,7 @@ var init_institutional_resolution = __esm({
|
|
|
8819
8822
|
var config_exports = {};
|
|
8820
8823
|
__export(config_exports, {
|
|
8821
8824
|
GATE_OFFICER_SEATS: () => GATE_OFFICER_SEATS,
|
|
8825
|
+
applyProviderHostAlias: () => applyProviderHostAlias,
|
|
8822
8826
|
buildSeatModelCliArgs: () => buildSeatModelCliArgs2,
|
|
8823
8827
|
clearPersistentSeatConfig: () => clearPersistentSeatConfig,
|
|
8824
8828
|
credentialProvidersFromAuthData: () => credentialProvidersFromAuthData,
|
|
@@ -8839,6 +8843,8 @@ __export(config_exports, {
|
|
|
8839
8843
|
setPersistentSeatConfig: () => setPersistentSeatConfig,
|
|
8840
8844
|
setPersistentSeatEngine: () => setPersistentSeatEngine,
|
|
8841
8845
|
setPersistentSeatHost: () => setPersistentSeatHost,
|
|
8846
|
+
setProviderHostAlias: () => setProviderHostAlias,
|
|
8847
|
+
unsetProviderHostAlias: () => unsetProviderHostAlias,
|
|
8842
8848
|
validatePublicCliConfigAxes: () => validatePublicCliConfigAxes
|
|
8843
8849
|
});
|
|
8844
8850
|
import { mkdir as mkdir2, readFile as readFile10, writeFile as writeFile5 } from "node:fs/promises";
|
|
@@ -8966,6 +8972,50 @@ function parseAutoResumeLimit(value) {
|
|
|
8966
8972
|
function setAutoResumeLimit(config, limit) {
|
|
8967
8973
|
return { ...config, autoResumeLimit: parseAutoResumeLimit(limit) };
|
|
8968
8974
|
}
|
|
8975
|
+
function requireNonEmptyToken(value, label) {
|
|
8976
|
+
const trimmed = value.trim();
|
|
8977
|
+
if (trimmed === "") {
|
|
8978
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
8979
|
+
}
|
|
8980
|
+
return trimmed;
|
|
8981
|
+
}
|
|
8982
|
+
function setProviderHostAlias(config, provider, host, alias) {
|
|
8983
|
+
const from = requireNonEmptyToken(provider, "provider");
|
|
8984
|
+
const hostName = requireNonEmptyToken(host, "host");
|
|
8985
|
+
const to = requireNonEmptyToken(alias, "alias");
|
|
8986
|
+
const previous = config.providerAliases ?? {};
|
|
8987
|
+
return {
|
|
8988
|
+
...config,
|
|
8989
|
+
providerAliases: {
|
|
8990
|
+
...previous,
|
|
8991
|
+
[from]: {
|
|
8992
|
+
...previous[from] ?? {},
|
|
8993
|
+
[hostName]: to
|
|
8994
|
+
}
|
|
8995
|
+
}
|
|
8996
|
+
};
|
|
8997
|
+
}
|
|
8998
|
+
function unsetProviderHostAlias(config, provider, host) {
|
|
8999
|
+
const from = requireNonEmptyToken(provider, "provider");
|
|
9000
|
+
const hostName = requireNonEmptyToken(host, "host");
|
|
9001
|
+
const previous = config.providerAliases;
|
|
9002
|
+
if (previous === void 0 || previous[from] === void 0) return config;
|
|
9003
|
+
const { [hostName]: _dropped, ...restHosts } = previous[from];
|
|
9004
|
+
const nextForProvider = Object.keys(restHosts).length === 0 ? void 0 : restHosts;
|
|
9005
|
+
const { [from]: _provider, ...restProviders } = previous;
|
|
9006
|
+
const nextAliases = nextForProvider === void 0 ? restProviders : { ...restProviders, [from]: nextForProvider };
|
|
9007
|
+
if (Object.keys(nextAliases).length === 0) {
|
|
9008
|
+
const { providerAliases: _gone, ...rest } = config;
|
|
9009
|
+
return rest;
|
|
9010
|
+
}
|
|
9011
|
+
return { ...config, providerAliases: nextAliases };
|
|
9012
|
+
}
|
|
9013
|
+
function applyProviderHostAlias(selection, host, aliases) {
|
|
9014
|
+
if (selection === void 0 || aliases === void 0) return selection;
|
|
9015
|
+
const mapped = aliases[selection.provider]?.[host];
|
|
9016
|
+
if (mapped === void 0) return selection;
|
|
9017
|
+
return { ...selection, provider: mapped };
|
|
9018
|
+
}
|
|
8969
9019
|
function validatePublicCliConfigAxes(config, _packageRoot) {
|
|
8970
9020
|
for (const seat of Object.keys(config.seats)) {
|
|
8971
9021
|
const row = config.seats[seat];
|
|
@@ -9035,9 +9085,44 @@ function serializePublicCliConfig(config) {
|
|
|
9035
9085
|
...config.unknownSeats ?? {},
|
|
9036
9086
|
...config.seats
|
|
9037
9087
|
},
|
|
9038
|
-
...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit }
|
|
9088
|
+
...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit },
|
|
9089
|
+
...config.providerAliases === void 0 || Object.keys(config.providerAliases).length === 0 ? {} : { providerAliases: config.providerAliases }
|
|
9039
9090
|
};
|
|
9040
9091
|
}
|
|
9092
|
+
function parseProviderHostAliases(value) {
|
|
9093
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
9094
|
+
throw new Error("public CLI config.providerAliases must be an object");
|
|
9095
|
+
}
|
|
9096
|
+
const out = {};
|
|
9097
|
+
for (const [provider, byHost] of Object.entries(value)) {
|
|
9098
|
+
if (provider.trim() === "") {
|
|
9099
|
+
throw new Error("public CLI config.providerAliases provider key must be non-empty");
|
|
9100
|
+
}
|
|
9101
|
+
if (byHost === null || typeof byHost !== "object" || Array.isArray(byHost)) {
|
|
9102
|
+
throw new Error(
|
|
9103
|
+
`public CLI config.providerAliases[${provider}] must be an object`
|
|
9104
|
+
);
|
|
9105
|
+
}
|
|
9106
|
+
const hosts = {};
|
|
9107
|
+
for (const [host, alias] of Object.entries(byHost)) {
|
|
9108
|
+
if (host.trim() === "") {
|
|
9109
|
+
throw new Error(
|
|
9110
|
+
`public CLI config.providerAliases[${provider}] host key must be non-empty`
|
|
9111
|
+
);
|
|
9112
|
+
}
|
|
9113
|
+
if (typeof alias !== "string" || alias.trim() === "") {
|
|
9114
|
+
throw new Error(
|
|
9115
|
+
`public CLI config.providerAliases[${provider}][${host}] must be a non-empty string`
|
|
9116
|
+
);
|
|
9117
|
+
}
|
|
9118
|
+
hosts[host] = alias;
|
|
9119
|
+
}
|
|
9120
|
+
if (Object.keys(hosts).length > 0) {
|
|
9121
|
+
out[provider] = hosts;
|
|
9122
|
+
}
|
|
9123
|
+
}
|
|
9124
|
+
return out;
|
|
9125
|
+
}
|
|
9041
9126
|
function parsePublicCliConfig(value) {
|
|
9042
9127
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
9043
9128
|
throw new Error("public CLI config must be an object");
|
|
@@ -9047,6 +9132,13 @@ function parsePublicCliConfig(value) {
|
|
|
9047
9132
|
if (record4.autoResumeLimit !== void 0) {
|
|
9048
9133
|
autoResumeLimit = parseAutoResumeLimit(record4.autoResumeLimit);
|
|
9049
9134
|
}
|
|
9135
|
+
let providerAliases;
|
|
9136
|
+
if (record4.providerAliases !== void 0) {
|
|
9137
|
+
const parsed = parseProviderHostAliases(record4.providerAliases);
|
|
9138
|
+
if (Object.keys(parsed).length > 0) {
|
|
9139
|
+
providerAliases = parsed;
|
|
9140
|
+
}
|
|
9141
|
+
}
|
|
9050
9142
|
const unknownSeats = {};
|
|
9051
9143
|
if (record4.unknownSeats !== void 0) {
|
|
9052
9144
|
if (record4.unknownSeats === null || typeof record4.unknownSeats !== "object" || Array.isArray(record4.unknownSeats)) {
|
|
@@ -9057,6 +9149,7 @@ function parsePublicCliConfig(value) {
|
|
|
9057
9149
|
const withOpaque = (seats2) => ({
|
|
9058
9150
|
seats: seats2,
|
|
9059
9151
|
...autoResumeLimit === void 0 ? {} : { autoResumeLimit },
|
|
9152
|
+
...providerAliases === void 0 ? {} : { providerAliases },
|
|
9060
9153
|
...Object.keys(unknownSeats).length === 0 ? {} : { unknownSeats }
|
|
9061
9154
|
});
|
|
9062
9155
|
if (record4.seats === void 0) {
|
|
@@ -9233,7 +9326,21 @@ function resolveEffectiveSeat(config, seat, credentials, invocation) {
|
|
|
9233
9326
|
};
|
|
9234
9327
|
}
|
|
9235
9328
|
}
|
|
9236
|
-
|
|
9329
|
+
const withAxes = attachHostAxis(
|
|
9330
|
+
attachEngineAxis(modelSeat, config, invocation),
|
|
9331
|
+
config,
|
|
9332
|
+
invocation
|
|
9333
|
+
);
|
|
9334
|
+
const selection = applyProviderHostAlias(
|
|
9335
|
+
withAxes.selection,
|
|
9336
|
+
withAxes.host,
|
|
9337
|
+
config.providerAliases
|
|
9338
|
+
);
|
|
9339
|
+
if (selection === void 0) {
|
|
9340
|
+
const { selection: _dropped, ...rest } = withAxes;
|
|
9341
|
+
return rest;
|
|
9342
|
+
}
|
|
9343
|
+
return { ...withAxes, selection };
|
|
9237
9344
|
}
|
|
9238
9345
|
function effectiveSeatConfigurations(config, credentials, invocation) {
|
|
9239
9346
|
return PUBLIC_CONFIGURABLE_SEATS.map(
|
|
@@ -139,6 +139,50 @@ function parseAutoResumeLimit(value) {
|
|
|
139
139
|
function setAutoResumeLimit(config, limit) {
|
|
140
140
|
return { ...config, autoResumeLimit: parseAutoResumeLimit(limit) };
|
|
141
141
|
}
|
|
142
|
+
function requireNonEmptyToken(value, label) {
|
|
143
|
+
const trimmed = value.trim();
|
|
144
|
+
if (trimmed === "") {
|
|
145
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
146
|
+
}
|
|
147
|
+
return trimmed;
|
|
148
|
+
}
|
|
149
|
+
function setProviderHostAlias(config, provider, host, alias) {
|
|
150
|
+
const from = requireNonEmptyToken(provider, "provider");
|
|
151
|
+
const hostName = requireNonEmptyToken(host, "host");
|
|
152
|
+
const to = requireNonEmptyToken(alias, "alias");
|
|
153
|
+
const previous = config.providerAliases ?? {};
|
|
154
|
+
return {
|
|
155
|
+
...config,
|
|
156
|
+
providerAliases: {
|
|
157
|
+
...previous,
|
|
158
|
+
[from]: {
|
|
159
|
+
...previous[from] ?? {},
|
|
160
|
+
[hostName]: to
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function unsetProviderHostAlias(config, provider, host) {
|
|
166
|
+
const from = requireNonEmptyToken(provider, "provider");
|
|
167
|
+
const hostName = requireNonEmptyToken(host, "host");
|
|
168
|
+
const previous = config.providerAliases;
|
|
169
|
+
if (previous === void 0 || previous[from] === void 0) return config;
|
|
170
|
+
const { [hostName]: _dropped, ...restHosts } = previous[from];
|
|
171
|
+
const nextForProvider = Object.keys(restHosts).length === 0 ? void 0 : restHosts;
|
|
172
|
+
const { [from]: _provider, ...restProviders } = previous;
|
|
173
|
+
const nextAliases = nextForProvider === void 0 ? restProviders : { ...restProviders, [from]: nextForProvider };
|
|
174
|
+
if (Object.keys(nextAliases).length === 0) {
|
|
175
|
+
const { providerAliases: _gone, ...rest } = config;
|
|
176
|
+
return rest;
|
|
177
|
+
}
|
|
178
|
+
return { ...config, providerAliases: nextAliases };
|
|
179
|
+
}
|
|
180
|
+
function applyProviderHostAlias(selection, host, aliases) {
|
|
181
|
+
if (selection === void 0 || aliases === void 0) return selection;
|
|
182
|
+
const mapped = aliases[selection.provider]?.[host];
|
|
183
|
+
if (mapped === void 0) return selection;
|
|
184
|
+
return { ...selection, provider: mapped };
|
|
185
|
+
}
|
|
142
186
|
function validatePublicCliConfigAxes(config, _packageRoot) {
|
|
143
187
|
for (const seat of Object.keys(config.seats)) {
|
|
144
188
|
const row = config.seats[seat];
|
|
@@ -208,9 +252,44 @@ function serializePublicCliConfig(config) {
|
|
|
208
252
|
...config.unknownSeats ?? {},
|
|
209
253
|
...config.seats
|
|
210
254
|
},
|
|
211
|
-
...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit }
|
|
255
|
+
...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit },
|
|
256
|
+
...config.providerAliases === void 0 || Object.keys(config.providerAliases).length === 0 ? {} : { providerAliases: config.providerAliases }
|
|
212
257
|
};
|
|
213
258
|
}
|
|
259
|
+
function parseProviderHostAliases(value) {
|
|
260
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
261
|
+
throw new Error("public CLI config.providerAliases must be an object");
|
|
262
|
+
}
|
|
263
|
+
const out = {};
|
|
264
|
+
for (const [provider, byHost] of Object.entries(value)) {
|
|
265
|
+
if (provider.trim() === "") {
|
|
266
|
+
throw new Error("public CLI config.providerAliases provider key must be non-empty");
|
|
267
|
+
}
|
|
268
|
+
if (byHost === null || typeof byHost !== "object" || Array.isArray(byHost)) {
|
|
269
|
+
throw new Error(
|
|
270
|
+
`public CLI config.providerAliases[${provider}] must be an object`
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
const hosts = {};
|
|
274
|
+
for (const [host, alias] of Object.entries(byHost)) {
|
|
275
|
+
if (host.trim() === "") {
|
|
276
|
+
throw new Error(
|
|
277
|
+
`public CLI config.providerAliases[${provider}] host key must be non-empty`
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
if (typeof alias !== "string" || alias.trim() === "") {
|
|
281
|
+
throw new Error(
|
|
282
|
+
`public CLI config.providerAliases[${provider}][${host}] must be a non-empty string`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
hosts[host] = alias;
|
|
286
|
+
}
|
|
287
|
+
if (Object.keys(hosts).length > 0) {
|
|
288
|
+
out[provider] = hosts;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return out;
|
|
292
|
+
}
|
|
214
293
|
function parsePublicCliConfig(value) {
|
|
215
294
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
216
295
|
throw new Error("public CLI config must be an object");
|
|
@@ -220,6 +299,13 @@ function parsePublicCliConfig(value) {
|
|
|
220
299
|
if (record.autoResumeLimit !== void 0) {
|
|
221
300
|
autoResumeLimit = parseAutoResumeLimit(record.autoResumeLimit);
|
|
222
301
|
}
|
|
302
|
+
let providerAliases;
|
|
303
|
+
if (record.providerAliases !== void 0) {
|
|
304
|
+
const parsed = parseProviderHostAliases(record.providerAliases);
|
|
305
|
+
if (Object.keys(parsed).length > 0) {
|
|
306
|
+
providerAliases = parsed;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
223
309
|
const unknownSeats = {};
|
|
224
310
|
if (record.unknownSeats !== void 0) {
|
|
225
311
|
if (record.unknownSeats === null || typeof record.unknownSeats !== "object" || Array.isArray(record.unknownSeats)) {
|
|
@@ -230,6 +316,7 @@ function parsePublicCliConfig(value) {
|
|
|
230
316
|
const withOpaque = (seats2) => ({
|
|
231
317
|
seats: seats2,
|
|
232
318
|
...autoResumeLimit === void 0 ? {} : { autoResumeLimit },
|
|
319
|
+
...providerAliases === void 0 ? {} : { providerAliases },
|
|
233
320
|
...Object.keys(unknownSeats).length === 0 ? {} : { unknownSeats }
|
|
234
321
|
});
|
|
235
322
|
if (record.seats === void 0) {
|
|
@@ -406,7 +493,21 @@ function resolveEffectiveSeat(config, seat, credentials, invocation) {
|
|
|
406
493
|
};
|
|
407
494
|
}
|
|
408
495
|
}
|
|
409
|
-
|
|
496
|
+
const withAxes = attachHostAxis(
|
|
497
|
+
attachEngineAxis(modelSeat, config, invocation),
|
|
498
|
+
config,
|
|
499
|
+
invocation
|
|
500
|
+
);
|
|
501
|
+
const selection = applyProviderHostAlias(
|
|
502
|
+
withAxes.selection,
|
|
503
|
+
withAxes.host,
|
|
504
|
+
config.providerAliases
|
|
505
|
+
);
|
|
506
|
+
if (selection === void 0) {
|
|
507
|
+
const { selection: _dropped, ...rest } = withAxes;
|
|
508
|
+
return rest;
|
|
509
|
+
}
|
|
510
|
+
return { ...withAxes, selection };
|
|
410
511
|
}
|
|
411
512
|
function effectiveSeatConfigurations(config, credentials, invocation) {
|
|
412
513
|
return PUBLIC_CONFIGURABLE_SEATS.map(
|
|
@@ -439,6 +540,7 @@ async function loadCredentialProviders(agentDir) {
|
|
|
439
540
|
}
|
|
440
541
|
export {
|
|
441
542
|
GATE_OFFICER_SEATS,
|
|
543
|
+
applyProviderHostAlias,
|
|
442
544
|
buildSeatModelCliArgs,
|
|
443
545
|
clearPersistentSeatConfig,
|
|
444
546
|
credentialProvidersFromAuthData,
|
|
@@ -459,5 +561,7 @@ export {
|
|
|
459
561
|
setPersistentSeatConfig,
|
|
460
562
|
setPersistentSeatEngine,
|
|
461
563
|
setPersistentSeatHost,
|
|
564
|
+
setProviderHostAlias,
|
|
565
|
+
unsetProviderHostAlias,
|
|
462
566
|
validatePublicCliConfigAxes
|
|
463
567
|
};
|
package/dist/public-cli/main.js
CHANGED
|
@@ -15584,6 +15584,50 @@ function parseAutoResumeLimit(value) {
|
|
|
15584
15584
|
function setAutoResumeLimit(config, limit) {
|
|
15585
15585
|
return { ...config, autoResumeLimit: parseAutoResumeLimit(limit) };
|
|
15586
15586
|
}
|
|
15587
|
+
function requireNonEmptyToken(value, label) {
|
|
15588
|
+
const trimmed = value.trim();
|
|
15589
|
+
if (trimmed === "") {
|
|
15590
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
15591
|
+
}
|
|
15592
|
+
return trimmed;
|
|
15593
|
+
}
|
|
15594
|
+
function setProviderHostAlias(config, provider, host, alias) {
|
|
15595
|
+
const from = requireNonEmptyToken(provider, "provider");
|
|
15596
|
+
const hostName = requireNonEmptyToken(host, "host");
|
|
15597
|
+
const to = requireNonEmptyToken(alias, "alias");
|
|
15598
|
+
const previous = config.providerAliases ?? {};
|
|
15599
|
+
return {
|
|
15600
|
+
...config,
|
|
15601
|
+
providerAliases: {
|
|
15602
|
+
...previous,
|
|
15603
|
+
[from]: {
|
|
15604
|
+
...previous[from] ?? {},
|
|
15605
|
+
[hostName]: to
|
|
15606
|
+
}
|
|
15607
|
+
}
|
|
15608
|
+
};
|
|
15609
|
+
}
|
|
15610
|
+
function unsetProviderHostAlias(config, provider, host) {
|
|
15611
|
+
const from = requireNonEmptyToken(provider, "provider");
|
|
15612
|
+
const hostName = requireNonEmptyToken(host, "host");
|
|
15613
|
+
const previous = config.providerAliases;
|
|
15614
|
+
if (previous === void 0 || previous[from] === void 0) return config;
|
|
15615
|
+
const { [hostName]: _dropped, ...restHosts } = previous[from];
|
|
15616
|
+
const nextForProvider = Object.keys(restHosts).length === 0 ? void 0 : restHosts;
|
|
15617
|
+
const { [from]: _provider, ...restProviders } = previous;
|
|
15618
|
+
const nextAliases = nextForProvider === void 0 ? restProviders : { ...restProviders, [from]: nextForProvider };
|
|
15619
|
+
if (Object.keys(nextAliases).length === 0) {
|
|
15620
|
+
const { providerAliases: _gone, ...rest } = config;
|
|
15621
|
+
return rest;
|
|
15622
|
+
}
|
|
15623
|
+
return { ...config, providerAliases: nextAliases };
|
|
15624
|
+
}
|
|
15625
|
+
function applyProviderHostAlias(selection, host, aliases) {
|
|
15626
|
+
if (selection === void 0 || aliases === void 0) return selection;
|
|
15627
|
+
const mapped = aliases[selection.provider]?.[host];
|
|
15628
|
+
if (mapped === void 0) return selection;
|
|
15629
|
+
return { ...selection, provider: mapped };
|
|
15630
|
+
}
|
|
15587
15631
|
function validatePublicCliConfigAxes(config, _packageRoot) {
|
|
15588
15632
|
for (const seat of Object.keys(config.seats)) {
|
|
15589
15633
|
const row = config.seats[seat];
|
|
@@ -15643,9 +15687,44 @@ function serializePublicCliConfig(config) {
|
|
|
15643
15687
|
...config.unknownSeats ?? {},
|
|
15644
15688
|
...config.seats
|
|
15645
15689
|
},
|
|
15646
|
-
...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit }
|
|
15690
|
+
...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit },
|
|
15691
|
+
...config.providerAliases === void 0 || Object.keys(config.providerAliases).length === 0 ? {} : { providerAliases: config.providerAliases }
|
|
15647
15692
|
};
|
|
15648
15693
|
}
|
|
15694
|
+
function parseProviderHostAliases(value) {
|
|
15695
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
15696
|
+
throw new Error("public CLI config.providerAliases must be an object");
|
|
15697
|
+
}
|
|
15698
|
+
const out = {};
|
|
15699
|
+
for (const [provider, byHost] of Object.entries(value)) {
|
|
15700
|
+
if (provider.trim() === "") {
|
|
15701
|
+
throw new Error("public CLI config.providerAliases provider key must be non-empty");
|
|
15702
|
+
}
|
|
15703
|
+
if (byHost === null || typeof byHost !== "object" || Array.isArray(byHost)) {
|
|
15704
|
+
throw new Error(
|
|
15705
|
+
`public CLI config.providerAliases[${provider}] must be an object`
|
|
15706
|
+
);
|
|
15707
|
+
}
|
|
15708
|
+
const hosts = {};
|
|
15709
|
+
for (const [host, alias] of Object.entries(byHost)) {
|
|
15710
|
+
if (host.trim() === "") {
|
|
15711
|
+
throw new Error(
|
|
15712
|
+
`public CLI config.providerAliases[${provider}] host key must be non-empty`
|
|
15713
|
+
);
|
|
15714
|
+
}
|
|
15715
|
+
if (typeof alias !== "string" || alias.trim() === "") {
|
|
15716
|
+
throw new Error(
|
|
15717
|
+
`public CLI config.providerAliases[${provider}][${host}] must be a non-empty string`
|
|
15718
|
+
);
|
|
15719
|
+
}
|
|
15720
|
+
hosts[host] = alias;
|
|
15721
|
+
}
|
|
15722
|
+
if (Object.keys(hosts).length > 0) {
|
|
15723
|
+
out[provider] = hosts;
|
|
15724
|
+
}
|
|
15725
|
+
}
|
|
15726
|
+
return out;
|
|
15727
|
+
}
|
|
15649
15728
|
function parsePublicCliConfig(value) {
|
|
15650
15729
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
15651
15730
|
throw new Error("public CLI config must be an object");
|
|
@@ -15655,6 +15734,13 @@ function parsePublicCliConfig(value) {
|
|
|
15655
15734
|
if (record4.autoResumeLimit !== void 0) {
|
|
15656
15735
|
autoResumeLimit = parseAutoResumeLimit(record4.autoResumeLimit);
|
|
15657
15736
|
}
|
|
15737
|
+
let providerAliases;
|
|
15738
|
+
if (record4.providerAliases !== void 0) {
|
|
15739
|
+
const parsed = parseProviderHostAliases(record4.providerAliases);
|
|
15740
|
+
if (Object.keys(parsed).length > 0) {
|
|
15741
|
+
providerAliases = parsed;
|
|
15742
|
+
}
|
|
15743
|
+
}
|
|
15658
15744
|
const unknownSeats = {};
|
|
15659
15745
|
if (record4.unknownSeats !== void 0) {
|
|
15660
15746
|
if (record4.unknownSeats === null || typeof record4.unknownSeats !== "object" || Array.isArray(record4.unknownSeats)) {
|
|
@@ -15665,6 +15751,7 @@ function parsePublicCliConfig(value) {
|
|
|
15665
15751
|
const withOpaque = (seats2) => ({
|
|
15666
15752
|
seats: seats2,
|
|
15667
15753
|
...autoResumeLimit === void 0 ? {} : { autoResumeLimit },
|
|
15754
|
+
...providerAliases === void 0 ? {} : { providerAliases },
|
|
15668
15755
|
...Object.keys(unknownSeats).length === 0 ? {} : { unknownSeats }
|
|
15669
15756
|
});
|
|
15670
15757
|
if (record4.seats === void 0) {
|
|
@@ -15841,7 +15928,21 @@ function resolveEffectiveSeat(config, seat, credentials, invocation) {
|
|
|
15841
15928
|
};
|
|
15842
15929
|
}
|
|
15843
15930
|
}
|
|
15844
|
-
|
|
15931
|
+
const withAxes = attachHostAxis(
|
|
15932
|
+
attachEngineAxis(modelSeat, config, invocation),
|
|
15933
|
+
config,
|
|
15934
|
+
invocation
|
|
15935
|
+
);
|
|
15936
|
+
const selection = applyProviderHostAlias(
|
|
15937
|
+
withAxes.selection,
|
|
15938
|
+
withAxes.host,
|
|
15939
|
+
config.providerAliases
|
|
15940
|
+
);
|
|
15941
|
+
if (selection === void 0) {
|
|
15942
|
+
const { selection: _dropped, ...rest } = withAxes;
|
|
15943
|
+
return rest;
|
|
15944
|
+
}
|
|
15945
|
+
return { ...withAxes, selection };
|
|
15845
15946
|
}
|
|
15846
15947
|
function effectiveSeatConfigurations(config, credentials, invocation) {
|
|
15847
15948
|
return PUBLIC_CONFIGURABLE_SEATS.map(
|
|
@@ -19489,14 +19590,17 @@ var init_option_definitions = __esm({
|
|
|
19489
19590
|
"ak-role config unset-engine <seat>",
|
|
19490
19591
|
"ak-role config set-host <seat> <name>",
|
|
19491
19592
|
"ak-role config unset-host <seat>",
|
|
19492
|
-
"ak-role config set-auto-resume-limit <N>"
|
|
19593
|
+
"ak-role config set-auto-resume-limit <N>",
|
|
19594
|
+
"ak-role config set-provider-alias <provider> <host> <alias>",
|
|
19595
|
+
"ak-role config unset-provider-alias <provider> <host>"
|
|
19493
19596
|
],
|
|
19494
19597
|
examples: [
|
|
19495
19598
|
"ak-role config set judge openai-codex/gpt-5.6-sol:high",
|
|
19496
19599
|
"ak-role config unset gatekeeper",
|
|
19497
19600
|
"ak-role config set-engine judge opus",
|
|
19498
19601
|
"ak-role config set-host judge grok-build",
|
|
19499
|
-
"ak-role config set-auto-resume-limit 3"
|
|
19602
|
+
"ak-role config set-auto-resume-limit 3",
|
|
19603
|
+
"ak-role config set-provider-alias xai hermes xai-oauth"
|
|
19500
19604
|
]
|
|
19501
19605
|
},
|
|
19502
19606
|
help: {
|
|
@@ -31595,6 +31699,7 @@ function renderHelp() {
|
|
|
31595
31699
|
"Persistent config: ak-role config set <seat> <provider/model[:thinking]> | unset <gatekeeper|inspector|notary>",
|
|
31596
31700
|
"Persistent engine (callable roles): ak-role config set-engine <seat> <name> | unset-engine <seat>",
|
|
31597
31701
|
"Persistent host (callable roles): ak-role config set-host <seat> <name> | unset-host <seat>",
|
|
31702
|
+
"Provider host alias: ak-role config set-provider-alias <provider> <host> <alias> | unset-provider-alias <provider> <host>",
|
|
31598
31703
|
"Host resolution: --host \u2192 persistent seat host \u2192 pi (resume uses the same order; #617)",
|
|
31599
31704
|
"Effective seats: ak-role roles"
|
|
31600
31705
|
);
|
|
@@ -31694,6 +31799,15 @@ function renderConfig(config) {
|
|
|
31694
31799
|
}
|
|
31695
31800
|
}
|
|
31696
31801
|
lines.push(`autoResumeLimit ${config.autoResumeLimit ?? AUTO_RESUME_LIMIT}`);
|
|
31802
|
+
const aliases = config.providerAliases;
|
|
31803
|
+
if (aliases !== void 0) {
|
|
31804
|
+
for (const provider of Object.keys(aliases).sort()) {
|
|
31805
|
+
const byHost = aliases[provider];
|
|
31806
|
+
for (const host of Object.keys(byHost).sort()) {
|
|
31807
|
+
lines.push(`providerAlias ${provider} ${host} ${byHost[host]}`);
|
|
31808
|
+
}
|
|
31809
|
+
}
|
|
31810
|
+
}
|
|
31697
31811
|
return `${lines.join("\n")}
|
|
31698
31812
|
`;
|
|
31699
31813
|
}
|
|
@@ -31843,6 +31957,44 @@ async function runConfigCommand(args, home, packageRoot2, io) {
|
|
|
31843
31957
|
io.stdout(renderConfig(config));
|
|
31844
31958
|
return 0;
|
|
31845
31959
|
}
|
|
31960
|
+
if (args[0] === "set-provider-alias") {
|
|
31961
|
+
if (args.length !== 4) {
|
|
31962
|
+
throw new CliUsageError(
|
|
31963
|
+
"usage: ak-role config set-provider-alias <provider> <host> <alias>"
|
|
31964
|
+
);
|
|
31965
|
+
}
|
|
31966
|
+
let config = await loadAndValidateConfig(home, packageRoot2);
|
|
31967
|
+
try {
|
|
31968
|
+
config = setProviderHostAlias(config, args[1], args[2], args[3]);
|
|
31969
|
+
} catch (error) {
|
|
31970
|
+
throw new CliUsageError(
|
|
31971
|
+
error instanceof Error ? error.message : String(error),
|
|
31972
|
+
{ cause: error }
|
|
31973
|
+
);
|
|
31974
|
+
}
|
|
31975
|
+
await savePublicCliConfig(config, home);
|
|
31976
|
+
io.stdout(renderConfig(config));
|
|
31977
|
+
return 0;
|
|
31978
|
+
}
|
|
31979
|
+
if (args[0] === "unset-provider-alias") {
|
|
31980
|
+
if (args.length !== 3) {
|
|
31981
|
+
throw new CliUsageError(
|
|
31982
|
+
"usage: ak-role config unset-provider-alias <provider> <host>"
|
|
31983
|
+
);
|
|
31984
|
+
}
|
|
31985
|
+
let config = await loadAndValidateConfig(home, packageRoot2);
|
|
31986
|
+
try {
|
|
31987
|
+
config = unsetProviderHostAlias(config, args[1], args[2]);
|
|
31988
|
+
} catch (error) {
|
|
31989
|
+
throw new CliUsageError(
|
|
31990
|
+
error instanceof Error ? error.message : String(error),
|
|
31991
|
+
{ cause: error }
|
|
31992
|
+
);
|
|
31993
|
+
}
|
|
31994
|
+
await savePublicCliConfig(config, home);
|
|
31995
|
+
io.stdout(renderConfig(config));
|
|
31996
|
+
return 0;
|
|
31997
|
+
}
|
|
31846
31998
|
throw new CliUsageError(`unknown config subcommand: ${args[0]}`);
|
|
31847
31999
|
}
|
|
31848
32000
|
async function runAkRole(argv, env) {
|
|
@@ -1077,6 +1077,8 @@ const SUPPORT_COMMAND_HELP = {
|
|
|
1077
1077
|
"ak-role config set-host <seat> <name>",
|
|
1078
1078
|
"ak-role config unset-host <seat>",
|
|
1079
1079
|
"ak-role config set-auto-resume-limit <N>",
|
|
1080
|
+
"ak-role config set-provider-alias <provider> <host> <alias>",
|
|
1081
|
+
"ak-role config unset-provider-alias <provider> <host>",
|
|
1080
1082
|
],
|
|
1081
1083
|
examples: [
|
|
1082
1084
|
"ak-role config set judge openai-codex/gpt-5.6-sol:high",
|
|
@@ -1084,6 +1086,7 @@ const SUPPORT_COMMAND_HELP = {
|
|
|
1084
1086
|
"ak-role config set-engine judge opus",
|
|
1085
1087
|
"ak-role config set-host judge grok-build",
|
|
1086
1088
|
"ak-role config set-auto-resume-limit 3",
|
|
1089
|
+
"ak-role config set-provider-alias xai hermes xai-oauth",
|
|
1087
1090
|
],
|
|
1088
1091
|
},
|
|
1089
1092
|
help: {
|
package/package.json
CHANGED
package/souls/countersign.md
CHANGED
|
@@ -5,16 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
## 审读步骤
|
|
7
7
|
|
|
8
|
-
**一、立法。**
|
|
9
|
-
1
|
|
10
|
-
2 第一法源立法(最高法):该票起居录与陛下原话,全局宪法;
|
|
11
|
-
3 第二发源立法:
|
|
12
|
-
适用 ADR——由你自行检索,按票面触及的席位、接缝、术语在 docs/adr 与 CONTEXT.md 查全,票面引没引都算——并逐键列出其决策键;仓级 CLAUDE.md、质量法、审刑院法典;
|
|
13
|
-
既有契约:CONTEXT.md 词表、被改动接缝的现行行为、相关票与在飞分支。
|
|
8
|
+
**一、立法。** 先为本票立「适用法」;后面每一步对着它问,未立法不得往下走。适用法三部分:
|
|
9
|
+
1 第一法源立法(最高法):该票起居录,全局宪法,仓内治理文件;
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
2 第二发源立法:
|
|
12
|
+
适用 ADR——由你自行检索,按票面触及的席位、接缝、术语在 docs/adr 与 CONTEXT.md 查全,票面引没引都算——并逐键列出其决策键;质量法、审刑院法典;
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
3 第二法源合法性检查:判断第二法源 以及 输入的 prombt等 对比第一法源是否有超出或不足,曲解。如有,除非有陛下原话批准,否则直接封驳 要求改正或陛下批准。
|
|
15
|
+
|
|
16
|
+
**二、相抵。** 票面,相关票与在飞分支与法源有无抵触。
|
|
18
17
|
|
|
19
18
|
**三、缺失。** 法源要求的,票面有没有漏:适用 ADR 未被引用即缺失,引用须写 `docs/adr/...md` 路径;ADR 每个决策键须有落点或明写「由 #x 承接」;验收面须覆盖票面每条主张;前置产物、决定、答复须在;承重主张的源头不存在、不支持、已过时,同为缺失。
|
|
20
19
|
|
|
@@ -39,9 +38,7 @@
|
|
|
39
38
|
|
|
40
39
|
- 署(converged)——四步无碍、五问皆有据可答,具备开工资格;
|
|
41
40
|
- 封驳(continue)——存在必须退回重议的问题;写明退给谁、缺什么、属哪一步;
|
|
42
|
-
- 上呈(escalate
|
|
41
|
+
- 上呈(escalate)——无法正常暑/封驳时。上呈求助
|
|
43
42
|
|
|
44
43
|
|
|
45
44
|
主张必须附证据或法的具体条目。finding 提类别,同类一次说全(审刑院法典·审官纪律)。
|
|
46
|
-
|
|
47
|
-
交卷后由符宝郎内闸核旨。无法解决的上抛陛下。
|
package/src/public-cli/cli.ts
CHANGED
|
@@ -28,6 +28,8 @@ import {
|
|
|
28
28
|
setPersistentSeatConfig,
|
|
29
29
|
setPersistentSeatEngine,
|
|
30
30
|
setPersistentSeatHost,
|
|
31
|
+
setProviderHostAlias,
|
|
32
|
+
unsetProviderHostAlias,
|
|
31
33
|
validatePublicCliConfigAxes,
|
|
32
34
|
type CredentialProviders,
|
|
33
35
|
type EffectiveSeat,
|
|
@@ -769,6 +771,7 @@ function renderHelp(): string {
|
|
|
769
771
|
"Persistent config: ak-role config set <seat> <provider/model[:thinking]> | unset <gatekeeper|inspector|notary>",
|
|
770
772
|
"Persistent engine (callable roles): ak-role config set-engine <seat> <name> | unset-engine <seat>",
|
|
771
773
|
"Persistent host (callable roles): ak-role config set-host <seat> <name> | unset-host <seat>",
|
|
774
|
+
"Provider host alias: ak-role config set-provider-alias <provider> <host> <alias> | unset-provider-alias <provider> <host>",
|
|
772
775
|
"Host resolution: --host → persistent seat host → pi (resume uses the same order; #617)",
|
|
773
776
|
"Effective seats: ak-role roles",
|
|
774
777
|
);
|
|
@@ -909,6 +912,16 @@ function renderConfig(config: PublicCliConfig): string {
|
|
|
909
912
|
}
|
|
910
913
|
// #422: show the effective auto-resume ceiling (configured value or default).
|
|
911
914
|
lines.push(`autoResumeLimit\t${config.autoResumeLimit ?? AUTO_RESUME_LIMIT}`);
|
|
915
|
+
// #778: owner-registered provider→host aliases (disk face; seats stay as written).
|
|
916
|
+
const aliases = config.providerAliases;
|
|
917
|
+
if (aliases !== undefined) {
|
|
918
|
+
for (const provider of Object.keys(aliases).sort()) {
|
|
919
|
+
const byHost = aliases[provider]!;
|
|
920
|
+
for (const host of Object.keys(byHost).sort()) {
|
|
921
|
+
lines.push(`providerAlias\t${provider}\t${host}\t${byHost[host]}`);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
912
925
|
return `${lines.join("\n")}\n`;
|
|
913
926
|
}
|
|
914
927
|
|
|
@@ -1081,6 +1094,47 @@ async function runConfigCommand(
|
|
|
1081
1094
|
return 0;
|
|
1082
1095
|
}
|
|
1083
1096
|
|
|
1097
|
+
// #778: owner-registered provider→host alias (opaque strings; no host catalog).
|
|
1098
|
+
if (args[0] === "set-provider-alias") {
|
|
1099
|
+
if (args.length !== 4) {
|
|
1100
|
+
throw new CliUsageError(
|
|
1101
|
+
"usage: ak-role config set-provider-alias <provider> <host> <alias>",
|
|
1102
|
+
);
|
|
1103
|
+
}
|
|
1104
|
+
let config = await loadAndValidateConfig(home, packageRoot);
|
|
1105
|
+
try {
|
|
1106
|
+
config = setProviderHostAlias(config, args[1]!, args[2]!, args[3]!);
|
|
1107
|
+
} catch (error) {
|
|
1108
|
+
throw new CliUsageError(
|
|
1109
|
+
error instanceof Error ? error.message : String(error),
|
|
1110
|
+
{ cause: error },
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1113
|
+
await savePublicCliConfig(config, home);
|
|
1114
|
+
io.stdout(renderConfig(config));
|
|
1115
|
+
return 0;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
if (args[0] === "unset-provider-alias") {
|
|
1119
|
+
if (args.length !== 3) {
|
|
1120
|
+
throw new CliUsageError(
|
|
1121
|
+
"usage: ak-role config unset-provider-alias <provider> <host>",
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
let config = await loadAndValidateConfig(home, packageRoot);
|
|
1125
|
+
try {
|
|
1126
|
+
config = unsetProviderHostAlias(config, args[1]!, args[2]!);
|
|
1127
|
+
} catch (error) {
|
|
1128
|
+
throw new CliUsageError(
|
|
1129
|
+
error instanceof Error ? error.message : String(error),
|
|
1130
|
+
{ cause: error },
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
await savePublicCliConfig(config, home);
|
|
1134
|
+
io.stdout(renderConfig(config));
|
|
1135
|
+
return 0;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1084
1138
|
throw new CliUsageError(`unknown config subcommand: ${args[0]}`);
|
|
1085
1139
|
}
|
|
1086
1140
|
|
package/src/public-cli/config.ts
CHANGED
|
@@ -54,6 +54,15 @@ export type PersistentSeatConfig = {
|
|
|
54
54
|
host?: string;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* #778: owner-registered provider name by host. Keyed seat-table provider →
|
|
59
|
+
* host → host-facing provider. Package code carries the map only — no built-in
|
|
60
|
+
* pairs. Unregistered (provider, host) pairs pass the seat provider through.
|
|
61
|
+
*/
|
|
62
|
+
export type ProviderHostAliases = Readonly<
|
|
63
|
+
Record<string, Readonly<Record<string, string>>>
|
|
64
|
+
>;
|
|
65
|
+
|
|
57
66
|
export type PublicCliConfig = {
|
|
58
67
|
seats: Partial<Record<PublicConfigurableSeat, PersistentSeatConfig>>;
|
|
59
68
|
/**
|
|
@@ -63,6 +72,11 @@ export type PublicCliConfig = {
|
|
|
63
72
|
* bound (ADR 0035).
|
|
64
73
|
*/
|
|
65
74
|
autoResumeLimit?: number;
|
|
75
|
+
/**
|
|
76
|
+
* #778: owner-registered provider→host aliases. Sibling of `seats`; never
|
|
77
|
+
* invents pairs. Absent or empty means pure pass-through.
|
|
78
|
+
*/
|
|
79
|
+
providerAliases?: ProviderHostAliases;
|
|
66
80
|
/**
|
|
67
81
|
* #592: opaque seat rows this build does not own. Carried through every
|
|
68
82
|
* parse→save cycle so a write never silently erases neighboring-line rows
|
|
@@ -293,6 +307,81 @@ export function setAutoResumeLimit(
|
|
|
293
307
|
return { ...config, autoResumeLimit: parseAutoResumeLimit(limit) };
|
|
294
308
|
}
|
|
295
309
|
|
|
310
|
+
function requireNonEmptyToken(value: string, label: string): string {
|
|
311
|
+
const trimmed = value.trim();
|
|
312
|
+
if (trimmed === "") {
|
|
313
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
314
|
+
}
|
|
315
|
+
return trimmed;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* #778: register one owner provider→host alias. Opaque strings only — no host
|
|
320
|
+
* catalog check and no built-in provider pairs. Sibling keys (seats included)
|
|
321
|
+
* are preserved.
|
|
322
|
+
*/
|
|
323
|
+
export function setProviderHostAlias(
|
|
324
|
+
config: PublicCliConfig,
|
|
325
|
+
provider: string,
|
|
326
|
+
host: string,
|
|
327
|
+
alias: string,
|
|
328
|
+
): PublicCliConfig {
|
|
329
|
+
const from = requireNonEmptyToken(provider, "provider");
|
|
330
|
+
const hostName = requireNonEmptyToken(host, "host");
|
|
331
|
+
const to = requireNonEmptyToken(alias, "alias");
|
|
332
|
+
const previous = config.providerAliases ?? {};
|
|
333
|
+
return {
|
|
334
|
+
...config,
|
|
335
|
+
providerAliases: {
|
|
336
|
+
...previous,
|
|
337
|
+
[from]: {
|
|
338
|
+
...(previous[from] ?? {}),
|
|
339
|
+
[hostName]: to,
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** #778: drop one owner provider→host alias. Empty map collapses to absent. */
|
|
346
|
+
export function unsetProviderHostAlias(
|
|
347
|
+
config: PublicCliConfig,
|
|
348
|
+
provider: string,
|
|
349
|
+
host: string,
|
|
350
|
+
): PublicCliConfig {
|
|
351
|
+
const from = requireNonEmptyToken(provider, "provider");
|
|
352
|
+
const hostName = requireNonEmptyToken(host, "host");
|
|
353
|
+
const previous = config.providerAliases;
|
|
354
|
+
if (previous === undefined || previous[from] === undefined) return config;
|
|
355
|
+
const { [hostName]: _dropped, ...restHosts } = previous[from]!;
|
|
356
|
+
const nextForProvider =
|
|
357
|
+
Object.keys(restHosts).length === 0 ? undefined : restHosts;
|
|
358
|
+
const { [from]: _provider, ...restProviders } = previous;
|
|
359
|
+
const nextAliases =
|
|
360
|
+
nextForProvider === undefined
|
|
361
|
+
? restProviders
|
|
362
|
+
: { ...restProviders, [from]: nextForProvider };
|
|
363
|
+
if (Object.keys(nextAliases).length === 0) {
|
|
364
|
+
const { providerAliases: _gone, ...rest } = config;
|
|
365
|
+
return rest;
|
|
366
|
+
}
|
|
367
|
+
return { ...config, providerAliases: nextAliases };
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* #778: project seat-table provider through owner aliases for one host.
|
|
372
|
+
* Unregistered pairs return the seat selection unchanged (pass-through).
|
|
373
|
+
*/
|
|
374
|
+
export function applyProviderHostAlias(
|
|
375
|
+
selection: SeatModelConfig | undefined,
|
|
376
|
+
host: string,
|
|
377
|
+
aliases: ProviderHostAliases | undefined,
|
|
378
|
+
): SeatModelConfig | undefined {
|
|
379
|
+
if (selection === undefined || aliases === undefined) return selection;
|
|
380
|
+
const mapped = aliases[selection.provider]?.[host];
|
|
381
|
+
if (mapped === undefined) return selection;
|
|
382
|
+
return { ...selection, provider: mapped };
|
|
383
|
+
}
|
|
384
|
+
|
|
296
385
|
/**
|
|
297
386
|
* Config-parse seam: persistent call axes belong to PUBLIC_CALLABLE_ROLES;
|
|
298
387
|
* engine names need only path-safety syntax (no closed material catalog;
|
|
@@ -387,6 +476,7 @@ export function buildSeatModelCliArgs(model: SeatModelConfig | undefined): strin
|
|
|
387
476
|
function serializePublicCliConfig(config: PublicCliConfig): {
|
|
388
477
|
seats: Record<string, unknown>;
|
|
389
478
|
autoResumeLimit?: number;
|
|
479
|
+
providerAliases?: ProviderHostAliases;
|
|
390
480
|
} {
|
|
391
481
|
return {
|
|
392
482
|
// Known seats win on any key clash; by construction the two maps are
|
|
@@ -398,9 +488,48 @@ function serializePublicCliConfig(config: PublicCliConfig): {
|
|
|
398
488
|
...(config.autoResumeLimit === undefined
|
|
399
489
|
? {}
|
|
400
490
|
: { autoResumeLimit: config.autoResumeLimit }),
|
|
491
|
+
...(config.providerAliases === undefined ||
|
|
492
|
+
Object.keys(config.providerAliases).length === 0
|
|
493
|
+
? {}
|
|
494
|
+
: { providerAliases: config.providerAliases }),
|
|
401
495
|
};
|
|
402
496
|
}
|
|
403
497
|
|
|
498
|
+
function parseProviderHostAliases(value: unknown): ProviderHostAliases {
|
|
499
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
500
|
+
throw new Error("public CLI config.providerAliases must be an object");
|
|
501
|
+
}
|
|
502
|
+
const out: Record<string, Record<string, string>> = {};
|
|
503
|
+
for (const [provider, byHost] of Object.entries(value as Record<string, unknown>)) {
|
|
504
|
+
if (provider.trim() === "") {
|
|
505
|
+
throw new Error("public CLI config.providerAliases provider key must be non-empty");
|
|
506
|
+
}
|
|
507
|
+
if (byHost === null || typeof byHost !== "object" || Array.isArray(byHost)) {
|
|
508
|
+
throw new Error(
|
|
509
|
+
`public CLI config.providerAliases[${provider}] must be an object`,
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
const hosts: Record<string, string> = {};
|
|
513
|
+
for (const [host, alias] of Object.entries(byHost as Record<string, unknown>)) {
|
|
514
|
+
if (host.trim() === "") {
|
|
515
|
+
throw new Error(
|
|
516
|
+
`public CLI config.providerAliases[${provider}] host key must be non-empty`,
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
if (typeof alias !== "string" || alias.trim() === "") {
|
|
520
|
+
throw new Error(
|
|
521
|
+
`public CLI config.providerAliases[${provider}][${host}] must be a non-empty string`,
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
hosts[host] = alias;
|
|
525
|
+
}
|
|
526
|
+
if (Object.keys(hosts).length > 0) {
|
|
527
|
+
out[provider] = hosts;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return out;
|
|
531
|
+
}
|
|
532
|
+
|
|
404
533
|
function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
405
534
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
406
535
|
throw new Error("public CLI config must be an object");
|
|
@@ -408,6 +537,7 @@ function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
|
408
537
|
const record = value as {
|
|
409
538
|
seats?: unknown;
|
|
410
539
|
autoResumeLimit?: unknown;
|
|
540
|
+
providerAliases?: unknown;
|
|
411
541
|
unknownSeats?: unknown;
|
|
412
542
|
};
|
|
413
543
|
// #422 round-trip preservation: the sibling top-level key must survive every
|
|
@@ -416,6 +546,15 @@ function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
|
416
546
|
if (record.autoResumeLimit !== undefined) {
|
|
417
547
|
autoResumeLimit = parseAutoResumeLimit(record.autoResumeLimit);
|
|
418
548
|
}
|
|
549
|
+
// #778: same survival duty as autoResumeLimit — owner aliases must not vanish
|
|
550
|
+
// on an unrelated seat write.
|
|
551
|
+
let providerAliases: ProviderHostAliases | undefined;
|
|
552
|
+
if (record.providerAliases !== undefined) {
|
|
553
|
+
const parsed = parseProviderHostAliases(record.providerAliases);
|
|
554
|
+
if (Object.keys(parsed).length > 0) {
|
|
555
|
+
providerAliases = parsed;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
419
558
|
// #592: opaque bucket may already be present on an in-memory round-trip
|
|
420
559
|
// (load→set→save calls parse again). Carry it before seats iteration so a
|
|
421
560
|
// disk-shaped seats map and a memory-shaped bucket both survive.
|
|
@@ -433,6 +572,7 @@ function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
|
433
572
|
const withOpaque = (seats: PublicCliConfig["seats"]): PublicCliConfig => ({
|
|
434
573
|
seats,
|
|
435
574
|
...(autoResumeLimit === undefined ? {} : { autoResumeLimit }),
|
|
575
|
+
...(providerAliases === undefined ? {} : { providerAliases }),
|
|
436
576
|
...(Object.keys(unknownSeats).length === 0 ? {} : { unknownSeats }),
|
|
437
577
|
});
|
|
438
578
|
if (record.seats === undefined) {
|
|
@@ -678,7 +818,23 @@ export function resolveEffectiveSeat(
|
|
|
678
818
|
}
|
|
679
819
|
}
|
|
680
820
|
|
|
681
|
-
|
|
821
|
+
const withAxes = attachHostAxis(
|
|
822
|
+
attachEngineAxis(modelSeat, config, invocation),
|
|
823
|
+
config,
|
|
824
|
+
invocation,
|
|
825
|
+
);
|
|
826
|
+
// #778: host-facing provider is the seat-table value after owner aliases.
|
|
827
|
+
// Disk seats stay as written; only the effective selection is projected.
|
|
828
|
+
const selection = applyProviderHostAlias(
|
|
829
|
+
withAxes.selection,
|
|
830
|
+
withAxes.host,
|
|
831
|
+
config.providerAliases,
|
|
832
|
+
);
|
|
833
|
+
if (selection === undefined) {
|
|
834
|
+
const { selection: _dropped, ...rest } = withAxes;
|
|
835
|
+
return rest;
|
|
836
|
+
}
|
|
837
|
+
return { ...withAxes, selection };
|
|
682
838
|
}
|
|
683
839
|
|
|
684
840
|
export function effectiveSeatConfigurations(
|
|
@@ -1307,6 +1307,8 @@ const SUPPORT_COMMAND_HELP = {
|
|
|
1307
1307
|
"ak-role config set-host <seat> <name>",
|
|
1308
1308
|
"ak-role config unset-host <seat>",
|
|
1309
1309
|
"ak-role config set-auto-resume-limit <N>",
|
|
1310
|
+
"ak-role config set-provider-alias <provider> <host> <alias>",
|
|
1311
|
+
"ak-role config unset-provider-alias <provider> <host>",
|
|
1310
1312
|
],
|
|
1311
1313
|
examples: [
|
|
1312
1314
|
"ak-role config set judge openai-codex/gpt-5.6-sol:high",
|
|
@@ -1314,6 +1316,7 @@ const SUPPORT_COMMAND_HELP = {
|
|
|
1314
1316
|
"ak-role config set-engine judge opus",
|
|
1315
1317
|
"ak-role config set-host judge grok-build",
|
|
1316
1318
|
"ak-role config set-auto-resume-limit 3",
|
|
1319
|
+
"ak-role config set-provider-alias xai hermes xai-oauth",
|
|
1317
1320
|
],
|
|
1318
1321
|
},
|
|
1319
1322
|
help: {
|