@ouro.bot/cli 0.1.0-alpha.39 → 0.1.0-alpha.390
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 +109 -14
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
- package/changelog.json +2368 -4
- 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 +58 -3
- 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 +378 -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 +111 -128
- package/dist/heart/core.js +803 -259
- package/dist/heart/cross-chat-delivery.js +131 -0
- package/dist/heart/daemon/agent-config-check.js +384 -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 +205 -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 +599 -0
- package/dist/heart/daemon/cli-exec.js +3384 -0
- package/dist/heart/daemon/cli-help.js +385 -0
- package/dist/heart/daemon/cli-parse.js +1097 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +560 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/daemon-cli.js +28 -1582
- package/dist/heart/daemon/daemon-entry.js +356 -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 +684 -58
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +419 -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 +182 -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 +4 -2
- package/dist/heart/daemon/ouro-entry.js +3 -1
- package/dist/heart/daemon/process-manager.js +201 -0
- package/dist/heart/daemon/provider-discovery.js +137 -0
- package/dist/heart/daemon/pulse.js +475 -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 +73 -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 +119 -30
- 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 +55 -126
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
- package/dist/heart/{daemon → hatch}/specialist-tools.js +33 -12
- package/dist/heart/identity.js +153 -65
- package/dist/heart/kept-notes.js +357 -0
- package/dist/heart/kicks.js +2 -20
- package/dist/heart/machine-identity.js +161 -0
- package/dist/heart/mcp/mcp-server.js +653 -0
- package/dist/heart/migrate-config.js +100 -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 +195 -0
- package/dist/heart/outlook/readers/agent-machine.js +359 -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 +232 -0
- package/dist/heart/outlook/readers/shared.js +111 -0
- package/dist/heart/platform.js +81 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-attempt.js +133 -0
- package/dist/heart/provider-binding-resolver.js +239 -0
- package/dist/heart/provider-credentials.js +379 -0
- package/dist/heart/provider-failover.js +266 -0
- package/dist/heart/provider-models.js +81 -0
- package/dist/heart/provider-ping.js +237 -0
- package/dist/heart/provider-state.js +216 -0
- package/dist/heart/provider-visibility.js +186 -0
- package/dist/heart/providers/anthropic-token.js +131 -0
- package/dist/heart/providers/anthropic.js +193 -55
- package/dist/heart/providers/azure.js +103 -12
- package/dist/heart/providers/error-classification.js +63 -0
- package/dist/heart/providers/github-copilot.js +145 -0
- package/dist/heart/providers/minimax-vlm.js +189 -0
- package/dist/heart/providers/minimax.js +29 -7
- package/dist/heart/providers/openai-codex.js +39 -29
- package/dist/heart/runtime-credentials.js +181 -0
- package/dist/heart/session-activity.js +190 -0
- package/dist/heart/session-events.js +855 -0
- package/dist/heart/session-transcript.js +167 -0
- package/dist/heart/start-of-turn-packet.js +345 -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 +351 -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 +301 -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/bundle-manifest.js +7 -1
- package/dist/mind/context.js +141 -94
- 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 +21 -0
- package/dist/mind/friends/group-context.js +144 -0
- package/dist/mind/friends/resolver.js +38 -1
- package/dist/mind/friends/store-file.js +39 -3
- package/dist/mind/friends/trust-explanation.js +74 -0
- package/dist/mind/friends/types.js +1 -1
- package/dist/mind/journal-index.js +161 -0
- package/dist/mind/note-search.js +268 -0
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +66 -7
- package/dist/mind/prompt-refresh.js +3 -2
- package/dist/mind/prompt.js +946 -167
- 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-rules.js +15 -6
- package/dist/nerves/coverage/audit.js +28 -2
- package/dist/nerves/coverage/cli.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-BAcU08c-.css +1 -0
- package/dist/outlook-ui/assets/index-D7l3l4vY.js +61 -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 +365 -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 +107 -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 +371 -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 +15 -24
- 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 +317 -0
- package/dist/repertoire/tools-base.js +42 -690
- 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-notes.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 +40 -0
- package/dist/repertoire/tools.js +144 -115
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/user-profile.js +118 -0
- package/dist/repertoire/vault-setup.js +246 -0
- package/dist/repertoire/vault-unlock.js +366 -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} +260 -9
- package/dist/senses/bluebubbles/entry.js +70 -0
- package/dist/senses/bluebubbles/inbound-log.js +113 -0
- package/dist/senses/bluebubbles/index.js +1620 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -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 +60 -8
- package/dist/senses/cli-layout.js +187 -0
- package/dist/senses/cli.js +526 -211
- package/dist/senses/commands.js +66 -3
- 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 +600 -95
- package/dist/senses/pipeline.js +539 -61
- package/dist/senses/proactive-content-guard.js +51 -0
- package/dist/senses/shared-turn.js +205 -0
- package/dist/senses/surface-tool.js +68 -0
- package/dist/senses/teams-entry.js +60 -8
- package/dist/senses/teams.js +569 -237
- package/dist/senses/trust-gate.js +6 -7
- package/package.json +28 -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 +101 -0
- package/skills/travel-planning.md +134 -0
- package/dist/heart/daemon/ouro-path-installer.js +0 -178
- package/dist/heart/daemon/subagent-installer.js +0 -134
- package/dist/mind/associative-recall.js +0 -197
- package/dist/senses/bluebubbles-entry.js +0 -11
- package/dist/senses/bluebubbles.js +0 -832
- package/dist/senses/debug-activity.js +0 -127
- package/subagents/README.md +0 -60
- 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-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
|
@@ -86,7 +86,15 @@ function startUpdateChecker(options) {
|
|
|
86
86
|
if (result.available && options.onUpdate) {
|
|
87
87
|
await options.onUpdate(result);
|
|
88
88
|
}
|
|
89
|
-
})()
|
|
89
|
+
})().catch((err) => {
|
|
90
|
+
(0, runtime_1.emitNervesEvent)({
|
|
91
|
+
component: "daemon",
|
|
92
|
+
event: "daemon.update_checker_error",
|
|
93
|
+
level: "warn",
|
|
94
|
+
message: "update checker tick failed",
|
|
95
|
+
meta: { reason: err instanceof Error ? err.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(err) },
|
|
96
|
+
});
|
|
97
|
+
});
|
|
90
98
|
}, intervalMs);
|
|
91
99
|
}
|
|
92
100
|
function stopUpdateChecker() {
|
|
@@ -94,9 +102,11 @@ function stopUpdateChecker() {
|
|
|
94
102
|
clearInterval(_intervalId);
|
|
95
103
|
_intervalId = null;
|
|
96
104
|
}
|
|
105
|
+
// `_end` (not `_stop`) to satisfy the nerves audit's start/end pairing
|
|
106
|
+
// rule — counterpart to `daemon.update_checker_start` above.
|
|
97
107
|
(0, runtime_1.emitNervesEvent)({
|
|
98
108
|
component: "daemon",
|
|
99
|
-
event: "daemon.
|
|
109
|
+
event: "daemon.update_checker_end",
|
|
100
110
|
message: "stopping update checker",
|
|
101
111
|
meta: {},
|
|
102
112
|
});
|
|
@@ -65,74 +65,78 @@ async function applyPendingUpdates(bundlesRoot, currentVersion) {
|
|
|
65
65
|
message: "applying pending updates",
|
|
66
66
|
meta: { bundlesRoot, currentVersion },
|
|
67
67
|
});
|
|
68
|
-
if (!fs.existsSync(bundlesRoot)) {
|
|
69
|
-
return summary;
|
|
70
|
-
}
|
|
71
|
-
let entries;
|
|
72
68
|
try {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
for (const entry of entries) {
|
|
79
|
-
if (!entry.isDirectory() || !entry.name.endsWith(".ouro"))
|
|
80
|
-
continue;
|
|
81
|
-
const agentRoot = path.join(bundlesRoot, entry.name);
|
|
82
|
-
let previousVersion;
|
|
83
|
-
const metaPath = path.join(agentRoot, "bundle-meta.json");
|
|
69
|
+
if (!fs.existsSync(bundlesRoot)) {
|
|
70
|
+
return summary;
|
|
71
|
+
}
|
|
72
|
+
let entries;
|
|
84
73
|
try {
|
|
85
|
-
|
|
86
|
-
const raw = fs.readFileSync(metaPath, "utf-8");
|
|
87
|
-
const meta = JSON.parse(raw);
|
|
88
|
-
previousVersion = meta.runtimeVersion;
|
|
89
|
-
if (previousVersion === currentVersion) {
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
// Skip downgrades — only update forward
|
|
93
|
-
if (semver.valid(previousVersion) && semver.valid(currentVersion) && semver.gte(previousVersion, currentVersion)) {
|
|
94
|
-
(0, runtime_1.emitNervesEvent)({
|
|
95
|
-
component: "daemon",
|
|
96
|
-
event: "daemon.update_hook_skip_downgrade",
|
|
97
|
-
message: "skipping downgrade",
|
|
98
|
-
meta: { agentRoot, previousVersion, currentVersion },
|
|
99
|
-
});
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
74
|
+
entries = fs.readdirSync(bundlesRoot, { withFileTypes: true });
|
|
103
75
|
}
|
|
104
76
|
catch {
|
|
105
|
-
|
|
106
|
-
previousVersion = undefined;
|
|
77
|
+
return summary;
|
|
107
78
|
}
|
|
108
|
-
const
|
|
109
|
-
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
if (!entry.isDirectory() || !entry.name.endsWith(".ouro"))
|
|
81
|
+
continue;
|
|
82
|
+
const agentRoot = path.join(bundlesRoot, entry.name);
|
|
83
|
+
let previousVersion;
|
|
84
|
+
const metaPath = path.join(agentRoot, "bundle-meta.json");
|
|
110
85
|
try {
|
|
111
|
-
|
|
86
|
+
if (fs.existsSync(metaPath)) {
|
|
87
|
+
const raw = fs.readFileSync(metaPath, "utf-8");
|
|
88
|
+
const meta = JSON.parse(raw);
|
|
89
|
+
previousVersion = meta.runtimeVersion;
|
|
90
|
+
if (previousVersion === currentVersion) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
// Skip downgrades — only update forward
|
|
94
|
+
if (semver.valid(previousVersion) && semver.valid(currentVersion) && semver.gte(previousVersion, currentVersion)) {
|
|
95
|
+
(0, runtime_1.emitNervesEvent)({
|
|
96
|
+
component: "daemon",
|
|
97
|
+
event: "daemon.update_hook_skip_downgrade",
|
|
98
|
+
message: "skipping downgrade",
|
|
99
|
+
meta: { agentRoot, previousVersion, currentVersion },
|
|
100
|
+
});
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Malformed or unreadable bundle-meta.json -- treat as needing update
|
|
107
|
+
previousVersion = undefined;
|
|
112
108
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
109
|
+
const ctx = { agentRoot, currentVersion, previousVersion };
|
|
110
|
+
for (const hook of _hooks) {
|
|
111
|
+
try {
|
|
112
|
+
await hook(ctx);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
(0, runtime_1.emitNervesEvent)({
|
|
116
|
+
component: "daemon",
|
|
117
|
+
event: "daemon.update_hook_error",
|
|
118
|
+
message: "update hook threw",
|
|
119
|
+
meta: {
|
|
120
|
+
agentRoot,
|
|
121
|
+
error: err instanceof Error ? err.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(err),
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
123
125
|
}
|
|
126
|
+
summary.updated.push({
|
|
127
|
+
agent: entry.name.replace(/\.ouro$/, ""),
|
|
128
|
+
from: previousVersion,
|
|
129
|
+
to: currentVersion,
|
|
130
|
+
});
|
|
124
131
|
}
|
|
125
|
-
summary
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
132
|
+
return summary;
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
(0, runtime_1.emitNervesEvent)({
|
|
136
|
+
component: "daemon",
|
|
137
|
+
event: "daemon.apply_pending_updates_end",
|
|
138
|
+
message: "pending updates applied",
|
|
139
|
+
meta: { bundlesRoot },
|
|
129
140
|
});
|
|
130
141
|
}
|
|
131
|
-
(0, runtime_1.emitNervesEvent)({
|
|
132
|
-
component: "daemon",
|
|
133
|
-
event: "daemon.apply_pending_updates_end",
|
|
134
|
-
message: "pending updates applied",
|
|
135
|
-
meta: { bundlesRoot },
|
|
136
|
-
});
|
|
137
|
-
return summary;
|
|
138
142
|
}
|
|
@@ -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,42 @@ 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
|
+
exports.postTurnTrim = postTurnTrim;
|
|
43
|
+
exports.postTurnPersist = postTurnPersist;
|
|
44
|
+
exports.deferPostTurnPersist = deferPostTurnPersist;
|
|
42
45
|
exports.deleteSession = deleteSession;
|
|
43
46
|
const config_1 = require("../heart/config");
|
|
47
|
+
const session_events_1 = require("../heart/session-events");
|
|
44
48
|
const runtime_1 = require("../nerves/runtime");
|
|
45
49
|
const fs = __importStar(require("fs"));
|
|
46
50
|
const path = __importStar(require("path"));
|
|
47
51
|
const token_estimate_1 = require("./token-estimate");
|
|
52
|
+
var session_events_2 = require("../heart/session-events");
|
|
53
|
+
Object.defineProperty(exports, "migrateToolNames", { enumerable: true, get: function () { return session_events_2.migrateToolNames; } });
|
|
54
|
+
Object.defineProperty(exports, "repairSessionMessages", { enumerable: true, get: function () { return session_events_2.repairSessionMessages; } });
|
|
55
|
+
Object.defineProperty(exports, "validateSessionMessages", { enumerable: true, get: function () { return session_events_2.validateSessionMessages; } });
|
|
48
56
|
function buildTrimmableBlocks(messages) {
|
|
49
57
|
const blocks = [];
|
|
50
58
|
let i = 0;
|
|
51
59
|
while (i < messages.length) {
|
|
52
60
|
const msg = messages[i];
|
|
53
|
-
if (msg
|
|
61
|
+
if (msg.role === "system") {
|
|
54
62
|
i++;
|
|
55
63
|
continue;
|
|
56
64
|
}
|
|
57
65
|
// Tool coherence block: assistant message with tool_calls + immediately following tool results
|
|
58
|
-
if (msg
|
|
66
|
+
if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0) {
|
|
59
67
|
const indices = [i];
|
|
60
68
|
i++;
|
|
61
69
|
while (i < messages.length) {
|
|
62
70
|
const next = messages[i];
|
|
63
|
-
if (next
|
|
71
|
+
if (next.role !== "tool")
|
|
64
72
|
break;
|
|
65
73
|
indices.push(i);
|
|
66
74
|
i++;
|
|
@@ -78,13 +86,13 @@ function buildTrimmableBlocks(messages) {
|
|
|
78
86
|
function getSystemMessageIndices(messages) {
|
|
79
87
|
const indices = [];
|
|
80
88
|
for (let i = 0; i < messages.length; i++) {
|
|
81
|
-
if (messages[i]
|
|
89
|
+
if (messages[i].role === "system")
|
|
82
90
|
indices.push(i);
|
|
83
91
|
}
|
|
84
92
|
return indices;
|
|
85
93
|
}
|
|
86
94
|
function buildTrimmedMessages(messages, kept) {
|
|
87
|
-
return messages.filter((m, idx) => m
|
|
95
|
+
return messages.filter((m, idx) => m.role === "system" || kept.has(idx));
|
|
88
96
|
}
|
|
89
97
|
function trimMessages(messages, maxTokens, contextMargin, actualTokenCount) {
|
|
90
98
|
const targetTokens = Math.floor(maxTokens * (1 - contextMargin / 100));
|
|
@@ -132,7 +140,7 @@ function trimMessages(messages, maxTokens, contextMargin, actualTokenCount) {
|
|
|
132
140
|
let remaining = actualTokenCount;
|
|
133
141
|
const kept = new Set();
|
|
134
142
|
for (let i = 0; i < messages.length; i++) {
|
|
135
|
-
if (messages[i]
|
|
143
|
+
if (messages[i].role !== "system")
|
|
136
144
|
kept.add(i);
|
|
137
145
|
}
|
|
138
146
|
// Drop oldest blocks until we fall under target.
|
|
@@ -146,7 +154,7 @@ function trimMessages(messages, maxTokens, contextMargin, actualTokenCount) {
|
|
|
146
154
|
let trimmed = buildTrimmedMessages(messages, kept);
|
|
147
155
|
// If we're still above budget after dropping everything trimmable, preserve system only.
|
|
148
156
|
if (remaining > targetTokens) {
|
|
149
|
-
trimmed = messages.filter((m) => m
|
|
157
|
+
trimmed = messages.filter((m) => m.role === "system");
|
|
150
158
|
}
|
|
151
159
|
const estimatedAfter = (0, token_estimate_1.estimateTokensForMessages)(trimmed);
|
|
152
160
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -173,106 +181,94 @@ function trimMessages(messages, maxTokens, contextMargin, actualTokenCount) {
|
|
|
173
181
|
* user → assistant (with optional tool calls/results) → user → assistant...
|
|
174
182
|
* Never assistant → assistant without a user in between.
|
|
175
183
|
*/
|
|
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;
|
|
184
|
+
function denormalizeContinuityState(state) {
|
|
185
|
+
if (!state.mustResolveBeforeHandoff && typeof state.lastFriendActivityAt !== "string")
|
|
186
|
+
return undefined;
|
|
187
|
+
return {
|
|
188
|
+
...(state.mustResolveBeforeHandoff ? { mustResolveBeforeHandoff: true } : {}),
|
|
189
|
+
...(typeof state.lastFriendActivityAt === "string" ? { lastFriendActivityAt: state.lastFriendActivityAt } : {}),
|
|
190
|
+
};
|
|
200
191
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
component: "mind",
|
|
225
|
-
message: "repaired session invariant violations",
|
|
226
|
-
meta: { violations },
|
|
192
|
+
function writeSessionEnvelope(filePath, envelope) {
|
|
193
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
194
|
+
fs.writeFileSync(filePath, JSON.stringify(envelope, null, 2));
|
|
195
|
+
}
|
|
196
|
+
function saveSession(filePath, messages, lastUsage, state) {
|
|
197
|
+
const existing = (0, session_events_1.loadSessionEnvelopeFile)(filePath);
|
|
198
|
+
const previousMessages = existing ? (0, session_events_1.projectProviderMessages)(existing) : [];
|
|
199
|
+
const currentIngressTimes = messages.map(session_events_1.getIngressTime);
|
|
200
|
+
const sanitized = (0, session_events_1.sanitizeProviderMessages)(messages);
|
|
201
|
+
const { envelope } = (0, session_events_1.buildCanonicalSessionEnvelope)({
|
|
202
|
+
existing,
|
|
203
|
+
previousMessages,
|
|
204
|
+
currentMessages: sanitized,
|
|
205
|
+
trimmedMessages: sanitized,
|
|
206
|
+
currentIngressTimes,
|
|
207
|
+
recordedAt: new Date().toISOString(),
|
|
208
|
+
lastUsage: lastUsage ?? null,
|
|
209
|
+
state,
|
|
210
|
+
projectionBasis: {
|
|
211
|
+
maxTokens: null,
|
|
212
|
+
contextMargin: null,
|
|
213
|
+
inputTokens: lastUsage?.input_tokens ?? null,
|
|
214
|
+
},
|
|
227
215
|
});
|
|
228
|
-
|
|
216
|
+
writeSessionEnvelope(filePath, envelope);
|
|
229
217
|
}
|
|
230
|
-
function
|
|
231
|
-
|
|
232
|
-
|
|
218
|
+
function appendSyntheticAssistantMessage(filePath, content) {
|
|
219
|
+
try {
|
|
220
|
+
if (!fs.existsSync(filePath))
|
|
221
|
+
return false;
|
|
222
|
+
const envelope = (0, session_events_1.loadSessionEnvelopeFile)(filePath);
|
|
223
|
+
if (!envelope)
|
|
224
|
+
return false;
|
|
225
|
+
const updated = (0, session_events_1.appendSyntheticAssistantEvent)(envelope, content, new Date().toISOString());
|
|
226
|
+
writeSessionEnvelope(filePath, updated);
|
|
233
227
|
(0, runtime_1.emitNervesEvent)({
|
|
234
|
-
level: "warn",
|
|
235
|
-
event: "mind.session_invariant_violation",
|
|
236
228
|
component: "mind",
|
|
237
|
-
|
|
238
|
-
|
|
229
|
+
event: "mind.session_synthetic_message_appended",
|
|
230
|
+
message: "appended synthetic assistant message to session",
|
|
231
|
+
meta: { path: filePath, contentLength: content.length },
|
|
239
232
|
});
|
|
240
|
-
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return false;
|
|
241
237
|
}
|
|
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
238
|
}
|
|
248
239
|
function loadSession(filePath) {
|
|
249
240
|
try {
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
if (data.version !== 1)
|
|
241
|
+
const envelope = (0, session_events_1.loadSessionEnvelopeFile)(filePath);
|
|
242
|
+
if (!envelope)
|
|
253
243
|
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 };
|
|
244
|
+
return {
|
|
245
|
+
messages: (0, session_events_1.annotateMessageTimestamps)(envelope, (0, session_events_1.projectProviderMessages)(envelope)),
|
|
246
|
+
events: envelope.events,
|
|
247
|
+
lastUsage: envelope.lastUsage ?? undefined,
|
|
248
|
+
state: denormalizeContinuityState(envelope.state),
|
|
249
|
+
};
|
|
267
250
|
}
|
|
268
251
|
catch {
|
|
269
252
|
return null;
|
|
270
253
|
}
|
|
271
254
|
}
|
|
272
|
-
|
|
255
|
+
/**
|
|
256
|
+
* Synchronous post-turn: sanitize, trim (mutates messages in place), and persist to disk.
|
|
257
|
+
* For non-blocking persist, use postTurnTrim() + deferPostTurnPersist() instead.
|
|
258
|
+
*/
|
|
259
|
+
function postTurn(messages, sessPath, usage, hooks, state) {
|
|
260
|
+
const prepared = postTurnTrim(messages, usage, hooks);
|
|
261
|
+
postTurnPersist(sessPath, prepared, usage, state);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Synchronous phase: run hooks, sanitize, trim, and mutate the messages array in place.
|
|
265
|
+
* Returns the data needed by postTurnPersist / deferPostTurnPersist.
|
|
266
|
+
*/
|
|
267
|
+
function postTurnTrim(messages, usage, hooks) {
|
|
268
|
+
const preTrimMessages = [...messages];
|
|
273
269
|
if (hooks?.beforeTrim) {
|
|
274
270
|
try {
|
|
275
|
-
hooks.beforeTrim(
|
|
271
|
+
hooks.beforeTrim(preTrimMessages);
|
|
276
272
|
}
|
|
277
273
|
catch (error) {
|
|
278
274
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -287,9 +283,60 @@ function postTurn(messages, sessPath, usage, hooks) {
|
|
|
287
283
|
}
|
|
288
284
|
}
|
|
289
285
|
const { maxTokens, contextMargin } = (0, config_1.getContextConfig)();
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
286
|
+
const currentIngressTimes = messages.map(session_events_1.getIngressTime);
|
|
287
|
+
const currentMessages = (0, session_events_1.sanitizeProviderMessages)(messages);
|
|
288
|
+
const trimmedMessages = trimMessages(currentMessages, maxTokens, contextMargin, usage?.input_tokens);
|
|
289
|
+
messages.splice(0, messages.length, ...trimmedMessages);
|
|
290
|
+
return { currentMessages, trimmedMessages, currentIngressTimes, maxTokens, contextMargin };
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Synchronous persist: load existing envelope, build canonical envelope, write to disk.
|
|
294
|
+
*/
|
|
295
|
+
function postTurnPersist(sessPath, prepared, usage, state) {
|
|
296
|
+
const existing = (0, session_events_1.loadSessionEnvelopeFile)(sessPath);
|
|
297
|
+
const previousMessages = existing ? (0, session_events_1.projectProviderMessages)(existing) : [];
|
|
298
|
+
const { envelope, evictedEvents } = (0, session_events_1.buildCanonicalSessionEnvelope)({
|
|
299
|
+
existing,
|
|
300
|
+
previousMessages,
|
|
301
|
+
currentMessages: prepared.currentMessages,
|
|
302
|
+
trimmedMessages: prepared.trimmedMessages,
|
|
303
|
+
currentIngressTimes: prepared.currentIngressTimes,
|
|
304
|
+
recordedAt: new Date().toISOString(),
|
|
305
|
+
lastUsage: usage ?? null,
|
|
306
|
+
state,
|
|
307
|
+
projectionBasis: {
|
|
308
|
+
maxTokens: prepared.maxTokens,
|
|
309
|
+
contextMargin: prepared.contextMargin,
|
|
310
|
+
inputTokens: usage?.input_tokens ?? null,
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
(0, session_events_1.appendEvictedToArchive)(sessPath, evictedEvents);
|
|
314
|
+
writeSessionEnvelope(sessPath, envelope);
|
|
315
|
+
return envelope.events;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Deferred persist: same as postTurnPersist but runs on the next event loop tick.
|
|
319
|
+
* Returns a promise that resolves when the persist completes.
|
|
320
|
+
*/
|
|
321
|
+
function deferPostTurnPersist(sessPath, prepared, usage, state) {
|
|
322
|
+
return new Promise((resolve) => {
|
|
323
|
+
setImmediate(() => {
|
|
324
|
+
try {
|
|
325
|
+
const events = postTurnPersist(sessPath, prepared, usage, state);
|
|
326
|
+
resolve(events);
|
|
327
|
+
}
|
|
328
|
+
catch (err) {
|
|
329
|
+
(0, runtime_1.emitNervesEvent)({
|
|
330
|
+
level: "warn",
|
|
331
|
+
component: "mind",
|
|
332
|
+
event: "mind.deferred_persist_error",
|
|
333
|
+
message: "deferred session persist failed",
|
|
334
|
+
meta: { error: err instanceof Error ? err.message : String(err) },
|
|
335
|
+
});
|
|
336
|
+
resolve([]);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
});
|
|
293
340
|
}
|
|
294
341
|
function deleteSession(filePath) {
|
|
295
342
|
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
|
+
}
|