@ouro.bot/cli 0.1.0-alpha.657 → 0.1.0-alpha.658
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/README.md +13 -13
- package/changelog.json +9 -0
- package/dist/arc/evolution.js +1 -1
- package/dist/arc/flight-recorder.js +369 -0
- package/dist/arc/obligations.js +24 -2
- package/dist/heart/active-work.js +1 -1
- package/dist/heart/config-registry.js +5 -5
- package/dist/heart/daemon/agent-config-check.js +1 -1
- package/dist/heart/daemon/agent-service.js +18 -17
- package/dist/heart/daemon/cli-exec.js +27 -12
- package/dist/heart/daemon/cli-help.js +14 -0
- package/dist/heart/daemon/cli-parse.js +26 -0
- package/dist/heart/daemon/daemon-entry.js +1 -1
- package/dist/heart/daemon/daemon.js +3 -3
- package/dist/heart/daemon/hooks/bundle-meta.js +29 -9
- package/dist/heart/daemon/inner-status.js +4 -15
- package/dist/heart/habits/habit-parser.js +64 -1
- package/dist/heart/hatch/hatch-flow.js +17 -9
- package/dist/heart/hatch/specialist-tools.js +15 -11
- package/dist/heart/kept-notes.js +5 -73
- package/dist/heart/mailbox/readers/runtime-readers.js +21 -49
- package/dist/heart/mcp/mcp-server.js +8 -8
- package/dist/heart/session-events.js +1 -31
- package/dist/heart/start-of-turn-packet.js +8 -2
- package/dist/heart/tool-description.js +15 -3
- package/dist/heart/turn-context.js +27 -7
- package/dist/heart/work-card.js +386 -0
- package/dist/mailbox-ui/assets/{index-9-AxCxuB.js → index-Cbasiy6y.js} +1 -1
- package/dist/mailbox-ui/index.html +1 -1
- package/dist/mind/bundle-manifest.js +9 -3
- package/dist/mind/context.js +1 -2
- package/dist/mind/desk-section.js +53 -1
- package/dist/mind/diary.js +2 -3
- package/dist/mind/note-search.js +36 -106
- package/dist/mind/prompt.js +37 -102
- package/dist/mind/record-paths.js +312 -0
- package/dist/repertoire/bundle-templates.js +4 -5
- package/dist/repertoire/tools-bundle.js +1 -1
- package/dist/repertoire/tools-evolution.js +4 -4
- package/dist/repertoire/tools-notes.js +42 -62
- package/dist/repertoire/tools-record.js +16 -11
- package/dist/repertoire/tools-session.js +4 -4
- package/dist/repertoire/tools.js +1 -1
- package/dist/senses/habit-turn-message.js +19 -5
- package/dist/senses/inner-dialog-worker.js +58 -9
- package/dist/senses/inner-dialog.js +30 -11
- package/dist/senses/pipeline.js +135 -1
- package/dist/util/frontmatter.js +17 -1
- package/package.json +3 -3
- package/skills/configure-dev-tools.md +1 -1
- package/skills/travel-planning.md +1 -1
- package/dist/mind/journal-index.js +0 -162
package/dist/heart/kept-notes.js
CHANGED
|
@@ -1,44 +1,9 @@
|
|
|
1
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.gatherKeptNotesCandidates = gatherKeptNotesCandidates;
|
|
37
4
|
exports.renderKeptNotesOutcome = renderKeptNotesOutcome;
|
|
38
5
|
exports.injectKeptNotes = injectKeptNotes;
|
|
39
6
|
exports.createKeptNotesJudge = createKeptNotesJudge;
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
7
|
const diary_1 = require("../mind/diary");
|
|
43
8
|
const runtime_1 = require("../nerves/runtime");
|
|
44
9
|
const DEFAULT_TIMEOUT_MS = 2500;
|
|
@@ -82,26 +47,6 @@ function scoreText(queryTerms, text) {
|
|
|
82
47
|
}
|
|
83
48
|
return matches / queryTerms.size;
|
|
84
49
|
}
|
|
85
|
-
function readJournalIndex(journalDir) {
|
|
86
|
-
try {
|
|
87
|
-
const parsed = JSON.parse(fs.readFileSync(path.join(journalDir, ".index.json"), "utf8"));
|
|
88
|
-
if (!Array.isArray(parsed))
|
|
89
|
-
return [];
|
|
90
|
-
return parsed
|
|
91
|
-
.filter((entry) => (typeof entry === "object" &&
|
|
92
|
-
entry !== null &&
|
|
93
|
-
typeof entry.filename === "string" &&
|
|
94
|
-
typeof entry.preview === "string"));
|
|
95
|
-
}
|
|
96
|
-
catch {
|
|
97
|
-
return [];
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
function journalDirForDiaryRoot(diaryRoot, explicitJournalDir) {
|
|
101
|
-
if (explicitJournalDir)
|
|
102
|
-
return explicitJournalDir;
|
|
103
|
-
return path.join(path.dirname(diaryRoot), "journal");
|
|
104
|
-
}
|
|
105
50
|
function diaryCandidate(fact) {
|
|
106
51
|
return {
|
|
107
52
|
text: fact.text,
|
|
@@ -133,17 +78,7 @@ function gatherKeptNotesCandidates(query, options = {}) {
|
|
|
133
78
|
const diaryCandidates = diaryEntries
|
|
134
79
|
.map((fact) => ({ candidate: diaryCandidate(fact), score: scoreText(queryTerms, fact.text) }))
|
|
135
80
|
.filter((entry) => entry.score > 0);
|
|
136
|
-
|
|
137
|
-
const journalCandidates = readJournalIndex(journalDir)
|
|
138
|
-
.map((entry) => ({
|
|
139
|
-
candidate: {
|
|
140
|
-
text: `${entry.filename}: ${entry.preview}`,
|
|
141
|
-
source: { kind: "journal", label: "journal", ref: entry.filename },
|
|
142
|
-
},
|
|
143
|
-
score: scoreText(queryTerms, `${entry.filename} ${entry.preview}`),
|
|
144
|
-
}))
|
|
145
|
-
.filter((entry) => entry.score > 0);
|
|
146
|
-
return [...diaryCandidates, ...journalCandidates, ...friendNoteCandidates(options.friend, queryTerms)]
|
|
81
|
+
return [...diaryCandidates, ...friendNoteCandidates(options.friend, queryTerms)]
|
|
147
82
|
.sort((left, right) => right.score - left.score)
|
|
148
83
|
.slice(0, MAX_CANDIDATES)
|
|
149
84
|
.map((entry) => entry.candidate);
|
|
@@ -176,18 +111,15 @@ function fuzzyLine(text) {
|
|
|
176
111
|
return trimmed;
|
|
177
112
|
return `I may have kept something related: ${trimmed}`;
|
|
178
113
|
}
|
|
179
|
-
const SOURCE_KIND_ORDER = ["diary", "
|
|
114
|
+
const SOURCE_KIND_ORDER = ["diary", "friend-note"];
|
|
180
115
|
const SOURCE_KIND_LABELS = {
|
|
181
|
-
diary: "my diary",
|
|
182
|
-
journal: "my journal",
|
|
116
|
+
diary: "my Desk record diary",
|
|
183
117
|
"friend-note": "my friend notes",
|
|
184
118
|
};
|
|
185
119
|
function joinLabels(labels) {
|
|
186
120
|
if (labels.length === 1)
|
|
187
121
|
return labels[0];
|
|
188
|
-
|
|
189
|
-
return `${labels[0]} and ${labels[1]}`;
|
|
190
|
-
return `${labels.slice(0, -1).join(", ")}, and ${labels[labels.length - 1]}`;
|
|
122
|
+
return `${labels[0]} and ${labels[1]}`;
|
|
191
123
|
}
|
|
192
124
|
function sourceHeading(sources) {
|
|
193
125
|
const sourceKinds = new Set(sources.map((source) => source.kind));
|
|
@@ -195,7 +127,7 @@ function sourceHeading(sources) {
|
|
|
195
127
|
.filter((kind) => sourceKinds.has(kind))
|
|
196
128
|
.map((kind) => SOURCE_KIND_LABELS[kind]);
|
|
197
129
|
if (labels.length === 0)
|
|
198
|
-
return "## from
|
|
130
|
+
return "## from my kept record";
|
|
199
131
|
return `## from ${joinLabels(labels)}`;
|
|
200
132
|
}
|
|
201
133
|
function renderKeptNotesOutcome(outcome) {
|
|
@@ -53,6 +53,7 @@ const daemon_health_1 = require("../../daemon/daemon-health");
|
|
|
53
53
|
const shared_1 = require("./shared");
|
|
54
54
|
const agent_machine_1 = require("./agent-machine");
|
|
55
55
|
const sessions_1 = require("./sessions");
|
|
56
|
+
const record_paths_1 = require("../../../mind/record-paths");
|
|
56
57
|
const NOTES_VIEW_LIMIT = 20;
|
|
57
58
|
/* v8 ignore start — defensive parsing of on-disk JSON, fallback branches are safety nets */
|
|
58
59
|
function readCodingDeep(agentRoot) {
|
|
@@ -324,71 +325,42 @@ function readDaemonHealthDeep(healthPath) {
|
|
|
324
325
|
}
|
|
325
326
|
/* v8 ignore stop */
|
|
326
327
|
function readNotesView(agentRoot) {
|
|
327
|
-
const
|
|
328
|
-
const effectiveDiaryRoot = fs.existsSync(diaryRoot) ? diaryRoot : null;
|
|
328
|
+
const recordPaths = (0, record_paths_1.resolveDeskRecordPaths)(agentRoot);
|
|
329
329
|
const diaryEntries = [];
|
|
330
|
-
if (effectiveDiaryRoot) {
|
|
331
|
-
const factsPath = path.join(effectiveDiaryRoot, "facts.jsonl");
|
|
332
|
-
try {
|
|
333
|
-
const raw = fs.readFileSync(factsPath, "utf-8");
|
|
334
|
-
for (const line of raw.split("\n")) {
|
|
335
|
-
if (!line.trim())
|
|
336
|
-
continue;
|
|
337
|
-
try {
|
|
338
|
-
const entry = JSON.parse(line);
|
|
339
|
-
if (typeof entry.id === "string" && typeof entry.text === "string") {
|
|
340
|
-
diaryEntries.push({
|
|
341
|
-
id: entry.id,
|
|
342
|
-
text: entry.text,
|
|
343
|
-
source: typeof entry.source === "string" ? entry.source : "",
|
|
344
|
-
createdAt: typeof entry.createdAt === "string" ? entry.createdAt : "",
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
catch {
|
|
349
|
-
// skip unparseable lines
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
catch {
|
|
354
|
-
// no diary facts file
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
diaryEntries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
358
|
-
const journalDir = path.join(agentRoot, "journal");
|
|
359
|
-
const journalEntries = [];
|
|
360
|
-
const indexPath = path.join(journalDir, ".index.json");
|
|
361
330
|
try {
|
|
362
|
-
const raw = fs.readFileSync(
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
331
|
+
const raw = fs.readFileSync(recordPaths.factsPath, "utf-8");
|
|
332
|
+
for (const line of raw.split("\n")) {
|
|
333
|
+
if (!line.trim())
|
|
334
|
+
continue;
|
|
335
|
+
try {
|
|
336
|
+
const entry = JSON.parse(line);
|
|
337
|
+
if (typeof entry.id === "string" && typeof entry.text === "string") {
|
|
338
|
+
diaryEntries.push({
|
|
339
|
+
id: entry.id,
|
|
340
|
+
text: entry.text,
|
|
341
|
+
source: typeof entry.source === "string" ? entry.source : "",
|
|
342
|
+
createdAt: typeof entry.createdAt === "string" ? entry.createdAt : "",
|
|
371
343
|
});
|
|
372
344
|
}
|
|
373
345
|
}
|
|
346
|
+
catch {
|
|
347
|
+
// skip unparseable lines
|
|
348
|
+
}
|
|
374
349
|
}
|
|
375
350
|
}
|
|
376
351
|
catch {
|
|
377
|
-
// no
|
|
352
|
+
// no diary facts file
|
|
378
353
|
}
|
|
379
|
-
|
|
380
|
-
const canonicalNotes = readCanonicalNotes(
|
|
354
|
+
diaryEntries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
355
|
+
const canonicalNotes = readCanonicalNotes(recordPaths.notesRoot);
|
|
381
356
|
return {
|
|
382
357
|
diaryEntryCount: diaryEntries.length,
|
|
383
358
|
recentDiaryEntries: diaryEntries.slice(0, NOTES_VIEW_LIMIT),
|
|
384
|
-
journalEntryCount: journalEntries.length,
|
|
385
|
-
recentJournalEntries: journalEntries.slice(0, NOTES_VIEW_LIMIT),
|
|
386
359
|
canonicalNoteCount: canonicalNotes.length,
|
|
387
360
|
recentCanonicalNotes: canonicalNotes.slice(0, NOTES_VIEW_LIMIT),
|
|
388
361
|
};
|
|
389
362
|
}
|
|
390
|
-
function readCanonicalNotes(
|
|
391
|
-
const notesRoot = path.join(agentRoot, "notes");
|
|
363
|
+
function readCanonicalNotes(notesRoot) {
|
|
392
364
|
const notes = [];
|
|
393
365
|
for (const filename of (0, shared_1.safeReaddir)(notesRoot)) {
|
|
394
366
|
if (!filename.endsWith(".md"))
|
|
@@ -123,7 +123,7 @@ const TOOL_TO_COMMAND = {
|
|
|
123
123
|
status: "agent.status",
|
|
124
124
|
catchup: "agent.catchup",
|
|
125
125
|
get_context: "agent.getContext",
|
|
126
|
-
|
|
126
|
+
search_facts: "agent.searchFacts",
|
|
127
127
|
get_task: "agent.getTask",
|
|
128
128
|
};
|
|
129
129
|
const UUID_PREFIX_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-/i;
|
|
@@ -326,7 +326,7 @@ function createMcpServer(options) {
|
|
|
326
326
|
status: "handleAgentStatus",
|
|
327
327
|
catchup: "handleAgentCatchup",
|
|
328
328
|
get_context: "handleAgentGetContext",
|
|
329
|
-
|
|
329
|
+
search_facts: "handleAgentSearchFacts",
|
|
330
330
|
get_task: "handleAgentGetTask",
|
|
331
331
|
};
|
|
332
332
|
function stringArg(args, key) {
|
|
@@ -537,7 +537,7 @@ function getToolSchemas() {
|
|
|
537
537
|
return [
|
|
538
538
|
{
|
|
539
539
|
name: "ask",
|
|
540
|
-
description: "Ask the agent a question through a full conversation turn. This has the same identity, tools, and session continuity as send_message; use
|
|
540
|
+
description: "Ask the agent a question through a full conversation turn. This has the same identity, tools, and session continuity as send_message; use search_facts or consult_notes for read-only record lookup.",
|
|
541
541
|
inputSchema: {
|
|
542
542
|
type: "object",
|
|
543
543
|
properties: {
|
|
@@ -548,7 +548,7 @@ function getToolSchemas() {
|
|
|
548
548
|
},
|
|
549
549
|
{
|
|
550
550
|
name: "status",
|
|
551
|
-
description: "Get the agent's current status including active sessions,
|
|
551
|
+
description: "Get the agent's current status including active sessions, Desk record state, and activity level.",
|
|
552
552
|
inputSchema: {
|
|
553
553
|
type: "object",
|
|
554
554
|
properties: {},
|
|
@@ -576,19 +576,19 @@ function getToolSchemas() {
|
|
|
576
576
|
},
|
|
577
577
|
{
|
|
578
578
|
name: "get_context",
|
|
579
|
-
description: "Get the agent's current working context including
|
|
579
|
+
description: "Get the agent's current working context including Desk record summary, active tasks, and relevant state.",
|
|
580
580
|
inputSchema: {
|
|
581
581
|
type: "object",
|
|
582
582
|
properties: {},
|
|
583
583
|
},
|
|
584
584
|
},
|
|
585
585
|
{
|
|
586
|
-
name: "
|
|
587
|
-
description: "Read-only
|
|
586
|
+
name: "search_facts",
|
|
587
|
+
description: "Read-only fact search. Returns matching Desk record diary lines without running an agent turn or treating missing matches as absence of agent belief.",
|
|
588
588
|
inputSchema: {
|
|
589
589
|
type: "object",
|
|
590
590
|
properties: {
|
|
591
|
-
query: { type: "string", description: "Search term to look for in agent
|
|
591
|
+
query: { type: "string", description: "Search term to look for in agent facts" },
|
|
592
592
|
},
|
|
593
593
|
required: ["query"],
|
|
594
594
|
},
|
|
@@ -57,12 +57,10 @@ exports.migrateLegacySessionEnvelope = migrateLegacySessionEnvelope;
|
|
|
57
57
|
exports.parseSessionEnvelope = parseSessionEnvelope;
|
|
58
58
|
exports.loadSessionEnvelopeFile = loadSessionEnvelopeFile;
|
|
59
59
|
exports.buildCanonicalSessionEnvelope = buildCanonicalSessionEnvelope;
|
|
60
|
-
exports.appendEvictedToArchive = appendEvictedToArchive;
|
|
61
60
|
exports.appendSyntheticAssistantEvent = appendSyntheticAssistantEvent;
|
|
62
61
|
const fs = __importStar(require("fs"));
|
|
63
62
|
const runtime_1 = require("../nerves/runtime");
|
|
64
63
|
const structured_output_1 = require("./structured-output");
|
|
65
|
-
let archiveDisabledEmitted = false;
|
|
66
64
|
exports.EVENT_CONTENT_MAX_CHARS = 256 * 1024;
|
|
67
65
|
function truncateLargeEventContent(content, maxChars) {
|
|
68
66
|
if (typeof content !== "string") {
|
|
@@ -120,7 +118,7 @@ const TOOL_NAME_MIGRATIONS = {
|
|
|
120
118
|
go_inward: "ponder",
|
|
121
119
|
descend: "ponder",
|
|
122
120
|
[`${LEGACY_WRITTEN_NOTE_PREFIX}_save`]: "diary_write",
|
|
123
|
-
[`${LEGACY_WRITTEN_NOTE_PREFIX}_search`]: "
|
|
121
|
+
[`${LEGACY_WRITTEN_NOTE_PREFIX}_search`]: "search_facts",
|
|
124
122
|
};
|
|
125
123
|
function normalizeUsage(usage) {
|
|
126
124
|
if (!usage || typeof usage !== "object")
|
|
@@ -1115,34 +1113,6 @@ function buildCanonicalSessionEnvelope(options) {
|
|
|
1115
1113
|
evictedEvents,
|
|
1116
1114
|
};
|
|
1117
1115
|
}
|
|
1118
|
-
function agentFromSessionPath(sessPath) {
|
|
1119
|
-
const match = sessPath.match(/(?:^|[/\\])AgentBundles[/\\]([^/\\]+)\.ouro(?:[/\\]|$)/);
|
|
1120
|
-
return match?.[1] ?? "unknown";
|
|
1121
|
-
}
|
|
1122
|
-
/**
|
|
1123
|
-
* Archive writes are intentionally disabled. The session envelope remains the
|
|
1124
|
-
* bounded working-memory record; evicted events are no longer persisted to an
|
|
1125
|
-
* unbounded sidecar.
|
|
1126
|
-
*/
|
|
1127
|
-
function appendEvictedToArchive(sessPath, evictedEvents) {
|
|
1128
|
-
if (evictedEvents.length === 0)
|
|
1129
|
-
return;
|
|
1130
|
-
if (!archiveDisabledEmitted) {
|
|
1131
|
-
archiveDisabledEmitted = true;
|
|
1132
|
-
(0, runtime_1.emitNervesEvent)({
|
|
1133
|
-
component: "heart",
|
|
1134
|
-
event: "heart.session_archive_disabled",
|
|
1135
|
-
message: "session archive append disabled",
|
|
1136
|
-
meta: {
|
|
1137
|
-
type: "session_archive_disabled",
|
|
1138
|
-
agent: agentFromSessionPath(sessPath),
|
|
1139
|
-
sessionPath: sessPath,
|
|
1140
|
-
evictedCount: evictedEvents.length,
|
|
1141
|
-
ts: new Date().toISOString(),
|
|
1142
|
-
},
|
|
1143
|
-
});
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
1116
|
function appendSyntheticAssistantEvent(envelope, content, recordedAt) {
|
|
1147
1117
|
// Use nextEventSequence(events) instead of `events.length + 1` so any gap
|
|
1148
1118
|
// (from pruning, archive replay, or self-heal dedup) cannot collide with
|
|
@@ -42,6 +42,7 @@ const path = __importStar(require("path"));
|
|
|
42
42
|
const runtime_1 = require("../nerves/runtime");
|
|
43
43
|
const bundle_state_1 = require("./bundle-state");
|
|
44
44
|
const tempo_1 = require("./tempo");
|
|
45
|
+
const flight_recorder_1 = require("../arc/flight-recorder");
|
|
45
46
|
function estimateTokens(text) {
|
|
46
47
|
return Math.ceil(text.length / 4);
|
|
47
48
|
}
|
|
@@ -191,6 +192,7 @@ function buildStartOfTurnPacket(view, opts) {
|
|
|
191
192
|
obligations: buildObligationsSection(effectiveObligations),
|
|
192
193
|
cares: buildCaresSection(view.activeCares),
|
|
193
194
|
presence: buildPresenceSection(view.peerPresence),
|
|
195
|
+
arcResume: opts?.flightRecorderResume ? (0, flight_recorder_1.formatFlightRecorderResume)(opts.flightRecorderResume) : undefined,
|
|
194
196
|
resumeHint: buildResumeHint(view, opts?.canonicalObligations ? effectiveObligations : undefined),
|
|
195
197
|
currentSessionTiming: opts?.currentSessionTiming,
|
|
196
198
|
tempo,
|
|
@@ -231,6 +233,7 @@ function renderStartOfTurnPacket(packet) {
|
|
|
231
233
|
{ label: "provider", content: packet.providerSelection ?? "", priority: 8 },
|
|
232
234
|
{ label: "bundleState", content: (0, bundle_state_1.renderBundleStateHint)(packet.bundleState ?? []), priority: 7 },
|
|
233
235
|
{ label: "syncFailure", content: packet.syncFailure ?? "", priority: 7 },
|
|
236
|
+
{ label: "arc", content: packet.arcResume ?? "", priority: 7 },
|
|
234
237
|
{ label: "resume", content: packet.resumeHint, priority: 6 },
|
|
235
238
|
{ label: "sessionTiming", content: packet.currentSessionTiming ?? "", priority: 5 },
|
|
236
239
|
{ label: "obligations", content: packet.obligations, priority: 5 },
|
|
@@ -256,8 +259,8 @@ function renderStartOfTurnPacket(packet) {
|
|
|
256
259
|
for (const section of sortedByPriority) {
|
|
257
260
|
if (tokens <= budget.max)
|
|
258
261
|
break;
|
|
259
|
-
// Skip
|
|
260
|
-
if (section.label === "resume")
|
|
262
|
+
// Skip continuity sections — they are protected.
|
|
263
|
+
if (section.label === "resume" || section.label === "arc")
|
|
261
264
|
continue;
|
|
262
265
|
// Remove this section entirely
|
|
263
266
|
const idx = sections.findIndex((s) => s.label === section.label);
|
|
@@ -285,6 +288,9 @@ function formatSections(sections) {
|
|
|
285
288
|
case "resume":
|
|
286
289
|
parts.push(`**Next:** ${section.content}`);
|
|
287
290
|
break;
|
|
291
|
+
case "arc":
|
|
292
|
+
parts.push(`**Arc:**\n${section.content}`);
|
|
293
|
+
break;
|
|
288
294
|
case "obligations":
|
|
289
295
|
parts.push(`**Owed:**\n${section.content}`);
|
|
290
296
|
break;
|
|
@@ -56,11 +56,23 @@ const TOOL_DESCRIPTIONS = {
|
|
|
56
56
|
return `searching code for '${truncate(p, 40)}'...`;
|
|
57
57
|
},
|
|
58
58
|
// Notes and knowledge
|
|
59
|
-
|
|
59
|
+
search_facts: (args) => {
|
|
60
60
|
const q = args.query;
|
|
61
61
|
if (!q)
|
|
62
|
-
return "searching
|
|
63
|
-
return `searching
|
|
62
|
+
return "searching facts...";
|
|
63
|
+
return `searching facts for '${truncate(q, 40)}'...`;
|
|
64
|
+
},
|
|
65
|
+
consult_diary: (args) => {
|
|
66
|
+
const q = args.query;
|
|
67
|
+
if (!q)
|
|
68
|
+
return "checking recent diary facts...";
|
|
69
|
+
return `consulting diary facts for '${truncate(q, 40)}'...`;
|
|
70
|
+
},
|
|
71
|
+
consult_notes: (args) => {
|
|
72
|
+
const q = args.query;
|
|
73
|
+
if (!q)
|
|
74
|
+
return "checking Desk record notes...";
|
|
75
|
+
return `consulting Desk record notes for '${truncate(q, 40)}'...`;
|
|
64
76
|
},
|
|
65
77
|
diary_write: (args) => {
|
|
66
78
|
const about = args.about;
|
|
@@ -58,9 +58,9 @@ const cares_1 = require("../arc/cares");
|
|
|
58
58
|
const config_1 = require("./config");
|
|
59
59
|
const runtime_credentials_1 = require("./runtime-credentials");
|
|
60
60
|
const daemon_health_1 = require("./daemon/daemon-health");
|
|
61
|
-
const prompt_1 = require("../mind/prompt");
|
|
62
61
|
const provider_visibility_1 = require("./provider-visibility");
|
|
63
62
|
const mail_import_discovery_1 = require("./mail-import-discovery");
|
|
63
|
+
const flight_recorder_1 = require("../arc/flight-recorder");
|
|
64
64
|
// ── Helpers ─────────────────────────────────────────────────────────
|
|
65
65
|
const DAEMON_SOCKET_PATH = "/tmp/ouroboros-daemon.sock";
|
|
66
66
|
function isLiveCodingSessionStatus(status) {
|
|
@@ -229,6 +229,26 @@ function readBundleMetaFile() {
|
|
|
229
229
|
/* v8 ignore stop */
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
|
+
function degradedFlightRecorderResume(issue) {
|
|
233
|
+
return {
|
|
234
|
+
schemaVersion: 1,
|
|
235
|
+
hasCompleteState: false,
|
|
236
|
+
canContinue: false,
|
|
237
|
+
missing: ["currentAsk", "nextSafeAction"],
|
|
238
|
+
gaps: [],
|
|
239
|
+
currentAsk: { value: null, confidence: "unknown", sourceEventIds: [] },
|
|
240
|
+
nextSafeAction: { value: null, stopBefore: [], sourceEventIds: [] },
|
|
241
|
+
blockedBecause: [],
|
|
242
|
+
activeObligationIds: [],
|
|
243
|
+
activeReturnObligationIds: [],
|
|
244
|
+
activePacketIds: [],
|
|
245
|
+
openEvolutionCaseIds: [],
|
|
246
|
+
recentClaimIds: [],
|
|
247
|
+
unverifiedClaimIds: [],
|
|
248
|
+
lastSafeCheckpoint: { turnId: null, sessionRef: null, recordedAt: null, sourceEventIds: [] },
|
|
249
|
+
recorderHealth: { status: "degraded", issues: [issue] },
|
|
250
|
+
};
|
|
251
|
+
}
|
|
232
252
|
// ── Builder ─────────────────────────────────────────────────────────
|
|
233
253
|
async function buildTurnContext(input) {
|
|
234
254
|
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
@@ -355,13 +375,13 @@ async function buildTurnContext(input) {
|
|
|
355
375
|
daemonHealth = null;
|
|
356
376
|
/* v8 ignore stop */
|
|
357
377
|
}
|
|
358
|
-
let
|
|
378
|
+
let flightRecorderResume;
|
|
359
379
|
try {
|
|
360
|
-
|
|
361
|
-
journalFiles = (0, prompt_1.readJournalFiles)(journalDir);
|
|
380
|
+
flightRecorderResume = (0, flight_recorder_1.readFlightRecorderResume)(agentRoot);
|
|
362
381
|
}
|
|
363
|
-
catch { /* v8 ignore start -- defensive: fallback on read failure @preserve */
|
|
364
|
-
|
|
382
|
+
catch (error) { /* v8 ignore start -- defensive: fallback on read failure @preserve */
|
|
383
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
384
|
+
flightRecorderResume = degradedFlightRecorderResume(`flight recorder read failed: ${reason}`);
|
|
365
385
|
/* v8 ignore stop */
|
|
366
386
|
}
|
|
367
387
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -397,6 +417,6 @@ async function buildTurnContext(input) {
|
|
|
397
417
|
senseStatusLines,
|
|
398
418
|
bundleMeta,
|
|
399
419
|
daemonHealth,
|
|
400
|
-
|
|
420
|
+
flightRecorderResume,
|
|
401
421
|
};
|
|
402
422
|
}
|