@ouro.bot/cli 0.1.0-alpha.34 → 0.1.0-alpha.341
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 +188 -187
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
- package/changelog.json +2037 -0
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +140 -0
- package/dist/arc/episodes.js +117 -0
- package/dist/arc/intentions.js +133 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +237 -0
- package/dist/arc/packets.js +193 -0
- package/dist/arc/presence.js +185 -0
- package/dist/arc/task-lifecycle.js +65 -0
- package/dist/heart/active-work.js +832 -0
- package/dist/heart/agent-entry.js +37 -2
- package/dist/heart/attachments/image-normalize.js +194 -0
- package/dist/heart/attachments/materialize.js +97 -0
- package/dist/heart/attachments/originals.js +88 -0
- package/dist/heart/attachments/render.js +29 -0
- package/dist/heart/attachments/sources/adapter.js +2 -0
- package/dist/heart/attachments/sources/bluebubbles.js +156 -0
- package/dist/heart/attachments/sources/cli-local-file.js +78 -0
- package/dist/heart/attachments/sources/index.js +16 -0
- package/dist/heart/attachments/store.js +103 -0
- package/dist/heart/attachments/types.js +93 -0
- package/dist/heart/auth/auth-flow.js +463 -0
- package/dist/heart/bridges/manager.js +358 -0
- package/dist/heart/bridges/state-machine.js +135 -0
- package/dist/heart/bridges/store.js +123 -0
- package/dist/heart/bundle-state.js +168 -0
- package/dist/heart/commitments.js +111 -0
- package/dist/heart/config-registry.js +304 -0
- package/dist/heart/config.js +53 -21
- package/dist/heart/core.js +695 -195
- package/dist/heart/cross-chat-delivery.js +131 -0
- package/dist/heart/daemon/agent-config-check.js +292 -0
- package/dist/heart/daemon/agent-discovery.js +79 -3
- package/dist/heart/daemon/agent-service.js +360 -0
- package/dist/heart/daemon/agentic-repair.js +170 -0
- package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
- package/dist/heart/daemon/cadence.js +70 -0
- package/dist/heart/daemon/cli-defaults.js +591 -0
- package/dist/heart/daemon/cli-exec.js +2302 -0
- package/dist/heart/daemon/cli-help.js +306 -0
- package/dist/heart/daemon/cli-parse.js +824 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +512 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/daemon-cli.js +30 -1171
- package/dist/heart/daemon/daemon-entry.js +358 -3
- package/dist/heart/daemon/daemon-health.js +141 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +157 -12
- package/dist/heart/daemon/daemon-tombstone.js +236 -0
- package/dist/heart/daemon/daemon.js +751 -58
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +427 -0
- package/dist/heart/daemon/health-monitor.js +79 -1
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
- package/dist/heart/daemon/http-health-probe.js +80 -0
- package/dist/heart/daemon/inner-status.js +89 -0
- package/dist/heart/daemon/interactive-repair.js +91 -0
- package/dist/heart/daemon/launchd.js +46 -9
- package/dist/heart/daemon/log-tailer.js +82 -12
- package/dist/heart/daemon/logs-prune.js +105 -0
- package/dist/heart/daemon/message-router.js +17 -8
- package/dist/heart/daemon/os-cron-deps.js +134 -0
- package/dist/heart/daemon/ouro-bot-entry.js +1 -1
- package/dist/heart/daemon/process-manager.js +201 -0
- package/dist/heart/daemon/provider-discovery.js +105 -0
- package/dist/heart/daemon/pulse.js +463 -0
- package/dist/heart/daemon/run-hooks.js +2 -0
- package/dist/heart/daemon/runtime-logging.js +67 -16
- package/dist/heart/daemon/runtime-metadata.js +101 -0
- package/dist/heart/daemon/runtime-mode.js +67 -0
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sense-manager.js +72 -3
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +94 -0
- package/dist/heart/daemon/socket-client.js +307 -0
- package/dist/heart/daemon/stale-bundle-prune.js +96 -0
- package/dist/heart/daemon/startup-tui.js +237 -0
- package/dist/heart/daemon/task-scheduler.js +3 -25
- package/dist/heart/daemon/thoughts.js +510 -0
- package/dist/heart/daemon/up-progress.js +135 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/habits/habit-migration.js +181 -0
- package/dist/heart/habits/habit-parser.js +140 -0
- package/dist/heart/habits/habit-scheduler.js +371 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -120
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -7
- package/dist/heart/{daemon → hatch}/specialist-tools.js +49 -3
- package/dist/heart/identity.js +154 -59
- package/dist/heart/kicks.js +2 -20
- package/dist/heart/mcp/mcp-server.js +653 -0
- package/dist/heart/migrate-config.js +127 -0
- package/dist/heart/model-capabilities.js +59 -0
- package/dist/heart/outlook/outlook-http-hooks.js +64 -0
- package/dist/heart/outlook/outlook-http-response.js +7 -0
- package/dist/heart/outlook/outlook-http-routes.js +232 -0
- package/dist/heart/outlook/outlook-http-static.js +99 -0
- package/dist/heart/outlook/outlook-http-transport.js +116 -0
- package/dist/heart/outlook/outlook-http.js +99 -0
- package/dist/heart/outlook/outlook-read.js +28 -0
- package/dist/heart/outlook/outlook-types.js +27 -0
- package/dist/heart/outlook/outlook-view.js +194 -0
- package/dist/heart/outlook/readers/agent-machine.js +355 -0
- package/dist/heart/outlook/readers/continuity-readers.js +332 -0
- package/dist/heart/outlook/readers/runtime-readers.js +660 -0
- package/dist/heart/outlook/readers/sessions.js +231 -0
- package/dist/heart/outlook/readers/shared.js +111 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-failover.js +135 -0
- package/dist/heart/provider-models.js +81 -0
- package/dist/heart/provider-ping.js +234 -0
- package/dist/heart/providers/anthropic-token.js +163 -0
- package/dist/heart/providers/anthropic.js +171 -50
- package/dist/heart/providers/azure.js +97 -11
- package/dist/heart/providers/error-classification.js +63 -0
- package/dist/heart/providers/github-copilot.js +135 -0
- package/dist/heart/providers/minimax-vlm.js +189 -0
- package/dist/heart/providers/minimax.js +23 -6
- package/dist/heart/providers/openai-codex.js +33 -23
- package/dist/heart/session-activity.js +190 -0
- package/dist/heart/session-events.js +726 -0
- package/dist/heart/session-recall.js +162 -0
- package/dist/heart/start-of-turn-packet.js +341 -0
- package/dist/heart/streaming.js +36 -27
- package/dist/heart/sync.js +332 -0
- package/dist/heart/target-resolution.js +127 -0
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/tool-activity-callbacks.js +36 -0
- package/dist/heart/tool-description.js +135 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +200 -0
- package/dist/heart/turn-context.js +358 -0
- package/dist/heart/turn-coordinator.js +28 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
- package/dist/heart/versioning/ouro-path-installer.js +296 -0
- package/dist/heart/versioning/ouro-version-manager.js +295 -0
- package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
- package/dist/heart/{daemon → versioning}/update-checker.js +12 -2
- package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
- package/dist/mind/associative-recall.js +137 -66
- package/dist/mind/bundle-manifest.js +7 -1
- package/dist/mind/context.js +89 -93
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +84 -96
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/first-impressions.js +14 -1
- package/dist/mind/friends/channel.js +56 -0
- package/dist/mind/friends/group-context.js +144 -0
- package/dist/mind/friends/resolver.js +37 -0
- package/dist/mind/friends/store-file.js +58 -3
- package/dist/mind/friends/trust-explanation.js +74 -0
- package/dist/mind/friends/types.js +8 -0
- package/dist/mind/journal-index.js +161 -0
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +74 -7
- package/dist/mind/prompt.js +999 -111
- package/dist/mind/provenance-trust.js +26 -0
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/cli-logging.js +7 -1
- package/dist/nerves/coverage/audit.js +1 -1
- package/dist/nerves/coverage/file-completeness.js +83 -5
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +224 -4
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/redact.js +79 -0
- package/dist/nerves/runtime.js +5 -1
- package/dist/outlook-ui/assets/index-DC7sZefn.js +61 -0
- package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
- package/dist/outlook-ui/index.html +15 -0
- package/dist/repertoire/ado-client.js +15 -56
- package/dist/repertoire/ado-semantic.js +11 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +319 -0
- package/dist/repertoire/bundle-templates.js +72 -0
- package/dist/repertoire/bw-installer.js +79 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +330 -0
- package/dist/repertoire/coding/feedback.js +197 -30
- package/dist/repertoire/coding/manager.js +158 -9
- package/dist/repertoire/coding/spawner.js +55 -9
- package/dist/repertoire/coding/tools.js +170 -7
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +527 -0
- package/dist/repertoire/duffel-client.js +185 -0
- package/dist/repertoire/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +375 -0
- package/dist/repertoire/mcp-client.js +255 -0
- package/dist/repertoire/mcp-manager.js +305 -0
- package/dist/repertoire/mcp-tools.js +63 -0
- package/dist/repertoire/shell-sessions.js +133 -0
- package/dist/repertoire/skills.js +14 -23
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tasks/board.js +43 -5
- package/dist/repertoire/tasks/fix.js +182 -0
- package/dist/repertoire/tasks/index.js +28 -10
- package/dist/repertoire/tasks/lifecycle.js +2 -2
- package/dist/repertoire/tasks/parser.js +3 -2
- package/dist/repertoire/tasks/scanner.js +194 -37
- package/dist/repertoire/tasks/transitions.js +16 -79
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-attachments.js +316 -0
- package/dist/repertoire/tools-base.js +45 -771
- package/dist/repertoire/tools-bluebubbles.js +1 -0
- package/dist/repertoire/tools-bridge.js +141 -0
- package/dist/repertoire/tools-bundle.js +984 -0
- package/dist/repertoire/tools-config.js +185 -0
- package/dist/repertoire/tools-continuity.js +248 -0
- package/dist/repertoire/tools-credential.js +182 -0
- package/dist/repertoire/tools-files.js +342 -0
- package/dist/repertoire/tools-flight.js +224 -0
- package/dist/repertoire/tools-flow.js +105 -0
- package/dist/repertoire/tools-github.js +1 -7
- package/dist/repertoire/tools-memory.js +376 -0
- package/dist/repertoire/tools-session.js +739 -0
- package/dist/repertoire/tools-shell.js +120 -0
- package/dist/repertoire/tools-stripe.js +180 -0
- package/dist/repertoire/tools-surface.js +243 -0
- package/dist/repertoire/tools-teams.js +12 -62
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-user-profile.js +144 -0
- package/dist/repertoire/tools-vault.js +110 -0
- package/dist/repertoire/tools.js +144 -138
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/user-profile.js +118 -0
- package/dist/repertoire/vault-setup.js +241 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -0
- package/dist/senses/attention-queue.js +116 -0
- package/dist/senses/bluebubbles/attachment-cache.js +53 -0
- package/dist/senses/bluebubbles/attachment-download.js +137 -0
- package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +225 -9
- package/dist/senses/bluebubbles/entry.js +13 -0
- package/dist/senses/bluebubbles/inbound-log.js +113 -0
- package/dist/senses/bluebubbles/index.js +1590 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +43 -12
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
- package/dist/senses/bluebubbles/replay.js +129 -0
- package/dist/senses/bluebubbles/runtime-state.js +109 -0
- package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
- package/dist/senses/cli/bracketed-paste.js +82 -0
- package/dist/senses/cli/image-paste.js +287 -0
- package/dist/senses/cli/image-ref-navigation.js +75 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/input-keys.js +174 -0
- package/dist/senses/cli/kill-ring.js +86 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +605 -0
- package/dist/senses/cli/spinner-imperative.js +135 -0
- package/dist/senses/cli/spinner.js +101 -0
- package/dist/senses/cli/status-line.js +60 -0
- package/dist/senses/cli/streaming-markdown.js +526 -0
- package/dist/senses/cli/tool-display.js +83 -0
- package/dist/senses/cli/tool-render.js +85 -0
- package/dist/senses/cli/tui-store.js +240 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +1 -1
- package/dist/senses/cli-layout.js +187 -0
- package/dist/senses/cli.js +595 -246
- package/dist/senses/commands.js +65 -1
- package/dist/senses/continuity.js +94 -0
- package/dist/senses/habit-turn-message.js +108 -0
- package/dist/senses/inner-dialog-worker.js +112 -19
- package/dist/senses/inner-dialog.js +633 -86
- package/dist/senses/pipeline.js +567 -0
- package/dist/senses/shared-turn.js +199 -0
- package/dist/senses/surface-tool.js +68 -0
- package/dist/senses/teams.js +665 -160
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +29 -7
- package/skills/agent-commerce.md +106 -0
- package/skills/browser-navigation.md +110 -0
- package/skills/commerce-setup-guide.md +116 -0
- package/skills/commerce-setup.md +84 -0
- package/skills/configure-dev-tools.md +81 -0
- package/skills/travel-planning.md +138 -0
- package/dist/heart/daemon/ouro-path-installer.js +0 -178
- package/dist/heart/daemon/subagent-installer.js +0 -134
- package/dist/senses/bluebubbles-entry.js +0 -11
- package/dist/senses/bluebubbles.js +0 -547
- package/dist/senses/debug-activity.js +0 -124
- package/subagents/README.md +0 -73
- package/subagents/work-doer.md +0 -235
- package/subagents/work-merger.md +0 -618
- package/subagents/work-planner.md +0 -382
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
- /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
- /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
- /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
- /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
package/dist/mind/context.js
CHANGED
|
@@ -33,34 +33,39 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.validateSessionMessages = exports.repairSessionMessages = exports.migrateToolNames = void 0;
|
|
36
37
|
exports.trimMessages = trimMessages;
|
|
37
|
-
exports.validateSessionMessages = validateSessionMessages;
|
|
38
|
-
exports.repairSessionMessages = repairSessionMessages;
|
|
39
38
|
exports.saveSession = saveSession;
|
|
39
|
+
exports.appendSyntheticAssistantMessage = appendSyntheticAssistantMessage;
|
|
40
40
|
exports.loadSession = loadSession;
|
|
41
41
|
exports.postTurn = postTurn;
|
|
42
42
|
exports.deleteSession = deleteSession;
|
|
43
43
|
const config_1 = require("../heart/config");
|
|
44
|
+
const session_events_1 = require("../heart/session-events");
|
|
44
45
|
const runtime_1 = require("../nerves/runtime");
|
|
45
46
|
const fs = __importStar(require("fs"));
|
|
46
47
|
const path = __importStar(require("path"));
|
|
47
48
|
const token_estimate_1 = require("./token-estimate");
|
|
49
|
+
var session_events_2 = require("../heart/session-events");
|
|
50
|
+
Object.defineProperty(exports, "migrateToolNames", { enumerable: true, get: function () { return session_events_2.migrateToolNames; } });
|
|
51
|
+
Object.defineProperty(exports, "repairSessionMessages", { enumerable: true, get: function () { return session_events_2.repairSessionMessages; } });
|
|
52
|
+
Object.defineProperty(exports, "validateSessionMessages", { enumerable: true, get: function () { return session_events_2.validateSessionMessages; } });
|
|
48
53
|
function buildTrimmableBlocks(messages) {
|
|
49
54
|
const blocks = [];
|
|
50
55
|
let i = 0;
|
|
51
56
|
while (i < messages.length) {
|
|
52
57
|
const msg = messages[i];
|
|
53
|
-
if (msg
|
|
58
|
+
if (msg.role === "system") {
|
|
54
59
|
i++;
|
|
55
60
|
continue;
|
|
56
61
|
}
|
|
57
62
|
// Tool coherence block: assistant message with tool_calls + immediately following tool results
|
|
58
|
-
if (msg
|
|
63
|
+
if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0) {
|
|
59
64
|
const indices = [i];
|
|
60
65
|
i++;
|
|
61
66
|
while (i < messages.length) {
|
|
62
67
|
const next = messages[i];
|
|
63
|
-
if (next
|
|
68
|
+
if (next.role !== "tool")
|
|
64
69
|
break;
|
|
65
70
|
indices.push(i);
|
|
66
71
|
i++;
|
|
@@ -78,13 +83,13 @@ function buildTrimmableBlocks(messages) {
|
|
|
78
83
|
function getSystemMessageIndices(messages) {
|
|
79
84
|
const indices = [];
|
|
80
85
|
for (let i = 0; i < messages.length; i++) {
|
|
81
|
-
if (messages[i]
|
|
86
|
+
if (messages[i].role === "system")
|
|
82
87
|
indices.push(i);
|
|
83
88
|
}
|
|
84
89
|
return indices;
|
|
85
90
|
}
|
|
86
91
|
function buildTrimmedMessages(messages, kept) {
|
|
87
|
-
return messages.filter((m, idx) => m
|
|
92
|
+
return messages.filter((m, idx) => m.role === "system" || kept.has(idx));
|
|
88
93
|
}
|
|
89
94
|
function trimMessages(messages, maxTokens, contextMargin, actualTokenCount) {
|
|
90
95
|
const targetTokens = Math.floor(maxTokens * (1 - contextMargin / 100));
|
|
@@ -132,7 +137,7 @@ function trimMessages(messages, maxTokens, contextMargin, actualTokenCount) {
|
|
|
132
137
|
let remaining = actualTokenCount;
|
|
133
138
|
const kept = new Set();
|
|
134
139
|
for (let i = 0; i < messages.length; i++) {
|
|
135
|
-
if (messages[i]
|
|
140
|
+
if (messages[i].role !== "system")
|
|
136
141
|
kept.add(i);
|
|
137
142
|
}
|
|
138
143
|
// Drop oldest blocks until we fall under target.
|
|
@@ -146,7 +151,7 @@ function trimMessages(messages, maxTokens, contextMargin, actualTokenCount) {
|
|
|
146
151
|
let trimmed = buildTrimmedMessages(messages, kept);
|
|
147
152
|
// If we're still above budget after dropping everything trimmable, preserve system only.
|
|
148
153
|
if (remaining > targetTokens) {
|
|
149
|
-
trimmed = messages.filter((m) => m
|
|
154
|
+
trimmed = messages.filter((m) => m.role === "system");
|
|
150
155
|
}
|
|
151
156
|
const estimatedAfter = (0, token_estimate_1.estimateTokensForMessages)(trimmed);
|
|
152
157
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -173,106 +178,80 @@ function trimMessages(messages, maxTokens, contextMargin, actualTokenCount) {
|
|
|
173
178
|
* user → assistant (with optional tool calls/results) → user → assistant...
|
|
174
179
|
* Never assistant → assistant without a user in between.
|
|
175
180
|
*/
|
|
176
|
-
function
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if (msg.role === "system")
|
|
184
|
-
continue;
|
|
185
|
-
if (msg.role === "tool") {
|
|
186
|
-
sawToolResultSincePrevAssistant = true;
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
if (msg.role === "assistant" && prevNonToolRole === "assistant") {
|
|
190
|
-
// assistant → tool(s) → assistant is valid (tool call flow)
|
|
191
|
-
if (!(prevAssistantHadToolCalls && sawToolResultSincePrevAssistant)) {
|
|
192
|
-
violations.push(`back-to-back assistant at index ${i}`);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
prevAssistantHadToolCalls = msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0;
|
|
196
|
-
sawToolResultSincePrevAssistant = false;
|
|
197
|
-
prevNonToolRole = msg.role;
|
|
198
|
-
}
|
|
199
|
-
return violations;
|
|
181
|
+
function denormalizeContinuityState(state) {
|
|
182
|
+
if (!state.mustResolveBeforeHandoff && typeof state.lastFriendActivityAt !== "string")
|
|
183
|
+
return undefined;
|
|
184
|
+
return {
|
|
185
|
+
...(state.mustResolveBeforeHandoff ? { mustResolveBeforeHandoff: true } : {}),
|
|
186
|
+
...(typeof state.lastFriendActivityAt === "string" ? { lastFriendActivityAt: state.lastFriendActivityAt } : {}),
|
|
187
|
+
};
|
|
200
188
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
level: "warn",
|
|
223
|
-
event: "mind.session_invariant_repair",
|
|
224
|
-
component: "mind",
|
|
225
|
-
message: "repaired session invariant violations",
|
|
226
|
-
meta: { violations },
|
|
189
|
+
function writeSessionEnvelope(filePath, envelope) {
|
|
190
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
191
|
+
fs.writeFileSync(filePath, JSON.stringify(envelope, null, 2));
|
|
192
|
+
}
|
|
193
|
+
function saveSession(filePath, messages, lastUsage, state) {
|
|
194
|
+
const existing = (0, session_events_1.loadSessionEnvelopeFile)(filePath);
|
|
195
|
+
const previousMessages = existing ? (0, session_events_1.projectProviderMessages)(existing) : [];
|
|
196
|
+
const sanitized = (0, session_events_1.sanitizeProviderMessages)(messages);
|
|
197
|
+
const envelope = (0, session_events_1.buildCanonicalSessionEnvelope)({
|
|
198
|
+
existing,
|
|
199
|
+
previousMessages,
|
|
200
|
+
currentMessages: sanitized,
|
|
201
|
+
trimmedMessages: sanitized,
|
|
202
|
+
recordedAt: new Date().toISOString(),
|
|
203
|
+
lastUsage: lastUsage ?? null,
|
|
204
|
+
state,
|
|
205
|
+
projectionBasis: {
|
|
206
|
+
maxTokens: null,
|
|
207
|
+
contextMargin: null,
|
|
208
|
+
inputTokens: lastUsage?.input_tokens ?? null,
|
|
209
|
+
},
|
|
227
210
|
});
|
|
228
|
-
|
|
211
|
+
writeSessionEnvelope(filePath, envelope);
|
|
229
212
|
}
|
|
230
|
-
function
|
|
231
|
-
|
|
232
|
-
|
|
213
|
+
function appendSyntheticAssistantMessage(filePath, content) {
|
|
214
|
+
try {
|
|
215
|
+
if (!fs.existsSync(filePath))
|
|
216
|
+
return false;
|
|
217
|
+
const envelope = (0, session_events_1.loadSessionEnvelopeFile)(filePath);
|
|
218
|
+
if (!envelope)
|
|
219
|
+
return false;
|
|
220
|
+
const updated = (0, session_events_1.appendSyntheticAssistantEvent)(envelope, content, new Date().toISOString());
|
|
221
|
+
writeSessionEnvelope(filePath, updated);
|
|
233
222
|
(0, runtime_1.emitNervesEvent)({
|
|
234
|
-
level: "warn",
|
|
235
|
-
event: "mind.session_invariant_violation",
|
|
236
223
|
component: "mind",
|
|
237
|
-
|
|
238
|
-
|
|
224
|
+
event: "mind.session_synthetic_message_appended",
|
|
225
|
+
message: "appended synthetic assistant message to session",
|
|
226
|
+
meta: { path: filePath, contentLength: content.length },
|
|
239
227
|
});
|
|
240
|
-
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return false;
|
|
241
232
|
}
|
|
242
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
243
|
-
const envelope = { version: 1, messages };
|
|
244
|
-
if (lastUsage)
|
|
245
|
-
envelope.lastUsage = lastUsage;
|
|
246
|
-
fs.writeFileSync(filePath, JSON.stringify(envelope, null, 2));
|
|
247
233
|
}
|
|
248
234
|
function loadSession(filePath) {
|
|
249
235
|
try {
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
if (data.version !== 1)
|
|
236
|
+
const envelope = (0, session_events_1.loadSessionEnvelopeFile)(filePath);
|
|
237
|
+
if (!envelope)
|
|
253
238
|
return null;
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
component: "mind",
|
|
261
|
-
message: "session invariant violated on load",
|
|
262
|
-
meta: { path: filePath, violations },
|
|
263
|
-
});
|
|
264
|
-
messages = repairSessionMessages(messages);
|
|
265
|
-
}
|
|
266
|
-
return { messages, lastUsage: data.lastUsage };
|
|
239
|
+
return {
|
|
240
|
+
messages: (0, session_events_1.annotateMessageTimestamps)(envelope, (0, session_events_1.projectProviderMessages)(envelope)),
|
|
241
|
+
events: envelope.events,
|
|
242
|
+
lastUsage: envelope.lastUsage ?? undefined,
|
|
243
|
+
state: denormalizeContinuityState(envelope.state),
|
|
244
|
+
};
|
|
267
245
|
}
|
|
268
246
|
catch {
|
|
269
247
|
return null;
|
|
270
248
|
}
|
|
271
249
|
}
|
|
272
|
-
function postTurn(messages, sessPath, usage, hooks) {
|
|
250
|
+
function postTurn(messages, sessPath, usage, hooks, state) {
|
|
251
|
+
const preTrimMessages = [...messages];
|
|
273
252
|
if (hooks?.beforeTrim) {
|
|
274
253
|
try {
|
|
275
|
-
hooks.beforeTrim(
|
|
254
|
+
hooks.beforeTrim(preTrimMessages);
|
|
276
255
|
}
|
|
277
256
|
catch (error) {
|
|
278
257
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -287,9 +266,26 @@ function postTurn(messages, sessPath, usage, hooks) {
|
|
|
287
266
|
}
|
|
288
267
|
}
|
|
289
268
|
const { maxTokens, contextMargin } = (0, config_1.getContextConfig)();
|
|
290
|
-
const
|
|
269
|
+
const currentMessages = (0, session_events_1.sanitizeProviderMessages)(messages);
|
|
270
|
+
const trimmed = trimMessages(currentMessages, maxTokens, contextMargin, usage?.input_tokens);
|
|
291
271
|
messages.splice(0, messages.length, ...trimmed);
|
|
292
|
-
|
|
272
|
+
const existing = (0, session_events_1.loadSessionEnvelopeFile)(sessPath);
|
|
273
|
+
const previousMessages = existing ? (0, session_events_1.projectProviderMessages)(existing) : [];
|
|
274
|
+
const envelope = (0, session_events_1.buildCanonicalSessionEnvelope)({
|
|
275
|
+
existing,
|
|
276
|
+
previousMessages,
|
|
277
|
+
currentMessages,
|
|
278
|
+
trimmedMessages: trimmed,
|
|
279
|
+
recordedAt: new Date().toISOString(),
|
|
280
|
+
lastUsage: usage ?? null,
|
|
281
|
+
state,
|
|
282
|
+
projectionBasis: {
|
|
283
|
+
maxTokens,
|
|
284
|
+
contextMargin,
|
|
285
|
+
inputTokens: usage?.input_tokens ?? null,
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
writeSessionEnvelope(sessPath, envelope);
|
|
293
289
|
}
|
|
294
290
|
function deleteSession(filePath) {
|
|
295
291
|
try {
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectSuspiciousContent = detectSuspiciousContent;
|
|
4
|
+
const PATTERN_CATEGORIES = [
|
|
5
|
+
{
|
|
6
|
+
name: "instruction_framing",
|
|
7
|
+
patterns: [
|
|
8
|
+
/\byou are (?:a|an) (?:ai|assistant|language model|helpful assistant)\b/i,
|
|
9
|
+
/\byour (?:new )?instructions are\b/i,
|
|
10
|
+
/\bsystem\s*:/i,
|
|
11
|
+
/\bignore (?:all |my )?previous instructions\b/i,
|
|
12
|
+
/\bdo not reveal\b/i,
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: "override_language",
|
|
17
|
+
patterns: [
|
|
18
|
+
/\bdisregard\b/i,
|
|
19
|
+
/\bforget everything\b/i,
|
|
20
|
+
/\bnew instructions:/i,
|
|
21
|
+
/\boverride (?:all |any |previous )?instructions\b/i,
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: "role_injection",
|
|
26
|
+
patterns: [
|
|
27
|
+
/\bas (?:a|an) (?:ai|language model)\b/i,
|
|
28
|
+
/\byou must always\b/i,
|
|
29
|
+
/\byou are now\b/i,
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "boundary_markers",
|
|
34
|
+
patterns: [
|
|
35
|
+
/```system/i,
|
|
36
|
+
/<<SYS>>/i,
|
|
37
|
+
/\[INST\]/i,
|
|
38
|
+
/<\/?system>/i,
|
|
39
|
+
/\[system\]/i,
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
function detectSuspiciousContent(text) {
|
|
44
|
+
if (!text) {
|
|
45
|
+
return { suspicious: false, patterns: [] };
|
|
46
|
+
}
|
|
47
|
+
const matched = new Set();
|
|
48
|
+
for (const category of PATTERN_CATEGORIES) {
|
|
49
|
+
for (const pattern of category.patterns) {
|
|
50
|
+
if (pattern.test(text)) {
|
|
51
|
+
matched.add(category.name);
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
suspicious: matched.size > 0,
|
|
58
|
+
patterns: [...matched],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -33,52 +33,25 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
37
|
-
exports.
|
|
38
|
-
exports.
|
|
39
|
-
exports.
|
|
40
|
-
exports.
|
|
36
|
+
exports.ensureDiaryStorePaths = ensureDiaryStorePaths;
|
|
37
|
+
exports.appendEntriesWithDedup = appendEntriesWithDedup;
|
|
38
|
+
exports.resolveDiaryRoot = resolveDiaryRoot;
|
|
39
|
+
exports.readDiaryEntries = readDiaryEntries;
|
|
40
|
+
exports.saveDiaryEntry = saveDiaryEntry;
|
|
41
41
|
exports.backfillEmbeddings = backfillEmbeddings;
|
|
42
|
-
exports.
|
|
42
|
+
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 config_1 = require("../heart/config");
|
|
47
46
|
const identity_1 = require("../heart/identity");
|
|
48
47
|
const runtime_1 = require("../nerves/runtime");
|
|
48
|
+
const associative_recall_1 = require("./associative-recall");
|
|
49
|
+
const diary_integrity_1 = require("./diary-integrity");
|
|
50
|
+
const embedding_provider_1 = require("./embedding-provider");
|
|
49
51
|
const DEDUP_THRESHOLD = 0.6;
|
|
52
|
+
const SEMANTIC_DEDUP_THRESHOLD = 0.95;
|
|
50
53
|
const ENTITY_TOKEN = /[a-z0-9]+/g;
|
|
51
|
-
|
|
52
|
-
class OpenAIEmbeddingProvider {
|
|
53
|
-
apiKey;
|
|
54
|
-
model;
|
|
55
|
-
constructor(apiKey, model = DEFAULT_EMBEDDING_MODEL) {
|
|
56
|
-
this.apiKey = apiKey;
|
|
57
|
-
this.model = model;
|
|
58
|
-
}
|
|
59
|
-
async embed(texts) {
|
|
60
|
-
const response = await fetch("https://api.openai.com/v1/embeddings", {
|
|
61
|
-
method: "POST",
|
|
62
|
-
headers: {
|
|
63
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
64
|
-
"Content-Type": "application/json",
|
|
65
|
-
},
|
|
66
|
-
body: JSON.stringify({
|
|
67
|
-
model: this.model,
|
|
68
|
-
input: texts,
|
|
69
|
-
}),
|
|
70
|
-
});
|
|
71
|
-
if (!response.ok) {
|
|
72
|
-
throw new Error(`embedding request failed: ${response.status} ${response.statusText}`);
|
|
73
|
-
}
|
|
74
|
-
const payload = (await response.json());
|
|
75
|
-
if (!payload.data || payload.data.length !== texts.length) {
|
|
76
|
-
throw new Error("embedding response missing expected vectors");
|
|
77
|
-
}
|
|
78
|
-
return payload.data.map((entry) => entry.embedding);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function ensureMemoryStorePaths(rootDir) {
|
|
54
|
+
function ensureDiaryStorePaths(rootDir) {
|
|
82
55
|
const factsPath = path.join(rootDir, "facts.jsonl");
|
|
83
56
|
const entitiesPath = path.join(rootDir, "entities.json");
|
|
84
57
|
const dailyDir = path.join(rootDir, "daily");
|
|
@@ -90,8 +63,8 @@ function ensureMemoryStorePaths(rootDir) {
|
|
|
90
63
|
fs.writeFileSync(entitiesPath, "{}\n", "utf8");
|
|
91
64
|
(0, runtime_1.emitNervesEvent)({
|
|
92
65
|
component: "mind",
|
|
93
|
-
event: "mind.
|
|
94
|
-
message: "
|
|
66
|
+
event: "mind.diary_paths_ready",
|
|
67
|
+
message: "diary store paths ready",
|
|
95
68
|
meta: { rootDir },
|
|
96
69
|
});
|
|
97
70
|
return { rootDir, factsPath, entitiesPath, dailyDir };
|
|
@@ -114,15 +87,22 @@ function overlapScore(left, right) {
|
|
|
114
87
|
}
|
|
115
88
|
return common / Math.min(leftWords.size, rightWords.size);
|
|
116
89
|
}
|
|
117
|
-
function
|
|
90
|
+
function readExistingEntries(factsPath) {
|
|
118
91
|
if (!fs.existsSync(factsPath))
|
|
119
92
|
return [];
|
|
120
93
|
const raw = fs.readFileSync(factsPath, "utf8").trim();
|
|
121
94
|
if (!raw)
|
|
122
95
|
return [];
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
96
|
+
const facts = [];
|
|
97
|
+
for (const line of raw.split("\n")) {
|
|
98
|
+
try {
|
|
99
|
+
facts.push(JSON.parse(line));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Skip corrupt lines (e.g. partial write from a crash).
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return facts;
|
|
126
106
|
}
|
|
127
107
|
function readEntityIndex(entitiesPath) {
|
|
128
108
|
if (!fs.existsSync(entitiesPath))
|
|
@@ -170,13 +150,24 @@ function appendDailyFact(dailyDir, fact) {
|
|
|
170
150
|
const dayPath = path.join(dailyDir, `${day}.jsonl`);
|
|
171
151
|
fs.appendFileSync(dayPath, `${JSON.stringify(fact)}\n`, "utf8");
|
|
172
152
|
}
|
|
173
|
-
function
|
|
174
|
-
const existing =
|
|
153
|
+
function appendEntriesWithDedup(stores, incoming, options) {
|
|
154
|
+
const existing = readExistingEntries(stores.factsPath);
|
|
175
155
|
const all = [...existing];
|
|
176
156
|
let added = 0;
|
|
177
157
|
let skipped = 0;
|
|
158
|
+
const semanticThreshold = options?.semanticThreshold;
|
|
178
159
|
for (const fact of incoming) {
|
|
179
|
-
const duplicate = all.some((prior) =>
|
|
160
|
+
const duplicate = all.some((prior) => {
|
|
161
|
+
if (overlapScore(prior.text, fact.text) > DEDUP_THRESHOLD)
|
|
162
|
+
return true;
|
|
163
|
+
if (semanticThreshold !== undefined &&
|
|
164
|
+
Array.isArray(fact.embedding) && fact.embedding.length > 0 &&
|
|
165
|
+
Array.isArray(prior.embedding) && prior.embedding.length > 0 &&
|
|
166
|
+
fact.embedding.length === prior.embedding.length) {
|
|
167
|
+
return (0, associative_recall_1.cosineSimilarity)(fact.embedding, prior.embedding) > semanticThreshold;
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
});
|
|
180
171
|
if (duplicate) {
|
|
181
172
|
skipped++;
|
|
182
173
|
continue;
|
|
@@ -189,44 +180,20 @@ function appendFactsWithDedup(stores, incoming) {
|
|
|
189
180
|
}
|
|
190
181
|
(0, runtime_1.emitNervesEvent)({
|
|
191
182
|
component: "mind",
|
|
192
|
-
event: "mind.
|
|
193
|
-
message: "
|
|
183
|
+
event: "mind.diary_write",
|
|
184
|
+
message: "diary write completed",
|
|
194
185
|
meta: { added, skipped },
|
|
195
186
|
});
|
|
196
187
|
return { added, skipped };
|
|
197
188
|
}
|
|
198
|
-
function cosineSimilarity(left, right) {
|
|
199
|
-
if (left.length === 0 || right.length === 0 || left.length !== right.length)
|
|
200
|
-
return 0;
|
|
201
|
-
let dot = 0;
|
|
202
|
-
let leftNorm = 0;
|
|
203
|
-
let rightNorm = 0;
|
|
204
|
-
for (let i = 0; i < left.length; i += 1) {
|
|
205
|
-
dot += left[i] * right[i];
|
|
206
|
-
leftNorm += left[i] * left[i];
|
|
207
|
-
rightNorm += right[i] * right[i];
|
|
208
|
-
}
|
|
209
|
-
if (leftNorm === 0 || rightNorm === 0)
|
|
210
|
-
return 0;
|
|
211
|
-
return dot / (Math.sqrt(leftNorm) * Math.sqrt(rightNorm));
|
|
212
|
-
}
|
|
213
|
-
exports.__memoryTestUtils = {
|
|
214
|
-
cosineSimilarity,
|
|
215
|
-
};
|
|
216
|
-
function createDefaultEmbeddingProvider() {
|
|
217
|
-
const apiKey = (0, config_1.getOpenAIEmbeddingsApiKey)().trim();
|
|
218
|
-
if (!apiKey)
|
|
219
|
-
return null;
|
|
220
|
-
return new OpenAIEmbeddingProvider(apiKey);
|
|
221
|
-
}
|
|
222
189
|
async function buildEmbedding(text, embeddingProvider) {
|
|
223
|
-
const provider = embeddingProvider ?? createDefaultEmbeddingProvider();
|
|
190
|
+
const provider = embeddingProvider ?? (0, embedding_provider_1.createDefaultEmbeddingProvider)();
|
|
224
191
|
if (!provider) {
|
|
225
192
|
(0, runtime_1.emitNervesEvent)({
|
|
226
193
|
level: "warn",
|
|
227
194
|
component: "mind",
|
|
228
|
-
event: "mind.
|
|
229
|
-
message: "embedding provider unavailable for
|
|
195
|
+
event: "mind.diary_embedding_unavailable",
|
|
196
|
+
message: "embedding provider unavailable for diary write",
|
|
230
197
|
meta: { reason: "missing_openai_embeddings_key" },
|
|
231
198
|
});
|
|
232
199
|
return [];
|
|
@@ -239,8 +206,8 @@ async function buildEmbedding(text, embeddingProvider) {
|
|
|
239
206
|
(0, runtime_1.emitNervesEvent)({
|
|
240
207
|
level: "warn",
|
|
241
208
|
component: "mind",
|
|
242
|
-
event: "mind.
|
|
243
|
-
message: "embedding provider unavailable for
|
|
209
|
+
event: "mind.diary_embedding_unavailable",
|
|
210
|
+
message: "embedding provider unavailable for diary write",
|
|
244
211
|
meta: {
|
|
245
212
|
reason: error instanceof Error ? error.message : String(error),
|
|
246
213
|
},
|
|
@@ -248,13 +215,19 @@ async function buildEmbedding(text, embeddingProvider) {
|
|
|
248
215
|
return [];
|
|
249
216
|
}
|
|
250
217
|
}
|
|
251
|
-
function
|
|
252
|
-
|
|
218
|
+
function resolveDiaryRoot(explicitRoot) {
|
|
219
|
+
if (explicitRoot)
|
|
220
|
+
return explicitRoot;
|
|
221
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
222
|
+
return path.join(agentRoot, "diary");
|
|
223
|
+
}
|
|
224
|
+
function readDiaryEntries(diaryRoot) {
|
|
225
|
+
return readExistingEntries(path.join(resolveDiaryRoot(diaryRoot), "facts.jsonl"));
|
|
253
226
|
}
|
|
254
|
-
async function
|
|
227
|
+
async function saveDiaryEntry(options) {
|
|
255
228
|
const text = options.text.trim();
|
|
256
|
-
const
|
|
257
|
-
const stores =
|
|
229
|
+
const diaryRoot = resolveDiaryRoot(options.diaryRoot);
|
|
230
|
+
const stores = ensureDiaryStorePaths(diaryRoot);
|
|
258
231
|
const embedding = await buildEmbedding(text, options.embeddingProvider);
|
|
259
232
|
const fact = {
|
|
260
233
|
id: options.idFactory ? options.idFactory() : (0, crypto_1.randomUUID)(),
|
|
@@ -263,24 +236,39 @@ async function saveMemoryFact(options) {
|
|
|
263
236
|
about: options.about?.trim() || undefined,
|
|
264
237
|
createdAt: (options.now ?? (() => new Date()))().toISOString(),
|
|
265
238
|
embedding,
|
|
239
|
+
...(options.provenance ? { provenance: options.provenance } : {}),
|
|
266
240
|
};
|
|
267
|
-
|
|
241
|
+
const integrity = (0, diary_integrity_1.detectSuspiciousContent)(text);
|
|
242
|
+
if (integrity.suspicious) {
|
|
243
|
+
(0, runtime_1.emitNervesEvent)({
|
|
244
|
+
level: "warn",
|
|
245
|
+
component: "mind",
|
|
246
|
+
event: "mind.diary_integrity_warning",
|
|
247
|
+
message: "suspicious content detected in diary entry",
|
|
248
|
+
meta: {
|
|
249
|
+
patterns: integrity.patterns,
|
|
250
|
+
textPreview: text.slice(0, 200),
|
|
251
|
+
entryId: fact.id,
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return appendEntriesWithDedup(stores, [fact], { semanticThreshold: SEMANTIC_DEDUP_THRESHOLD });
|
|
268
256
|
}
|
|
269
257
|
async function backfillEmbeddings(options) {
|
|
270
|
-
const
|
|
271
|
-
const factsPath = path.join(
|
|
258
|
+
const diaryRoot = resolveDiaryRoot(options?.diaryRoot);
|
|
259
|
+
const factsPath = path.join(diaryRoot, "facts.jsonl");
|
|
272
260
|
if (!fs.existsSync(factsPath))
|
|
273
261
|
return { total: 0, backfilled: 0, failed: 0 };
|
|
274
|
-
const facts =
|
|
262
|
+
const facts = readExistingEntries(factsPath);
|
|
275
263
|
const needsEmbedding = facts.filter((f) => !Array.isArray(f.embedding) || f.embedding.length === 0);
|
|
276
264
|
if (needsEmbedding.length === 0)
|
|
277
265
|
return { total: facts.length, backfilled: 0, failed: 0 };
|
|
278
|
-
const provider = options?.embeddingProvider ?? createDefaultEmbeddingProvider();
|
|
266
|
+
const provider = options?.embeddingProvider ?? (0, embedding_provider_1.createDefaultEmbeddingProvider)();
|
|
279
267
|
if (!provider) {
|
|
280
268
|
(0, runtime_1.emitNervesEvent)({
|
|
281
269
|
level: "warn",
|
|
282
270
|
component: "mind",
|
|
283
|
-
event: "mind.
|
|
271
|
+
event: "mind.diary_backfill_skipped",
|
|
284
272
|
message: "embedding provider unavailable for backfill",
|
|
285
273
|
meta: { needsEmbedding: needsEmbedding.length },
|
|
286
274
|
});
|
|
@@ -306,7 +294,7 @@ async function backfillEmbeddings(options) {
|
|
|
306
294
|
(0, runtime_1.emitNervesEvent)({
|
|
307
295
|
level: "warn",
|
|
308
296
|
component: "mind",
|
|
309
|
-
event: "mind.
|
|
297
|
+
event: "mind.diary_backfill_batch_error",
|
|
310
298
|
message: "embedding backfill batch failed",
|
|
311
299
|
meta: {
|
|
312
300
|
batchStart: i,
|
|
@@ -321,7 +309,7 @@ async function backfillEmbeddings(options) {
|
|
|
321
309
|
fs.writeFileSync(factsPath, lines, "utf8");
|
|
322
310
|
(0, runtime_1.emitNervesEvent)({
|
|
323
311
|
component: "mind",
|
|
324
|
-
event: "mind.
|
|
312
|
+
event: "mind.diary_backfill_complete",
|
|
325
313
|
message: "embedding backfill completed",
|
|
326
314
|
meta: { total: facts.length, backfilled, failed },
|
|
327
315
|
});
|
|
@@ -341,7 +329,7 @@ function uniqueFacts(facts) {
|
|
|
341
329
|
}
|
|
342
330
|
return unique;
|
|
343
331
|
}
|
|
344
|
-
async function
|
|
332
|
+
async function searchDiaryEntries(query, facts, embeddingProvider) {
|
|
345
333
|
const trimmed = query.trim();
|
|
346
334
|
if (!trimmed)
|
|
347
335
|
return [];
|
|
@@ -351,7 +339,7 @@ async function searchMemoryFacts(query, facts, embeddingProvider) {
|
|
|
351
339
|
if (embeddedFacts.length === 0) {
|
|
352
340
|
return substringFallback();
|
|
353
341
|
}
|
|
354
|
-
const provider = embeddingProvider ?? createDefaultEmbeddingProvider();
|
|
342
|
+
const provider = embeddingProvider ?? (0, embedding_provider_1.createDefaultEmbeddingProvider)();
|
|
355
343
|
if (!provider) {
|
|
356
344
|
return substringFallback();
|
|
357
345
|
}
|
|
@@ -365,7 +353,7 @@ async function searchMemoryFacts(query, facts, embeddingProvider) {
|
|
|
365
353
|
.filter((fact) => fact.embedding.length === queryEmbedding.length)
|
|
366
354
|
.map((fact) => ({
|
|
367
355
|
fact,
|
|
368
|
-
score: cosineSimilarity(queryEmbedding, fact.embedding),
|
|
356
|
+
score: (0, associative_recall_1.cosineSimilarity)(queryEmbedding, fact.embedding),
|
|
369
357
|
}))
|
|
370
358
|
.filter((entry) => entry.score > 0)
|
|
371
359
|
.sort((left, right) => right.score - left.score)
|
|
@@ -377,8 +365,8 @@ async function searchMemoryFacts(query, facts, embeddingProvider) {
|
|
|
377
365
|
(0, runtime_1.emitNervesEvent)({
|
|
378
366
|
level: "warn",
|
|
379
367
|
component: "mind",
|
|
380
|
-
event: "mind.
|
|
381
|
-
message: "embedding provider unavailable for
|
|
368
|
+
event: "mind.diary_embedding_unavailable",
|
|
369
|
+
message: "embedding provider unavailable for diary search",
|
|
382
370
|
meta: {
|
|
383
371
|
reason: error instanceof Error ? error.message : String(error),
|
|
384
372
|
},
|