@ouro.bot/cli 0.1.0-alpha.327 → 0.1.0-alpha.329
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 +13 -0
- package/dist/heart/auth/auth-flow.js +14 -7
- package/dist/heart/core.js +29 -3
- package/dist/heart/daemon/cli-defaults.js +2 -7
- package/dist/heart/daemon/cli-exec.js +10 -1
- package/dist/heart/hatch/hatch-flow.js +4 -2
- package/dist/heart/provider-failover.js +70 -23
- package/dist/heart/provider-models.js +81 -0
- package/dist/senses/pipeline.js +5 -3
- package/package.json +2 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
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.329",
|
|
6
|
+
"changes": [
|
|
7
|
+
"fix(wrapper): make fresh first-run `npx ouro.bot --version` pass through to the installed CLI after bootstrap, while preserving first-install PATH guidance for bare `npx ouro.bot`."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"version": "0.1.0-alpha.328",
|
|
12
|
+
"changes": [
|
|
13
|
+
"fix(auth): keep provider switches model-aware so changing providers updates incompatible model pairings to safe provider defaults instead of carrying stale model names across OpenAI Codex, Anthropic, MiniMax, Azure, and GitHub Copilot.",
|
|
14
|
+
"fix(auth): rewrite provider auth/failover guidance into multiline actionable sections with provider error details, model-mismatch repair commands, and ready-provider switch prompts."
|
|
15
|
+
]
|
|
16
|
+
},
|
|
4
17
|
{
|
|
5
18
|
"version": "0.1.0-alpha.327",
|
|
6
19
|
"changes": [
|
|
@@ -48,33 +48,29 @@ const path = __importStar(require("path"));
|
|
|
48
48
|
const runtime_1 = require("../../nerves/runtime");
|
|
49
49
|
const identity_1 = require("../identity");
|
|
50
50
|
const migrate_config_1 = require("../migrate-config");
|
|
51
|
+
const provider_models_1 = require("../provider-models");
|
|
51
52
|
const ANTHROPIC_SETUP_TOKEN_PREFIX = "sk-ant-oat01-";
|
|
52
53
|
const ANTHROPIC_SETUP_TOKEN_MIN_LENGTH = 80;
|
|
53
54
|
const DEFAULT_SECRETS_TEMPLATE = {
|
|
54
55
|
providers: {
|
|
55
56
|
azure: {
|
|
56
|
-
modelName: "gpt-4o-mini",
|
|
57
57
|
apiKey: "",
|
|
58
58
|
endpoint: "",
|
|
59
59
|
deployment: "",
|
|
60
60
|
apiVersion: "2025-04-01-preview",
|
|
61
61
|
},
|
|
62
62
|
minimax: {
|
|
63
|
-
model: "MiniMax-M2.7",
|
|
64
63
|
apiKey: "",
|
|
65
64
|
},
|
|
66
65
|
anthropic: {
|
|
67
|
-
model: "claude-opus-4-6",
|
|
68
66
|
setupToken: "",
|
|
69
67
|
refreshToken: "",
|
|
70
68
|
expiresAt: 0,
|
|
71
69
|
},
|
|
72
70
|
"openai-codex": {
|
|
73
|
-
model: "gpt-5.4",
|
|
74
71
|
oauthAccessToken: "",
|
|
75
72
|
},
|
|
76
73
|
"github-copilot": {
|
|
77
|
-
model: "claude-sonnet-4.6",
|
|
78
74
|
githubToken: "",
|
|
79
75
|
baseUrl: "",
|
|
80
76
|
},
|
|
@@ -176,16 +172,27 @@ function readAgentConfigForAgent(agentName, bundlesRoot = (0, identity_1.getAgen
|
|
|
176
172
|
function writeAgentProviderSelection(agentName, facing, provider, bundlesRoot = (0, identity_1.getAgentBundlesRoot)()) {
|
|
177
173
|
const { configPath, config } = readAgentConfigForAgent(agentName, bundlesRoot);
|
|
178
174
|
const facingKey = facing === "human" ? "humanFacing" : "agentFacing";
|
|
175
|
+
const previousFacing = config[facingKey];
|
|
176
|
+
const resolved = (0, provider_models_1.resolveModelForProviderSelection)(provider, previousFacing.model);
|
|
179
177
|
const nextConfig = {
|
|
180
178
|
...config,
|
|
181
|
-
[facingKey]: { ...
|
|
179
|
+
[facingKey]: { ...previousFacing, provider, model: resolved.model },
|
|
182
180
|
};
|
|
183
181
|
fs.writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf8");
|
|
184
182
|
(0, runtime_1.emitNervesEvent)({
|
|
185
183
|
component: "daemon",
|
|
186
184
|
event: "daemon.auth_provider_selected",
|
|
187
185
|
message: "updated agent provider selection after auth flow",
|
|
188
|
-
meta: {
|
|
186
|
+
meta: {
|
|
187
|
+
agentName,
|
|
188
|
+
facing,
|
|
189
|
+
provider,
|
|
190
|
+
previousProvider: previousFacing.provider,
|
|
191
|
+
previousModel: previousFacing.model,
|
|
192
|
+
model: resolved.model,
|
|
193
|
+
preservedModel: resolved.preserved,
|
|
194
|
+
configPath,
|
|
195
|
+
},
|
|
189
196
|
});
|
|
190
197
|
return configPath;
|
|
191
198
|
}
|
package/dist/heart/core.js
CHANGED
|
@@ -32,6 +32,7 @@ const obligations_1 = require("../arc/obligations");
|
|
|
32
32
|
const tool_loop_1 = require("./tool-loop");
|
|
33
33
|
const packets_1 = require("../arc/packets");
|
|
34
34
|
const tool_friction_1 = require("./tool-friction");
|
|
35
|
+
const provider_models_1 = require("./provider-models");
|
|
35
36
|
const _providerRuntimes = {
|
|
36
37
|
human: null,
|
|
37
38
|
agent: null,
|
|
@@ -405,6 +406,33 @@ const RETRY_LABELS = {
|
|
|
405
406
|
"network-error": "network error",
|
|
406
407
|
"unknown": "error",
|
|
407
408
|
};
|
|
409
|
+
function buildAuthFailureGuidance(provider, model, agentName, detail) {
|
|
410
|
+
const mismatch = (0, provider_models_1.getProviderModelMismatchMessage)(provider, model);
|
|
411
|
+
const modelLabel = model
|
|
412
|
+
? mismatch
|
|
413
|
+
? `${provider} [configured model: ${model}]`
|
|
414
|
+
: `${provider} (${model})`
|
|
415
|
+
: provider;
|
|
416
|
+
const lines = [`${modelLabel} authentication failed.`];
|
|
417
|
+
const cleanDetail = detail.replace(/\s+/g, " ").trim();
|
|
418
|
+
if (cleanDetail)
|
|
419
|
+
lines.push(`provider detail: ${cleanDetail.length > 300 ? `${cleanDetail.slice(0, 297)}...` : cleanDetail}`);
|
|
420
|
+
lines.push("");
|
|
421
|
+
lines.push("To keep using this provider:");
|
|
422
|
+
lines.push(` 1. Run \`ouro auth --agent ${agentName} --provider ${provider}\``);
|
|
423
|
+
if (mismatch) {
|
|
424
|
+
const defaultModel = (0, provider_models_1.getDefaultModelForProvider)(provider);
|
|
425
|
+
lines.push("");
|
|
426
|
+
lines.push("Config warning:");
|
|
427
|
+
lines.push(` - ${mismatch}`);
|
|
428
|
+
lines.push(" - Repair the configured model with:");
|
|
429
|
+
lines.push(` \`ouro config model --agent ${agentName} --facing human ${defaultModel}\``);
|
|
430
|
+
lines.push(` \`ouro config model --agent ${agentName} --facing agent ${defaultModel}\``);
|
|
431
|
+
}
|
|
432
|
+
lines.push("");
|
|
433
|
+
lines.push(`To use another configured provider instead, run \`ouro auth switch --agent ${agentName} --provider <provider>\`.`);
|
|
434
|
+
return lines.join("\n");
|
|
435
|
+
}
|
|
408
436
|
async function runAgent(messages, callbacks, channel, signal, options) {
|
|
409
437
|
const facing = (0, channel_1.channelToFacing)(channel);
|
|
410
438
|
const providerRuntime = getProviderRuntime(facing);
|
|
@@ -1025,9 +1053,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1025
1053
|
if (terminalErrorClassification === "auth-failure") {
|
|
1026
1054
|
const agentName = (0, identity_2.getAgentName)();
|
|
1027
1055
|
const currentProvider = providerRuntime.id;
|
|
1028
|
-
callbacks.onError(new Error(
|
|
1029
|
-
`Run \`ouro auth --agent ${agentName} --provider ${currentProvider}\` to refresh credentials, ` +
|
|
1030
|
-
`or \`ouro auth switch --agent ${agentName} --provider <other>\` to switch providers.`), "terminal");
|
|
1056
|
+
callbacks.onError(new Error(buildAuthFailureGuidance(currentProvider, providerRuntime.model, agentName, terminalError.message)), "terminal");
|
|
1031
1057
|
}
|
|
1032
1058
|
else {
|
|
1033
1059
|
callbacks.onError(terminalError, "terminal");
|
|
@@ -70,6 +70,7 @@ const launchd_1 = require("./launchd");
|
|
|
70
70
|
const socket_client_1 = require("./socket-client");
|
|
71
71
|
const session_activity_1 = require("../session-activity");
|
|
72
72
|
const auth_flow_1 = require("../auth/auth-flow");
|
|
73
|
+
const provider_models_1 = require("../provider-models");
|
|
73
74
|
const cli_parse_1 = require("./cli-parse");
|
|
74
75
|
const provider_discovery_1 = require("./provider-discovery");
|
|
75
76
|
// ── Default implementations ──
|
|
@@ -305,13 +306,7 @@ async function defaultRunSerpentGuide() {
|
|
|
305
306
|
const existingBundleCount = (0, specialist_orchestrator_1.listExistingBundles)((0, identity_1.getAgentBundlesRoot)()).length;
|
|
306
307
|
const hatchVerb = existingBundleCount > 0 ? "let's hatch a new agent." : "let's hatch your first agent.";
|
|
307
308
|
// Default models per provider (used when entering new credentials)
|
|
308
|
-
const defaultModels =
|
|
309
|
-
anthropic: "claude-opus-4-6",
|
|
310
|
-
minimax: "MiniMax-M2.7",
|
|
311
|
-
"openai-codex": "gpt-5.4",
|
|
312
|
-
"github-copilot": "claude-sonnet-4.6",
|
|
313
|
-
azure: "",
|
|
314
|
-
};
|
|
309
|
+
const defaultModels = provider_models_1.DEFAULT_PROVIDER_MODELS;
|
|
315
310
|
// Scan environment variables for API keys using the shared helper
|
|
316
311
|
const envCreds = (0, provider_discovery_1.scanEnvVarCredentials)(process.env);
|
|
317
312
|
const envDiscovered = [];
|
|
@@ -1776,7 +1776,16 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
1776
1776
|
(0, auth_flow_1.writeAgentProviderSelection)(command.agent, "human", command.provider, deps.bundlesRoot);
|
|
1777
1777
|
(0, auth_flow_1.writeAgentProviderSelection)(command.agent, "agent", command.provider, deps.bundlesRoot);
|
|
1778
1778
|
}
|
|
1779
|
-
const
|
|
1779
|
+
const { config: updatedConfig } = (0, auth_flow_1.readAgentConfigForAgent)(command.agent, deps.bundlesRoot);
|
|
1780
|
+
const facingSummary = command.facing
|
|
1781
|
+
? (() => {
|
|
1782
|
+
const facingConfig = command.facing === "human" ? updatedConfig.humanFacing : updatedConfig.agentFacing;
|
|
1783
|
+
return `${command.facing} model: ${facingConfig.model}`;
|
|
1784
|
+
})()
|
|
1785
|
+
: updatedConfig.humanFacing.model === updatedConfig.agentFacing.model
|
|
1786
|
+
? `model: ${updatedConfig.humanFacing.model}`
|
|
1787
|
+
: `human model: ${updatedConfig.humanFacing.model}; agent model: ${updatedConfig.agentFacing.model}`;
|
|
1788
|
+
const message = `switched ${command.agent} to ${command.provider} (${facingSummary}; verified working)`;
|
|
1780
1789
|
deps.writeStdout(message);
|
|
1781
1790
|
return message;
|
|
1782
1791
|
}
|
|
@@ -42,6 +42,7 @@ const identity_1 = require("../identity");
|
|
|
42
42
|
const config_1 = require("../config");
|
|
43
43
|
const runtime_1 = require("../../nerves/runtime");
|
|
44
44
|
const auth_flow_1 = require("../auth/auth-flow");
|
|
45
|
+
const provider_models_1 = require("../provider-models");
|
|
45
46
|
const habit_parser_1 = require("../habits/habit-parser");
|
|
46
47
|
const hatch_specialist_1 = require("./hatch-specialist");
|
|
47
48
|
function requiredCredentialKeys(provider) {
|
|
@@ -124,9 +125,10 @@ function writeDiaryScaffold(bundleRoot) {
|
|
|
124
125
|
}
|
|
125
126
|
function writeHatchlingAgentConfig(bundleRoot, input) {
|
|
126
127
|
const template = (0, identity_1.buildDefaultAgentTemplate)(input.agentName);
|
|
128
|
+
const model = (0, provider_models_1.getDefaultModelForProvider)(input.provider);
|
|
127
129
|
template.provider = input.provider;
|
|
128
|
-
template.humanFacing = { provider: input.provider, model
|
|
129
|
-
template.agentFacing = { provider: input.provider, model
|
|
130
|
+
template.humanFacing = { provider: input.provider, model };
|
|
131
|
+
template.agentFacing = { provider: input.provider, model };
|
|
130
132
|
template.enabled = true;
|
|
131
133
|
fs.writeFileSync(path.join(bundleRoot, "agent.json"), `${JSON.stringify(template, null, 2)}\n`, "utf-8");
|
|
132
134
|
}
|
|
@@ -2,15 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildFailoverContext = buildFailoverContext;
|
|
4
4
|
exports.handleFailoverReply = handleFailoverReply;
|
|
5
|
+
const provider_models_1 = require("./provider-models");
|
|
5
6
|
const runtime_1 = require("../nerves/runtime");
|
|
6
|
-
const FAILING_PROVIDER_LABELS = {
|
|
7
|
-
"auth-failure": "its credentials need to be refreshed",
|
|
8
|
-
"usage-limit": "has also hit its usage limit",
|
|
9
|
-
"rate-limit": "is also being rate limited",
|
|
10
|
-
"server-error": "is also experiencing an outage",
|
|
11
|
-
"network-error": "could not be reached",
|
|
12
|
-
"unknown": "could not be reached",
|
|
13
|
-
};
|
|
14
7
|
const CLASSIFICATION_LABELS = {
|
|
15
8
|
"auth-failure": "authentication failed",
|
|
16
9
|
"usage-limit": "hit its usage limit",
|
|
@@ -19,10 +12,43 @@ const CLASSIFICATION_LABELS = {
|
|
|
19
12
|
"network-error": "is unreachable (network error)",
|
|
20
13
|
"unknown": "encountered an error",
|
|
21
14
|
};
|
|
22
|
-
function
|
|
15
|
+
function formatProviderWithModel(provider, model) {
|
|
16
|
+
if (!model)
|
|
17
|
+
return provider;
|
|
18
|
+
if ((0, provider_models_1.getProviderModelMismatchMessage)(provider, model)) {
|
|
19
|
+
return `${provider} [configured model: ${model}]`;
|
|
20
|
+
}
|
|
21
|
+
return `${provider} (${model})`;
|
|
22
|
+
}
|
|
23
|
+
function formatErrorDetail(errorMessage, errorSummary) {
|
|
24
|
+
const detail = errorMessage.replace(/\s+/g, " ").trim();
|
|
25
|
+
if (!detail || detail === errorSummary)
|
|
26
|
+
return "";
|
|
27
|
+
return detail.length > 300 ? `${detail.slice(0, 297)}...` : detail;
|
|
28
|
+
}
|
|
29
|
+
function formatFailingProviderLine(provider, classification, agentName) {
|
|
30
|
+
const authCommand = `ouro auth --agent ${agentName} --provider ${provider}`;
|
|
31
|
+
switch (classification) {
|
|
32
|
+
case "auth-failure":
|
|
33
|
+
return ` - ${provider}: credentials need to be refreshed. Run \`${authCommand}\`.`;
|
|
34
|
+
case "network-error":
|
|
35
|
+
return ` - ${provider}: could not be reached. Check network/provider availability; if credentials may be stale, run \`${authCommand}\`.`;
|
|
36
|
+
case "server-error":
|
|
37
|
+
return ` - ${provider}: provider outage or server error. Retry later; if it keeps failing, run \`${authCommand}\`.`;
|
|
38
|
+
case "rate-limit":
|
|
39
|
+
return ` - ${provider}: rate limited. Wait and retry, or switch to a ready provider below.`;
|
|
40
|
+
case "usage-limit":
|
|
41
|
+
return ` - ${provider}: usage limit hit. Wait for quota reset, raise quota, or switch to a ready provider below.`;
|
|
42
|
+
case "unknown":
|
|
43
|
+
return ` - ${provider}: could not be reached. Run \`${authCommand}\` if credentials may be stale.`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function buildFailoverContext(errorMessage, classification, currentProvider, currentModel, agentName, inventory, providerModels) {
|
|
23
47
|
const label = CLASSIFICATION_LABELS[classification];
|
|
24
|
-
const providerWithModel =
|
|
48
|
+
const providerWithModel = formatProviderWithModel(currentProvider, currentModel);
|
|
25
49
|
const errorSummary = `${providerWithModel} ${label}`;
|
|
50
|
+
const errorDetail = formatErrorDetail(errorMessage, errorSummary);
|
|
51
|
+
const modelMismatch = (0, provider_models_1.getProviderModelMismatchMessage)(currentProvider, currentModel);
|
|
26
52
|
const workingProviders = [];
|
|
27
53
|
const unconfiguredProviders = [];
|
|
28
54
|
const failingProviders = [];
|
|
@@ -39,27 +65,48 @@ function buildFailoverContext(_errorMessage, classification, currentProvider, cu
|
|
|
39
65
|
}
|
|
40
66
|
}
|
|
41
67
|
const lines = [`${errorSummary}.`];
|
|
68
|
+
if (errorDetail) {
|
|
69
|
+
lines.push(`provider detail: ${errorDetail}`);
|
|
70
|
+
}
|
|
71
|
+
if (classification === "auth-failure") {
|
|
72
|
+
lines.push("");
|
|
73
|
+
lines.push("To keep using the current provider:");
|
|
74
|
+
lines.push(` 1. Run \`ouro auth --agent ${agentName} --provider ${currentProvider}\``);
|
|
75
|
+
}
|
|
76
|
+
if (modelMismatch) {
|
|
77
|
+
const defaultModel = (0, provider_models_1.getDefaultModelForProvider)(currentProvider);
|
|
78
|
+
lines.push("");
|
|
79
|
+
lines.push("Config warning:");
|
|
80
|
+
lines.push(` - ${modelMismatch}`);
|
|
81
|
+
lines.push(" - Repair the configured model with:");
|
|
82
|
+
lines.push(` \`ouro config model --agent ${agentName} --facing human ${defaultModel}\``);
|
|
83
|
+
lines.push(` \`ouro config model --agent ${agentName} --facing agent ${defaultModel}\``);
|
|
84
|
+
}
|
|
42
85
|
if (workingProviders.length > 0) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
lines.push(`reply ${switchOptions} to continue.`);
|
|
86
|
+
lines.push("");
|
|
87
|
+
lines.push("Ready providers:");
|
|
88
|
+
for (const provider of workingProviders) {
|
|
89
|
+
const model = (0, provider_models_1.resolveModelForProviderDisplay)(provider, providerModels[provider]);
|
|
90
|
+
lines.push(` - ${provider} (${model}): reply "switch to ${provider}"`);
|
|
91
|
+
}
|
|
50
92
|
}
|
|
51
93
|
if (failingProviders.length > 0) {
|
|
94
|
+
lines.push("");
|
|
95
|
+
lines.push("Configured but unavailable:");
|
|
52
96
|
for (const { provider, classification } of failingProviders) {
|
|
53
|
-
|
|
54
|
-
const detail = FAILING_PROVIDER_LABELS[classification] ?? "could not be reached";
|
|
55
|
-
lines.push(`${provider} is configured but ${detail}. run \`ouro auth --agent ${agentName} --provider ${provider}\` to refresh.`);
|
|
97
|
+
lines.push(formatFailingProviderLine(provider, classification, agentName));
|
|
56
98
|
}
|
|
57
99
|
}
|
|
58
100
|
if (unconfiguredProviders.length > 0) {
|
|
59
|
-
lines.push(
|
|
101
|
+
lines.push("");
|
|
102
|
+
lines.push("Not configured:");
|
|
103
|
+
for (const provider of unconfiguredProviders) {
|
|
104
|
+
lines.push(` - ${provider}: run \`ouro auth --agent ${agentName} --provider ${provider}\``);
|
|
105
|
+
}
|
|
60
106
|
}
|
|
61
107
|
if (workingProviders.length === 0 && unconfiguredProviders.length === 0 && failingProviders.length === 0) {
|
|
62
|
-
lines.push(
|
|
108
|
+
lines.push("");
|
|
109
|
+
lines.push(`No other providers are available. Run \`ouro auth --agent ${agentName}\` in terminal to configure one.`);
|
|
63
110
|
}
|
|
64
111
|
(0, runtime_1.emitNervesEvent)({
|
|
65
112
|
component: "engine",
|
|
@@ -74,7 +121,7 @@ function buildFailoverContext(_errorMessage, classification, currentProvider, cu
|
|
|
74
121
|
agentName,
|
|
75
122
|
workingProviders,
|
|
76
123
|
unconfiguredProviders,
|
|
77
|
-
userMessage: lines.join("
|
|
124
|
+
userMessage: lines.join("\n"),
|
|
78
125
|
};
|
|
79
126
|
}
|
|
80
127
|
function handleFailoverReply(reply, context) {
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_PROVIDER_MODELS = void 0;
|
|
4
|
+
exports.getProviderDisplayName = getProviderDisplayName;
|
|
5
|
+
exports.getDefaultModelForProvider = getDefaultModelForProvider;
|
|
6
|
+
exports.isModelClearlyIncompatibleWithProvider = isModelClearlyIncompatibleWithProvider;
|
|
7
|
+
exports.resolveModelForProviderSelection = resolveModelForProviderSelection;
|
|
8
|
+
exports.resolveModelForProviderDisplay = resolveModelForProviderDisplay;
|
|
9
|
+
exports.getProviderModelMismatchMessage = getProviderModelMismatchMessage;
|
|
10
|
+
const runtime_1 = require("../nerves/runtime");
|
|
11
|
+
exports.DEFAULT_PROVIDER_MODELS = {
|
|
12
|
+
anthropic: "claude-opus-4-6",
|
|
13
|
+
azure: "gpt-4o-mini",
|
|
14
|
+
minimax: "MiniMax-M2.7",
|
|
15
|
+
"openai-codex": "gpt-5.4",
|
|
16
|
+
"github-copilot": "claude-sonnet-4.6",
|
|
17
|
+
};
|
|
18
|
+
const PROVIDER_NAMES = {
|
|
19
|
+
anthropic: "Anthropic",
|
|
20
|
+
azure: "Azure OpenAI",
|
|
21
|
+
minimax: "MiniMax",
|
|
22
|
+
"openai-codex": "OpenAI Codex",
|
|
23
|
+
"github-copilot": "GitHub Copilot",
|
|
24
|
+
};
|
|
25
|
+
function normalized(model) {
|
|
26
|
+
return model.trim().toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
function getProviderDisplayName(provider) {
|
|
29
|
+
return PROVIDER_NAMES[provider];
|
|
30
|
+
}
|
|
31
|
+
function getDefaultModelForProvider(provider) {
|
|
32
|
+
return exports.DEFAULT_PROVIDER_MODELS[provider];
|
|
33
|
+
}
|
|
34
|
+
function isModelClearlyIncompatibleWithProvider(provider, model) {
|
|
35
|
+
const value = normalized(model);
|
|
36
|
+
if (!value)
|
|
37
|
+
return true;
|
|
38
|
+
switch (provider) {
|
|
39
|
+
case "anthropic":
|
|
40
|
+
return !value.startsWith("claude-");
|
|
41
|
+
case "minimax":
|
|
42
|
+
return !value.startsWith("minimax");
|
|
43
|
+
case "openai-codex":
|
|
44
|
+
return value.startsWith("claude-") || value.startsWith("minimax");
|
|
45
|
+
case "azure":
|
|
46
|
+
return value.startsWith("claude-") || value.startsWith("minimax");
|
|
47
|
+
case "github-copilot":
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function resolveModelForProviderSelection(provider, currentModel) {
|
|
52
|
+
const trimmed = currentModel.trim();
|
|
53
|
+
if (trimmed && !isModelClearlyIncompatibleWithProvider(provider, trimmed)) {
|
|
54
|
+
return { model: trimmed, preserved: true };
|
|
55
|
+
}
|
|
56
|
+
const model = getDefaultModelForProvider(provider);
|
|
57
|
+
(0, runtime_1.emitNervesEvent)({
|
|
58
|
+
component: "config/identity",
|
|
59
|
+
event: "config_identity.provider_model_defaulted",
|
|
60
|
+
message: "defaulted provider model during provider selection",
|
|
61
|
+
meta: { provider, previousModel: currentModel, model },
|
|
62
|
+
});
|
|
63
|
+
return { model, preserved: false };
|
|
64
|
+
}
|
|
65
|
+
function resolveModelForProviderDisplay(provider, modelHint) {
|
|
66
|
+
const hint = modelHint?.trim() ?? "";
|
|
67
|
+
if (hint && !isModelClearlyIncompatibleWithProvider(provider, hint))
|
|
68
|
+
return hint;
|
|
69
|
+
return getDefaultModelForProvider(provider);
|
|
70
|
+
}
|
|
71
|
+
function getProviderModelMismatchMessage(provider, model) {
|
|
72
|
+
const trimmed = model.trim();
|
|
73
|
+
if (!isModelClearlyIncompatibleWithProvider(provider, trimmed))
|
|
74
|
+
return null;
|
|
75
|
+
const providerName = getProviderDisplayName(provider);
|
|
76
|
+
const defaultModel = getDefaultModelForProvider(provider);
|
|
77
|
+
if (!trimmed) {
|
|
78
|
+
return `${providerName} has no model set. Suggested model: ${defaultModel}.`;
|
|
79
|
+
}
|
|
80
|
+
return `${providerName} is currently paired with ${trimmed}, which does not look like a model for ${providerName}. Suggested model: ${defaultModel}.`;
|
|
81
|
+
}
|
package/dist/senses/pipeline.js
CHANGED
|
@@ -54,6 +54,7 @@ const obligations_1 = require("../arc/obligations");
|
|
|
54
54
|
const provider_failover_1 = require("../heart/provider-failover");
|
|
55
55
|
const provider_ping_1 = require("../heart/provider-ping");
|
|
56
56
|
const auth_flow_1 = require("../heart/auth/auth-flow");
|
|
57
|
+
const provider_models_1 = require("../heart/provider-models");
|
|
57
58
|
const tempo_1 = require("../heart/tempo");
|
|
58
59
|
const temporal_view_1 = require("../heart/temporal-view");
|
|
59
60
|
const start_of_turn_packet_1 = require("../heart/start-of-turn-packet");
|
|
@@ -162,14 +163,15 @@ async function handleInboundTurn(input) {
|
|
|
162
163
|
try {
|
|
163
164
|
const { secrets } = (0, auth_flow_1.loadAgentSecrets)(failoverAgentName);
|
|
164
165
|
const cfg = secrets.providers[failoverAction.provider];
|
|
165
|
-
|
|
166
|
+
const hint = cfg?.model ?? cfg?.modelName;
|
|
167
|
+
return (0, provider_models_1.resolveModelForProviderDisplay)(failoverAction.provider, typeof hint === "string" ? hint : "");
|
|
166
168
|
/* v8 ignore next 2 -- defensive: secrets read failure @preserve */
|
|
167
169
|
}
|
|
168
170
|
catch {
|
|
169
|
-
return
|
|
171
|
+
return (0, provider_models_1.resolveModelForProviderDisplay)(failoverAction.provider);
|
|
170
172
|
}
|
|
171
173
|
})();
|
|
172
|
-
const newProviderLabel =
|
|
174
|
+
const newProviderLabel = `${failoverAction.provider} (${newProviderSecrets})`;
|
|
173
175
|
input.messages = [{
|
|
174
176
|
role: "user",
|
|
175
177
|
content: `[provider switch: ${pendingContext.errorSummary}. switched to ${newProviderLabel}. your conversation history is intact — respond to the user's last message.]`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouro.bot/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.329",
|
|
4
4
|
"main": "dist/heart/daemon/ouro-entry.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"cli": "dist/heart/daemon/ouro-bot-entry.js",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"test:coverage": "node scripts/run-coverage-gate.cjs",
|
|
32
32
|
"build": "tsc && (cd packages/outlook-ui && npm install --ignore-scripts 2>/dev/null && npm run build && cp -r dist ../../dist/outlook-ui) || echo 'outlook-ui build skipped'",
|
|
33
33
|
"lint": "eslint src/",
|
|
34
|
+
"release:smoke": "node scripts/release-smoke.cjs",
|
|
34
35
|
"audit:nerves": "npm run build && node dist/nerves/coverage/cli-main.js"
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|