@ouro.bot/cli 0.1.0-alpha.191 → 0.1.0-alpha.193

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
@@ -2,8 +2,15 @@
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
4
  {
5
- "version": "0.1.0-alpha.191",
5
+ "version": "0.1.0-alpha.193",
6
6
  "changes": [
7
+ "feat: Outlook visibility \u2014 orientation, obligations, changes, self-fix, memory decisions, route migration to /"
8
+ ]
9
+ },
10
+ {
11
+ "version": "0.1.0-alpha.192",
12
+ "changes": [
13
+ "refactor: canonical obligations \u2014 ActiveWorkFrame as single source of truth for prompt sections",
7
14
  "feat(mcp): dynamic server add/remove \u2014 agents can manage MCP servers without daemon restart"
8
15
  ]
9
16
  },
@@ -1197,4 +1204,4 @@
1197
1204
  ]
1198
1205
  }
1199
1206
  ]
1200
- }
1207
+ }
@@ -666,8 +666,8 @@ function formatActiveWorkFrame(frame, options) {
666
666
  }
667
667
  if ((frame.pendingObligations ?? []).length > 0) {
668
668
  const openCount = frame.pendingObligations.filter((ob) => (0, obligations_1.isOpenObligationStatus)(ob.status)).length;
669
- if (options?.hasWakePacket && openCount > 0) {
670
- // Wake packet carries enriched obligations (with resumeHint, stalenessClass, waitingOn).
669
+ if (options?.obligationDetailsRenderedElsewhere && openCount > 0) {
670
+ // Enriched obligation data (with resumeHint, stalenessClass, waitingOn) is rendered elsewhere.
671
671
  // Avoid duplicating the full list — just anchor the count here.
672
672
  lines.push("");
673
673
  lines.push(`return obligations: ${openCount} active (canonical details in **Owed** section of wake packet)`);
@@ -208,7 +208,7 @@ class OuroDaemon {
208
208
  daemon: "running",
209
209
  health: workers.every((worker) => worker.status === "running") ? "ok" : "warn",
210
210
  socketPath: this.socketPath,
211
- outlookUrl: `${this.outlookServer?.origin ?? "http://127.0.0.1:0"}/outlook`,
211
+ outlookUrl: this.outlookServer?.origin ?? "http://127.0.0.1:0",
212
212
  ...(0, runtime_metadata_1.getRuntimeMetadata)(),
213
213
  workerCount: workers.length,
214
214
  senseCount: senses.length,
@@ -196,6 +196,12 @@ async function startOutlookHttpServer(options = {}) {
196
196
  readAgentBridges: options.readAgentBridges ?? ((agentName) => (0, outlook_read_1.readBridgeInventory)(agentRoot(agentName))),
197
197
  readAgentMemory: options.readAgentMemory ?? ((agentName) => (0, outlook_read_1.readMemoryView)(agentRoot(agentName))),
198
198
  readAgentFriends: options.readAgentFriends ?? ((agentName) => (0, outlook_read_1.readFriendView)(agentName, bundlesRoot ? { bundlesRoot } : undefined)),
199
+ readAgentContinuity: options.readAgentContinuity ?? ((agentName) => (0, outlook_read_1.readOutlookContinuity)(agentRoot(agentName), agentName)),
200
+ readAgentOrientation: options.readAgentOrientation ?? ((agentName) => (0, outlook_read_1.readOrientationView)(agentRoot(agentName), agentName)),
201
+ readAgentObligations: options.readAgentObligations ?? ((agentName) => (0, outlook_read_1.readObligationDetailView)(agentRoot(agentName))),
202
+ readAgentChanges: options.readAgentChanges ?? ((agentName) => (0, outlook_read_1.readChangesView)(agentRoot(agentName))),
203
+ readAgentSelfFix: options.readAgentSelfFix ?? ((agentName) => (0, outlook_read_1.readSelfFixView)(agentRoot(agentName))),
204
+ readAgentMemoryDecisions: options.readAgentMemoryDecisions ?? ((agentName) => (0, outlook_read_1.readMemoryDecisionView)(agentRoot(agentName))),
199
205
  readAgentHabits: options.readAgentHabits ?? ((agentName) => (0, outlook_read_1.readHabitView)(agentRoot(agentName))),
200
206
  readDaemonHealth: options.readDaemonHealth ?? (() => (0, outlook_read_1.readDaemonHealthDeep)(options.healthPath)),
201
207
  readLogs: options.readLogs ?? (() => (0, outlook_read_1.readLogView)(options.logPath ?? null)),
@@ -208,14 +214,8 @@ async function startOutlookHttpServer(options = {}) {
208
214
  }) : null;
209
215
  /* v8 ignore stop */
210
216
  const server = http.createServer((request, response) => {
211
- const pathname = normalizePath(request.url);
217
+ let pathname = normalizePath(request.url);
212
218
  const origin = `http://${host}:${server.address().port}`;
213
- if (pathname === "/outlook/api/events") {
214
- response.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-cache", "connection": "keep-alive", "access-control-allow-origin": "*" });
215
- response.write(":ok\n\n");
216
- sse.add(response);
217
- return;
218
- }
219
219
  /* v8 ignore start — SPA static asset serving */
220
220
  // Serve built SPA static assets: /assets/*
221
221
  if (pathname.startsWith("/assets/")) {
@@ -235,23 +235,39 @@ async function startOutlookHttpServer(options = {}) {
235
235
  response.end();
236
236
  return;
237
237
  }
238
- if (pathname === "/outlook/api/machine") {
238
+ // Compatibility alias: /outlook/api/* → /api/*
239
+ /* v8 ignore start -- legacy compat path: tested via integration @preserve */
240
+ if (pathname.startsWith("/outlook/api/")) {
241
+ pathname = pathname.slice("/outlook".length);
242
+ }
243
+ else if (pathname === "/outlook/api") {
244
+ pathname = "/api";
245
+ }
246
+ /* v8 ignore stop */
247
+ // SSE event stream
248
+ if (pathname === "/api/events") {
249
+ response.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-cache", "connection": "keep-alive", "access-control-allow-origin": "*" });
250
+ response.write(":ok\n\n");
251
+ sse.add(response);
252
+ return;
253
+ }
254
+ if (pathname === "/api/machine") {
239
255
  const machine = readMachineState();
240
256
  const machineView = readMachineView?.({ origin, machine });
241
257
  writeJson(response, 200, machineView ?? machine);
242
258
  return;
243
259
  }
244
- if (pathname === "/outlook/api/machine/health") {
260
+ if (pathname === "/api/machine/health") {
245
261
  const health = hooks.readDaemonHealth();
246
262
  writeJson(response, 200, health ?? { status: "unavailable" });
247
263
  return;
248
264
  }
249
- if (pathname === "/outlook/api/machine/logs") {
265
+ if (pathname === "/api/machine/logs") {
250
266
  writeJson(response, 200, hooks.readLogs());
251
267
  return;
252
268
  }
253
- // Agent-level endpoints: /outlook/api/agents/:agent[/:surface[/:params...]]
254
- const agentMatch = /^\/outlook\/api\/agents\/([^/]+)(?:\/(.+))?$/.exec(pathname);
269
+ // Agent-level endpoints: /api/agents/:agent[/:surface[/:params...]]
270
+ const agentMatch = /^\/api\/agents\/([^/]+)(?:\/(.+))?$/.exec(pathname);
255
271
  if (agentMatch) {
256
272
  const agent = decodeURIComponent(agentMatch[1]);
257
273
  const surface = agentMatch[2] ?? null;
@@ -306,6 +322,30 @@ async function startOutlookHttpServer(options = {}) {
306
322
  writeJson(response, 200, hooks.readAgentFriends(agent));
307
323
  return;
308
324
  }
325
+ if (surface === "continuity") {
326
+ writeJson(response, 200, hooks.readAgentContinuity(agent));
327
+ return;
328
+ }
329
+ if (surface === "orientation") {
330
+ writeJson(response, 200, hooks.readAgentOrientation(agent));
331
+ return;
332
+ }
333
+ if (surface === "obligations") {
334
+ writeJson(response, 200, hooks.readAgentObligations(agent));
335
+ return;
336
+ }
337
+ if (surface === "changes") {
338
+ writeJson(response, 200, hooks.readAgentChanges(agent));
339
+ return;
340
+ }
341
+ if (surface === "self-fix") {
342
+ writeJson(response, 200, hooks.readAgentSelfFix(agent));
343
+ return;
344
+ }
345
+ if (surface === "memory-decisions") {
346
+ writeJson(response, 200, hooks.readAgentMemoryDecisions(agent));
347
+ return;
348
+ }
309
349
  /* v8 ignore start — desk prefs write + reads */
310
350
  if (surface === "dismiss-obligation" && request.method === "POST") {
311
351
  let body = "";
@@ -48,6 +48,11 @@ exports.readHabitView = readHabitView;
48
48
  exports.readNeedsMeView = readNeedsMeView;
49
49
  exports.readDeskPrefs = readDeskPrefs;
50
50
  exports.readOutlookContinuity = readOutlookContinuity;
51
+ exports.readOrientationView = readOrientationView;
52
+ exports.readObligationDetailView = readObligationDetailView;
53
+ exports.readChangesView = readChangesView;
54
+ exports.readSelfFixView = readSelfFixView;
55
+ exports.readMemoryDecisionView = readMemoryDecisionView;
51
56
  const fs = __importStar(require("fs"));
52
57
  const path = __importStar(require("path"));
53
58
  const runtime_1 = require("../../nerves/runtime");
@@ -1329,3 +1334,286 @@ function readOutlookContinuity(agentRoot, agentName) {
1329
1334
  },
1330
1335
  };
1331
1336
  }
1337
+ // ---------------------------------------------------------------------------
1338
+ // Orientation reader — daemon-side assembly of "where am I?"
1339
+ // ---------------------------------------------------------------------------
1340
+ function readOrientationView(agentRoot, agentName) {
1341
+ // Read obligations for primary selection
1342
+ let obligations = [];
1343
+ try {
1344
+ obligations = (0, obligations_1.readObligations)(agentRoot);
1345
+ }
1346
+ catch {
1347
+ obligations = [];
1348
+ }
1349
+ const openObligations = obligations.filter(obligations_1.isOpenObligation);
1350
+ // Select primary obligation (most advanced status, then most recent)
1351
+ const statusPriority = {
1352
+ returning: 0,
1353
+ collaborating: 1,
1354
+ in_progress: 2,
1355
+ delegated: 3,
1356
+ accepted: 4,
1357
+ pending: 5,
1358
+ };
1359
+ const sorted = [...openObligations].sort((a, b) => {
1360
+ const sp = (statusPriority[a.status] ?? 99) - (statusPriority[b.status] ?? 99);
1361
+ if (sp !== 0)
1362
+ return sp;
1363
+ const aMs = new Date(a.updatedAt ?? a.createdAt).getTime();
1364
+ const bMs = new Date(b.updatedAt ?? b.createdAt).getTime();
1365
+ return bMs - aMs;
1366
+ });
1367
+ const primary = sorted[0] ?? null;
1368
+ // Read session activity for current session and others
1369
+ let sessions = [];
1370
+ try {
1371
+ sessions = (0, session_activity_1.listSessionActivity)({
1372
+ sessionsDir: path.join(agentRoot, "state", "sessions"),
1373
+ friendsDir: path.join(agentRoot, "friends"),
1374
+ agentName,
1375
+ });
1376
+ }
1377
+ catch {
1378
+ sessions = [];
1379
+ }
1380
+ const sortedSessions = [...sessions].sort((a, b) => b.lastActivityMs - a.lastActivityMs);
1381
+ const currentSession = sortedSessions.length > 0
1382
+ ? {
1383
+ friendId: sortedSessions[0].friendId,
1384
+ channel: sortedSessions[0].channel,
1385
+ key: sortedSessions[0].key,
1386
+ lastActivityAt: sortedSessions[0].lastActivityAt,
1387
+ }
1388
+ : null;
1389
+ const otherActiveSessions = sortedSessions.slice(1).map((s) => ({
1390
+ friendId: s.friendId,
1391
+ friendName: s.friendName,
1392
+ channel: s.channel,
1393
+ key: s.key,
1394
+ lastActivityAt: s.lastActivityAt,
1395
+ }));
1396
+ // Derive center of gravity summary
1397
+ const parts = [];
1398
+ if (primary)
1399
+ parts.push(primary.content);
1400
+ if (openObligations.length > 1)
1401
+ parts.push(`${openObligations.length} open obligations`);
1402
+ if (sessions.length > 0)
1403
+ parts.push(`${sessions.length} active sessions`);
1404
+ const centerOfGravity = parts.length > 0 ? parts.join(" | ") : "idle";
1405
+ const primaryObligation = primary
1406
+ ? {
1407
+ id: primary.id,
1408
+ content: primary.content,
1409
+ status: primary.status,
1410
+ nextAction: primary.nextAction ?? null,
1411
+ waitingOn: primary.meaning?.waitingOn?.detail ?? null,
1412
+ }
1413
+ : null;
1414
+ (0, runtime_1.emitNervesEvent)({
1415
+ component: "heart",
1416
+ event: "heart.outlook_orientation_read",
1417
+ message: `outlook orientation: ${openObligations.length} obligations, ${sessions.length} sessions`,
1418
+ meta: { obligationCount: openObligations.length, sessionCount: sessions.length, primaryId: primary?.id ?? null },
1419
+ });
1420
+ return {
1421
+ currentSession,
1422
+ centerOfGravity,
1423
+ primaryObligation,
1424
+ resumeHandle: null,
1425
+ otherActiveSessions,
1426
+ rawState: null,
1427
+ };
1428
+ }
1429
+ // ---------------------------------------------------------------------------
1430
+ // Obligation detail reader — richer view with primary selection context
1431
+ // ---------------------------------------------------------------------------
1432
+ function readObligationDetailView(agentRoot) {
1433
+ let obligations = [];
1434
+ try {
1435
+ obligations = (0, obligations_1.readObligations)(agentRoot);
1436
+ }
1437
+ catch {
1438
+ obligations = [];
1439
+ }
1440
+ const openObligations = obligations.filter(obligations_1.isOpenObligation);
1441
+ // Select primary (same logic as orientation)
1442
+ const statusPriority = {
1443
+ returning: 0,
1444
+ collaborating: 1,
1445
+ in_progress: 2,
1446
+ delegated: 3,
1447
+ accepted: 4,
1448
+ pending: 5,
1449
+ };
1450
+ const sorted = [...openObligations].sort((a, b) => {
1451
+ const sp = (statusPriority[a.status] ?? 99) - (statusPriority[b.status] ?? 99);
1452
+ if (sp !== 0)
1453
+ return sp;
1454
+ const aMs = new Date(a.updatedAt ?? a.createdAt).getTime();
1455
+ const bMs = new Date(b.updatedAt ?? b.createdAt).getTime();
1456
+ return bMs - aMs;
1457
+ });
1458
+ const primary = sorted[0] ?? null;
1459
+ const items = openObligations.map((ob) => ({
1460
+ id: ob.id,
1461
+ status: ob.status,
1462
+ content: ob.content,
1463
+ updatedAt: ob.updatedAt ?? ob.createdAt,
1464
+ nextAction: ob.nextAction ?? null,
1465
+ origin: ob.origin ?? null,
1466
+ currentSurface: ob.currentSurface ? { kind: ob.currentSurface.kind, label: ob.currentSurface.label } : null,
1467
+ meaning: ob.meaning ? { waitingOn: ob.meaning.waitingOn?.detail ?? null } : null,
1468
+ isPrimary: primary ? ob.id === primary.id : false,
1469
+ }));
1470
+ let primarySelectionReason = null;
1471
+ if (primary) {
1472
+ if (primary.status !== "pending") {
1473
+ primarySelectionReason = `most advanced status: ${primary.status}`;
1474
+ }
1475
+ else {
1476
+ primarySelectionReason = "most recent pending";
1477
+ }
1478
+ }
1479
+ (0, runtime_1.emitNervesEvent)({
1480
+ component: "heart",
1481
+ event: "heart.outlook_obligations_read",
1482
+ message: `outlook obligations: ${openObligations.length} open`,
1483
+ meta: { openCount: openObligations.length, primaryId: primary?.id ?? null },
1484
+ });
1485
+ return {
1486
+ openCount: openObligations.length,
1487
+ primaryId: primary?.id ?? null,
1488
+ primarySelectionReason,
1489
+ items,
1490
+ };
1491
+ }
1492
+ // ---------------------------------------------------------------------------
1493
+ // Changes reader — cross-session drift via snapshot comparison
1494
+ // ---------------------------------------------------------------------------
1495
+ const active_work_1 = require("../active-work");
1496
+ function readChangesView(agentRoot) {
1497
+ const snapshotPath = path.join(agentRoot, "state", "outlook", "active-work-snapshot.json");
1498
+ // Read prior snapshot
1499
+ let previous = null;
1500
+ try {
1501
+ const raw = fs.readFileSync(snapshotPath, "utf-8");
1502
+ previous = JSON.parse(raw);
1503
+ if (!previous.obligationSnapshots || !previous.codingSnapshots)
1504
+ previous = null;
1505
+ }
1506
+ catch {
1507
+ previous = null;
1508
+ }
1509
+ // Build current snapshot from raw state
1510
+ let obligations = [];
1511
+ try {
1512
+ obligations = (0, obligations_1.readObligations)(agentRoot);
1513
+ }
1514
+ catch {
1515
+ obligations = [];
1516
+ }
1517
+ const openObligations = obligations.filter(obligations_1.isOpenObligation);
1518
+ const current = {
1519
+ obligationSnapshots: openObligations.map((ob) => ({
1520
+ id: ob.id,
1521
+ status: ob.status,
1522
+ artifact: ob.currentArtifact?.trim() || null,
1523
+ nextAction: ob.nextAction?.trim() || null,
1524
+ })),
1525
+ codingSnapshots: [],
1526
+ timestamp: new Date().toISOString(),
1527
+ };
1528
+ // Persist current as the new snapshot
1529
+ try {
1530
+ fs.mkdirSync(path.dirname(snapshotPath), { recursive: true });
1531
+ fs.writeFileSync(snapshotPath, JSON.stringify(current, null, 2) + "\n", "utf-8");
1532
+ }
1533
+ catch {
1534
+ // Best effort
1535
+ }
1536
+ if (!previous) {
1537
+ return { changeCount: 0, items: [], snapshotAge: null, formatted: "" };
1538
+ }
1539
+ const changes = (0, active_work_1.detectActiveWorkChanges)(previous, current);
1540
+ const formatted = (0, active_work_1.formatActiveWorkChanges)(changes);
1541
+ (0, runtime_1.emitNervesEvent)({
1542
+ component: "heart",
1543
+ event: "heart.outlook_changes_read",
1544
+ message: `outlook changes: ${changes.length} detected`,
1545
+ meta: { changeCount: changes.length, snapshotAge: previous.timestamp },
1546
+ });
1547
+ return {
1548
+ changeCount: changes.length,
1549
+ items: changes.map((c) => ({ kind: c.kind, id: c.id, from: c.from, to: c.to, summary: c.summary })),
1550
+ snapshotAge: previous.timestamp,
1551
+ formatted,
1552
+ };
1553
+ }
1554
+ // ---------------------------------------------------------------------------
1555
+ // Self-fix workflow reader — derived from task board and coding state
1556
+ // ---------------------------------------------------------------------------
1557
+ function readSelfFixView(agentRoot) {
1558
+ // Derive self-fix state from task scanner
1559
+ let tasks = [];
1560
+ try {
1561
+ const scanned = (0, scanner_1.scanTasks)(path.join(agentRoot, "tasks"));
1562
+ tasks = scanned.tasks.map((t) => ({ name: t.name, title: t.title, status: t.status }));
1563
+ }
1564
+ catch {
1565
+ tasks = [];
1566
+ }
1567
+ // Look for self-fix-related tasks
1568
+ const selfFixTasks = tasks.filter((t) => t.title.toLowerCase().includes("fix") || t.title.toLowerCase().includes("self-fix"));
1569
+ if (selfFixTasks.length === 0) {
1570
+ return { active: false, currentStep: null, steps: [] };
1571
+ }
1572
+ const steps = selfFixTasks.map((t) => ({
1573
+ label: t.title,
1574
+ status: t.status === "done" ? "done" : t.status === "processing" ? "active" : "pending",
1575
+ detail: `task ${t.name}: ${t.status}`,
1576
+ }));
1577
+ const activeStep = steps.find((s) => s.status === "active");
1578
+ (0, runtime_1.emitNervesEvent)({
1579
+ component: "heart",
1580
+ event: "heart.outlook_selffix_read",
1581
+ message: `outlook self-fix: ${selfFixTasks.length} tasks`,
1582
+ meta: { taskCount: selfFixTasks.length, active: !!activeStep },
1583
+ });
1584
+ return {
1585
+ active: !!activeStep,
1586
+ currentStep: activeStep?.label ?? null,
1587
+ steps,
1588
+ };
1589
+ }
1590
+ // ---------------------------------------------------------------------------
1591
+ // Memory decisions reader — append-only JSONL log
1592
+ // ---------------------------------------------------------------------------
1593
+ function readMemoryDecisionView(agentRoot, limit = 50) {
1594
+ const logPath = path.join(agentRoot, "state", "outlook", "memory-decisions.jsonl");
1595
+ let lines = [];
1596
+ try {
1597
+ const raw = fs.readFileSync(logPath, "utf-8");
1598
+ lines = raw.split("\n").filter((l) => l.trim().length > 0);
1599
+ }
1600
+ catch {
1601
+ return { totalCount: 0, items: [] };
1602
+ }
1603
+ const items = [];
1604
+ for (const line of lines) {
1605
+ try {
1606
+ const parsed = JSON.parse(line);
1607
+ if (parsed.kind && parsed.decision && parsed.timestamp) {
1608
+ items.push(parsed);
1609
+ }
1610
+ }
1611
+ catch {
1612
+ // Skip malformed lines
1613
+ }
1614
+ }
1615
+ // Reverse chronological
1616
+ items.reverse();
1617
+ const limited = items.slice(0, limit);
1618
+ return { totalCount: items.length, items: limited };
1619
+ }
@@ -65,10 +65,11 @@ function buildPresenceSection(peers) {
65
65
  .map((p) => `- ${p.agentName}: ${p.availability}/${p.lane}`)
66
66
  .join("\n");
67
67
  }
68
- function buildResumeHint(view) {
68
+ function buildResumeHint(view, obligations) {
69
69
  // Compose from authored obligation resumeHints and top intentions
70
70
  const hints = [];
71
- for (const ob of view.activeObligations) {
71
+ const effectiveObligations = obligations ?? view.activeObligations;
72
+ for (const ob of effectiveObligations) {
72
73
  if (ob.meaning?.resumeHint) {
73
74
  hints.push(ob.meaning.resumeHint);
74
75
  }
@@ -78,23 +79,24 @@ function buildResumeHint(view) {
78
79
  }
79
80
  if (hints.length === 0) {
80
81
  // Fall back to top obligation content
81
- if (view.activeObligations.length > 0) {
82
- hints.push(view.activeObligations[0].content);
82
+ if (effectiveObligations.length > 0) {
83
+ hints.push(effectiveObligations[0].content);
83
84
  }
84
85
  }
85
86
  if (hints.length === 0)
86
87
  return "";
87
88
  return hints.join("; ");
88
89
  }
89
- function buildWakePacket(view) {
90
+ function buildWakePacket(view, opts) {
90
91
  const tempo = view.tempo;
91
92
  const tokenBudget = tempo_1.TEMPO_BUDGETS[tempo];
93
+ const effectiveObligations = opts?.canonicalObligations ? opts.canonicalObligations.all : view.activeObligations;
92
94
  const packet = {
93
95
  plotLine: buildPlotLine(view.recentEpisodes, tempo),
94
- obligations: buildObligationsSection(view.activeObligations),
96
+ obligations: buildObligationsSection(effectiveObligations),
95
97
  cares: buildCaresSection(view.activeCares),
96
98
  presence: buildPresenceSection(view.peerPresence),
97
- resumeHint: buildResumeHint(view),
99
+ resumeHint: buildResumeHint(view, opts?.canonicalObligations ? effectiveObligations : undefined),
98
100
  tempo,
99
101
  tokenBudget,
100
102
  assembledAt: new Date().toISOString(),
@@ -106,7 +106,10 @@ function resetPsycheCache() {
106
106
  }
107
107
  const DEFAULT_ACTIVE_THRESHOLD_MS = 24 * 60 * 60 * 1000; // 24 hours
108
108
  function buildSessionSummary(options) {
109
- const { sessionsDir, friendsDir, agentName, currentFriendId, currentChannel, currentKey, activeThresholdMs = DEFAULT_ACTIVE_THRESHOLD_MS, } = options;
109
+ const { sessionsDir, friendsDir, agentName, currentSession, activeThresholdMs = DEFAULT_ACTIVE_THRESHOLD_MS, } = options;
110
+ const currentFriendId = currentSession?.friendId ?? options.currentFriendId;
111
+ const currentChannel = currentSession?.channel ?? options.currentChannel;
112
+ const currentKey = currentSession?.key ?? options.currentKey;
110
113
  const now = Date.now();
111
114
  const query = {
112
115
  sessionsDir,
@@ -519,7 +522,7 @@ function wakePacketSection(options) {
519
522
  function activeWorkSection(options) {
520
523
  if (!options?.activeWorkFrame)
521
524
  return "";
522
- return (0, active_work_1.formatActiveWorkFrame)(options.activeWorkFrame, { hasWakePacket: !!options?.wakePacket });
525
+ return (0, active_work_1.formatActiveWorkFrame)(options.activeWorkFrame, { obligationDetailsRenderedElsewhere: !!options?.wakePacket });
523
526
  }
524
527
  function liveWorldStateSection(options) {
525
528
  if (!options?.activeWorkFrame)
@@ -1079,6 +1082,9 @@ async function buildSystem(channel = "cli", options, context) {
1079
1082
  sessionsDir: path.join((0, identity_1.getAgentRoot)(), "state", "sessions"),
1080
1083
  friendsDir: path.join((0, identity_1.getAgentRoot)(), "friends"),
1081
1084
  agentName: (0, identity_1.getAgentName)(),
1085
+ currentSession: options?.activeWorkFrame?.currentSession
1086
+ ? { friendId: options.activeWorkFrame.currentSession.friendId, channel: options.activeWorkFrame.currentSession.channel, key: options.activeWorkFrame.currentSession.key }
1087
+ : undefined,
1082
1088
  currentFriendId: context?.friend?.id,
1083
1089
  currentChannel: channel,
1084
1090
  currentKey: options?.currentSessionKey ?? "session",