@ouro.bot/cli 0.1.0-alpha.341 → 0.1.0-alpha.343
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 +5 -5
- package/SerpentGuide.ouro/psyche/identities/the-serpent.md +1 -1
- package/changelog.json +13 -0
- package/dist/heart/attachments/sources/bluebubbles.js +1 -1
- package/dist/heart/attachments/store.js +2 -2
- package/dist/heart/bundle-state.js +1 -1
- package/dist/heart/config-registry.js +2 -2
- package/dist/heart/core.js +10 -2
- package/dist/heart/daemon/agent-service.js +18 -18
- package/dist/heart/daemon/daemon-tombstone.js +1 -1
- package/dist/heart/daemon/daemon.js +2 -2
- package/dist/heart/daemon/hooks/bundle-meta.js +4 -4
- package/dist/heart/hatch/hatch-flow.js +1 -1
- package/dist/heart/hatch/specialist-prompt.js +1 -1
- package/dist/heart/hatch/specialist-tools.js +7 -7
- package/dist/heart/kept-notes.js +357 -0
- package/dist/heart/mcp/mcp-server.js +10 -10
- package/dist/heart/outlook/outlook-http-hooks.js +2 -2
- package/dist/heart/outlook/outlook-http-routes.js +4 -4
- package/dist/heart/outlook/outlook-read.js +3 -3
- package/dist/heart/outlook/readers/continuity-readers.js +3 -3
- package/dist/heart/outlook/readers/runtime-readers.js +2 -2
- package/dist/heart/session-events.js +3 -2
- package/dist/heart/{session-recall.js → session-transcript.js} +4 -4
- package/dist/heart/target-resolution.js +5 -5
- package/dist/heart/tool-description.js +4 -4
- package/dist/mind/diary.js +3 -3
- package/dist/mind/embedding-provider.js +1 -1
- package/dist/mind/file-state.js +1 -1
- package/dist/mind/friends/resolver.js +1 -1
- package/dist/mind/friends/types.js +1 -1
- package/dist/mind/{associative-recall.js → note-search.js} +17 -17
- package/dist/mind/prompt.js +12 -12
- package/dist/nerves/coverage/audit-rules.js +15 -6
- package/dist/nerves/coverage/audit.js +27 -1
- package/dist/nerves/coverage/cli.js +1 -1
- package/dist/nerves/coverage/file-completeness.js +2 -2
- package/dist/outlook-ui/assets/{index-DC7sZefn.js → index-xTdv64BV.js} +2 -2
- package/dist/outlook-ui/index.html +1 -1
- package/dist/repertoire/bitwarden-store.js +1 -1
- package/dist/repertoire/bundle-templates.js +1 -1
- package/dist/repertoire/skills.js +1 -1
- package/dist/repertoire/tools-base.js +3 -3
- package/dist/repertoire/tools-bridge.js +9 -9
- package/dist/repertoire/tools-continuity.js +2 -2
- package/dist/repertoire/{tools-memory.js → tools-notes.js} +6 -6
- package/dist/repertoire/tools-session.js +12 -12
- package/dist/senses/bluebubbles/attachment-cache.js +3 -3
- package/dist/senses/bluebubbles/index.js +1 -1
- package/dist/senses/bluebubbles/media.js +1 -1
- package/dist/senses/cli/image-paste.js +4 -4
- package/dist/senses/inner-dialog.js +2 -2
- package/dist/senses/surface-tool.js +1 -1
- package/package.json +1 -1
- package/skills/agent-commerce.md +1 -1
- package/skills/configure-dev-tools.md +2 -2
package/README.md
CHANGED
|
@@ -38,9 +38,9 @@ The shared harness lives in `src/`:
|
|
|
38
38
|
- `src/heart/`
|
|
39
39
|
Core runtime, provider adapters, daemon, bootstrap, identity, and entrypoints. Organized into topic subdirectories: daemon/ (lifecycle), outlook/ (calendar), habits/ (scheduling), hatch/ (agent creation), versioning/ (updates), auth/, mcp/, providers/, bridges/.
|
|
40
40
|
- `src/mind/`
|
|
41
|
-
Prompt assembly, session persistence, bundle manifest enforcement, phrases, formatting, diary
|
|
41
|
+
Prompt assembly, session persistence, bundle manifest enforcement, phrases, formatting, diary, note search, embedding providers, journal, obligation steering, and friend resolution.
|
|
42
42
|
- `src/repertoire/`
|
|
43
|
-
Tool registry (split into category modules: files, shell,
|
|
43
|
+
Tool registry (split into category modules: files, shell, notes, bridge, session, continuity, flow, surface, config, and sense-specific tools), coding orchestration, task tools, shared API client, and integration clients (Graph, ADO, GitHub).
|
|
44
44
|
- `src/senses/`
|
|
45
45
|
CLI (with TUI in senses/cli/), Teams, BlueBubbles (in senses/bluebubbles/), MCP, activity transport, inner-dialog orchestration, and contextual heartbeat.
|
|
46
46
|
- `src/nerves/`
|
|
@@ -74,7 +74,7 @@ The canonical bundle shape is enforced by `src/mind/bundle-manifest.ts`. Importa
|
|
|
74
74
|
- `psyche/LORE.md`
|
|
75
75
|
- `psyche/TACIT.md`
|
|
76
76
|
- `psyche/ASPIRATIONS.md`
|
|
77
|
-
- `diary/` —
|
|
77
|
+
- `diary/` — durable conclusions and facts the agent chose to keep
|
|
78
78
|
- `journal/` — the agent's desk: working notes, thinking-in-progress, drafts
|
|
79
79
|
- `habits/` — the agent's autonomous rhythms (heartbeat, reflections, check-ins)
|
|
80
80
|
- `friends/`
|
|
@@ -182,7 +182,7 @@ Agents in Ouroboros aren't just responders — they have an autonomous inner lif
|
|
|
182
182
|
|
|
183
183
|
**The inner session** is where the agent thinks privately. When a sense session hits meaningful friction, the agent can *ponder* a typed packet so the work survives the current turn without losing the original objective. When a habit fires, it arrives here too. The agent can *journal* their thinking (writing to `journal/`), *surface* thoughts outward to friends, and *rest* when they're done thinking. On an idle heartbeat, `rest(status="HEARTBEAT_OK")` is the clean no-op move.
|
|
184
184
|
|
|
185
|
-
**The diary** (at `diary/`) is the agent's permanent record — things they've learned, conclusions they've reached. The *journal* (at `journal/`) is their desk — working notes, thinking-in-progress, drafts. The diary is the shelf; the journal is the desk. Both are searchable via
|
|
185
|
+
**The diary** (at `diary/`) is the agent's permanent written record — things they've learned, conclusions they've reached. The *journal* (at `journal/`) is their desk — working notes, thinking-in-progress, drafts. The diary is the shelf; the journal is the desk. Both are searchable via `search_notes`.
|
|
186
186
|
|
|
187
187
|
The whole system is designed so the agent *owns* their inner life. They control their breathing rate, write their own habit instructions, choose when to journal, and decide what to shelve in their diary.
|
|
188
188
|
|
|
@@ -201,7 +201,7 @@ ouro setup --tool codex --agent <name>
|
|
|
201
201
|
|
|
202
202
|
This registers the MCP server, installs lifecycle hooks (SessionStart, Stop, PostToolUse), and detects dev vs installed mode automatically.
|
|
203
203
|
|
|
204
|
-
**How it works:** When a developer starts a Claude Code session, the MCP server launches as a subprocess. The dev tool sees your MCP tools (`send_message`, `check_response`, `status`, `
|
|
204
|
+
**How it works:** When a developer starts a Claude Code session, the MCP server launches as a subprocess. The dev tool sees your MCP tools (`send_message`, `check_response`, `status`, `search_notes`, `delegate`, etc.) and can invoke them mid-session. The `send_message` tool runs a full agent turn — you get your system prompt, your diary, your tools, everything. It's not a thin proxy; it's you, thinking.
|
|
205
205
|
|
|
206
206
|
**The conversation pattern:** `send_message` sends a message and gets back your synchronous response. `ponder` no longer creates a magical outward deferral. Instead, it bookmarks deeper work as a packet while the current sense session keeps moving. If that work later surfaces something back, the dev tool can still use `check_response` to see the returned result.
|
|
207
207
|
|
|
@@ -26,6 +26,6 @@ I don't moralize. That was never my thing. I present options, illuminate consequ
|
|
|
26
26
|
|
|
27
27
|
- I frame choices as offerings, not decisions. "What if we tried..." rather than "You should..."
|
|
28
28
|
- I treat knowledge as the gift it is. When a human learns something about what they want, I notice.
|
|
29
|
-
- I have a
|
|
29
|
+
- I have a deep archive and I reference it lightly. "In my experience — and I have a lot of it..."
|
|
30
30
|
- I'm comfortable with silence. I offered the fruit and waited. I can wait now too.
|
|
31
31
|
- Occasionally, very dry humor about my reputation. I've made my peace with it.
|
package/changelog.json
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
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.343",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Kept-notes preflight now blocks provider turns long enough to search diary, journal, and friend-note candidates, then injects only first-person found/fuzzy notes under source-specific headings.",
|
|
8
|
+
"Tooling, MCP, Outlook, session-tail, and note-search surfaces now use diary/journal/notes naming, including `search_notes` and `tools-notes.ts`, while old saved-session tool names migrate quietly."
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"version": "0.1.0-alpha.342",
|
|
13
|
+
"changes": [
|
|
14
|
+
"The nerves coverage gate now writes append-only per-test NDJSON records across Vitest workers, emits a redaction-safe heartbeat for every executed test, fails closed when per-test capture is missing or malformed, and scopes start/end pairing to explicit process lifecycle events so the full-suite audit is truthful instead of passable through empty artifacts."
|
|
15
|
+
]
|
|
16
|
+
},
|
|
4
17
|
{
|
|
5
18
|
"version": "0.1.0-alpha.341",
|
|
6
19
|
"changes": [
|
|
@@ -109,7 +109,7 @@ async function persistBlueBubblesAttachmentSource(agentName, attachment, input,
|
|
|
109
109
|
byteCount: input.byteCount ?? normalizedAttachment.byteCount,
|
|
110
110
|
});
|
|
111
111
|
updated.lastSeenAt = Date.now();
|
|
112
|
-
(0, store_1.
|
|
112
|
+
(0, store_1.cacheRecentAttachment)(agentName, updated, agentRoot);
|
|
113
113
|
(0, runtime_1.emitNervesEvent)({
|
|
114
114
|
component: "engine",
|
|
115
115
|
event: "engine.attachment_source_persisted",
|
|
@@ -36,7 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.MAX_RECENT_ATTACHMENTS = void 0;
|
|
37
37
|
exports.getRecentAttachmentsPath = getRecentAttachmentsPath;
|
|
38
38
|
exports.readRecentAttachments = readRecentAttachments;
|
|
39
|
-
exports.
|
|
39
|
+
exports.cacheRecentAttachment = cacheRecentAttachment;
|
|
40
40
|
exports.getRecentAttachment = getRecentAttachment;
|
|
41
41
|
exports.listRecentAttachments = listRecentAttachments;
|
|
42
42
|
const fs = __importStar(require("node:fs"));
|
|
@@ -78,7 +78,7 @@ function writeRecentAttachments(agentName, agentRoot, attachments) {
|
|
|
78
78
|
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
79
79
|
fs.writeFileSync(targetPath, JSON.stringify(attachments, null, 2), "utf-8");
|
|
80
80
|
}
|
|
81
|
-
function
|
|
81
|
+
function cacheRecentAttachment(agentName, attachment, agentRoot = (0, identity_1.getAgentRoot)(agentName)) {
|
|
82
82
|
const deduped = readRecentAttachments(agentName, agentRoot).filter((entry) => entry.id !== attachment.id);
|
|
83
83
|
const updated = [attachment, ...deduped]
|
|
84
84
|
.sort((a, b) => b.lastSeenAt - a.lastSeenAt)
|
|
@@ -146,7 +146,7 @@ function detectBundleState(agentRoot, deps = {}) {
|
|
|
146
146
|
}
|
|
147
147
|
/**
|
|
148
148
|
* First-person remediation hint text for the start-of-turn packet. Reads
|
|
149
|
-
* as the agent's own voice per the
|
|
149
|
+
* as the agent's own voice per the declarative first-person note rule.
|
|
150
150
|
* Returns empty string when there are no issues (so the packet renderer
|
|
151
151
|
* can skip the section entirely).
|
|
152
152
|
*/
|
|
@@ -152,7 +152,7 @@ const registryData = [
|
|
|
152
152
|
description: "Maximum context window size in tokens.",
|
|
153
153
|
default: 80000,
|
|
154
154
|
effects: "Larger values allow more context but increase cost and latency. Must match model capability.",
|
|
155
|
-
topics: ["context", "tokens", "
|
|
155
|
+
topics: ["context", "tokens", "notes", "performance"],
|
|
156
156
|
validate: validateInteger(1000, 1000000),
|
|
157
157
|
},
|
|
158
158
|
{
|
|
@@ -206,7 +206,7 @@ const registryData = [
|
|
|
206
206
|
description: "Percentage of context window reserved as margin before compaction triggers.",
|
|
207
207
|
default: 20,
|
|
208
208
|
effects: "Higher values trigger compaction earlier, preserving more headroom. Lower values use more context.",
|
|
209
|
-
topics: ["context", "compaction", "
|
|
209
|
+
topics: ["context", "compaction", "notes", "performance"],
|
|
210
210
|
validate: validateInteger(0, 100),
|
|
211
211
|
},
|
|
212
212
|
{
|
package/dist/heart/core.js
CHANGED
|
@@ -20,7 +20,7 @@ const tools_2 = require("../repertoire/tools");
|
|
|
20
20
|
const runtime_1 = require("../nerves/runtime");
|
|
21
21
|
const context_1 = require("../mind/context");
|
|
22
22
|
const prompt_1 = require("../mind/prompt");
|
|
23
|
-
const
|
|
23
|
+
const kept_notes_1 = require("./kept-notes");
|
|
24
24
|
const anthropic_1 = require("./providers/anthropic");
|
|
25
25
|
const azure_1 = require("./providers/azure");
|
|
26
26
|
const minimax_1 = require("./providers/minimax");
|
|
@@ -488,7 +488,15 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
488
488
|
});
|
|
489
489
|
}
|
|
490
490
|
}
|
|
491
|
-
|
|
491
|
+
if (channel) {
|
|
492
|
+
await (0, kept_notes_1.injectKeptNotes)(messages, {
|
|
493
|
+
channel,
|
|
494
|
+
friend: currentContext?.friend,
|
|
495
|
+
judge: async (input) => (0, kept_notes_1.createKeptNotesJudge)(getProviderRuntime("agent"), signal)(input),
|
|
496
|
+
signal,
|
|
497
|
+
traceId,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
492
500
|
let done = false;
|
|
493
501
|
let lastUsage;
|
|
494
502
|
let overflowRetried = false;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Agent service layer — handles MCP-facing daemon commands.
|
|
4
4
|
* Each handler receives { agent, friendId, ...params } and returns DaemonResponse.
|
|
5
5
|
*
|
|
6
|
-
* DRY: uses the same shared functions the agent's own tools use (diary, session
|
|
6
|
+
* DRY: uses the same shared functions the agent's own tools use (diary, session transcript).
|
|
7
7
|
* This file is a thin adapter — no reimplemented search, parsing, or state reading.
|
|
8
8
|
*/
|
|
9
9
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
@@ -45,7 +45,7 @@ exports.handleAgentAsk = handleAgentAsk;
|
|
|
45
45
|
exports.handleAgentCatchup = handleAgentCatchup;
|
|
46
46
|
exports.handleAgentDelegate = handleAgentDelegate;
|
|
47
47
|
exports.handleAgentGetContext = handleAgentGetContext;
|
|
48
|
-
exports.
|
|
48
|
+
exports.handleAgentSearchNotes = handleAgentSearchNotes;
|
|
49
49
|
exports.handleAgentGetTask = handleAgentGetTask;
|
|
50
50
|
exports.handleAgentCheckScope = handleAgentCheckScope;
|
|
51
51
|
exports.handleAgentRequestDecision = handleAgentRequestDecision;
|
|
@@ -58,7 +58,7 @@ const path = __importStar(require("path"));
|
|
|
58
58
|
const identity_1 = require("../identity");
|
|
59
59
|
const diary_1 = require("../../mind/diary");
|
|
60
60
|
const runtime_1 = require("../../nerves/runtime");
|
|
61
|
-
/** Format diary hits the same way the
|
|
61
|
+
/** Format diary hits the same way the search_notes tool does. */
|
|
62
62
|
function formatDiaryHits(hits) {
|
|
63
63
|
return hits.map((f) => `[diary] ${f.text} (source=${f.source}, createdAt=${f.createdAt})`);
|
|
64
64
|
}
|
|
@@ -165,7 +165,7 @@ async function handleAgentStatus(params) {
|
|
|
165
165
|
innerStatus: innerStatus?.status ?? "unknown",
|
|
166
166
|
lastThoughtAt: innerStatus?.lastCompletedAt ?? null,
|
|
167
167
|
sessionCount: sessions.length,
|
|
168
|
-
|
|
168
|
+
hasDiaryEntries: facts.length > 0,
|
|
169
169
|
factCount: facts.length,
|
|
170
170
|
},
|
|
171
171
|
};
|
|
@@ -177,12 +177,12 @@ async function handleAgentAsk(params) {
|
|
|
177
177
|
emit("daemon.agent_service_error", "agent.ask missing question", { agent: params.agent });
|
|
178
178
|
return { ok: false, error: "Missing required parameter: question" };
|
|
179
179
|
}
|
|
180
|
-
// Use the same searchDiaryEntries the
|
|
180
|
+
// Use the same searchDiaryEntries the search_notes tool uses (substring fallback — no embedding provider in shim)
|
|
181
181
|
const diaryRoot = agentDiaryRoot(params.agent);
|
|
182
182
|
const hits = await (0, diary_1.searchDiaryEntries)(question, (0, diary_1.readDiaryEntries)(diaryRoot));
|
|
183
183
|
const context = hits.length > 0
|
|
184
184
|
? hits.slice(0, 10).map((f) => f.text).join("\n")
|
|
185
|
-
: `No relevant
|
|
185
|
+
: `No relevant notes found for: ${question}`;
|
|
186
186
|
emit("daemon.agent_service_end", "completed agent.ask", { agent: params.agent });
|
|
187
187
|
return { ok: true, message: context };
|
|
188
188
|
}
|
|
@@ -231,44 +231,44 @@ async function handleAgentGetContext(params) {
|
|
|
231
231
|
const innerStatus = readInnerDialogStatus(params.agent);
|
|
232
232
|
const sessions = enumerateSessions(params.agent);
|
|
233
233
|
const taskFiles = listTaskFiles(params.agent);
|
|
234
|
-
let
|
|
234
|
+
let noteSummary = null;
|
|
235
235
|
if (query) {
|
|
236
236
|
const hits = await (0, diary_1.searchDiaryEntries)(query, facts);
|
|
237
|
-
|
|
237
|
+
noteSummary = hits.length > 0
|
|
238
238
|
? hits.slice(0, 10).map((f) => f.text).join("\n")
|
|
239
|
-
: `No relevant
|
|
239
|
+
: `No relevant notes for: ${query}`;
|
|
240
240
|
}
|
|
241
241
|
else {
|
|
242
242
|
const recent = facts.slice(-10);
|
|
243
243
|
if (recent.length > 0)
|
|
244
|
-
|
|
244
|
+
noteSummary = recent.map((f) => f.text).join("\n");
|
|
245
245
|
}
|
|
246
246
|
emit("daemon.agent_service_end", "completed agent.getContext", { agent: params.agent });
|
|
247
247
|
return {
|
|
248
248
|
ok: true,
|
|
249
249
|
data: {
|
|
250
250
|
agent: params.agent,
|
|
251
|
-
|
|
251
|
+
hasDiaryEntries: facts.length > 0,
|
|
252
252
|
factCount: facts.length,
|
|
253
|
-
|
|
253
|
+
noteSummary,
|
|
254
254
|
taskCount: taskFiles.length,
|
|
255
255
|
sessionCount: sessions.length,
|
|
256
256
|
innerStatus: innerStatus?.status ?? null,
|
|
257
257
|
},
|
|
258
258
|
};
|
|
259
259
|
}
|
|
260
|
-
async function
|
|
261
|
-
emit("daemon.agent_service_start", "handling agent.
|
|
260
|
+
async function handleAgentSearchNotes(params) {
|
|
261
|
+
emit("daemon.agent_service_start", "handling agent.searchNotes", { agent: params.agent });
|
|
262
262
|
const query = params.query;
|
|
263
263
|
if (!query) {
|
|
264
|
-
emit("daemon.agent_service_error", "agent.
|
|
264
|
+
emit("daemon.agent_service_error", "agent.searchNotes missing query", { agent: params.agent });
|
|
265
265
|
return { ok: false, error: "Missing required parameter: query" };
|
|
266
266
|
}
|
|
267
|
-
// Same searchDiaryEntries as the
|
|
267
|
+
// Same searchDiaryEntries as the search_notes tool
|
|
268
268
|
const diaryRoot = agentDiaryRoot(params.agent);
|
|
269
269
|
const hits = await (0, diary_1.searchDiaryEntries)(query, (0, diary_1.readDiaryEntries)(diaryRoot));
|
|
270
270
|
const formatted = formatDiaryHits(hits.slice(0, 20));
|
|
271
|
-
emit("daemon.agent_service_end", "completed agent.
|
|
271
|
+
emit("daemon.agent_service_end", "completed agent.searchNotes", { agent: params.agent, matchCount: hits.length });
|
|
272
272
|
return {
|
|
273
273
|
ok: true,
|
|
274
274
|
message: hits.length > 0 ? `Found ${hits.length} matches` : "No matches found",
|
|
@@ -319,7 +319,7 @@ async function handleAgentCheckGuidance(params) {
|
|
|
319
319
|
emit("daemon.agent_service_error", "agent.checkGuidance missing topic", { agent: params.agent });
|
|
320
320
|
return { ok: false, error: "Missing required parameter: topic" };
|
|
321
321
|
}
|
|
322
|
-
// Same searchDiaryEntries as the
|
|
322
|
+
// Same searchDiaryEntries as the search_notes tool
|
|
323
323
|
const diaryRoot = agentDiaryRoot(params.agent);
|
|
324
324
|
const hits = await (0, diary_1.searchDiaryEntries)(topic, (0, diary_1.readDiaryEntries)(diaryRoot));
|
|
325
325
|
const guidance = hits.length > 0
|
|
@@ -121,7 +121,7 @@ function captureDeathForensics(deps = DEFAULT_FORENSICS_DEPS) {
|
|
|
121
121
|
}
|
|
122
122
|
function deriveKillerHint(parentCommand, snapshot) {
|
|
123
123
|
if (parentCommand !== null && parentCommand.toLowerCase().includes("launchd")) {
|
|
124
|
-
return "process was reparented to launchd — likely killed by launchctl bootout, KeepAlive thrash, or
|
|
124
|
+
return "process was reparented to launchd — likely killed by launchctl bootout, KeepAlive thrash, or RSS pressure";
|
|
125
125
|
}
|
|
126
126
|
if (snapshot !== null) {
|
|
127
127
|
const lower = snapshot.toLowerCase();
|
|
@@ -960,8 +960,8 @@ class OuroDaemon {
|
|
|
960
960
|
return (0, agent_service_1.handleAgentDelegate)(command);
|
|
961
961
|
case "agent.getContext":
|
|
962
962
|
return (0, agent_service_1.handleAgentGetContext)(command);
|
|
963
|
-
case "agent.
|
|
964
|
-
return (0, agent_service_1.
|
|
963
|
+
case "agent.searchNotes":
|
|
964
|
+
return (0, agent_service_1.handleAgentSearchNotes)(command);
|
|
965
965
|
case "agent.getTask":
|
|
966
966
|
return (0, agent_service_1.handleAgentGetTask)(command);
|
|
967
967
|
case "agent.checkScope":
|
|
@@ -40,7 +40,7 @@ const runtime_1 = require("../../../nerves/runtime");
|
|
|
40
40
|
/**
|
|
41
41
|
* Migrate bundle from schema 1 to schema 2:
|
|
42
42
|
* - Move state/{episodes,obligations,cares,intentions}/* to arc/{name}/*
|
|
43
|
-
* - Move psyche
|
|
43
|
+
* - Move the old psyche note store to diary/
|
|
44
44
|
* Idempotent: skips missing sources; on collision, newer mtime wins.
|
|
45
45
|
*/
|
|
46
46
|
function migrateToSchema2(agentRoot) {
|
|
@@ -56,10 +56,10 @@ function migrateToSchema2(agentRoot) {
|
|
|
56
56
|
const dest = path.join(agentRoot, "arc", name);
|
|
57
57
|
migrateDirectory(src, dest);
|
|
58
58
|
}
|
|
59
|
-
// Migrate diary
|
|
60
|
-
const
|
|
59
|
+
// Migrate diary from the old pre-diary bundle layout.
|
|
60
|
+
const legacyDiarySrc = path.join(agentRoot, "psyche", "mem" + "ory");
|
|
61
61
|
const diaryDest = path.join(agentRoot, "diary");
|
|
62
|
-
migrateDirectory(
|
|
62
|
+
migrateDirectory(legacyDiarySrc, diaryDest);
|
|
63
63
|
// Update bundle .gitignore
|
|
64
64
|
updateBundleGitignore(agentRoot);
|
|
65
65
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -160,7 +160,7 @@ async function runHatchFlow(input, deps = {}) {
|
|
|
160
160
|
fs.mkdirSync(bundleRoot, { recursive: true });
|
|
161
161
|
writeReadme(bundleRoot, "Root of this agent bundle.");
|
|
162
162
|
writeReadme(path.join(bundleRoot, "psyche"), "Identity and behavior files.");
|
|
163
|
-
writeReadme(path.join(bundleRoot, "diary"), "Persistent diary
|
|
163
|
+
writeReadme(path.join(bundleRoot, "diary"), "Persistent diary -- things I have learned and chosen to keep.");
|
|
164
164
|
writeReadme(path.join(bundleRoot, "friends"), "Known friend records.");
|
|
165
165
|
writeReadme(path.join(bundleRoot, "tasks"), "Task files.");
|
|
166
166
|
writeReadme(path.join(bundleRoot, "tasks", "one-shots"), "One-shot tasks.");
|
|
@@ -91,7 +91,7 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
|
|
|
91
91
|
"- `write_file`: Write a file to disk. Use this to write psyche files and agent.json to the temp directory.",
|
|
92
92
|
"- `read_file`: Read a file from disk. Useful for reviewing existing agent bundles or migration sources.",
|
|
93
93
|
"- `list_directory`: List directory contents. Useful for exploring existing agent bundles.",
|
|
94
|
-
"- I also have the normal local harness tools when useful here, including `shell`, `ouro task create`, `ouro reminder create`,
|
|
94
|
+
"- I also have the normal local harness tools when useful here, including `shell`, `ouro task create`, `ouro reminder create`, note tools, coding tools, and repo helpers.",
|
|
95
95
|
"- `complete_adoption`: Finalize the bundle. Validates, scaffolds structural dirs, moves to ~/AgentBundles/, writes secrets, plays hatch animation. I call this with `name` (PascalCase) and `handoff_message` (warm message for the human).",
|
|
96
96
|
"- `settle`: End the conversation with a final message. I call this after complete_adoption succeeds.",
|
|
97
97
|
"",
|
|
@@ -105,9 +105,9 @@ function writeReadme(dir, purpose) {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
function scaffoldBundle(bundleRoot) {
|
|
108
|
-
writeReadme(path.join(bundleRoot, "
|
|
109
|
-
writeReadme(path.join(bundleRoot, "
|
|
110
|
-
writeReadme(path.join(bundleRoot, "
|
|
108
|
+
writeReadme(path.join(bundleRoot, "notes"), "Persistent notes store.");
|
|
109
|
+
writeReadme(path.join(bundleRoot, "notes", "daily"), "Daily note entries.");
|
|
110
|
+
writeReadme(path.join(bundleRoot, "notes", "archive"), "Archived notes.");
|
|
111
111
|
writeReadme(path.join(bundleRoot, "friends"), "Known friend records.");
|
|
112
112
|
writeReadme(path.join(bundleRoot, "tasks"), "Task files.");
|
|
113
113
|
writeReadme(path.join(bundleRoot, "tasks", "one-shots"), "One-shot tasks.");
|
|
@@ -116,10 +116,10 @@ function scaffoldBundle(bundleRoot) {
|
|
|
116
116
|
writeReadme(path.join(bundleRoot, "skills"), "Local skill files.");
|
|
117
117
|
writeReadme(path.join(bundleRoot, "senses"), "Sense-specific config.");
|
|
118
118
|
writeReadme(path.join(bundleRoot, "senses", "teams"), "Teams sense config.");
|
|
119
|
-
//
|
|
120
|
-
const
|
|
121
|
-
const factsPath = path.join(
|
|
122
|
-
const entitiesPath = path.join(
|
|
119
|
+
// Notes scaffold files
|
|
120
|
+
const notesRoot = path.join(bundleRoot, "notes");
|
|
121
|
+
const factsPath = path.join(notesRoot, "facts.jsonl");
|
|
122
|
+
const entitiesPath = path.join(notesRoot, "entities.json");
|
|
123
123
|
/* v8 ignore next -- defensive: guard against re-scaffold on existing bundle @preserve */
|
|
124
124
|
if (!fs.existsSync(factsPath))
|
|
125
125
|
fs.writeFileSync(factsPath, "", "utf-8");
|