@ouro.bot/cli 0.1.0-alpha.132 → 0.1.0-alpha.133
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 +8 -0
- package/dist/heart/active-work.js +11 -0
- package/dist/heart/daemon/ouro-path-installer.js +10 -5
- package/dist/mind/obligations.js +134 -0
- package/dist/repertoire/tools-base.js +17 -4
- package/dist/senses/inner-dialog.js +53 -3
- package/dist/senses/pipeline.js +9 -0
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
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.133",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Inner return obligations: delegated inner dialog work now tracks a ReturnObligation through queued → running → returned/deferred lifecycle.",
|
|
8
|
+
"Exact-origin routing: inner dialog completions route back to the session that delegated the work, not just the freshest active session.",
|
|
9
|
+
"Active work frame surfaces pending inner return obligations so the agent knows what's outstanding."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
4
12
|
{
|
|
5
13
|
"version": "0.1.0-alpha.132",
|
|
6
14
|
"changes": [
|
|
@@ -439,6 +439,7 @@ function buildActiveWorkFrame(input) {
|
|
|
439
439
|
otherCodingSessions,
|
|
440
440
|
pendingObligations,
|
|
441
441
|
targetCandidates: input.targetCandidates ?? [],
|
|
442
|
+
innerReturnObligations: input.innerReturnObligations ?? [],
|
|
442
443
|
bridgeSuggestion: suggestBridgeForActiveWork({
|
|
443
444
|
currentSession: input.currentSession,
|
|
444
445
|
currentObligation: input.currentObligation,
|
|
@@ -588,6 +589,16 @@ function formatActiveWorkFrame(frame) {
|
|
|
588
589
|
lines.push(obligationLine);
|
|
589
590
|
}
|
|
590
591
|
}
|
|
592
|
+
if (frame.innerReturnObligations && frame.innerReturnObligations.length > 0) {
|
|
593
|
+
lines.push("");
|
|
594
|
+
lines.push("## inner return obligations");
|
|
595
|
+
for (const ob of frame.innerReturnObligations) {
|
|
596
|
+
const preview = ob.delegatedContent.length > 60
|
|
597
|
+
? `${ob.delegatedContent.slice(0, 57)}...`
|
|
598
|
+
: ob.delegatedContent;
|
|
599
|
+
lines.push(`- [${ob.status}] ${ob.origin.friendId}/${ob.origin.channel}/${ob.origin.key}: ${preview}`);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
591
602
|
// Bridge suggestion
|
|
592
603
|
if (frame.bridgeSuggestion) {
|
|
593
604
|
lines.push("");
|
|
@@ -46,6 +46,11 @@ if [ ! -e "$ENTRY" ]; then
|
|
|
46
46
|
fi
|
|
47
47
|
exec node "$ENTRY" "$@"
|
|
48
48
|
`;
|
|
49
|
+
function writeWrapperScript(scriptPath, mkdirSync, writeFileSync, chmodSync) {
|
|
50
|
+
mkdirSync(path.dirname(scriptPath), { recursive: true });
|
|
51
|
+
writeFileSync(scriptPath, WRAPPER_SCRIPT, { mode: 0o755 });
|
|
52
|
+
chmodSync(scriptPath, 0o755);
|
|
53
|
+
}
|
|
49
54
|
function detectShellProfile(homeDir, shell) {
|
|
50
55
|
if (!shell)
|
|
51
56
|
return null;
|
|
@@ -151,9 +156,9 @@ function installOuroCommand(deps = {}) {
|
|
|
151
156
|
meta: { scriptPath, binDir },
|
|
152
157
|
});
|
|
153
158
|
try {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
if (!modernCurrent) {
|
|
160
|
+
writeWrapperScript(scriptPath, mkdirSync, writeFileSync, chmodSync);
|
|
161
|
+
}
|
|
157
162
|
}
|
|
158
163
|
catch (error) {
|
|
159
164
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -166,8 +171,8 @@ function installOuroCommand(deps = {}) {
|
|
|
166
171
|
return { installed: false, scriptPath: null, pathReady: false, shellProfileUpdated: null, skippedReason: error instanceof Error ? error.message : /* v8 ignore next -- defensive @preserve */ String(error), repairedOldLauncher };
|
|
167
172
|
}
|
|
168
173
|
// Check if ~/.ouro-cli/bin is already in PATH
|
|
169
|
-
let shellProfileUpdated = null;
|
|
170
174
|
const pathReady = isBinDirInPath(binDir, envPath);
|
|
175
|
+
let shellProfileUpdated = null;
|
|
171
176
|
if (!pathReady) {
|
|
172
177
|
const profilePath = detectShellProfile(homeDir, shell);
|
|
173
178
|
if (profilePath) {
|
|
@@ -199,7 +204,7 @@ function installOuroCommand(deps = {}) {
|
|
|
199
204
|
component: "daemon",
|
|
200
205
|
event: "daemon.ouro_path_install_end",
|
|
201
206
|
message: "ouro command installed",
|
|
202
|
-
meta: { scriptPath, pathReady, shellProfileUpdated },
|
|
207
|
+
meta: { scriptPath, pathReady, shellProfileUpdated, oldScriptPath: oldExists ? oldScriptPath : null },
|
|
203
208
|
});
|
|
204
209
|
return { installed: true, scriptPath, pathReady, shellProfileUpdated, repairedOldLauncher };
|
|
205
210
|
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getObligationsDir = getObligationsDir;
|
|
37
|
+
exports.generateObligationId = generateObligationId;
|
|
38
|
+
exports.createObligation = createObligation;
|
|
39
|
+
exports.readObligation = readObligation;
|
|
40
|
+
exports.advanceObligation = advanceObligation;
|
|
41
|
+
exports.listActiveObligations = listActiveObligations;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const identity_1 = require("../heart/identity");
|
|
45
|
+
const runtime_1 = require("../nerves/runtime");
|
|
46
|
+
// ── Paths ────────────────────────────────────────────────────────
|
|
47
|
+
function getObligationsDir(agentName) {
|
|
48
|
+
return path.join((0, identity_1.getAgentRoot)(agentName), "state", "obligations", "inner");
|
|
49
|
+
}
|
|
50
|
+
// ── ID generation ────────────────────────────────────────────────
|
|
51
|
+
function generateObligationId(timestamp) {
|
|
52
|
+
return `${timestamp}-${Math.random().toString(36).slice(2, 10)}`;
|
|
53
|
+
}
|
|
54
|
+
// ── Store operations ─────────────────────────────────────────────
|
|
55
|
+
function createObligation(agentName, obligation) {
|
|
56
|
+
const dir = getObligationsDir(agentName);
|
|
57
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
58
|
+
const filePath = path.join(dir, `${obligation.id}.json`);
|
|
59
|
+
fs.writeFileSync(filePath, JSON.stringify(obligation, null, 2), "utf8");
|
|
60
|
+
(0, runtime_1.emitNervesEvent)({
|
|
61
|
+
event: "mind.obligation_created",
|
|
62
|
+
component: "mind",
|
|
63
|
+
message: "return obligation created",
|
|
64
|
+
meta: {
|
|
65
|
+
obligationId: obligation.id,
|
|
66
|
+
origin: `${obligation.origin.friendId}/${obligation.origin.channel}/${obligation.origin.key}`,
|
|
67
|
+
status: obligation.status,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
return filePath;
|
|
71
|
+
}
|
|
72
|
+
function readObligation(agentName, obligationId) {
|
|
73
|
+
const dir = getObligationsDir(agentName);
|
|
74
|
+
try {
|
|
75
|
+
const raw = fs.readFileSync(path.join(dir, `${obligationId}.json`), "utf-8");
|
|
76
|
+
return JSON.parse(raw);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function advanceObligation(agentName, obligationId, update) {
|
|
83
|
+
const existing = readObligation(agentName, obligationId);
|
|
84
|
+
if (!existing)
|
|
85
|
+
return null;
|
|
86
|
+
const updated = {
|
|
87
|
+
...existing,
|
|
88
|
+
status: update.status,
|
|
89
|
+
...(update.startedAt !== undefined ? { startedAt: update.startedAt } : {}),
|
|
90
|
+
...(update.returnedAt !== undefined ? { returnedAt: update.returnedAt } : {}),
|
|
91
|
+
...(update.returnTarget !== undefined ? { returnTarget: update.returnTarget } : {}),
|
|
92
|
+
};
|
|
93
|
+
const dir = getObligationsDir(agentName);
|
|
94
|
+
fs.writeFileSync(path.join(dir, `${obligationId}.json`), JSON.stringify(updated, null, 2), "utf8");
|
|
95
|
+
(0, runtime_1.emitNervesEvent)({
|
|
96
|
+
event: "mind.obligation_advanced",
|
|
97
|
+
component: "mind",
|
|
98
|
+
message: `obligation advanced to ${update.status}`,
|
|
99
|
+
meta: {
|
|
100
|
+
obligationId,
|
|
101
|
+
status: update.status,
|
|
102
|
+
...(update.returnTarget ? { returnTarget: update.returnTarget } : {}),
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
return updated;
|
|
106
|
+
}
|
|
107
|
+
function listActiveObligations(agentName) {
|
|
108
|
+
const dir = getObligationsDir(agentName);
|
|
109
|
+
if (!fs.existsSync(dir))
|
|
110
|
+
return [];
|
|
111
|
+
let entries;
|
|
112
|
+
try {
|
|
113
|
+
entries = fs.readdirSync(dir);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
const obligations = [];
|
|
119
|
+
for (const file of entries) {
|
|
120
|
+
if (!file.endsWith(".json"))
|
|
121
|
+
continue;
|
|
122
|
+
try {
|
|
123
|
+
const raw = fs.readFileSync(path.join(dir, file), "utf-8");
|
|
124
|
+
const parsed = JSON.parse(raw);
|
|
125
|
+
if (parsed.status === "queued" || parsed.status === "running") {
|
|
126
|
+
obligations.push(parsed);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// skip unparseable
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return obligations.sort((a, b) => a.createdAt - b.createdAt);
|
|
134
|
+
}
|
|
@@ -55,9 +55,10 @@ const coding_1 = require("./coding");
|
|
|
55
55
|
const memory_1 = require("../mind/memory");
|
|
56
56
|
const tasks_1 = require("./tasks");
|
|
57
57
|
const pending_1 = require("../mind/pending");
|
|
58
|
+
const obligations_1 = require("../mind/obligations");
|
|
58
59
|
const progress_story_1 = require("../heart/progress-story");
|
|
59
60
|
const cross_chat_delivery_1 = require("../heart/cross-chat-delivery");
|
|
60
|
-
const
|
|
61
|
+
const obligations_2 = require("../heart/obligations");
|
|
61
62
|
// Tracks which file paths have been read via read_file in this session.
|
|
62
63
|
// edit_file requires a file to be read first (must-read-first guard).
|
|
63
64
|
exports.editFileReadTracker = new Set();
|
|
@@ -207,7 +208,7 @@ function readActiveWorkInnerState() {
|
|
|
207
208
|
const { pendingMessages, turns, runtimeState } = (0, thoughts_1.readInnerDialogRawData)(sessionPath, pendingDir);
|
|
208
209
|
const dialogStatus = (0, thoughts_1.deriveInnerDialogStatus)(pendingMessages, turns, runtimeState);
|
|
209
210
|
const job = (0, thoughts_1.deriveInnerJob)(pendingMessages, turns, runtimeState);
|
|
210
|
-
const storeObligationPending = (0,
|
|
211
|
+
const storeObligationPending = (0, obligations_2.readPendingObligations)(agentRoot).length > 0;
|
|
211
212
|
return {
|
|
212
213
|
status: dialogStatus.processing === "started" ? "running" : "idle",
|
|
213
214
|
hasPending: dialogStatus.queue !== "clear",
|
|
@@ -256,7 +257,7 @@ async function buildToolActiveWorkFrame(ctx) {
|
|
|
256
257
|
}
|
|
257
258
|
const pendingObligations = (() => {
|
|
258
259
|
try {
|
|
259
|
-
return (0,
|
|
260
|
+
return (0, obligations_2.readPendingObligations)(agentRoot);
|
|
260
261
|
}
|
|
261
262
|
catch {
|
|
262
263
|
return [];
|
|
@@ -1122,6 +1123,7 @@ exports.baseToolDefinitions = [
|
|
|
1122
1123
|
...(delegatingBridgeId ? { bridgeId: delegatingBridgeId } : {}),
|
|
1123
1124
|
}
|
|
1124
1125
|
: undefined;
|
|
1126
|
+
const obligationId = delegatedFrom ? (0, obligations_1.generateObligationId)(now) : undefined;
|
|
1125
1127
|
const envelope = {
|
|
1126
1128
|
from: agentName,
|
|
1127
1129
|
friendId,
|
|
@@ -1130,12 +1132,13 @@ exports.baseToolDefinitions = [
|
|
|
1130
1132
|
content,
|
|
1131
1133
|
timestamp: now,
|
|
1132
1134
|
...(delegatedFrom ? { delegatedFrom, obligationStatus: "pending" } : {}),
|
|
1135
|
+
...(obligationId ? { obligationId } : {}),
|
|
1133
1136
|
};
|
|
1134
1137
|
if (isSelf) {
|
|
1135
1138
|
writePendingEnvelope(pendingDir, envelope);
|
|
1136
1139
|
if (delegatedFrom) {
|
|
1137
1140
|
try {
|
|
1138
|
-
(0,
|
|
1141
|
+
(0, obligations_2.createObligation)((0, identity_1.getAgentRoot)(), {
|
|
1139
1142
|
origin: {
|
|
1140
1143
|
friendId: delegatedFrom.friendId,
|
|
1141
1144
|
channel: delegatedFrom.channel,
|
|
@@ -1148,6 +1151,16 @@ exports.baseToolDefinitions = [
|
|
|
1148
1151
|
catch {
|
|
1149
1152
|
/* v8 ignore next -- defensive: obligation store write failure should not break send_message @preserve */
|
|
1150
1153
|
}
|
|
1154
|
+
/* v8 ignore next -- obligationId always set when delegatedFrom is set (see generateObligationId above) @preserve */
|
|
1155
|
+
if (obligationId) {
|
|
1156
|
+
(0, obligations_1.createObligation)(agentName, {
|
|
1157
|
+
id: obligationId,
|
|
1158
|
+
origin: delegatedFrom,
|
|
1159
|
+
status: "queued",
|
|
1160
|
+
delegatedContent: content.length > 120 ? `${content.slice(0, 117)}...` : content,
|
|
1161
|
+
createdAt: now,
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1151
1164
|
(0, runtime_1.emitNervesEvent)({
|
|
1152
1165
|
event: "repertoire.obligation_created",
|
|
1153
1166
|
component: "repertoire",
|
|
@@ -53,6 +53,7 @@ const prompt_1 = require("../mind/prompt");
|
|
|
53
53
|
const mcp_manager_1 = require("../repertoire/mcp-manager");
|
|
54
54
|
const bundle_manifest_1 = require("../mind/bundle-manifest");
|
|
55
55
|
const pending_1 = require("../mind/pending");
|
|
56
|
+
const obligations_1 = require("../mind/obligations");
|
|
56
57
|
const channel_1 = require("../mind/friends/channel");
|
|
57
58
|
const trust_gate_1 = require("./trust-gate");
|
|
58
59
|
const tokens_1 = require("../mind/friends/tokens");
|
|
@@ -62,7 +63,7 @@ const runtime_1 = require("../nerves/runtime");
|
|
|
62
63
|
const manager_1 = require("../heart/bridges/manager");
|
|
63
64
|
const session_activity_1 = require("../heart/session-activity");
|
|
64
65
|
const bluebubbles_1 = require("./bluebubbles");
|
|
65
|
-
const
|
|
66
|
+
const obligations_2 = require("../heart/obligations");
|
|
66
67
|
const DEFAULT_INNER_DIALOG_INSTINCTS = [
|
|
67
68
|
{
|
|
68
69
|
id: "heartbeat_checkin",
|
|
@@ -269,6 +270,12 @@ function sessionMatchesActivity(activity, session) {
|
|
|
269
270
|
&& activity.channel === session.channel
|
|
270
271
|
&& activity.key === session.key;
|
|
271
272
|
}
|
|
273
|
+
function resolveExactOriginSession(delegatedFrom, sessionActivity) {
|
|
274
|
+
return sessionActivity.find((activity) => activity.friendId === delegatedFrom.friendId
|
|
275
|
+
&& activity.channel === delegatedFrom.channel
|
|
276
|
+
&& activity.key === delegatedFrom.key
|
|
277
|
+
&& activity.channel !== "inner") ?? null;
|
|
278
|
+
}
|
|
272
279
|
function resolveBridgePreferredSession(delegatedFrom, sessionActivity) {
|
|
273
280
|
if (!delegatedFrom.bridgeId)
|
|
274
281
|
return null;
|
|
@@ -307,23 +314,46 @@ function enrichDelegatedFromWithBridge(delegatedFrom) {
|
|
|
307
314
|
}
|
|
308
315
|
return delegatedFrom;
|
|
309
316
|
}
|
|
317
|
+
function advanceObligationQuietly(agentName, obligationId, update) {
|
|
318
|
+
if (!obligationId)
|
|
319
|
+
return;
|
|
320
|
+
try {
|
|
321
|
+
(0, obligations_1.advanceObligation)(agentName, obligationId, update);
|
|
322
|
+
/* v8 ignore start -- best-effort: obligation fs errors must never block return routing @preserve */
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
// swallowed
|
|
326
|
+
}
|
|
327
|
+
/* v8 ignore stop */
|
|
328
|
+
}
|
|
310
329
|
async function routeDelegatedCompletion(agentRoot, agentName, completion, drainedPending, timestamp) {
|
|
311
330
|
const delegated = (drainedPending ?? []).find((message) => message.delegatedFrom);
|
|
312
331
|
if (!delegated?.delegatedFrom || !completion?.answer?.trim()) {
|
|
313
332
|
return;
|
|
314
333
|
}
|
|
315
334
|
const delegatedFrom = enrichDelegatedFromWithBridge(delegated.delegatedFrom);
|
|
335
|
+
const obligationId = delegated.obligationId;
|
|
336
|
+
// Advance any inner return obligations from queued -> running (they were drained this turn).
|
|
337
|
+
// drainedPending is guaranteed non-null here (we found delegated above).
|
|
338
|
+
for (const msg of drainedPending) {
|
|
339
|
+
if (msg.obligationId) {
|
|
340
|
+
advanceObligationQuietly(agentName, msg.obligationId, {
|
|
341
|
+
status: "running",
|
|
342
|
+
startedAt: timestamp,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
316
346
|
if (delegated.obligationStatus === "pending") {
|
|
317
347
|
// Fulfill the persistent obligation in the store
|
|
318
348
|
try {
|
|
319
|
-
const pending = (0,
|
|
349
|
+
const pending = (0, obligations_2.findPendingObligationForOrigin)(agentRoot, {
|
|
320
350
|
friendId: delegatedFrom.friendId,
|
|
321
351
|
channel: delegatedFrom.channel,
|
|
322
352
|
key: delegatedFrom.key,
|
|
323
353
|
});
|
|
324
354
|
/* v8 ignore next 2 -- obligation fulfillment tested via obligations.test.ts; integration requires real disk state @preserve */
|
|
325
355
|
if (pending) {
|
|
326
|
-
(0,
|
|
356
|
+
(0, obligations_2.fulfillObligation)(agentRoot, pending.id);
|
|
327
357
|
}
|
|
328
358
|
}
|
|
329
359
|
catch {
|
|
@@ -348,20 +378,36 @@ async function routeDelegatedCompletion(agentRoot, agentName, completion, draine
|
|
|
348
378
|
content: completion.answer.trim(),
|
|
349
379
|
timestamp,
|
|
350
380
|
delegatedFrom,
|
|
381
|
+
...(obligationId ? { obligationId } : {}),
|
|
351
382
|
};
|
|
352
383
|
const sessionActivity = (0, session_activity_1.listSessionActivity)({
|
|
353
384
|
sessionsDir: path.join(agentRoot, "state", "sessions"),
|
|
354
385
|
friendsDir: path.join(agentRoot, "friends"),
|
|
355
386
|
agentName,
|
|
356
387
|
});
|
|
388
|
+
// Priority 1: Exact origin session (the session that delegated this work).
|
|
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).
|
|
357
400
|
const bridgeTarget = resolveBridgePreferredSession(delegatedFrom, sessionActivity);
|
|
358
401
|
if (bridgeTarget) {
|
|
359
402
|
if (await tryDeliverDelegatedCompletion(bridgeTarget, outboundEnvelope)) {
|
|
403
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "bridge-session" });
|
|
360
404
|
return;
|
|
361
405
|
}
|
|
362
406
|
writePendingEnvelope((0, pending_1.getPendingDir)(agentName, bridgeTarget.friendId, bridgeTarget.channel, bridgeTarget.key), outboundEnvelope);
|
|
407
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "bridge-session" });
|
|
363
408
|
return;
|
|
364
409
|
}
|
|
410
|
+
// Priority 3: Freshest active friend session.
|
|
365
411
|
const freshest = (0, session_activity_1.findFreshestFriendSession)({
|
|
366
412
|
sessionsDir: path.join(agentRoot, "state", "sessions"),
|
|
367
413
|
friendsDir: path.join(agentRoot, "friends"),
|
|
@@ -371,12 +417,16 @@ async function routeDelegatedCompletion(agentRoot, agentName, completion, draine
|
|
|
371
417
|
});
|
|
372
418
|
if (freshest && freshest.channel !== "inner") {
|
|
373
419
|
if (await tryDeliverDelegatedCompletion(freshest, outboundEnvelope)) {
|
|
420
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "freshest-session" });
|
|
374
421
|
return;
|
|
375
422
|
}
|
|
376
423
|
writePendingEnvelope((0, pending_1.getPendingDir)(agentName, freshest.friendId, freshest.channel, freshest.key), outboundEnvelope);
|
|
424
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "freshest-session" });
|
|
377
425
|
return;
|
|
378
426
|
}
|
|
427
|
+
// Priority 4: Deferred return queue.
|
|
379
428
|
writePendingEnvelope((0, pending_1.getDeferredReturnDir)(agentName, delegatedFrom.friendId), outboundEnvelope);
|
|
429
|
+
advanceObligationQuietly(agentName, obligationId, { status: "deferred", returnedAt: timestamp, returnTarget: "deferred" });
|
|
380
430
|
}
|
|
381
431
|
// Self-referencing friend record for inner dialog (agent talking to itself).
|
|
382
432
|
// No real friend to resolve -- this satisfies the pipeline's friend resolver contract.
|
package/dist/senses/pipeline.js
CHANGED
|
@@ -19,6 +19,7 @@ const target_resolution_1 = require("../heart/target-resolution");
|
|
|
19
19
|
const thoughts_1 = require("../heart/daemon/thoughts");
|
|
20
20
|
const pending_1 = require("../mind/pending");
|
|
21
21
|
const obligations_1 = require("../heart/obligations");
|
|
22
|
+
const obligations_2 = require("../mind/obligations");
|
|
22
23
|
const provider_failover_1 = require("../heart/provider-failover");
|
|
23
24
|
const provider_ping_1 = require("../heart/provider-ping");
|
|
24
25
|
const auth_flow_1 = require("../heart/daemon/auth-flow");
|
|
@@ -310,6 +311,14 @@ async function handleInboundTurn(input) {
|
|
|
310
311
|
})(),
|
|
311
312
|
friendActivity: sessionActivity,
|
|
312
313
|
targetCandidates,
|
|
314
|
+
innerReturnObligations: (() => {
|
|
315
|
+
try {
|
|
316
|
+
return (0, obligations_2.listActiveObligations)((0, identity_1.getAgentName)());
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
})(),
|
|
313
322
|
});
|
|
314
323
|
const delegationDecision = (0, delegation_1.decideDelegation)({
|
|
315
324
|
channel: input.channel,
|