@ouro.bot/cli 0.1.0-alpha.34 → 0.1.0-alpha.340
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 +2031 -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 +2297 -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 +401 -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/{daemon → versioning}/ouro-path-installer.js +78 -35
- 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/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
|
@@ -35,59 +35,43 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.cosineSimilarity = cosineSimilarity;
|
|
37
37
|
exports.recallFactsForQuery = recallFactsForQuery;
|
|
38
|
+
exports.searchJournalIndex = searchJournalIndex;
|
|
38
39
|
exports.injectAssociativeRecall = injectAssociativeRecall;
|
|
39
40
|
const fs = __importStar(require("fs"));
|
|
40
41
|
const path = __importStar(require("path"));
|
|
41
|
-
const config_1 = require("../heart/config");
|
|
42
|
-
const identity_1 = require("../heart/identity");
|
|
43
42
|
const runtime_1 = require("../nerves/runtime");
|
|
44
|
-
const
|
|
43
|
+
const diary_1 = require("./diary");
|
|
44
|
+
const provenance_trust_1 = require("./provenance-trust");
|
|
45
|
+
const embedding_provider_1 = require("./embedding-provider");
|
|
45
46
|
const DEFAULT_MIN_SCORE = 0.5;
|
|
46
47
|
const DEFAULT_TOP_K = 3;
|
|
47
|
-
class OpenAIEmbeddingProvider {
|
|
48
|
-
apiKey;
|
|
49
|
-
model;
|
|
50
|
-
constructor(apiKey, model = DEFAULT_EMBEDDING_MODEL) {
|
|
51
|
-
this.apiKey = apiKey;
|
|
52
|
-
this.model = model;
|
|
53
|
-
}
|
|
54
|
-
async embed(texts) {
|
|
55
|
-
const response = await fetch("https://api.openai.com/v1/embeddings", {
|
|
56
|
-
method: "POST",
|
|
57
|
-
headers: {
|
|
58
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
59
|
-
"Content-Type": "application/json",
|
|
60
|
-
},
|
|
61
|
-
body: JSON.stringify({
|
|
62
|
-
model: this.model,
|
|
63
|
-
input: texts,
|
|
64
|
-
}),
|
|
65
|
-
});
|
|
66
|
-
if (!response.ok) {
|
|
67
|
-
throw new Error(`embedding request failed: ${response.status} ${response.statusText}`);
|
|
68
|
-
}
|
|
69
|
-
const payload = (await response.json());
|
|
70
|
-
if (!payload.data || payload.data.length !== texts.length) {
|
|
71
|
-
throw new Error("embedding response missing expected vectors");
|
|
72
|
-
}
|
|
73
|
-
return payload.data.map((entry) => entry.embedding);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
48
|
function createDefaultProvider() {
|
|
77
|
-
const
|
|
78
|
-
if (!
|
|
49
|
+
const provider = (0, embedding_provider_1.createDefaultEmbeddingProvider)();
|
|
50
|
+
if (!provider) {
|
|
79
51
|
throw new Error("openaiEmbeddingsApiKey not configured");
|
|
80
52
|
}
|
|
81
|
-
return
|
|
53
|
+
return provider;
|
|
82
54
|
}
|
|
83
|
-
function readFacts(
|
|
84
|
-
const factsPath = path.join(
|
|
55
|
+
function readFacts(diaryRoot) {
|
|
56
|
+
const factsPath = path.join(diaryRoot, "facts.jsonl");
|
|
85
57
|
if (!fs.existsSync(factsPath))
|
|
86
58
|
return [];
|
|
87
59
|
const raw = fs.readFileSync(factsPath, "utf8").trim();
|
|
88
60
|
if (!raw)
|
|
89
61
|
return [];
|
|
90
|
-
|
|
62
|
+
const facts = [];
|
|
63
|
+
for (const line of raw.split("\n")) {
|
|
64
|
+
const trimmed = line.trim();
|
|
65
|
+
if (!trimmed)
|
|
66
|
+
continue;
|
|
67
|
+
try {
|
|
68
|
+
facts.push(JSON.parse(trimmed));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Skip corrupt lines (e.g. partial write from a crash).
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return facts;
|
|
91
75
|
}
|
|
92
76
|
function getLatestUserText(messages) {
|
|
93
77
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -133,6 +117,40 @@ async function recallFactsForQuery(query, facts, provider, options) {
|
|
|
133
117
|
.sort((left, right) => right.score - left.score)
|
|
134
118
|
.slice(0, topK);
|
|
135
119
|
}
|
|
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
|
+
}
|
|
136
154
|
async function injectAssociativeRecall(messages, options) {
|
|
137
155
|
try {
|
|
138
156
|
if (messages[0]?.role !== "system" || typeof messages[0].content !== "string")
|
|
@@ -140,37 +158,90 @@ async function injectAssociativeRecall(messages, options) {
|
|
|
140
158
|
const query = getLatestUserText(messages);
|
|
141
159
|
if (!query)
|
|
142
160
|
return;
|
|
143
|
-
const
|
|
144
|
-
const facts = readFacts(
|
|
145
|
-
|
|
161
|
+
const diaryRoot = options?.diaryRoot ?? (0, diary_1.resolveDiaryRoot)();
|
|
162
|
+
const facts = readFacts(diaryRoot);
|
|
163
|
+
const journalDir = resolveJournalDir(diaryRoot, options?.journalDir);
|
|
164
|
+
const journalEntries = readJournalIndex(journalDir);
|
|
165
|
+
if (facts.length === 0 && journalEntries.length === 0)
|
|
146
166
|
return;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
+
// Build combined result lines tagged by source
|
|
168
|
+
const resultLines = [];
|
|
169
|
+
let queryEmbedding;
|
|
170
|
+
// Search diary entries
|
|
171
|
+
if (facts.length > 0) {
|
|
172
|
+
let recalled;
|
|
173
|
+
try {
|
|
174
|
+
const provider = options?.provider ?? createDefaultProvider();
|
|
175
|
+
recalled = await recallFactsForQuery(query, facts, provider, options);
|
|
176
|
+
// Compute query embedding for journal search while provider is available
|
|
177
|
+
if (journalEntries.length > 0) {
|
|
178
|
+
const [qe] = await provider.embed([query.trim()]);
|
|
179
|
+
queryEmbedding = qe;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// Embeddings unavailable — fall back to substring matching
|
|
184
|
+
const lowerQuery = query.toLowerCase();
|
|
185
|
+
const topK = options?.topK ?? DEFAULT_TOP_K;
|
|
186
|
+
recalled = facts
|
|
187
|
+
.filter((fact) => fact.text.toLowerCase().includes(lowerQuery))
|
|
188
|
+
.slice(0, topK)
|
|
189
|
+
.map((fact) => ({ ...fact, score: 1 }));
|
|
190
|
+
if (recalled.length > 0) {
|
|
191
|
+
(0, runtime_1.emitNervesEvent)({
|
|
192
|
+
level: "warn",
|
|
193
|
+
component: "mind",
|
|
194
|
+
event: "mind.associative_recall_fallback",
|
|
195
|
+
message: "embeddings unavailable, used substring fallback",
|
|
196
|
+
meta: { matchCount: recalled.length },
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
for (const fact of recalled) {
|
|
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,
|
|
167
214
|
});
|
|
168
215
|
}
|
|
169
216
|
}
|
|
170
|
-
|
|
217
|
+
// Search journal entries (works whether diary had results or not)
|
|
218
|
+
if (journalEntries.length > 0) {
|
|
219
|
+
try {
|
|
220
|
+
if (!queryEmbedding) {
|
|
221
|
+
const provider = options?.provider ?? createDefaultProvider();
|
|
222
|
+
const [qe] = await provider.embed([query.trim()]);
|
|
223
|
+
queryEmbedding = qe;
|
|
224
|
+
}
|
|
225
|
+
if (queryEmbedding) {
|
|
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
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (resultLines.length === 0)
|
|
171
240
|
return;
|
|
172
|
-
|
|
173
|
-
|
|
241
|
+
// Sort all results by score descending
|
|
242
|
+
resultLines.sort((left, right) => right.score - left.score);
|
|
243
|
+
const recallSection = resultLines
|
|
244
|
+
.map((entry, index) => `${index + 1}. ${entry.text}`)
|
|
174
245
|
.join("\n");
|
|
175
246
|
messages[0] = {
|
|
176
247
|
role: "system",
|
|
@@ -180,7 +251,7 @@ async function injectAssociativeRecall(messages, options) {
|
|
|
180
251
|
component: "mind",
|
|
181
252
|
event: "mind.associative_recall",
|
|
182
253
|
message: "associative recall injected",
|
|
183
|
-
meta: { count:
|
|
254
|
+
meta: { count: resultLines.length },
|
|
184
255
|
});
|
|
185
256
|
}
|
|
186
257
|
catch (error) {
|
|
@@ -190,7 +261,7 @@ async function injectAssociativeRecall(messages, options) {
|
|
|
190
261
|
event: "mind.associative_recall_error",
|
|
191
262
|
message: "associative recall failed",
|
|
192
263
|
meta: {
|
|
193
|
-
reason: error instanceof Error ? error.message : String(error)
|
|
264
|
+
reason: error instanceof Error ? error.message : /* v8 ignore start -- defensive: non-Error catch branch @preserve */ String(error) /* v8 ignore stop */,
|
|
194
265
|
},
|
|
195
266
|
});
|
|
196
267
|
}
|
|
@@ -52,7 +52,13 @@ exports.CANONICAL_BUNDLE_MANIFEST = [
|
|
|
52
52
|
{ path: "psyche/LORE.md", kind: "file" },
|
|
53
53
|
{ path: "psyche/TACIT.md", kind: "file" },
|
|
54
54
|
{ path: "psyche/ASPIRATIONS.md", kind: "file" },
|
|
55
|
-
{ path: "
|
|
55
|
+
{ path: "arc", kind: "dir" },
|
|
56
|
+
{ path: "arc/episodes", kind: "dir" },
|
|
57
|
+
{ path: "arc/obligations", kind: "dir" },
|
|
58
|
+
{ path: "arc/cares", kind: "dir" },
|
|
59
|
+
{ path: "arc/intentions", kind: "dir" },
|
|
60
|
+
{ path: "diary", kind: "dir" },
|
|
61
|
+
{ path: "journal", kind: "dir" },
|
|
56
62
|
{ path: "friends", kind: "dir" },
|
|
57
63
|
{ path: "state", kind: "dir" },
|
|
58
64
|
{ path: "tasks", kind: "dir" },
|
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
|
+
}
|