@ouro.bot/cli 0.1.0-alpha.115 → 0.1.0-alpha.117

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 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.117",
6
+ "changes": [
7
+ "Failover messages now show human-readable reasons for failing providers instead of raw JSON API errors.",
8
+ "ouro auth now pings the provider after saving credentials and reports whether they work."
9
+ ]
10
+ },
11
+ {
12
+ "version": "0.1.0-alpha.116",
13
+ "changes": [
14
+ "Provider ping now uses a minimal direct API call (max_tokens:1, no thinking/reasoning params) instead of streamTurn, which was adding provider-specific features that could cause 400 errors unrelated to auth."
15
+ ]
16
+ },
4
17
  {
5
18
  "version": "0.1.0-alpha.115",
6
19
  "changes": [
@@ -12,7 +25,7 @@
12
25
  "changes": [
13
26
  "When a model provider fails mid-conversation (auth error, usage limit, outage), the harness now classifies the error, pings alternative configured providers, and surfaces validated failover options to the user in-channel. Reply 'switch to <provider>' to continue on a working provider.",
14
27
  "Each provider now has a `classifyError` method that distinguishes auth failures, usage/subscription limits, rate limits, server errors, and network errors. The old auth guidance wrappers are replaced by this unified classification system.",
15
- "New `pingProvider` function makes a real heartbeat completion call to verify provider credentials and quota are live no more format-only checks.",
28
+ "New `pingProvider` function makes a real heartbeat completion call to verify provider credentials and quota are live \u2014 no more format-only checks.",
16
29
  "Provider factories now accept optional config parameters, enabling credential injection for health inventory pings without touching disk config."
17
30
  ]
18
31
  },
@@ -147,7 +160,7 @@
147
160
  {
148
161
  "version": "0.1.0-alpha.94",
149
162
  "changes": [
150
- "Fix stale CurrentVersion symlink not healing during `ouro up` the daemon now detects and repairs dangling version symlinks before reading the active version.",
163
+ "Fix stale CurrentVersion symlink not healing during `ouro up` \u2014 the daemon now detects and repairs dangling version symlinks before reading the active version.",
151
164
  "Fix homedir regression in daemon-cli-defaults test and cover changelog-null branch."
152
165
  ]
153
166
  },
@@ -241,14 +254,14 @@
241
254
  {
242
255
  "version": "0.1.0-alpha.80",
243
256
  "changes": [
244
- "Bootstrap package (npx ouro.bot) now installs into ~/.ouro-cli/ versioned layout directly. No more silent npx updates every install and update is logged. Cleans up old ~/.local/bin/ouro wrapper."
257
+ "Bootstrap package (npx ouro.bot) now installs into ~/.ouro-cli/ versioned layout directly. No more silent npx updates \u2014 every install and update is logged. Cleans up old ~/.local/bin/ouro wrapper."
245
258
  ]
246
259
  },
247
260
  {
248
261
  "version": "0.1.0-alpha.79",
249
262
  "changes": [
250
263
  "New: Versioned CLI directory layout (~/.ouro-cli/) replaces npx-based ouro wrapper. Explicit version management, rollback support, and deterministic updates.",
251
- "New: `ouro up` now checks the registry for newer CLI versions, installs them into ~/.ouro-cli/versions/, activates via symlink flip, and re-execs no more silent npx downloads.",
264
+ "New: `ouro up` now checks the registry for newer CLI versions, installs them into ~/.ouro-cli/versions/, activates via symlink flip, and re-execs \u2014 no more silent npx downloads.",
252
265
  "New: `ouro rollback [<version>]` swaps CurrentVersion/previous symlinks, stops the daemon. With a version arg, installs if needed then activates.",
253
266
  "New: `ouro versions` lists cached CLI versions with * current and (previous) markers.",
254
267
  "Migration: On first run, old ~/.local/bin/ouro wrapper is removed, old PATH entry cleaned from shell profile, new ~/.ouro-cli/bin added to PATH.",
@@ -270,10 +283,10 @@
270
283
  {
271
284
  "version": "0.1.0-alpha.76",
272
285
  "changes": [
273
- "Fix: CLI chat terminal logging now filters to warn/error only info-level nerves logs go to ndjson file only, keeping the interactive TUI clean.",
286
+ "Fix: CLI chat terminal logging now filters to warn/error only \u2014 info-level nerves logs go to ndjson file only, keeping the interactive TUI clean.",
274
287
  "Fix: Streamed model output now wraps at word boundaries instead of mid-word. A new StreamingWordWrapper buffers partial lines and breaks at spaces when approaching terminal width.",
275
288
  "New: `ouro up` now prints 'ouro updated to <version> (was <previous>)' when npx downloads a newer CLI binary, separate from the agent bundle update message.",
276
- "Fix: Spinner/log interleave verified terminal sink reads pause/resume hooks at call time, not creation time, so the filterSink wrapper in CLI logging does not break spinner coordination."
289
+ "Fix: Spinner/log interleave verified \u2014 terminal sink reads pause/resume hooks at call time, not creation time, so the filterSink wrapper in CLI logging does not break spinner coordination."
277
290
  ]
278
291
  },
279
292
  {
@@ -1352,6 +1352,12 @@ function createDefaultOuroCliDeps(socketPath = socket_client_1.DEFAULT_DAEMON_SO
1352
1352
  promptInput: defaultPromptInput,
1353
1353
  runAdoptionSpecialist: defaultRunAdoptionSpecialist,
1354
1354
  runAuthFlow: auth_flow_1.runRuntimeAuthFlow,
1355
+ /* v8 ignore start -- integration: real API ping @preserve */
1356
+ pingProvider: async (provider, config) => {
1357
+ const { pingProvider: ping } = await Promise.resolve().then(() => __importStar(require("../../heart/provider-ping")));
1358
+ return ping(provider, config);
1359
+ },
1360
+ /* v8 ignore stop */
1355
1361
  registerOuroBundleType: ouro_uti_1.registerOuroBundleUti,
1356
1362
  installOuroCommand: ouro_path_installer_1.installOuroCommand,
1357
1363
  /* v8 ignore start -- self-healing: ensures active symlink matches running runtime version @preserve */
@@ -2064,6 +2070,23 @@ async function runOuroCli(args, deps = createDefaultOuroCliDeps()) {
2064
2070
  // Behavior: ouro auth stores credentials only — does NOT switch provider.
2065
2071
  // Use `ouro auth switch` to change the active provider.
2066
2072
  deps.writeStdout(result.message);
2073
+ // Verify the credentials actually work by pinging the provider
2074
+ /* v8 ignore start -- integration: real API ping after auth @preserve */
2075
+ try {
2076
+ const { secrets } = (0, auth_flow_1.loadAgentSecrets)(command.agent);
2077
+ const config = secrets.providers[provider];
2078
+ const pingResult = await deps.pingProvider(provider, config);
2079
+ if (pingResult.ok) {
2080
+ deps.writeStdout(`verified: ${provider} credentials are working.`);
2081
+ }
2082
+ else {
2083
+ deps.writeStdout(`warning: ${provider} credentials were saved but verification failed. you may need to re-run auth.`);
2084
+ }
2085
+ }
2086
+ catch {
2087
+ // Ping failure is non-blocking — credentials were saved regardless
2088
+ }
2089
+ /* v8 ignore stop */
2067
2090
  return result.message;
2068
2091
  }
2069
2092
  // ── auth verify (local, no daemon socket needed) ──
@@ -3,6 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildFailoverContext = buildFailoverContext;
4
4
  exports.handleFailoverReply = handleFailoverReply;
5
5
  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
+ };
6
14
  const CLASSIFICATION_LABELS = {
7
15
  "auth-failure": "authentication failed",
8
16
  "usage-limit": "hit its usage limit",
@@ -29,7 +37,7 @@ function buildFailoverContext(errorMessage, classification, currentProvider, cur
29
37
  }
30
38
  else {
31
39
  // Configured but ping failed (expired token, provider also down, etc.)
32
- failingProviders.push({ provider, reason: result.message });
40
+ failingProviders.push({ provider, classification: result.classification });
33
41
  }
34
42
  }
35
43
  const lines = [`${errorSummary}.`];
@@ -43,8 +51,10 @@ function buildFailoverContext(errorMessage, classification, currentProvider, cur
43
51
  lines.push(`reply ${switchOptions} to continue.`);
44
52
  }
45
53
  if (failingProviders.length > 0) {
46
- for (const { provider, reason } of failingProviders) {
47
- lines.push(`${provider} is configured but its credentials failed (${reason}). run \`ouro auth --agent ${agentName} --provider ${provider}\` to refresh.`);
54
+ for (const { provider, classification } of failingProviders) {
55
+ /* v8 ignore next -- defensive: all classifications have labels @preserve */
56
+ const detail = FAILING_PROVIDER_LABELS[classification] ?? "could not be reached";
57
+ lines.push(`${provider} is configured but ${detail}. run \`ouro auth --agent ${agentName} --provider ${provider}\` to refresh.`);
48
58
  }
49
59
  }
50
60
  if (unconfiguredProviders.length > 0) {
@@ -48,18 +48,6 @@ function createRuntimeForPing(provider, config) {
48
48
  throw new Error(`unsupported provider for ping: ${provider}`);
49
49
  }
50
50
  }
51
- /* v8 ignore start -- no-op stubs: never invoked, ping only needs streamTurn to not throw @preserve */
52
- const noop = () => { };
53
- /* v8 ignore stop */
54
- const noopCallbacks = {
55
- onModelStart: noop,
56
- onModelStreamStart: noop,
57
- onTextChunk: noop,
58
- onReasoningChunk: noop,
59
- onToolStart: noop,
60
- onToolEnd: noop,
61
- onError: noop,
62
- };
63
51
  async function pingProvider(provider, config) {
64
52
  if (hasEmptyCredentials(provider, config)) {
65
53
  return { ok: false, classification: "auth-failure", message: "no credentials configured" };
@@ -82,12 +70,19 @@ async function pingProvider(provider, config) {
82
70
  /* v8 ignore next -- timeout callback: only fires after 10s, tests resolve faster @preserve */
83
71
  const timeout = setTimeout(() => controller.abort(), PING_TIMEOUT_MS);
84
72
  try {
85
- await runtime.streamTurn({
86
- messages: [{ role: "user", content: "ping" }],
87
- activeTools: [],
88
- callbacks: noopCallbacks,
89
- signal: controller.signal,
90
- });
73
+ // Minimal API call — no thinking, no reasoning, no tools.
74
+ // We use the runtime's client directly to avoid provider-specific
75
+ // streamTurn params (adaptive thinking, reasoning effort, phase
76
+ // annotations) that can cause 400 errors unrelated to auth/quota.
77
+ if (provider === "anthropic") {
78
+ const client = runtime.client;
79
+ await client.messages.create({ model: runtime.model, max_tokens: 1, messages: [{ role: "user", content: "ping" }] }, { signal: controller.signal });
80
+ }
81
+ else {
82
+ // OpenAI-compatible providers (azure, codex, minimax, github-copilot)
83
+ const client = runtime.client;
84
+ await client.chat.completions.create({ model: runtime.model, max_tokens: 1, messages: [{ role: "user", content: "ping" }] }, { signal: controller.signal });
85
+ }
91
86
  return { ok: true };
92
87
  }
93
88
  finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.115",
3
+ "version": "0.1.0-alpha.117",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",