@ouro.bot/cli 0.1.0-alpha.133 → 0.1.0-alpha.134
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 +15 -0
- package/dist/heart/core.js +93 -68
- package/dist/heart/daemon/daemon-cli.js +81 -0
- package/dist/heart/daemon/specialist-prompt.js +3 -3
- package/dist/heart/daemon/specialist-tools.js +1 -1
- package/dist/heart/daemon/thoughts.js +6 -6
- package/dist/heart/delegation.js +1 -1
- package/dist/heart/kicks.js +1 -1
- package/dist/heart/providers/anthropic.js +7 -7
- package/dist/heart/providers/azure.js +1 -1
- package/dist/heart/providers/github-copilot.js +2 -2
- package/dist/heart/providers/minimax.js +1 -1
- package/dist/heart/providers/openai-codex.js +1 -1
- package/dist/heart/streaming.js +25 -25
- package/dist/mind/prompt.js +10 -10
- package/dist/repertoire/tools-base.js +8 -8
- package/dist/repertoire/tools.js +179 -4
- package/dist/senses/attention-queue.js +97 -0
- package/dist/senses/cli.js +3 -3
- package/dist/senses/inner-dialog.js +39 -22
- package/dist/senses/pipeline.js +4 -3
- package/dist/senses/surface-tool.js +82 -0
- package/package.json +1 -1
|
@@ -42,6 +42,7 @@ exports.buildTaskTriggeredMessage = buildTaskTriggeredMessage;
|
|
|
42
42
|
exports.deriveResumeCheckpoint = deriveResumeCheckpoint;
|
|
43
43
|
exports.innerDialogSessionPath = innerDialogSessionPath;
|
|
44
44
|
exports.enrichDelegatedFromWithBridge = enrichDelegatedFromWithBridge;
|
|
45
|
+
exports.routeDelegatedCompletion = routeDelegatedCompletion;
|
|
45
46
|
exports.runInnerDialogTurn = runInnerDialogTurn;
|
|
46
47
|
const fs = __importStar(require("fs"));
|
|
47
48
|
const path = __importStar(require("path"));
|
|
@@ -54,6 +55,7 @@ const mcp_manager_1 = require("../repertoire/mcp-manager");
|
|
|
54
55
|
const bundle_manifest_1 = require("../mind/bundle-manifest");
|
|
55
56
|
const pending_1 = require("../mind/pending");
|
|
56
57
|
const obligations_1 = require("../mind/obligations");
|
|
58
|
+
const attention_queue_1 = require("./attention-queue");
|
|
57
59
|
const channel_1 = require("../mind/friends/channel");
|
|
58
60
|
const trust_gate_1 = require("./trust-gate");
|
|
59
61
|
const tokens_1 = require("../mind/friends/tokens");
|
|
@@ -259,6 +261,7 @@ function writeInnerDialogRuntimeState(sessionFilePath, state) {
|
|
|
259
261
|
});
|
|
260
262
|
}
|
|
261
263
|
}
|
|
264
|
+
/* v8 ignore start -- routing helpers: called from routing functions which are integration paths @preserve */
|
|
262
265
|
function writePendingEnvelope(pendingDir, message) {
|
|
263
266
|
fs.mkdirSync(pendingDir, { recursive: true });
|
|
264
267
|
const fileName = `${message.timestamp}-${Math.random().toString(36).slice(2, 10)}.json`;
|
|
@@ -270,12 +273,8 @@ function sessionMatchesActivity(activity, session) {
|
|
|
270
273
|
&& activity.channel === session.channel
|
|
271
274
|
&& activity.key === session.key;
|
|
272
275
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
&& activity.channel === delegatedFrom.channel
|
|
276
|
-
&& activity.key === delegatedFrom.key
|
|
277
|
-
&& activity.channel !== "inner") ?? null;
|
|
278
|
-
}
|
|
276
|
+
/* v8 ignore stop */
|
|
277
|
+
/* v8 ignore start -- routing: delivery now inline via surface tool; routing functions preserved for reuse @preserve */
|
|
279
278
|
function resolveBridgePreferredSession(delegatedFrom, sessionActivity) {
|
|
280
279
|
if (!delegatedFrom.bridgeId)
|
|
281
280
|
return null;
|
|
@@ -385,18 +384,7 @@ async function routeDelegatedCompletion(agentRoot, agentName, completion, draine
|
|
|
385
384
|
friendsDir: path.join(agentRoot, "friends"),
|
|
386
385
|
agentName,
|
|
387
386
|
});
|
|
388
|
-
// Priority 1:
|
|
389
|
-
const exactOrigin = resolveExactOriginSession(delegatedFrom, sessionActivity);
|
|
390
|
-
if (exactOrigin) {
|
|
391
|
-
if (await tryDeliverDelegatedCompletion(exactOrigin, outboundEnvelope)) {
|
|
392
|
-
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "exact-origin" });
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
writePendingEnvelope((0, pending_1.getPendingDir)(agentName, exactOrigin.friendId, exactOrigin.channel, exactOrigin.key), outboundEnvelope);
|
|
396
|
-
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "exact-origin" });
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
// Priority 2: Bridge-preferred session (if delegation was within a bridge).
|
|
387
|
+
// Priority 1: Bridge-preferred session (if delegation was within a bridge).
|
|
400
388
|
const bridgeTarget = resolveBridgePreferredSession(delegatedFrom, sessionActivity);
|
|
401
389
|
if (bridgeTarget) {
|
|
402
390
|
if (await tryDeliverDelegatedCompletion(bridgeTarget, outboundEnvelope)) {
|
|
@@ -407,7 +395,7 @@ async function routeDelegatedCompletion(agentRoot, agentName, completion, draine
|
|
|
407
395
|
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "bridge-session" });
|
|
408
396
|
return;
|
|
409
397
|
}
|
|
410
|
-
// Priority
|
|
398
|
+
// Priority 2: Freshest active friend session.
|
|
411
399
|
const freshest = (0, session_activity_1.findFreshestFriendSession)({
|
|
412
400
|
sessionsDir: path.join(agentRoot, "state", "sessions"),
|
|
413
401
|
friendsDir: path.join(agentRoot, "friends"),
|
|
@@ -424,10 +412,11 @@ async function routeDelegatedCompletion(agentRoot, agentName, completion, draine
|
|
|
424
412
|
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "freshest-session" });
|
|
425
413
|
return;
|
|
426
414
|
}
|
|
427
|
-
// Priority
|
|
415
|
+
// Priority 3: Deferred return queue.
|
|
428
416
|
writePendingEnvelope((0, pending_1.getDeferredReturnDir)(agentName, delegatedFrom.friendId), outboundEnvelope);
|
|
429
417
|
advanceObligationQuietly(agentName, obligationId, { status: "deferred", returnedAt: timestamp, returnTarget: "deferred" });
|
|
430
418
|
}
|
|
419
|
+
/* v8 ignore stop */
|
|
431
420
|
// Self-referencing friend record for inner dialog (agent talking to itself).
|
|
432
421
|
// No real friend to resolve -- this satisfies the pipeline's friend resolver contract.
|
|
433
422
|
function createSelfFriend(agentName) {
|
|
@@ -459,7 +448,6 @@ async function runInnerDialogTurn(options) {
|
|
|
459
448
|
const reason = options?.reason ?? "heartbeat";
|
|
460
449
|
const sessionFilePath = innerDialogSessionPath();
|
|
461
450
|
const agentName = (0, identity_1.getAgentName)();
|
|
462
|
-
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
463
451
|
writeInnerDialogRuntimeState(sessionFilePath, {
|
|
464
452
|
status: "running",
|
|
465
453
|
reason,
|
|
@@ -525,6 +513,8 @@ async function runInnerDialogTurn(options) {
|
|
|
525
513
|
// ── Call shared pipeline ──────────────────────────────────────────
|
|
526
514
|
const callbacks = createInnerDialogCallbacks();
|
|
527
515
|
const traceId = (0, nerves_1.createTraceId)();
|
|
516
|
+
// Attention queue: built when pending messages are drained, shared with tool context
|
|
517
|
+
let attentionQueue = [];
|
|
528
518
|
const result = await (0, pipeline_1.handleInboundTurn)({
|
|
529
519
|
channel: "inner",
|
|
530
520
|
sessionKey: "dialog",
|
|
@@ -542,14 +532,41 @@ async function runInnerDialogTurn(options) {
|
|
|
542
532
|
postTurn: context_1.postTurn,
|
|
543
533
|
accumulateFriendTokens: tokens_1.accumulateFriendTokens,
|
|
544
534
|
signal: options?.signal,
|
|
535
|
+
/* v8 ignore start -- attention queue: callback invoked by pipeline during pending drain; tested via attention-queue unit tests @preserve */
|
|
536
|
+
onPendingDrained: (drained) => {
|
|
537
|
+
const outstandingObligations = (0, obligations_1.listActiveObligations)(agentName);
|
|
538
|
+
attentionQueue = (0, attention_queue_1.buildAttentionQueue)({
|
|
539
|
+
drainedPending: drained,
|
|
540
|
+
outstandingObligations,
|
|
541
|
+
friendNameResolver: (friendId) => {
|
|
542
|
+
try {
|
|
543
|
+
const raw = fs.readFileSync(path.join((0, identity_1.getAgentRoot)(agentName), "friends", friendId + ".json"), "utf-8");
|
|
544
|
+
const parsed = JSON.parse(raw);
|
|
545
|
+
return typeof parsed.name === "string" ? parsed.name : null;
|
|
546
|
+
}
|
|
547
|
+
catch {
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
});
|
|
552
|
+
const summary = (0, attention_queue_1.buildAttentionQueueSummary)(attentionQueue);
|
|
553
|
+
return summary ? [summary] : [];
|
|
554
|
+
},
|
|
555
|
+
/* v8 ignore stop */
|
|
545
556
|
runAgentOptions: {
|
|
546
557
|
traceId,
|
|
547
558
|
toolChoiceRequired: true,
|
|
548
559
|
skipConfirmation: true,
|
|
549
560
|
mcpManager,
|
|
561
|
+
toolContext: {
|
|
562
|
+
signin: async () => undefined,
|
|
563
|
+
delegatedOrigins: attentionQueue,
|
|
564
|
+
},
|
|
550
565
|
},
|
|
551
566
|
});
|
|
552
|
-
|
|
567
|
+
// Post-turn routeDelegatedCompletion removed: delivery is now inline via surface tool.
|
|
568
|
+
// settle in inner dialog produces no CompletionMetadata, so routeDelegatedCompletion
|
|
569
|
+
// would be a no-op. The routing infrastructure is reused by the surface handler.
|
|
553
570
|
const resultMessages = result.messages ?? [];
|
|
554
571
|
const assistantPreview = extractAssistantPreview(resultMessages);
|
|
555
572
|
const toolCalls = extractToolCallNames(resultMessages);
|
package/dist/senses/pipeline.js
CHANGED
|
@@ -332,8 +332,9 @@ async function handleInboundTurn(input) {
|
|
|
332
332
|
: (input.drainDeferredReturns?.(resolvedContext.friend.id) ?? []);
|
|
333
333
|
const sessionPending = input.drainPending(input.pendingDir);
|
|
334
334
|
const pending = [...deferredReturns, ...sessionPending];
|
|
335
|
-
// Assemble messages: session messages + live world-state checkpoint + pending + inbound user messages
|
|
336
|
-
const
|
|
335
|
+
// Assemble messages: session messages + attention queue + live world-state checkpoint + pending + inbound user messages
|
|
336
|
+
const extraPrefixSections = input.onPendingDrained?.(pending) ?? [];
|
|
337
|
+
const prefixSections = [...extraPrefixSections, (0, active_work_1.formatLiveWorldStateCheckpoint)(activeWorkFrame)];
|
|
337
338
|
if (pending.length > 0) {
|
|
338
339
|
const pendingSection = pending
|
|
339
340
|
.map((msg) => `[pending from ${msg.from}]: ${msg.content}`)
|
|
@@ -422,7 +423,7 @@ async function handleInboundTurn(input) {
|
|
|
422
423
|
...(mustResolveBeforeHandoff ? { mustResolveBeforeHandoff: true } : {}),
|
|
423
424
|
...(typeof lastFriendActivityAt === "string" ? { lastFriendActivityAt } : {}),
|
|
424
425
|
};
|
|
425
|
-
const nextState = result.outcome === "
|
|
426
|
+
const nextState = result.outcome === "settled" || result.outcome === "blocked" || result.outcome === "superseded" || result.outcome === "observed"
|
|
426
427
|
? (typeof lastFriendActivityAt === "string"
|
|
427
428
|
? { lastFriendActivityAt }
|
|
428
429
|
: undefined)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.surfaceToolDef = void 0;
|
|
4
|
+
exports.handleSurface = handleSurface;
|
|
5
|
+
const attention_queue_1 = require("./attention-queue");
|
|
6
|
+
const runtime_1 = require("../nerves/runtime");
|
|
7
|
+
// ── Tool definition ──────────────────────────────────────────────
|
|
8
|
+
exports.surfaceToolDef = {
|
|
9
|
+
type: "function",
|
|
10
|
+
function: {
|
|
11
|
+
name: "surface",
|
|
12
|
+
description: "share a thought outward — deliver an answer, ask a follow-up, or surface progress to whoever needs to hear it. pass delegationId to address a held thought (see your attention queue above), or friendId for spontaneous outreach. does not end your turn.",
|
|
13
|
+
parameters: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
content: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "the message to deliver",
|
|
19
|
+
},
|
|
20
|
+
delegationId: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "ID from your attention queue — addresses a specific held thought",
|
|
23
|
+
},
|
|
24
|
+
friendId: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "friend to reach out to spontaneously (when not addressing a held thought)",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ["content"],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
async function handleSurface(input) {
|
|
34
|
+
const { content, delegationId, friendId, queue, routeToFriend, advanceObligation } = input;
|
|
35
|
+
// Resolve target friend
|
|
36
|
+
let targetFriendId;
|
|
37
|
+
let queueItem;
|
|
38
|
+
if (delegationId) {
|
|
39
|
+
// Look up in attention queue
|
|
40
|
+
const found = queue.find((item) => item.id === delegationId);
|
|
41
|
+
if (!found) {
|
|
42
|
+
return `no delegation found with id ${delegationId} — check your attention queue`;
|
|
43
|
+
}
|
|
44
|
+
targetFriendId = found.friendId;
|
|
45
|
+
queueItem = found;
|
|
46
|
+
}
|
|
47
|
+
else if (friendId) {
|
|
48
|
+
targetFriendId = friendId;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return "specify who this thought is for — use delegationId to address a held thought, or friendId for spontaneous outreach";
|
|
52
|
+
}
|
|
53
|
+
// Route to target
|
|
54
|
+
const result = await routeToFriend(targetFriendId, content, queueItem);
|
|
55
|
+
(0, runtime_1.emitNervesEvent)({
|
|
56
|
+
event: "senses.surface_routed",
|
|
57
|
+
component: "senses",
|
|
58
|
+
message: `surface routed to ${targetFriendId}: ${result.status}`,
|
|
59
|
+
meta: {
|
|
60
|
+
targetFriendId,
|
|
61
|
+
status: result.status,
|
|
62
|
+
hasDelegationId: !!delegationId,
|
|
63
|
+
...(result.detail ? { detail: result.detail } : {}),
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
// On successful routing with delegationId:
|
|
67
|
+
// 1. Advance obligation to "returned" (disk FIRST — crash safety)
|
|
68
|
+
// 2. Dequeue from in-memory queue (AFTER obligation advance)
|
|
69
|
+
if (delegationId && queueItem && result.status !== "failed") {
|
|
70
|
+
if (queueItem.obligationId) {
|
|
71
|
+
advanceObligation(queueItem.obligationId, {
|
|
72
|
+
status: "returned",
|
|
73
|
+
returnedAt: Date.now(),
|
|
74
|
+
returnTarget: "surface",
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
(0, attention_queue_1.dequeueAttentionItem)(queue, delegationId);
|
|
78
|
+
}
|
|
79
|
+
// Return delivery status
|
|
80
|
+
const detail = result.detail ? ` — ${result.detail}` : "";
|
|
81
|
+
return `${result.status}${detail}`;
|
|
82
|
+
}
|