@ouro.bot/cli 0.1.0-alpha.655 → 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 +21 -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 +14 -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 +134 -15
- package/dist/heart/daemon/cli-help.js +21 -2
- package/dist/heart/daemon/cli-parse.js +31 -3
- 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/daemon/sense-manager.js +16 -1
- 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/identity.js +4 -1
- 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/sense-truth.js +2 -0
- 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 +34 -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 +45 -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
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta name="color-scheme" content="dark" />
|
|
7
7
|
<title>Ouro Mailbox</title>
|
|
8
8
|
<meta name="description" content="The daemon-hosted shared orientation surface for agents alive on this machine." />
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-Cbasiy6y.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="/assets/index-CWzt267f.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
@@ -57,8 +57,10 @@ exports.CANONICAL_BUNDLE_MANIFEST = [
|
|
|
57
57
|
{ path: "arc/obligations", kind: "dir" },
|
|
58
58
|
{ path: "arc/cares", kind: "dir" },
|
|
59
59
|
{ path: "arc/intentions", kind: "dir" },
|
|
60
|
-
{ path: "
|
|
61
|
-
{ path: "
|
|
60
|
+
{ path: "arc/flight-recorder", kind: "dir" },
|
|
61
|
+
{ path: "arc/flight-recorder/events", kind: "dir" },
|
|
62
|
+
{ path: "arc/flight-recorder/habit-receipts", kind: "dir" },
|
|
63
|
+
{ path: "arc/claims", kind: "dir" },
|
|
62
64
|
{ path: "friends", kind: "dir" },
|
|
63
65
|
{ path: "state", kind: "dir" },
|
|
64
66
|
{ path: "tasks", kind: "dir" },
|
|
@@ -72,6 +74,10 @@ exports.CANONICAL_BUNDLE_MANIFEST = [
|
|
|
72
74
|
// separate from the legacy `tasks/one-shots/` flat layout.
|
|
73
75
|
{ path: "plugins", kind: "dir" },
|
|
74
76
|
{ path: "desk", kind: "dir" },
|
|
77
|
+
{ path: "desk/_record", kind: "dir" },
|
|
78
|
+
{ path: "desk/_record/diary", kind: "dir" },
|
|
79
|
+
{ path: "desk/_record/diary/daily", kind: "dir" },
|
|
80
|
+
{ path: "desk/_record/notes", kind: "dir" },
|
|
75
81
|
];
|
|
76
82
|
function getChangelogPath() {
|
|
77
83
|
const changelogPath = path.resolve(__dirname, "../../changelog.json");
|
|
@@ -98,7 +104,7 @@ function getPackageVersion() {
|
|
|
98
104
|
function createBundleMeta() {
|
|
99
105
|
return {
|
|
100
106
|
runtimeVersion: getPackageVersion(),
|
|
101
|
-
bundleSchemaVersion:
|
|
107
|
+
bundleSchemaVersion: 3,
|
|
102
108
|
lastUpdated: new Date().toISOString(),
|
|
103
109
|
};
|
|
104
110
|
}
|
package/dist/mind/context.js
CHANGED
|
@@ -382,7 +382,7 @@ function postTurnTrim(messages, usage, hooks) {
|
|
|
382
382
|
function postTurnPersist(sessPath, prepared, usage, state) {
|
|
383
383
|
const existing = (0, session_events_1.loadSessionEnvelopeFile)(sessPath);
|
|
384
384
|
const previousMessages = existing ? (0, session_events_1.projectProviderMessages)(existing) : [];
|
|
385
|
-
const { envelope
|
|
385
|
+
const { envelope } = (0, session_events_1.buildCanonicalSessionEnvelope)({
|
|
386
386
|
existing,
|
|
387
387
|
previousMessages,
|
|
388
388
|
currentMessages: prepared.currentMessages,
|
|
@@ -397,7 +397,6 @@ function postTurnPersist(sessPath, prepared, usage, state) {
|
|
|
397
397
|
inputTokens: usage?.input_tokens ?? null,
|
|
398
398
|
},
|
|
399
399
|
});
|
|
400
|
-
(0, session_events_1.appendEvictedToArchive)(sessPath, evictedEvents);
|
|
401
400
|
writeSessionEnvelope(sessPath, envelope);
|
|
402
401
|
return envelope.events;
|
|
403
402
|
}
|
|
@@ -34,11 +34,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.formatRelative = formatRelative;
|
|
37
|
+
exports.deskRecordOrientationSection = deskRecordOrientationSection;
|
|
37
38
|
exports.deskSection = deskSection;
|
|
38
39
|
const fs = __importStar(require("fs"));
|
|
39
40
|
const path = __importStar(require("path"));
|
|
40
41
|
const identity_1 = require("../heart/identity");
|
|
41
42
|
const runtime_1 = require("../nerves/runtime");
|
|
43
|
+
const record_paths_1 = require("./record-paths");
|
|
42
44
|
// ──────────────────────────────────────────────────────────────────────────────
|
|
43
45
|
// Static body — the agent's daily-read description of its desk.
|
|
44
46
|
//
|
|
@@ -66,7 +68,10 @@ i have a desk. it lives at \`desk/\` — a quiet room of my work, persistent acr
|
|
|
66
68
|
**what doesn't:**
|
|
67
69
|
- a single-turn answer — it'll be done before the page turns
|
|
68
70
|
- ephemeral debugging that resolves in the same exchange
|
|
69
|
-
-
|
|
71
|
+
- live continuity, claims, and obligations — those belong in Arc
|
|
72
|
+
- habit definitions — those stay in habits/
|
|
73
|
+
- scratch thinking that is not worth recording — it can disappear with the session
|
|
74
|
+
- stale top-level rooms. the maintained record belongs under desk/_record, not in a separate scratch workspace.
|
|
70
75
|
|
|
71
76
|
**shape.** tracks group related work — drawers in the cabinet, or sections of a shelf if you prefer the library framing. tasks live in tracks. each task has iterations: one per work session, with \`planning.md\` and \`doing.md\` laid side-by-side on the page.
|
|
72
77
|
|
|
@@ -291,6 +296,53 @@ function renderCurrently(deskRoot, now = new Date()) {
|
|
|
291
296
|
lines.push(`tasks still open: ${nonTerminalCount}`);
|
|
292
297
|
return lines.join("\n");
|
|
293
298
|
}
|
|
299
|
+
function countDiaryFacts(agentRoot) {
|
|
300
|
+
const paths = (0, record_paths_1.resolveDeskRecordPaths)(agentRoot);
|
|
301
|
+
try {
|
|
302
|
+
return fs.readFileSync(paths.factsPath, "utf-8")
|
|
303
|
+
.split(/\r?\n/)
|
|
304
|
+
.filter((line) => line.trim().length > 0)
|
|
305
|
+
.length;
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return 0;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function countRecordNotes(agentRoot) {
|
|
312
|
+
const paths = (0, record_paths_1.resolveDeskRecordPaths)(agentRoot);
|
|
313
|
+
try {
|
|
314
|
+
return fs.readdirSync(paths.notesRoot, { withFileTypes: true })
|
|
315
|
+
.filter((entry) => entry.isFile() && !entry.name.startsWith(".") && entry.name.endsWith(".md"))
|
|
316
|
+
.length;
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
return 0;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function deskRecordOrientationSection(agentRoot = (0, identity_1.getAgentRoot)(), now = new Date()) {
|
|
323
|
+
const deskRoot = path.join(agentRoot, "desk");
|
|
324
|
+
const tracks = (() => {
|
|
325
|
+
try {
|
|
326
|
+
return listSubdirs(deskRoot)
|
|
327
|
+
.map((slug) => readTrack(deskRoot, slug))
|
|
328
|
+
.filter((track) => Boolean(track));
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
return [];
|
|
332
|
+
}
|
|
333
|
+
})();
|
|
334
|
+
const activeTracks = tracks.filter((track) => !TERMINAL_TRACK_STATUSES.has(track.status));
|
|
335
|
+
const openTaskCount = tracks.reduce((sum, track) => sum + nonTerminalTasks(track).length, 0);
|
|
336
|
+
const lines = ["## Desk orientation"];
|
|
337
|
+
lines.push(`active tracks: ${activeTracks.length}`);
|
|
338
|
+
lines.push(`open tasks: ${openTaskCount}`);
|
|
339
|
+
lines.push(`diary facts: ${countDiaryFacts(agentRoot)}`);
|
|
340
|
+
lines.push(`record notes: ${countRecordNotes(agentRoot)}`);
|
|
341
|
+
const currently = fs.existsSync(deskRoot) ? renderCurrently(deskRoot, now) : "";
|
|
342
|
+
if (currently)
|
|
343
|
+
lines.push(currently);
|
|
344
|
+
return lines.join("\n");
|
|
345
|
+
}
|
|
294
346
|
// ──────────────────────────────────────────────────────────────────────────────
|
|
295
347
|
// Public entry — every-turn synchronous read
|
|
296
348
|
// ──────────────────────────────────────────────────────────────────────────────
|
package/dist/mind/diary.js
CHANGED
|
@@ -43,12 +43,12 @@ exports.searchDiaryEntries = searchDiaryEntries;
|
|
|
43
43
|
const fs = __importStar(require("fs"));
|
|
44
44
|
const path = __importStar(require("path"));
|
|
45
45
|
const crypto_1 = require("crypto");
|
|
46
|
-
const identity_1 = require("../heart/identity");
|
|
47
46
|
const session_events_1 = require("../heart/session-events");
|
|
48
47
|
const runtime_1 = require("../nerves/runtime");
|
|
49
48
|
const note_search_1 = require("./note-search");
|
|
50
49
|
const diary_integrity_1 = require("./diary-integrity");
|
|
51
50
|
const embedding_provider_1 = require("./embedding-provider");
|
|
51
|
+
const record_paths_1 = require("./record-paths");
|
|
52
52
|
const DEDUP_THRESHOLD = 0.6;
|
|
53
53
|
const SEMANTIC_DEDUP_THRESHOLD = 0.95;
|
|
54
54
|
const ENTITY_TOKEN = /[a-z0-9]+/g;
|
|
@@ -223,8 +223,7 @@ async function buildEmbedding(text, embeddingProvider) {
|
|
|
223
223
|
function resolveDiaryRoot(explicitRoot) {
|
|
224
224
|
if (explicitRoot)
|
|
225
225
|
return explicitRoot;
|
|
226
|
-
|
|
227
|
-
return path.join(agentRoot, "diary");
|
|
226
|
+
return (0, record_paths_1.resolveRecordDiaryRoot)();
|
|
228
227
|
}
|
|
229
228
|
function readDiaryEntries(diaryRoot) {
|
|
230
229
|
return readExistingEntries(path.join(resolveDiaryRoot(diaryRoot), "facts.jsonl"));
|
package/dist/mind/note-search.js
CHANGED
|
@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.cosineSimilarity = cosineSimilarity;
|
|
37
37
|
exports.searchDiaryFactsForQuery = searchDiaryFactsForQuery;
|
|
38
|
-
exports.searchJournalIndex = searchJournalIndex;
|
|
39
38
|
exports.injectNoteSearchContext = injectNoteSearchContext;
|
|
40
39
|
const fs = __importStar(require("fs"));
|
|
41
40
|
const path = __importStar(require("path"));
|
|
@@ -117,40 +116,6 @@ async function searchDiaryFactsForQuery(query, facts, provider, options) {
|
|
|
117
116
|
.sort((left, right) => right.score - left.score)
|
|
118
117
|
.slice(0, topK);
|
|
119
118
|
}
|
|
120
|
-
function readJournalIndex(journalDir) {
|
|
121
|
-
const indexPath = path.join(journalDir, ".index.json");
|
|
122
|
-
try {
|
|
123
|
-
const raw = fs.readFileSync(indexPath, "utf8");
|
|
124
|
-
const parsed = JSON.parse(raw);
|
|
125
|
-
if (!Array.isArray(parsed))
|
|
126
|
-
return [];
|
|
127
|
-
return parsed;
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
return [];
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
function searchJournalIndex(queryEmbedding, entries, options) {
|
|
134
|
-
const minScore = options?.minScore ?? DEFAULT_MIN_SCORE;
|
|
135
|
-
const topK = options?.topK ?? DEFAULT_TOP_K;
|
|
136
|
-
return entries
|
|
137
|
-
.filter((entry) => Array.isArray(entry.embedding) && entry.embedding.length > 0)
|
|
138
|
-
.map((entry) => ({
|
|
139
|
-
filename: entry.filename,
|
|
140
|
-
preview: entry.preview,
|
|
141
|
-
score: cosineSimilarity(queryEmbedding, entry.embedding),
|
|
142
|
-
}))
|
|
143
|
-
.filter((entry) => entry.score >= minScore)
|
|
144
|
-
.sort((left, right) => right.score - left.score)
|
|
145
|
-
.slice(0, topK);
|
|
146
|
-
}
|
|
147
|
-
function resolveJournalDir(diaryRoot, explicitJournalDir) {
|
|
148
|
-
if (explicitJournalDir)
|
|
149
|
-
return explicitJournalDir;
|
|
150
|
-
// journal/ is a sibling of diary/ at the agent root level
|
|
151
|
-
const agentRoot = path.dirname(diaryRoot);
|
|
152
|
-
return path.join(agentRoot, "journal");
|
|
153
|
-
}
|
|
154
119
|
async function injectNoteSearchContext(messages, options) {
|
|
155
120
|
try {
|
|
156
121
|
if (messages[0]?.role !== "system" || typeof messages[0].content !== "string")
|
|
@@ -160,92 +125,57 @@ async function injectNoteSearchContext(messages, options) {
|
|
|
160
125
|
return;
|
|
161
126
|
const diaryRoot = options?.diaryRoot ?? (0, diary_1.resolveDiaryRoot)();
|
|
162
127
|
const facts = readFacts(diaryRoot);
|
|
163
|
-
|
|
164
|
-
const journalEntries = readJournalIndex(journalDir);
|
|
165
|
-
if (facts.length === 0 && journalEntries.length === 0)
|
|
128
|
+
if (facts.length === 0)
|
|
166
129
|
return;
|
|
167
|
-
// Build combined result lines tagged by source
|
|
168
130
|
const resultLines = [];
|
|
169
|
-
let
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
.
|
|
189
|
-
.map((fact) => ({ ...fact, score: 1 }));
|
|
190
|
-
if (found.length > 0) {
|
|
191
|
-
(0, runtime_1.emitNervesEvent)({
|
|
192
|
-
level: "warn",
|
|
193
|
-
component: "mind",
|
|
194
|
-
event: "mind.note_search_fallback",
|
|
195
|
-
message: "embeddings unavailable, used substring fallback",
|
|
196
|
-
meta: { matchCount: found.length },
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
for (const fact of found) {
|
|
201
|
-
let meta = `score=${fact.score.toFixed(3)} source=${fact.source}`;
|
|
202
|
-
if (fact.provenance) {
|
|
203
|
-
if (fact.provenance.channel)
|
|
204
|
-
meta += ` channel=${fact.provenance.channel}`;
|
|
205
|
-
if (fact.provenance.friendName)
|
|
206
|
-
meta += ` friend=${fact.provenance.friendName}`;
|
|
207
|
-
if (fact.provenance.trust)
|
|
208
|
-
meta += ` trust=${fact.provenance.trust}`;
|
|
209
|
-
}
|
|
210
|
-
const tag = (0, provenance_trust_1.classifyProvenanceTrust)(fact.provenance) === "external" ? "diary/external" : "diary";
|
|
211
|
-
resultLines.push({
|
|
212
|
-
text: `[${tag}] ${fact.text} [${meta}]`,
|
|
213
|
-
score: fact.score,
|
|
131
|
+
let found;
|
|
132
|
+
try {
|
|
133
|
+
const provider = options?.provider ?? createDefaultProvider();
|
|
134
|
+
found = await searchDiaryFactsForQuery(query, facts, provider, options);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// Embeddings unavailable — fall back to substring matching
|
|
138
|
+
const lowerQuery = query.toLowerCase();
|
|
139
|
+
const topK = options?.topK ?? DEFAULT_TOP_K;
|
|
140
|
+
found = facts
|
|
141
|
+
.filter((fact) => fact.text.toLowerCase().includes(lowerQuery))
|
|
142
|
+
.slice(0, topK)
|
|
143
|
+
.map((fact) => ({ ...fact, score: 1 }));
|
|
144
|
+
if (found.length > 0) {
|
|
145
|
+
(0, runtime_1.emitNervesEvent)({
|
|
146
|
+
level: "warn",
|
|
147
|
+
component: "mind",
|
|
148
|
+
event: "mind.note_search_fallback",
|
|
149
|
+
message: "embeddings unavailable, used substring fallback",
|
|
150
|
+
meta: { matchCount: found.length },
|
|
214
151
|
});
|
|
215
152
|
}
|
|
216
153
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const journalResults = searchJournalIndex(queryEmbedding, journalEntries, options);
|
|
227
|
-
for (const entry of journalResults) {
|
|
228
|
-
resultLines.push({
|
|
229
|
-
text: `[journal] ${entry.filename}: ${entry.preview} [score=${entry.score.toFixed(3)}]`,
|
|
230
|
-
score: entry.score,
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
catch {
|
|
236
|
-
// Embeddings unavailable — no journal fallback
|
|
154
|
+
for (const fact of found) {
|
|
155
|
+
let meta = `score=${fact.score.toFixed(3)} source=${fact.source}`;
|
|
156
|
+
if (fact.provenance) {
|
|
157
|
+
if (fact.provenance.channel)
|
|
158
|
+
meta += ` channel=${fact.provenance.channel}`;
|
|
159
|
+
if (fact.provenance.friendName)
|
|
160
|
+
meta += ` friend=${fact.provenance.friendName}`;
|
|
161
|
+
if (fact.provenance.trust)
|
|
162
|
+
meta += ` trust=${fact.provenance.trust}`;
|
|
237
163
|
}
|
|
164
|
+
const tag = (0, provenance_trust_1.classifyProvenanceTrust)(fact.provenance) === "external" ? "diary/external" : "diary";
|
|
165
|
+
resultLines.push({
|
|
166
|
+
text: `[${tag}] ${fact.text} [${meta}]`,
|
|
167
|
+
score: fact.score,
|
|
168
|
+
});
|
|
238
169
|
}
|
|
239
170
|
if (resultLines.length === 0)
|
|
240
171
|
return;
|
|
241
|
-
// Sort all results by score descending
|
|
242
172
|
resultLines.sort((left, right) => right.score - left.score);
|
|
243
173
|
const noteSection = resultLines
|
|
244
174
|
.map((entry, index) => `${index + 1}. ${entry.text}`)
|
|
245
175
|
.join("\n");
|
|
246
176
|
messages[0] = {
|
|
247
177
|
role: "system",
|
|
248
|
-
content: `${messages[0].content}\n\n## from my
|
|
178
|
+
content: `${messages[0].content}\n\n## retrieved from my Desk record diary\n${noteSection}`,
|
|
249
179
|
};
|
|
250
180
|
(0, runtime_1.emitNervesEvent)({
|
|
251
181
|
component: "mind",
|