@ouro.bot/cli 0.1.0-alpha.127 → 0.1.0-alpha.129
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,21 @@
|
|
|
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.129",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Fixed final_answer truth-check false positive: agents with intent=complete can now deliver answers even when delegation suggests going inward.",
|
|
8
|
+
"Fixed BlueBubbles message deduplication: messages are recorded immediately to prevent duplicate processing on webhook retries.",
|
|
9
|
+
"Fixed session key normalization: listSessionActivity now compares sanitized keys so the current session is correctly excluded from other-session lists.",
|
|
10
|
+
"ouro auth with no args now shows auth-specific help instead of full CLI help."
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"version": "0.1.0-alpha.128",
|
|
15
|
+
"changes": [
|
|
16
|
+
"Error message sanitizer now strips HTML responses (Cloudflare challenge pages, error pages) in addition to JSON."
|
|
17
|
+
]
|
|
18
|
+
},
|
|
4
19
|
{
|
|
5
20
|
"version": "0.1.0-alpha.127",
|
|
6
21
|
"changes": [
|
package/dist/heart/core.js
CHANGED
|
@@ -238,8 +238,11 @@ function isExternalStateQuery(toolName, args) {
|
|
|
238
238
|
return /\bgh\s+(pr|run|api|issue)\b/.test(cmd) || /\bnpm\s+(view|info|show)\b/.test(cmd);
|
|
239
239
|
}
|
|
240
240
|
function getFinalAnswerRetryError(mustResolveBeforeHandoff, intent, sawSteeringFollowUp, delegationDecision, sawSendMessageSelf, sawGoInward, sawQuerySession, currentObligation, innerJob, sawExternalStateQuery) {
|
|
241
|
-
// 1. Delegation adherence: delegate-inward without evidence of inward action
|
|
242
|
-
|
|
241
|
+
// 1. Delegation adherence: delegate-inward without evidence of inward action.
|
|
242
|
+
// Only enforce on the FIRST final_answer attempt — if the agent persists with
|
|
243
|
+
// intent=complete, respect it. The delegation is a suggestion, not a hard gate.
|
|
244
|
+
// Without this escape, the agent gets stuck in a loop unable to respond.
|
|
245
|
+
if (delegationDecision?.target === "delegate-inward" && !sawSendMessageSelf && !sawGoInward && !sawQuerySession && intent !== "complete" && intent !== "blocked") {
|
|
243
246
|
(0, runtime_1.emitNervesEvent)({
|
|
244
247
|
event: "engine.delegation_adherence_rejected",
|
|
245
248
|
component: "engine",
|
|
@@ -688,8 +688,14 @@ function parseAuthCommand(args) {
|
|
|
688
688
|
continue;
|
|
689
689
|
}
|
|
690
690
|
}
|
|
691
|
-
if (!agent)
|
|
692
|
-
throw new Error(
|
|
691
|
+
if (!agent) {
|
|
692
|
+
throw new Error([
|
|
693
|
+
"Usage:",
|
|
694
|
+
" ouro auth --agent <name> [--provider <provider>] Set up credentials",
|
|
695
|
+
" ouro auth verify --agent <name> [--provider <p>] Verify credentials work",
|
|
696
|
+
" ouro auth switch --agent <name> --provider <p> Switch active provider",
|
|
697
|
+
].join("\n"));
|
|
698
|
+
}
|
|
693
699
|
return provider ? { kind: "auth.run", agent, provider } : { kind: "auth.run", agent };
|
|
694
700
|
}
|
|
695
701
|
function parseReminderCommand(args) {
|
|
@@ -12,25 +12,33 @@ const auth_flow_1 = require("./daemon/auth-flow");
|
|
|
12
12
|
const runtime_1 = require("../nerves/runtime");
|
|
13
13
|
const PING_TIMEOUT_MS = 10_000;
|
|
14
14
|
/**
|
|
15
|
-
* Strip raw JSON API response bodies from error messages.
|
|
16
|
-
* SDK errors often include the full response
|
|
17
|
-
* Extract just the HTTP status
|
|
15
|
+
* Strip raw JSON/HTML API response bodies from error messages.
|
|
16
|
+
* SDK errors often include the full response: "400 {"type":"error",...}" or "403 <html>...".
|
|
17
|
+
* Extract just the HTTP status and a short human-readable summary.
|
|
18
18
|
*/
|
|
19
19
|
function sanitizeErrorMessage(message) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const statusMatch = message.match(/^(\d{3})\s/);
|
|
21
|
+
if (!statusMatch)
|
|
22
|
+
return message;
|
|
23
|
+
const status = statusMatch[1];
|
|
24
|
+
const body = message.slice(status.length).trim();
|
|
25
|
+
// HTML response (Cloudflare challenge, error pages, etc.)
|
|
26
|
+
if (body.startsWith("<") || body.includes("<!DOCTYPE") || body.includes("<html")) {
|
|
27
|
+
return `HTTP ${status}`;
|
|
28
|
+
}
|
|
29
|
+
// JSON response
|
|
30
|
+
if (body.startsWith("{")) {
|
|
24
31
|
try {
|
|
25
|
-
const json = JSON.parse(
|
|
32
|
+
const json = JSON.parse(body);
|
|
26
33
|
const inner = json?.error?.message;
|
|
27
34
|
if (typeof inner === "string" && inner && inner !== "Error") {
|
|
28
|
-
return `${
|
|
35
|
+
return `${status} ${inner}`;
|
|
29
36
|
}
|
|
30
37
|
}
|
|
31
|
-
catch { /* not valid JSON
|
|
32
|
-
return `HTTP ${
|
|
38
|
+
catch { /* not valid JSON */ }
|
|
39
|
+
return `HTTP ${status}`;
|
|
33
40
|
}
|
|
41
|
+
// Already clean (e.g., "401 Provided authentication token is expired.")
|
|
34
42
|
return message;
|
|
35
43
|
}
|
|
36
44
|
function hasEmptyCredentials(provider, config) {
|
|
@@ -38,6 +38,7 @@ exports.findFreshestFriendSession = findFreshestFriendSession;
|
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
39
|
const path = __importStar(require("path"));
|
|
40
40
|
const runtime_1 = require("../nerves/runtime");
|
|
41
|
+
const config_1 = require("./config");
|
|
41
42
|
const DEFAULT_ACTIVE_THRESHOLD_MS = 24 * 60 * 60 * 1000;
|
|
42
43
|
function activityPriority(source) {
|
|
43
44
|
return source === "friend-facing" ? 0 : 1;
|
|
@@ -130,7 +131,10 @@ function listSessionActivity(query) {
|
|
|
130
131
|
if (!keyFile.endsWith(".json"))
|
|
131
132
|
continue;
|
|
132
133
|
const key = keyFile.replace(/\.json$/, "");
|
|
133
|
-
|
|
134
|
+
// Compare with sanitizeKey on both sides — session keys from the filesystem
|
|
135
|
+
// are already sanitized (colons → underscores), but the canonical key from
|
|
136
|
+
// the pipeline may still have colons (e.g. "chat:any" vs "chat_any").
|
|
137
|
+
if (currentSession && friendId === currentSession.friendId && channel === currentSession.channel && (0, config_1.sanitizeKey)(key) === (0, config_1.sanitizeKey)(currentSession.key)) {
|
|
134
138
|
continue;
|
|
135
139
|
}
|
|
136
140
|
const sessionPath = path.join(channelPath, keyFile);
|
|
@@ -579,6 +579,9 @@ async function handleBlueBubblesNormalizedEvent(event, resolvedDeps, source) {
|
|
|
579
579
|
});
|
|
580
580
|
return { handled: true, notifiedAgent: false, kind: event.kind, reason: "already_processed" };
|
|
581
581
|
}
|
|
582
|
+
// Record EARLY to prevent duplicate processing. BB webhooks can retry
|
|
583
|
+
// before the first turn completes — recording after the turn is too late.
|
|
584
|
+
(0, bluebubbles_inbound_log_1.recordBlueBubblesInbound)(agentName, event, source);
|
|
582
585
|
if (source !== "webhook" && sessionLikelyContainsMessage(event, existing?.messages ?? sessionMessages)) {
|
|
583
586
|
(0, bluebubbles_inbound_log_1.recordBlueBubblesInbound)(agentName, event, "recovery-bootstrap");
|
|
584
587
|
(0, runtime_1.emitNervesEvent)({
|