@ouro.bot/cli 0.1.0-alpha.420 → 0.1.0-alpha.421
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/changelog.json +10 -0
- package/dist/heart/daemon/cli-exec.js +344 -182
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.421",
|
|
6
|
+
"changes": [
|
|
7
|
+
"`ouro vault create`, `ouro vault unlock`, `ouro vault replace`, `ouro vault recover`, `ouro vault status`, and `ouro vault config` now use the shared human CLI progress checklist for vault account creation, local unlock storage, vault probes, credential reads, runtime config writes, and recovery imports.",
|
|
8
|
+
"`ouro status --agent`, `ouro provider status`, `ouro config models`, and `ouro config model` now show progress while reading provider credentials, listing GitHub Copilot models, and checking selected models.",
|
|
9
|
+
"Hatch provider credential resolution and post-start `ouro up` repair auth now route progress through the shared command renderer instead of raw ad hoc output.",
|
|
10
|
+
"Credential command progress tests now cover successful phases, failure cleanup, provider model exceptions, and secret redaction so these flows stay visibly alive without leaking values.",
|
|
11
|
+
"`@ouro.bot/cli` and the `ouro.bot` wrapper are version-synced for the remaining credential command progress release."
|
|
12
|
+
]
|
|
13
|
+
},
|
|
4
14
|
{
|
|
5
15
|
"version": "0.1.0-alpha.420",
|
|
6
16
|
"changes": [
|
|
@@ -189,6 +189,18 @@ function createHumanCommandProgress(deps, commandName) {
|
|
|
189
189
|
commandName,
|
|
190
190
|
});
|
|
191
191
|
}
|
|
192
|
+
async function runCommandProgressPhase(progress, label, run, detail) {
|
|
193
|
+
progress.startPhase(label);
|
|
194
|
+
try {
|
|
195
|
+
const result = await Promise.resolve(run());
|
|
196
|
+
progress.completePhase(label, detail(result));
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
progress.completePhase(label, "failed");
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
192
204
|
function daemonProgressSummary(result) {
|
|
193
205
|
if (result.verifyStartupStatus === false)
|
|
194
206
|
return "not answering yet";
|
|
@@ -626,14 +638,25 @@ async function resolveHatchInput(command, deps) {
|
|
|
626
638
|
if (!agentName || !humanName || !(0, cli_parse_2.isAgentProvider)(providerRaw)) {
|
|
627
639
|
throw new Error(`Usage\n${(0, cli_parse_2.usage)()}`);
|
|
628
640
|
}
|
|
629
|
-
const
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
641
|
+
const progress = createHumanCommandProgress(deps, "hatch auth");
|
|
642
|
+
let credentials;
|
|
643
|
+
try {
|
|
644
|
+
progress.startPhase(`resolving ${providerRaw} credentials`);
|
|
645
|
+
credentials = await (0, auth_flow_1.resolveHatchCredentials)({
|
|
646
|
+
agentName,
|
|
647
|
+
provider: providerRaw,
|
|
648
|
+
credentials: command.credentials,
|
|
649
|
+
promptInput: prompt,
|
|
650
|
+
runAuthFlow: deps.runAuthFlow,
|
|
651
|
+
onProgress: (message) => progress.updateDetail(message),
|
|
652
|
+
});
|
|
653
|
+
progress.completePhase(`resolving ${providerRaw} credentials`, "ready");
|
|
654
|
+
}
|
|
655
|
+
catch (error) {
|
|
656
|
+
progress.end();
|
|
657
|
+
throw error;
|
|
658
|
+
}
|
|
659
|
+
progress.end();
|
|
637
660
|
return {
|
|
638
661
|
agentName,
|
|
639
662
|
humanName,
|
|
@@ -813,7 +836,7 @@ function rejectGeneratedVaultUnlockSecret(action) {
|
|
|
813
836
|
throw new Error(`vault ${action} no longer supports --generate-unlock-secret. Re-run without that flag and enter a human-chosen unlock secret; Ouro will not print vault unlock secrets.`);
|
|
814
837
|
}
|
|
815
838
|
async function createRepairVaultForAgent(input) {
|
|
816
|
-
const result = await (0, vault_setup_1.createVaultAccount)("Ouro credential vault", input.serverUrl, input.email, input.unlockSecret);
|
|
839
|
+
const result = await runCommandProgressPhase(input.progress, "creating vault account", () => (0, vault_setup_1.createVaultAccount)("Ouro credential vault", input.serverUrl, input.email, input.unlockSecret), (created) => created.success ? "created" : "failed");
|
|
817
840
|
if (!result.success) {
|
|
818
841
|
const message = [
|
|
819
842
|
`vault ${input.action} failed for ${input.agentName}: ${result.error}`,
|
|
@@ -827,14 +850,18 @@ async function createRepairVaultForAgent(input) {
|
|
|
827
850
|
input.deps.writeStdout(message);
|
|
828
851
|
return { ok: false, message };
|
|
829
852
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
853
|
+
const store = await runCommandProgressPhase(input.progress, "saving local unlock", () => {
|
|
854
|
+
writeAgentVaultConfig(input.agentName, input.configPath, input.config, { email: input.email, serverUrl: input.serverUrl });
|
|
855
|
+
return (0, vault_unlock_1.storeVaultUnlockSecret)({
|
|
856
|
+
agentName: input.agentName,
|
|
857
|
+
email: input.email,
|
|
858
|
+
serverUrl: input.serverUrl,
|
|
859
|
+
}, input.unlockSecret, { homeDir: input.deps.homeDir, store: input.store });
|
|
860
|
+
}, (saved) => saved.kind);
|
|
861
|
+
await runCommandProgressPhase(input.progress, "checking vault access", async () => {
|
|
862
|
+
(0, credential_access_1.resetCredentialStore)();
|
|
863
|
+
await (0, credential_access_1.getCredentialStore)(input.agentName).get("__ouro_vault_probe__");
|
|
864
|
+
}, () => "ok");
|
|
838
865
|
return { ok: true, store };
|
|
839
866
|
}
|
|
840
867
|
async function executeVaultUnlock(command, deps) {
|
|
@@ -845,13 +872,22 @@ async function executeVaultUnlock(command, deps) {
|
|
|
845
872
|
const { config } = (0, auth_flow_1.readAgentConfigForAgent)(command.agent, deps.bundlesRoot);
|
|
846
873
|
const vault = (0, identity_1.resolveVaultConfig)(command.agent, config.vault);
|
|
847
874
|
const unlockSecret = await promptSecret(`Ouro vault unlock secret for ${vault.email}: `);
|
|
848
|
-
const
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
875
|
+
const progress = createHumanCommandProgress(deps, "vault unlock");
|
|
876
|
+
let store;
|
|
877
|
+
try {
|
|
878
|
+
store = await runCommandProgressPhase(progress, "saving local unlock", () => (0, vault_unlock_1.storeVaultUnlockSecret)({
|
|
879
|
+
agentName: command.agent,
|
|
880
|
+
email: vault.email,
|
|
881
|
+
serverUrl: vault.serverUrl,
|
|
882
|
+
}, unlockSecret, { homeDir: deps.homeDir, store: command.store }), (saved) => saved.kind);
|
|
883
|
+
await runCommandProgressPhase(progress, "checking vault access", async () => {
|
|
884
|
+
(0, credential_access_1.resetCredentialStore)();
|
|
885
|
+
await (0, credential_access_1.getCredentialStore)(command.agent).get("__ouro_vault_probe__");
|
|
886
|
+
}, () => "ok");
|
|
887
|
+
}
|
|
888
|
+
finally {
|
|
889
|
+
progress.end();
|
|
890
|
+
}
|
|
855
891
|
const message = [
|
|
856
892
|
`vault unlocked for ${command.agent} on this machine`,
|
|
857
893
|
`vault: ${vault.email} at ${vault.serverUrl}`,
|
|
@@ -877,25 +913,40 @@ async function executeVaultCreate(command, deps) {
|
|
|
877
913
|
confirmQuestion: `Confirm Ouro vault unlock secret for ${email}: `,
|
|
878
914
|
emptyError: "vault create requires an unlock secret. Re-run in an interactive terminal and enter a human-chosen unlock secret.",
|
|
879
915
|
});
|
|
880
|
-
const
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
916
|
+
const progress = createHumanCommandProgress(deps, "vault create");
|
|
917
|
+
let store;
|
|
918
|
+
try {
|
|
919
|
+
const result = await runCommandProgressPhase(progress, "creating vault account", () => (0, vault_setup_1.createVaultAccount)("Ouro credential vault", serverUrl, email, unlockSecret), (created) => created.success ? "created" : "failed");
|
|
920
|
+
if (!result.success) {
|
|
921
|
+
const message = [
|
|
922
|
+
`vault create failed for ${command.agent}: ${result.error}`,
|
|
923
|
+
"",
|
|
924
|
+
"If this vault account already exists, run:",
|
|
925
|
+
` ouro vault unlock --agent ${command.agent}`,
|
|
926
|
+
].join("\n");
|
|
927
|
+
progress.end();
|
|
928
|
+
deps.writeStdout(message);
|
|
929
|
+
return message;
|
|
930
|
+
}
|
|
931
|
+
store = await runCommandProgressPhase(progress, "saving local unlock", () => {
|
|
932
|
+
writeAgentVaultConfig(command.agent, configPath, config, { email, serverUrl });
|
|
933
|
+
return (0, vault_unlock_1.storeVaultUnlockSecret)({
|
|
934
|
+
agentName: command.agent,
|
|
935
|
+
email,
|
|
936
|
+
serverUrl,
|
|
937
|
+
}, unlockSecret, { homeDir: deps.homeDir, store: command.store });
|
|
938
|
+
}, (saved) => saved.kind);
|
|
939
|
+
await runCommandProgressPhase(progress, "checking vault access", async () => {
|
|
940
|
+
(0, credential_access_1.resetCredentialStore)();
|
|
941
|
+
await (0, credential_access_1.getCredentialStore)(command.agent).get("__ouro_vault_probe__");
|
|
942
|
+
}, () => "ok");
|
|
943
|
+
}
|
|
944
|
+
finally {
|
|
945
|
+
progress.end();
|
|
890
946
|
}
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
email,
|
|
895
|
-
serverUrl,
|
|
896
|
-
}, unlockSecret, { homeDir: deps.homeDir, store: command.store });
|
|
897
|
-
(0, credential_access_1.resetCredentialStore)();
|
|
898
|
-
await (0, credential_access_1.getCredentialStore)(command.agent).get("__ouro_vault_probe__");
|
|
947
|
+
/* v8 ignore next -- defensive: success path assigns store before continuing @preserve */
|
|
948
|
+
if (!store)
|
|
949
|
+
throw new Error(`vault create failed for ${command.agent}: local unlock material was not saved`);
|
|
899
950
|
const message = appendBundleSyncSummary([
|
|
900
951
|
`vault created for ${command.agent}`,
|
|
901
952
|
`vault: ${email} at ${serverUrl}`,
|
|
@@ -923,17 +974,28 @@ async function executeVaultReplace(command, deps) {
|
|
|
923
974
|
confirmQuestion: `Confirm new Ouro vault unlock secret for ${email}: `,
|
|
924
975
|
emptyError: "vault replace requires an unlock secret. Re-run in an interactive terminal and enter a human-chosen unlock secret.",
|
|
925
976
|
});
|
|
926
|
-
const
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
977
|
+
const progress = createHumanCommandProgress(deps, "vault replace");
|
|
978
|
+
let repair;
|
|
979
|
+
try {
|
|
980
|
+
repair = await createRepairVaultForAgent({
|
|
981
|
+
action: "replace",
|
|
982
|
+
agentName: command.agent,
|
|
983
|
+
email,
|
|
984
|
+
serverUrl,
|
|
985
|
+
unlockSecret,
|
|
986
|
+
store: command.store,
|
|
987
|
+
deps,
|
|
988
|
+
progress,
|
|
989
|
+
configPath,
|
|
990
|
+
config,
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
finally {
|
|
994
|
+
progress.end();
|
|
995
|
+
}
|
|
996
|
+
/* v8 ignore next -- defensive: createRepairVaultForAgent either returns or throws @preserve */
|
|
997
|
+
if (!repair)
|
|
998
|
+
throw new Error(`vault replace failed for ${command.agent}: no vault repair result`);
|
|
937
999
|
if (!repair.ok)
|
|
938
1000
|
return repair.message;
|
|
939
1001
|
const message = appendBundleSyncSummary([
|
|
@@ -966,43 +1028,60 @@ async function executeVaultRecover(command, deps) {
|
|
|
966
1028
|
confirmQuestion: `Confirm new Ouro vault unlock secret for ${email}: `,
|
|
967
1029
|
emptyError: "vault recover requires an unlock secret. Re-run in an interactive terminal and enter a human-chosen unlock secret.",
|
|
968
1030
|
});
|
|
969
|
-
const
|
|
970
|
-
|
|
971
|
-
agentName: command.agent,
|
|
972
|
-
email,
|
|
973
|
-
serverUrl,
|
|
974
|
-
unlockSecret,
|
|
975
|
-
store: command.store,
|
|
976
|
-
deps,
|
|
977
|
-
configPath,
|
|
978
|
-
config,
|
|
979
|
-
});
|
|
980
|
-
if (!repair.ok)
|
|
981
|
-
return repair.message;
|
|
1031
|
+
const progress = createHumanCommandProgress(deps, "vault recover");
|
|
1032
|
+
let repair;
|
|
982
1033
|
const importedProviders = new Set();
|
|
983
|
-
let
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1034
|
+
let runtimeFields = [];
|
|
1035
|
+
let machineRuntimeFields = [];
|
|
1036
|
+
try {
|
|
1037
|
+
repair = await createRepairVaultForAgent({
|
|
1038
|
+
action: "recover",
|
|
1039
|
+
agentName: command.agent,
|
|
1040
|
+
email,
|
|
1041
|
+
serverUrl,
|
|
1042
|
+
unlockSecret,
|
|
1043
|
+
store: command.store,
|
|
1044
|
+
deps,
|
|
1045
|
+
progress,
|
|
1046
|
+
configPath,
|
|
1047
|
+
config,
|
|
1048
|
+
});
|
|
1049
|
+
if (!repair.ok)
|
|
1050
|
+
return repair.message;
|
|
1051
|
+
await runCommandProgressPhase(progress, "importing recovered credentials", async () => {
|
|
1052
|
+
let mergedRecoveredRuntimeConfig = {};
|
|
1053
|
+
for (const source of sourceImports) {
|
|
1054
|
+
for (const provider of source.providers) {
|
|
1055
|
+
await (0, provider_credentials_1.upsertProviderCredential)({
|
|
1056
|
+
agentName: command.agent,
|
|
1057
|
+
provider: provider.provider,
|
|
1058
|
+
credentials: provider.credentials,
|
|
1059
|
+
config: provider.config,
|
|
1060
|
+
provenance: { source: "manual" },
|
|
1061
|
+
now,
|
|
1062
|
+
});
|
|
1063
|
+
importedProviders.add(provider.provider);
|
|
1064
|
+
}
|
|
1065
|
+
mergedRecoveredRuntimeConfig = mergeRuntimeConfig(mergedRecoveredRuntimeConfig, source.runtimeConfig);
|
|
1066
|
+
}
|
|
1067
|
+
const splitRuntimeConfig = splitRuntimeConfigByScope(mergedRecoveredRuntimeConfig);
|
|
1068
|
+
runtimeFields = summarizeRuntimeConfigFields(splitRuntimeConfig.agentConfig);
|
|
1069
|
+
machineRuntimeFields = summarizeRuntimeConfigFields(splitRuntimeConfig.machineConfig);
|
|
1070
|
+
if (runtimeFields.length > 0) {
|
|
1071
|
+
await (0, runtime_credentials_1.upsertRuntimeCredentialConfig)(command.agent, splitRuntimeConfig.agentConfig, now);
|
|
1072
|
+
}
|
|
1073
|
+
if (machineRuntimeFields.length > 0) {
|
|
1074
|
+
await (0, runtime_credentials_1.upsertMachineRuntimeCredentialConfig)(command.agent, currentMachineId(deps), splitRuntimeConfig.machineConfig, now);
|
|
1075
|
+
}
|
|
1076
|
+
return {
|
|
1077
|
+
providerCount: importedProviders.size,
|
|
1078
|
+
runtimeCount: runtimeFields.length,
|
|
1079
|
+
machineRuntimeCount: machineRuntimeFields.length,
|
|
1080
|
+
};
|
|
1081
|
+
}, (imported) => `${imported.providerCount} providers, ${imported.runtimeCount + imported.machineRuntimeCount} runtime fields`);
|
|
1003
1082
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1083
|
+
finally {
|
|
1084
|
+
progress.end();
|
|
1006
1085
|
}
|
|
1007
1086
|
const providerList = [...importedProviders].sort();
|
|
1008
1087
|
const message = appendBundleSyncSummary([
|
|
@@ -1053,26 +1132,39 @@ async function executeVaultStatus(command, deps) {
|
|
|
1053
1132
|
`local unlock: ${status.stored ? "available" : "missing"}`,
|
|
1054
1133
|
];
|
|
1055
1134
|
if (status.stored) {
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
lines.push(`runtime credentials: ${runtime.reason} (${runtime.error})`);
|
|
1062
|
-
if (runtime.reason === "missing") {
|
|
1063
|
-
lines.push(` fix: Run 'ouro vault config set --agent ${command.agent} --key <field>' to store sense/integration credentials.`);
|
|
1135
|
+
const progress = createHumanCommandProgress(deps, "vault status");
|
|
1136
|
+
try {
|
|
1137
|
+
const runtime = await runCommandProgressPhase(progress, "reading runtime credentials", () => (0, runtime_credentials_1.refreshRuntimeCredentialConfig)(command.agent, { preserveCachedOnFailure: true }), (runtimeResult) => runtimeResult.ok ? runtimeResult.revision : runtimeResult.reason);
|
|
1138
|
+
if (runtime.ok) {
|
|
1139
|
+
lines.push(`runtime credentials: ${summarizeRuntimeConfigFields(runtime.config).join(", ") || "none stored"} (${runtime.revision})`);
|
|
1064
1140
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1141
|
+
else {
|
|
1142
|
+
lines.push(`runtime credentials: ${runtime.reason} (${runtime.error})`);
|
|
1143
|
+
if (runtime.reason === "missing") {
|
|
1144
|
+
lines.push(` fix: Run 'ouro vault config set --agent ${command.agent} --key <field>' to store sense/integration credentials.`);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
const pool = await runCommandProgressPhase(progress, "reading provider credentials", () => (0, provider_credentials_1.refreshProviderCredentialPool)(command.agent, {
|
|
1148
|
+
onProgress: (message) => progress.updateDetail(message),
|
|
1149
|
+
}), (poolResult) => {
|
|
1150
|
+
if (!poolResult.ok)
|
|
1151
|
+
return poolResult.reason;
|
|
1152
|
+
const summary = (0, provider_credentials_1.summarizeProviderCredentialPool)(poolResult.pool);
|
|
1153
|
+
return summary.providers.map((provider) => provider.provider).join(", ") || "none stored";
|
|
1154
|
+
});
|
|
1155
|
+
if (pool.ok) {
|
|
1156
|
+
const summary = (0, provider_credentials_1.summarizeProviderCredentialPool)(pool.pool);
|
|
1157
|
+
lines.push(`provider credentials: ${summary.providers.length === 0 ? "none stored" : ""}`);
|
|
1158
|
+
for (const provider of summary.providers) {
|
|
1159
|
+
lines.push(` ${provider.provider}: credential fields ${provider.credentialFields.join(", ") || "none"}, config fields ${provider.configFields.join(", ") || "none"}`);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
else {
|
|
1163
|
+
lines.push(`provider credentials: unavailable (${pool.error})`);
|
|
1072
1164
|
}
|
|
1073
1165
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1166
|
+
finally {
|
|
1167
|
+
progress.end();
|
|
1076
1168
|
}
|
|
1077
1169
|
}
|
|
1078
1170
|
else {
|
|
@@ -1190,13 +1282,24 @@ async function executeVaultConfigSet(command, deps) {
|
|
|
1190
1282
|
if (!value) {
|
|
1191
1283
|
throw new Error("vault config set requires --value <value> or an interactive prompt");
|
|
1192
1284
|
}
|
|
1193
|
-
const
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1285
|
+
const progress = createHumanCommandProgress(deps, "vault config set");
|
|
1286
|
+
let stored;
|
|
1287
|
+
try {
|
|
1288
|
+
stored = await runCommandProgressPhase(progress, "storing runtime credential", () => storeRuntimeConfigKey({
|
|
1289
|
+
agent: command.agent,
|
|
1290
|
+
key: command.key,
|
|
1291
|
+
value,
|
|
1292
|
+
scope,
|
|
1293
|
+
deps,
|
|
1294
|
+
onProgress: (message) => progress.updateDetail(message),
|
|
1295
|
+
}), (result) => result.revision);
|
|
1296
|
+
}
|
|
1297
|
+
finally {
|
|
1298
|
+
progress.end();
|
|
1299
|
+
}
|
|
1300
|
+
/* v8 ignore next -- defensive: storeRuntimeConfigKey either returns or throws @preserve */
|
|
1301
|
+
if (!stored)
|
|
1302
|
+
throw new Error(`vault config set failed for ${command.agent}: no stored runtime credential result`);
|
|
1200
1303
|
const message = [
|
|
1201
1304
|
`stored ${command.key} for ${command.agent} in ${runtimeScopeLabel(scope)}`,
|
|
1202
1305
|
`runtime credentials: ${stored.revision}`,
|
|
@@ -1214,27 +1317,33 @@ async function executeVaultConfigStatus(command, deps) {
|
|
|
1214
1317
|
}
|
|
1215
1318
|
const scopes = command.scope === "all" ? ["agent", "machine"] : [command.scope ?? "agent"];
|
|
1216
1319
|
const lines = [`agent: ${command.agent}`];
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
const
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
lines.push(
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1320
|
+
const progress = createHumanCommandProgress(deps, "vault config status");
|
|
1321
|
+
try {
|
|
1322
|
+
for (const scope of scopes) {
|
|
1323
|
+
const machineId = scope === "machine" ? currentMachineId(deps) : undefined;
|
|
1324
|
+
const runtime = await runCommandProgressPhase(progress, `reading ${scope} runtime config`, () => scope === "machine"
|
|
1325
|
+
? (0, runtime_credentials_1.refreshMachineRuntimeCredentialConfig)(command.agent, machineId, { preserveCachedOnFailure: true })
|
|
1326
|
+
: (0, runtime_credentials_1.refreshRuntimeCredentialConfig)(command.agent, { preserveCachedOnFailure: true }), (runtimeResult) => runtimeResult.ok ? runtimeResult.revision : runtimeResult.reason);
|
|
1327
|
+
if (scopes.length > 1)
|
|
1328
|
+
lines.push("");
|
|
1329
|
+
lines.push(`${scope} runtime config item: ${runtime.itemPath}`);
|
|
1330
|
+
if (runtime.ok) {
|
|
1331
|
+
lines.push(`status: available (${runtime.revision})`);
|
|
1332
|
+
const fields = summarizeRuntimeConfigFields(runtime.config);
|
|
1333
|
+
lines.push(`fields: ${fields.length === 0 ? "none stored" : fields.join(", ")}`);
|
|
1334
|
+
}
|
|
1335
|
+
else {
|
|
1336
|
+
lines.push(`status: ${runtime.reason}`);
|
|
1337
|
+
lines.push(`error: ${runtime.error}`);
|
|
1338
|
+
lines.push(runtime.reason === "missing"
|
|
1339
|
+
? `fix: Run 'ouro vault config set --agent ${command.agent} --key <field>${scope === "machine" ? " --scope machine" : ""}' to store runtime credentials.`
|
|
1340
|
+
: `fix: ${(0, vault_unlock_1.vaultUnlockReplaceRecoverFix)(command.agent, "Then retry 'ouro vault config status'.")}`);
|
|
1341
|
+
}
|
|
1236
1342
|
}
|
|
1237
1343
|
}
|
|
1344
|
+
finally {
|
|
1345
|
+
progress.end();
|
|
1346
|
+
}
|
|
1238
1347
|
const message = lines.join("\n");
|
|
1239
1348
|
deps.writeStdout(message);
|
|
1240
1349
|
return message;
|
|
@@ -1714,7 +1823,20 @@ function renderProviderCredentialLine(credential) {
|
|
|
1714
1823
|
}
|
|
1715
1824
|
async function executeProviderStatus(command, deps) {
|
|
1716
1825
|
const agentRoot = providerCliAgentRoot(command, deps);
|
|
1717
|
-
|
|
1826
|
+
const progress = createHumanCommandProgress(deps, "provider status");
|
|
1827
|
+
try {
|
|
1828
|
+
await runCommandProgressPhase(progress, "reading provider credentials", () => (0, provider_credentials_1.refreshProviderCredentialPool)(command.agent, {
|
|
1829
|
+
onProgress: (message) => progress.updateDetail(message),
|
|
1830
|
+
}), (poolResult) => {
|
|
1831
|
+
if (!poolResult.ok)
|
|
1832
|
+
return poolResult.reason;
|
|
1833
|
+
const summary = (0, provider_credentials_1.summarizeProviderCredentialPool)(poolResult.pool);
|
|
1834
|
+
return summary.providers.map((provider) => provider.provider).join(", ") || "none stored";
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
finally {
|
|
1838
|
+
progress.end();
|
|
1839
|
+
}
|
|
1718
1840
|
const homeDir = providerCliHomeDir(deps);
|
|
1719
1841
|
const lines = [`provider status: ${command.agent}`];
|
|
1720
1842
|
for (const lane of ["outward", "inner"]) {
|
|
@@ -2006,36 +2128,61 @@ async function executeLegacyConfigModel(command, deps) {
|
|
|
2006
2128
|
const lane = command.facing === "agent" ? "inner" : "outward";
|
|
2007
2129
|
const { agentRoot, state } = readOrBootstrapProviderState(command.agent, deps);
|
|
2008
2130
|
const binding = state.lanes[lane];
|
|
2131
|
+
const progress = binding.provider === "github-copilot" ? createHumanCommandProgress(deps, "config model") : null;
|
|
2132
|
+
const writeMessage = (message) => {
|
|
2133
|
+
progress?.end();
|
|
2134
|
+
deps.writeStdout(message);
|
|
2135
|
+
return message;
|
|
2136
|
+
};
|
|
2009
2137
|
if (binding.provider === "github-copilot") {
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
const
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2138
|
+
try {
|
|
2139
|
+
progress?.startPhase("reading github-copilot credentials");
|
|
2140
|
+
const credential = await readProviderCredentialRecord(command.agent, "github-copilot", deps, {
|
|
2141
|
+
onProgress: (message) => progress?.updateDetail(message),
|
|
2142
|
+
});
|
|
2143
|
+
if (credential.ok) {
|
|
2144
|
+
const ghConfig = {
|
|
2145
|
+
...credential.record.config,
|
|
2146
|
+
...credential.record.credentials,
|
|
2147
|
+
};
|
|
2148
|
+
const githubToken = ghConfig.githubToken;
|
|
2149
|
+
const baseUrl = ghConfig.baseUrl;
|
|
2150
|
+
if (typeof githubToken === "string" && typeof baseUrl === "string") {
|
|
2151
|
+
progress?.completePhase("reading github-copilot credentials", "found");
|
|
2152
|
+
const fetchFn = deps.fetchImpl ?? fetch;
|
|
2153
|
+
try {
|
|
2154
|
+
progress?.startPhase("listing github-copilot models");
|
|
2155
|
+
const models = await listGithubCopilotModels(baseUrl, githubToken, fetchFn);
|
|
2156
|
+
const available = models.map((m) => m.id);
|
|
2157
|
+
progress?.completePhase("listing github-copilot models", `${available.length} model${available.length === 1 ? "" : "s"}`);
|
|
2158
|
+
if (available.length > 0 && !available.includes(command.modelName)) {
|
|
2159
|
+
const message = `model '${command.modelName}' not found. available models:\n${available.map((id) => ` ${id}`).join("\n")}`;
|
|
2160
|
+
return writeMessage(message);
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
catch {
|
|
2164
|
+
progress?.completePhase("listing github-copilot models", "skipped");
|
|
2165
|
+
// Catalog validation failed; the live ping below gives the actionable result.
|
|
2166
|
+
}
|
|
2167
|
+
progress?.startPhase(`checking ${command.modelName}`);
|
|
2168
|
+
const pingResult = await (0, provider_ping_1.pingGithubCopilotModel)(baseUrl, githubToken, command.modelName, fetchFn);
|
|
2169
|
+
progress?.completePhase(`checking ${command.modelName}`, pingResult.ok ? "ok" : "failed");
|
|
2170
|
+
if (!pingResult.ok) {
|
|
2171
|
+
const message = `model '${command.modelName}' ping failed: ${pingResult.error}\nrun \`ouro config models --agent ${command.agent}\` to see available models.`;
|
|
2172
|
+
return writeMessage(message);
|
|
2027
2173
|
}
|
|
2028
2174
|
}
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
}
|
|
2032
|
-
const pingResult = await (0, provider_ping_1.pingGithubCopilotModel)(baseUrl, githubToken, command.modelName, fetchFn);
|
|
2033
|
-
if (!pingResult.ok) {
|
|
2034
|
-
const message = `model '${command.modelName}' ping failed: ${pingResult.error}\nrun \`ouro config models --agent ${command.agent}\` to see available models.`;
|
|
2035
|
-
deps.writeStdout(message);
|
|
2036
|
-
return message;
|
|
2175
|
+
else {
|
|
2176
|
+
progress?.completePhase("reading github-copilot credentials", "missing fields");
|
|
2037
2177
|
}
|
|
2038
2178
|
}
|
|
2179
|
+
else {
|
|
2180
|
+
progress?.completePhase("reading github-copilot credentials", credential.reason);
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
catch (error) {
|
|
2184
|
+
progress?.end();
|
|
2185
|
+
throw error;
|
|
2039
2186
|
}
|
|
2040
2187
|
}
|
|
2041
2188
|
const updatedAt = providerCliNow(deps).toISOString();
|
|
@@ -2049,8 +2196,7 @@ async function executeLegacyConfigModel(command, deps) {
|
|
|
2049
2196
|
delete state.readiness[lane];
|
|
2050
2197
|
(0, provider_state_1.writeProviderState)(agentRoot, state);
|
|
2051
2198
|
const message = `deprecated: updated ${command.agent} model on ${lane}/${binding.provider}: ${binding.model} -> ${command.modelName}\nUse \`ouro use --agent ${command.agent} --lane ${lane} --provider ${binding.provider} --model ${command.modelName}\` next time.`;
|
|
2052
|
-
|
|
2053
|
-
return message;
|
|
2199
|
+
return writeMessage(message);
|
|
2054
2200
|
}
|
|
2055
2201
|
// ── System setup ──
|
|
2056
2202
|
async function registerOuroBundleTypeNonBlocking(deps) {
|
|
@@ -2847,11 +2993,11 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
2847
2993
|
promptInput: deps.promptInput ?? (async () => "n"),
|
|
2848
2994
|
writeStdout: deps.writeStdout,
|
|
2849
2995
|
runAuthFlow: async (agent, providerOverride) => {
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2996
|
+
await executeAuthRun({
|
|
2997
|
+
kind: "auth.run",
|
|
2998
|
+
agent,
|
|
2999
|
+
...(providerOverride ? { provider: providerOverride } : {}),
|
|
3000
|
+
}, deps);
|
|
2855
3001
|
},
|
|
2856
3002
|
runVaultUnlock: async (agent) => {
|
|
2857
3003
|
await executeVaultUnlock({ kind: "vault.unlock", agent }, deps);
|
|
@@ -3561,28 +3707,44 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
3561
3707
|
deps.writeStdout(message);
|
|
3562
3708
|
return message;
|
|
3563
3709
|
}
|
|
3564
|
-
const
|
|
3565
|
-
const
|
|
3566
|
-
|
|
3567
|
-
: {};
|
|
3568
|
-
if (typeof ghConfig.githubToken !== "string" || typeof ghConfig.baseUrl !== "string") {
|
|
3569
|
-
throw new Error(`github-copilot credentials not configured. Run \`ouro auth --agent ${command.agent} --provider github-copilot\` first.`);
|
|
3570
|
-
}
|
|
3571
|
-
const fetchFn = deps.fetchImpl ?? fetch;
|
|
3572
|
-
const models = await listGithubCopilotModels(ghConfig.baseUrl, ghConfig.githubToken, fetchFn);
|
|
3573
|
-
if (models.length === 0) {
|
|
3574
|
-
const message = "no models found";
|
|
3710
|
+
const progress = createHumanCommandProgress(deps, "config models");
|
|
3711
|
+
const writeMessage = (message) => {
|
|
3712
|
+
progress.end();
|
|
3575
3713
|
deps.writeStdout(message);
|
|
3576
3714
|
return message;
|
|
3715
|
+
};
|
|
3716
|
+
try {
|
|
3717
|
+
progress.startPhase("reading github-copilot credentials");
|
|
3718
|
+
const credential = await readProviderCredentialRecord(command.agent, "github-copilot", deps, {
|
|
3719
|
+
onProgress: (message) => progress.updateDetail(message),
|
|
3720
|
+
});
|
|
3721
|
+
const ghConfig = credential.ok
|
|
3722
|
+
? { ...credential.record.config, ...credential.record.credentials }
|
|
3723
|
+
: {};
|
|
3724
|
+
if (!credential.ok || typeof ghConfig.githubToken !== "string" || typeof ghConfig.baseUrl !== "string") {
|
|
3725
|
+
progress.completePhase("reading github-copilot credentials", credential.ok ? "missing fields" : credential.reason);
|
|
3726
|
+
throw new Error(`github-copilot credentials not configured. Run \`ouro auth --agent ${command.agent} --provider github-copilot\` first.`);
|
|
3727
|
+
}
|
|
3728
|
+
progress.completePhase("reading github-copilot credentials", "found");
|
|
3729
|
+
const fetchFn = deps.fetchImpl ?? fetch;
|
|
3730
|
+
progress.startPhase("listing github-copilot models");
|
|
3731
|
+
const models = await listGithubCopilotModels(ghConfig.baseUrl, ghConfig.githubToken, fetchFn);
|
|
3732
|
+
progress.completePhase("listing github-copilot models", `${models.length} model${models.length === 1 ? "" : "s"}`);
|
|
3733
|
+
if (models.length === 0) {
|
|
3734
|
+
return writeMessage("no models found");
|
|
3735
|
+
}
|
|
3736
|
+
const lines = ["available models:"];
|
|
3737
|
+
for (const m of models) {
|
|
3738
|
+
const caps = m.capabilities?.length ? ` (${m.capabilities.join(", ")})` : "";
|
|
3739
|
+
lines.push(` ${m.id}${caps}`);
|
|
3740
|
+
}
|
|
3741
|
+
const message = lines.join("\n");
|
|
3742
|
+
return writeMessage(message);
|
|
3577
3743
|
}
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
lines.push(` ${m.id}${caps}`);
|
|
3744
|
+
catch (error) {
|
|
3745
|
+
progress.end();
|
|
3746
|
+
throw error;
|
|
3582
3747
|
}
|
|
3583
|
-
const message = lines.join("\n");
|
|
3584
|
-
deps.writeStdout(message);
|
|
3585
|
-
return message;
|
|
3586
3748
|
}
|
|
3587
3749
|
/* v8 ignore stop */
|
|
3588
3750
|
// ── config model (local, no daemon socket needed) ──
|