@ouro.bot/cli 0.1.0-alpha.46 → 0.1.0-alpha.461
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 +127 -19
- 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 +2928 -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 +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 +426 -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 +110 -128
- package/dist/heart/core.js +745 -227
- package/dist/heart/cross-chat-delivery.js +131 -0
- package/dist/heart/daemon/agent-config-check.js +490 -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 +216 -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 +631 -0
- package/dist/heart/daemon/cli-exec.js +6158 -0
- package/dist/heart/daemon/cli-help.js +457 -0
- package/dist/heart/daemon/cli-parse.js +1273 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +561 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/connect-bay.js +323 -0
- package/dist/heart/daemon/daemon-cli.js +29 -1688
- package/dist/heart/daemon/daemon-entry.js +345 -3
- package/dist/heart/daemon/daemon-health.js +141 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +190 -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 +435 -0
- package/dist/heart/daemon/health-monitor.js +92 -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/human-command-screens.js +234 -0
- package/dist/heart/daemon/human-readiness.js +114 -0
- package/dist/heart/daemon/inner-status.js +89 -0
- package/dist/heart/daemon/interactive-repair.js +394 -0
- package/dist/heart/daemon/launchd.js +25 -5
- package/dist/heart/daemon/log-tailer.js +82 -12
- package/dist/heart/daemon/logs-prune.js +110 -0
- package/dist/heart/daemon/message-router.js +2 -2
- 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 +214 -0
- package/dist/heart/daemon/provider-discovery.js +137 -0
- package/dist/heart/daemon/provider-ping-progress.js +83 -0
- package/dist/heart/daemon/pulse.js +475 -0
- package/dist/heart/daemon/readiness-repair.js +365 -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 +178 -37
- 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 +264 -0
- package/dist/heart/daemon/task-scheduler.js +3 -25
- package/dist/heart/daemon/terminal-ui.js +499 -0
- package/dist/heart/daemon/thoughts.js +298 -13
- package/dist/heart/daemon/up-progress.js +366 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/habits/habit-migration.js +189 -0
- package/dist/heart/habits/habit-parser.js +140 -0
- package/dist/heart/habits/habit-runtime-state.js +100 -0
- package/dist/heart/habits/habit-scheduler.js +372 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -117
- 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 +35 -12
- package/dist/heart/identity.js +201 -66
- package/dist/heart/kept-notes.js +357 -0
- package/dist/heart/kicks.js +1 -1
- 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 +66 -0
- package/dist/heart/outlook/outlook-http-response.js +7 -0
- package/dist/heart/outlook/outlook-http-routes.js +244 -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 +31 -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/mail.js +273 -0
- package/dist/heart/outlook/readers/runtime-readers.js +644 -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 +134 -0
- package/dist/heart/provider-binding-resolver.js +255 -0
- package/dist/heart/provider-credentials.js +424 -0
- package/dist/heart/provider-failover.js +266 -0
- package/dist/heart/provider-models.js +81 -0
- package/dist/heart/provider-ping.js +262 -0
- package/dist/heart/provider-state.js +216 -0
- package/dist/heart/provider-visibility.js +188 -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 +62 -38
- package/dist/heart/runtime-capability-check.js +170 -0
- package/dist/heart/runtime-credentials.js +260 -0
- package/dist/heart/sense-truth.js +11 -4
- 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 +361 -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 +425 -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 +5 -1
- package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
- package/dist/mailroom/attention.js +154 -0
- package/dist/mailroom/blob-store.js +302 -0
- package/dist/mailroom/core.js +538 -0
- package/dist/mailroom/entry.js +160 -0
- package/dist/mailroom/file-store.js +392 -0
- package/dist/mailroom/mbox-import.js +105 -0
- package/dist/mailroom/outbound.js +177 -0
- package/dist/mailroom/policy.js +263 -0
- package/dist/mailroom/reader.js +166 -0
- package/dist/mailroom/smtp-ingress.js +176 -0
- package/dist/mailroom/travel-extract.js +89 -0
- package/dist/mind/bundle-manifest.js +7 -1
- package/dist/mind/context.js +132 -93
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +74 -93
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/friends/channel.js +30 -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 +2 -2
- 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 +976 -169
- package/dist/mind/provenance-trust.js +26 -0
- package/dist/mind/scrutiny.js +173 -0
- 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/contract.js +5 -5
- 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-BBM5EysT.js +61 -0
- package/dist/outlook-ui/assets/index-BPr5vNuM.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 +774 -0
- package/dist/repertoire/bundle-templates.js +72 -0
- package/dist/repertoire/bw-installer.js +180 -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 +111 -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 +396 -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 +37 -4
- 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 -78
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-attachments.js +317 -0
- package/dist/repertoire/tools-base.js +44 -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 +361 -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-mail.js +762 -0
- 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 +9 -39
- 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 -113
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/user-profile.js +131 -0
- package/dist/repertoire/vault-setup.js +246 -0
- package/dist/repertoire/vault-unlock.js +561 -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} +219 -18
- package/dist/senses/bluebubbles/entry.js +73 -0
- package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +7 -3
- 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} +3 -3
- package/dist/senses/bluebubbles/replay.js +129 -0
- package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +2 -2
- 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 +516 -211
- package/dist/senses/commands.js +66 -3
- package/dist/senses/habit-turn-message.js +108 -0
- package/dist/senses/inner-dialog-worker.js +97 -17
- package/dist/senses/inner-dialog.js +534 -106
- package/dist/senses/mail-entry.js +66 -0
- package/dist/senses/mail.js +224 -0
- package/dist/senses/pipeline.js +533 -72
- 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 +413 -163
- package/dist/senses/trust-gate.js +5 -5
- package/package.json +37 -7
- package/skills/agent-commerce.md +106 -0
- package/skills/browser-navigation.md +117 -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 +138 -0
- package/dist/heart/daemon/ouro-path-installer.js +0 -178
- package/dist/heart/daemon/subagent-installer.js +0 -166
- package/dist/mind/associative-recall.js +0 -209
- package/dist/senses/bluebubbles-entry.js +0 -13
- package/dist/senses/bluebubbles.js +0 -1028
- package/dist/senses/debug-activity.js +0 -127
- package/subagents/README.md +0 -86
- package/subagents/work-doer.md +0 -237
- package/subagents/work-merger.md +0 -618
- package/subagents/work-planner.md +0 -390
- /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
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FileMailroomStore = void 0;
|
|
37
|
+
exports.ingestRawMailToStore = ingestRawMailToStore;
|
|
38
|
+
exports.decryptMessages = decryptMessages;
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
const runtime_1 = require("../nerves/runtime");
|
|
42
|
+
const core_1 = require("./core");
|
|
43
|
+
function ensureDir(dir) {
|
|
44
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
function readJson(filePath) {
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function writeJson(filePath, value) {
|
|
55
|
+
ensureDir(path.dirname(filePath));
|
|
56
|
+
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
|
|
57
|
+
}
|
|
58
|
+
function compareNewestFirst(left, right) {
|
|
59
|
+
return Date.parse(right.receivedAt) - Date.parse(left.receivedAt);
|
|
60
|
+
}
|
|
61
|
+
function compareCandidatesNewestFirst(left, right) {
|
|
62
|
+
return Date.parse(right.lastSeenAt) - Date.parse(left.lastSeenAt);
|
|
63
|
+
}
|
|
64
|
+
class FileMailroomStore {
|
|
65
|
+
rootDir;
|
|
66
|
+
constructor(options) {
|
|
67
|
+
this.rootDir = options.rootDir;
|
|
68
|
+
ensureDir(this.messagesDir);
|
|
69
|
+
ensureDir(this.rawDir);
|
|
70
|
+
ensureDir(this.logsDir);
|
|
71
|
+
ensureDir(this.candidatesDir);
|
|
72
|
+
ensureDir(this.decisionsDir);
|
|
73
|
+
ensureDir(this.outboundDir);
|
|
74
|
+
(0, runtime_1.emitNervesEvent)({
|
|
75
|
+
component: "senses",
|
|
76
|
+
event: "senses.mail_file_store_init",
|
|
77
|
+
message: "file mailroom store initialized",
|
|
78
|
+
meta: { rootDir: this.rootDir },
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
get messagesDir() {
|
|
82
|
+
return path.join(this.rootDir, "messages");
|
|
83
|
+
}
|
|
84
|
+
get rawDir() {
|
|
85
|
+
return path.join(this.rootDir, "raw");
|
|
86
|
+
}
|
|
87
|
+
get logsDir() {
|
|
88
|
+
return path.join(this.rootDir, "access-log");
|
|
89
|
+
}
|
|
90
|
+
get candidatesDir() {
|
|
91
|
+
return path.join(this.rootDir, "candidates");
|
|
92
|
+
}
|
|
93
|
+
get decisionsDir() {
|
|
94
|
+
return path.join(this.rootDir, "decisions");
|
|
95
|
+
}
|
|
96
|
+
get outboundDir() {
|
|
97
|
+
return path.join(this.rootDir, "outbound");
|
|
98
|
+
}
|
|
99
|
+
messagePath(id) {
|
|
100
|
+
return path.join(this.messagesDir, `${id}.json`);
|
|
101
|
+
}
|
|
102
|
+
candidatePath(id) {
|
|
103
|
+
return path.join(this.candidatesDir, `${id}.json`);
|
|
104
|
+
}
|
|
105
|
+
rawPath(objectName) {
|
|
106
|
+
return path.join(this.rootDir, objectName);
|
|
107
|
+
}
|
|
108
|
+
decisionLogPath(agentId) {
|
|
109
|
+
return path.join(this.decisionsDir, `${agentId}.jsonl`);
|
|
110
|
+
}
|
|
111
|
+
outboundPath(id) {
|
|
112
|
+
return path.join(this.outboundDir, `${id}.json`);
|
|
113
|
+
}
|
|
114
|
+
accessLogPath(agentId) {
|
|
115
|
+
return path.join(this.logsDir, `${agentId}.jsonl`);
|
|
116
|
+
}
|
|
117
|
+
async putRawMessage(input) {
|
|
118
|
+
const { message, rawPayload, candidate } = await (0, core_1.buildStoredMailMessage)(input);
|
|
119
|
+
const existing = readJson(this.messagePath(message.id));
|
|
120
|
+
if (existing) {
|
|
121
|
+
(0, runtime_1.emitNervesEvent)({
|
|
122
|
+
component: "senses",
|
|
123
|
+
event: "senses.mail_store_dedupe",
|
|
124
|
+
message: "mailroom store deduped existing message",
|
|
125
|
+
meta: { id: message.id, agentId: message.agentId },
|
|
126
|
+
});
|
|
127
|
+
return { created: false, message: existing };
|
|
128
|
+
}
|
|
129
|
+
writeJson(this.rawPath(message.rawObject), rawPayload);
|
|
130
|
+
writeJson(this.messagePath(message.id), message);
|
|
131
|
+
if (candidate) {
|
|
132
|
+
writeJson(this.candidatePath(candidate.id), candidate);
|
|
133
|
+
}
|
|
134
|
+
(0, runtime_1.emitNervesEvent)({
|
|
135
|
+
component: "senses",
|
|
136
|
+
event: "senses.mail_store_message_written",
|
|
137
|
+
message: "mailroom store wrote message",
|
|
138
|
+
meta: { id: message.id, agentId: message.agentId, candidate: candidate !== undefined },
|
|
139
|
+
});
|
|
140
|
+
return { created: true, message };
|
|
141
|
+
}
|
|
142
|
+
async getMessage(id) {
|
|
143
|
+
const message = readJson(this.messagePath(id));
|
|
144
|
+
(0, runtime_1.emitNervesEvent)({
|
|
145
|
+
component: "senses",
|
|
146
|
+
event: "senses.mail_store_message_read",
|
|
147
|
+
message: "mailroom store read message",
|
|
148
|
+
meta: { id, found: message !== null },
|
|
149
|
+
});
|
|
150
|
+
return message;
|
|
151
|
+
}
|
|
152
|
+
async listMessages(filters) {
|
|
153
|
+
const messages = fs.readdirSync(this.messagesDir)
|
|
154
|
+
.filter((name) => name.endsWith(".json"))
|
|
155
|
+
.map((name) => readJson(path.join(this.messagesDir, name)))
|
|
156
|
+
.filter((message) => message !== null)
|
|
157
|
+
.filter((message) => message.agentId === filters.agentId)
|
|
158
|
+
.filter((message) => filters.placement ? message.placement === filters.placement : true)
|
|
159
|
+
.filter((message) => filters.compartmentKind ? message.compartmentKind === filters.compartmentKind : true)
|
|
160
|
+
.filter((message) => filters.source ? message.source === filters.source : true)
|
|
161
|
+
.sort(compareNewestFirst)
|
|
162
|
+
.slice(0, filters.limit ?? 20);
|
|
163
|
+
(0, runtime_1.emitNervesEvent)({
|
|
164
|
+
component: "senses",
|
|
165
|
+
event: "senses.mail_store_messages_listed",
|
|
166
|
+
message: "mailroom store listed messages",
|
|
167
|
+
meta: { agentId: filters.agentId, count: messages.length },
|
|
168
|
+
});
|
|
169
|
+
return messages;
|
|
170
|
+
}
|
|
171
|
+
async updateMessagePlacement(id, placement) {
|
|
172
|
+
const message = readJson(this.messagePath(id));
|
|
173
|
+
if (!message) {
|
|
174
|
+
(0, runtime_1.emitNervesEvent)({
|
|
175
|
+
component: "senses",
|
|
176
|
+
event: "senses.mail_store_message_placement_updated",
|
|
177
|
+
message: "mailroom store message placement update missed",
|
|
178
|
+
meta: { id, placement, found: false },
|
|
179
|
+
});
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
const updated = { ...message, placement };
|
|
183
|
+
writeJson(this.messagePath(id), updated);
|
|
184
|
+
(0, runtime_1.emitNervesEvent)({
|
|
185
|
+
component: "senses",
|
|
186
|
+
event: "senses.mail_store_message_placement_updated",
|
|
187
|
+
message: "mailroom store updated message placement",
|
|
188
|
+
meta: { id, placement, found: true },
|
|
189
|
+
});
|
|
190
|
+
return updated;
|
|
191
|
+
}
|
|
192
|
+
async readRawPayload(objectName) {
|
|
193
|
+
const payload = readJson(this.rawPath(objectName));
|
|
194
|
+
(0, runtime_1.emitNervesEvent)({
|
|
195
|
+
component: "senses",
|
|
196
|
+
event: "senses.mail_store_raw_read",
|
|
197
|
+
message: "mailroom store read raw payload",
|
|
198
|
+
meta: { objectName, found: payload !== null },
|
|
199
|
+
});
|
|
200
|
+
return payload;
|
|
201
|
+
}
|
|
202
|
+
async putScreenerCandidate(candidate) {
|
|
203
|
+
writeJson(this.candidatePath(candidate.id), candidate);
|
|
204
|
+
(0, runtime_1.emitNervesEvent)({
|
|
205
|
+
component: "senses",
|
|
206
|
+
event: "senses.mail_screener_candidate_written",
|
|
207
|
+
message: "mail screener candidate written",
|
|
208
|
+
meta: { id: candidate.id, agentId: candidate.agentId, status: candidate.status },
|
|
209
|
+
});
|
|
210
|
+
return candidate;
|
|
211
|
+
}
|
|
212
|
+
async updateScreenerCandidate(candidate) {
|
|
213
|
+
return this.putScreenerCandidate(candidate);
|
|
214
|
+
}
|
|
215
|
+
async listScreenerCandidates(filters) {
|
|
216
|
+
const candidates = fs.readdirSync(this.candidatesDir)
|
|
217
|
+
.filter((name) => name.endsWith(".json"))
|
|
218
|
+
.map((name) => readJson(path.join(this.candidatesDir, name)))
|
|
219
|
+
.filter((candidate) => candidate !== null)
|
|
220
|
+
.filter((candidate) => candidate.agentId === filters.agentId)
|
|
221
|
+
.filter((candidate) => filters.status ? candidate.status === filters.status : true)
|
|
222
|
+
.filter((candidate) => filters.placement ? candidate.placement === filters.placement : true)
|
|
223
|
+
.sort(compareCandidatesNewestFirst)
|
|
224
|
+
.slice(0, filters.limit ?? 50);
|
|
225
|
+
(0, runtime_1.emitNervesEvent)({
|
|
226
|
+
component: "senses",
|
|
227
|
+
event: "senses.mail_screener_candidates_listed",
|
|
228
|
+
message: "mail screener candidates listed",
|
|
229
|
+
meta: { agentId: filters.agentId, count: candidates.length },
|
|
230
|
+
});
|
|
231
|
+
return candidates;
|
|
232
|
+
}
|
|
233
|
+
async recordMailDecision(entry) {
|
|
234
|
+
const complete = {
|
|
235
|
+
schemaVersion: 1,
|
|
236
|
+
...entry,
|
|
237
|
+
id: entry.id ?? `decision_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
|
238
|
+
createdAt: entry.createdAt ?? new Date().toISOString(),
|
|
239
|
+
};
|
|
240
|
+
ensureDir(this.decisionsDir);
|
|
241
|
+
fs.appendFileSync(this.decisionLogPath(entry.agentId), `${JSON.stringify(complete)}\n`, "utf-8");
|
|
242
|
+
(0, runtime_1.emitNervesEvent)({
|
|
243
|
+
component: "senses",
|
|
244
|
+
event: "senses.mail_decision_recorded",
|
|
245
|
+
message: "mail decision recorded",
|
|
246
|
+
meta: { agentId: entry.agentId, messageId: entry.messageId, action: entry.action },
|
|
247
|
+
});
|
|
248
|
+
return complete;
|
|
249
|
+
}
|
|
250
|
+
async listMailDecisions(agentId) {
|
|
251
|
+
const filePath = this.decisionLogPath(agentId);
|
|
252
|
+
if (!fs.existsSync(filePath)) {
|
|
253
|
+
(0, runtime_1.emitNervesEvent)({
|
|
254
|
+
component: "senses",
|
|
255
|
+
event: "senses.mail_decisions_listed",
|
|
256
|
+
message: "mail decisions listed",
|
|
257
|
+
meta: { agentId, count: 0 },
|
|
258
|
+
});
|
|
259
|
+
return [];
|
|
260
|
+
}
|
|
261
|
+
const entries = fs.readFileSync(filePath, "utf-8")
|
|
262
|
+
.split(/\r?\n/)
|
|
263
|
+
.filter(Boolean)
|
|
264
|
+
.map((line) => JSON.parse(line));
|
|
265
|
+
(0, runtime_1.emitNervesEvent)({
|
|
266
|
+
component: "senses",
|
|
267
|
+
event: "senses.mail_decisions_listed",
|
|
268
|
+
message: "mail decisions listed",
|
|
269
|
+
meta: { agentId, count: entries.length },
|
|
270
|
+
});
|
|
271
|
+
return entries;
|
|
272
|
+
}
|
|
273
|
+
async upsertMailOutbound(record) {
|
|
274
|
+
writeJson(this.outboundPath(record.id), record);
|
|
275
|
+
(0, runtime_1.emitNervesEvent)({
|
|
276
|
+
component: "senses",
|
|
277
|
+
event: "senses.mail_outbound_record_written",
|
|
278
|
+
message: "mail outbound record written",
|
|
279
|
+
meta: { agentId: record.agentId, id: record.id, status: record.status },
|
|
280
|
+
});
|
|
281
|
+
return record;
|
|
282
|
+
}
|
|
283
|
+
async getMailOutbound(id) {
|
|
284
|
+
const record = readJson(this.outboundPath(id));
|
|
285
|
+
(0, runtime_1.emitNervesEvent)({
|
|
286
|
+
component: "senses",
|
|
287
|
+
event: "senses.mail_outbound_record_read",
|
|
288
|
+
message: "mail outbound record read",
|
|
289
|
+
meta: { id, found: record !== null },
|
|
290
|
+
});
|
|
291
|
+
return record;
|
|
292
|
+
}
|
|
293
|
+
async listMailOutbound(agentId) {
|
|
294
|
+
const records = fs.readdirSync(this.outboundDir)
|
|
295
|
+
.filter((name) => name.endsWith(".json"))
|
|
296
|
+
.map((name) => readJson(path.join(this.outboundDir, name)))
|
|
297
|
+
.filter((record) => record !== null)
|
|
298
|
+
.filter((record) => record.agentId === agentId)
|
|
299
|
+
.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
300
|
+
(0, runtime_1.emitNervesEvent)({
|
|
301
|
+
component: "senses",
|
|
302
|
+
event: "senses.mail_outbound_records_listed",
|
|
303
|
+
message: "mail outbound records listed",
|
|
304
|
+
meta: { agentId, count: records.length },
|
|
305
|
+
});
|
|
306
|
+
return records;
|
|
307
|
+
}
|
|
308
|
+
async recordAccess(entry) {
|
|
309
|
+
const complete = {
|
|
310
|
+
...entry,
|
|
311
|
+
id: `access_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
|
312
|
+
accessedAt: new Date().toISOString(),
|
|
313
|
+
};
|
|
314
|
+
ensureDir(this.logsDir);
|
|
315
|
+
fs.appendFileSync(this.accessLogPath(entry.agentId), `${JSON.stringify(complete)}\n`, "utf-8");
|
|
316
|
+
(0, runtime_1.emitNervesEvent)({
|
|
317
|
+
component: "senses",
|
|
318
|
+
event: "senses.mail_access_recorded",
|
|
319
|
+
message: "mail access recorded",
|
|
320
|
+
meta: { agentId: entry.agentId, messageId: entry.messageId ?? null, tool: entry.tool },
|
|
321
|
+
});
|
|
322
|
+
return complete;
|
|
323
|
+
}
|
|
324
|
+
async listAccessLog(agentId) {
|
|
325
|
+
const filePath = this.accessLogPath(agentId);
|
|
326
|
+
if (!fs.existsSync(filePath)) {
|
|
327
|
+
(0, runtime_1.emitNervesEvent)({
|
|
328
|
+
component: "senses",
|
|
329
|
+
event: "senses.mail_access_log_listed",
|
|
330
|
+
message: "mail access log listed",
|
|
331
|
+
meta: { agentId, count: 0 },
|
|
332
|
+
});
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
335
|
+
const entries = fs.readFileSync(filePath, "utf-8")
|
|
336
|
+
.split(/\r?\n/)
|
|
337
|
+
.filter(Boolean)
|
|
338
|
+
.map((line) => JSON.parse(line));
|
|
339
|
+
(0, runtime_1.emitNervesEvent)({
|
|
340
|
+
component: "senses",
|
|
341
|
+
event: "senses.mail_access_log_listed",
|
|
342
|
+
message: "mail access log listed",
|
|
343
|
+
meta: { agentId, count: entries.length },
|
|
344
|
+
});
|
|
345
|
+
return entries;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
exports.FileMailroomStore = FileMailroomStore;
|
|
349
|
+
async function ingestRawMailToStore(input) {
|
|
350
|
+
const { resolveMailAddress } = await Promise.resolve().then(() => __importStar(require("./core")));
|
|
351
|
+
const { classifyResolvedMailPlacement } = await Promise.resolve().then(() => __importStar(require("./policy")));
|
|
352
|
+
const accepted = [];
|
|
353
|
+
const rejectedRecipients = [];
|
|
354
|
+
for (const recipient of input.envelope.rcptTo) {
|
|
355
|
+
const resolved = resolveMailAddress(input.registry, recipient);
|
|
356
|
+
if (!resolved) {
|
|
357
|
+
rejectedRecipients.push(recipient);
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
const classification = classifyResolvedMailPlacement({
|
|
361
|
+
registry: input.registry,
|
|
362
|
+
resolved,
|
|
363
|
+
sender: input.envelope.mailFrom,
|
|
364
|
+
...(input.authentication ? { authentication: input.authentication } : {}),
|
|
365
|
+
});
|
|
366
|
+
const result = await input.store.putRawMessage({
|
|
367
|
+
resolved,
|
|
368
|
+
envelope: input.envelope,
|
|
369
|
+
rawMime: input.rawMime,
|
|
370
|
+
receivedAt: input.receivedAt,
|
|
371
|
+
classification,
|
|
372
|
+
});
|
|
373
|
+
accepted.push(result.message);
|
|
374
|
+
}
|
|
375
|
+
(0, runtime_1.emitNervesEvent)({
|
|
376
|
+
component: "senses",
|
|
377
|
+
event: "senses.mail_ingest_complete",
|
|
378
|
+
message: "mail ingest completed",
|
|
379
|
+
meta: { accepted: accepted.length, rejected: rejectedRecipients.length },
|
|
380
|
+
});
|
|
381
|
+
return { accepted, rejectedRecipients };
|
|
382
|
+
}
|
|
383
|
+
function decryptMessages(messages, privateKeys) {
|
|
384
|
+
const decrypted = messages.map((message) => (0, core_1.decryptStoredMailMessage)(message, privateKeys));
|
|
385
|
+
(0, runtime_1.emitNervesEvent)({
|
|
386
|
+
component: "senses",
|
|
387
|
+
event: "senses.mail_messages_decrypted",
|
|
388
|
+
message: "mail messages decrypted",
|
|
389
|
+
meta: { count: decrypted.length },
|
|
390
|
+
});
|
|
391
|
+
return decrypted;
|
|
392
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.splitMboxMessages = splitMboxMessages;
|
|
4
|
+
exports.importMboxToStore = importMboxToStore;
|
|
5
|
+
const mailparser_1 = require("mailparser");
|
|
6
|
+
const runtime_1 = require("../nerves/runtime");
|
|
7
|
+
const core_1 = require("./core");
|
|
8
|
+
function splitMboxMessages(rawMbox) {
|
|
9
|
+
const text = rawMbox.toString("utf-8");
|
|
10
|
+
const separators = [...text.matchAll(/^From [^\r\n]*(?:\r?\n)/gm)];
|
|
11
|
+
if (separators.length === 0) {
|
|
12
|
+
const trimmed = text.trim();
|
|
13
|
+
return trimmed ? [Buffer.from(text, "utf-8")] : [];
|
|
14
|
+
}
|
|
15
|
+
const messages = separators
|
|
16
|
+
.map((match, index) => {
|
|
17
|
+
const start = match.index + match[0].length;
|
|
18
|
+
const end = index + 1 < separators.length ? separators[index + 1].index : text.length;
|
|
19
|
+
return text.slice(start, end).replace(/\r?\n$/, "");
|
|
20
|
+
})
|
|
21
|
+
.filter((message) => message.trim().length > 0)
|
|
22
|
+
.map((message) => Buffer.from(message, "utf-8"));
|
|
23
|
+
(0, runtime_1.emitNervesEvent)({
|
|
24
|
+
component: "senses",
|
|
25
|
+
event: "senses.mail_mbox_split",
|
|
26
|
+
message: "mbox payload split into messages",
|
|
27
|
+
meta: { messages: messages.length },
|
|
28
|
+
});
|
|
29
|
+
return messages;
|
|
30
|
+
}
|
|
31
|
+
function findSourceGrant(input) {
|
|
32
|
+
const ownerEmail = input.ownerEmail ? (0, core_1.normalizeMailAddress)(input.ownerEmail) : undefined;
|
|
33
|
+
const source = input.source?.trim().toLowerCase();
|
|
34
|
+
const grants = input.registry.sourceGrants.filter((grant) => {
|
|
35
|
+
if (!grant.enabled || grant.agentId !== input.agentId)
|
|
36
|
+
return false;
|
|
37
|
+
if (ownerEmail && (0, core_1.normalizeMailAddress)(grant.ownerEmail) !== ownerEmail)
|
|
38
|
+
return false;
|
|
39
|
+
if (source && grant.source.toLowerCase() !== source)
|
|
40
|
+
return false;
|
|
41
|
+
return true;
|
|
42
|
+
});
|
|
43
|
+
if (grants.length === 0) {
|
|
44
|
+
throw new Error(`No enabled Mailroom source grant found for ${input.agentId}${ownerEmail ? ` owner ${ownerEmail}` : ""}${source ? ` source ${source}` : ""}`);
|
|
45
|
+
}
|
|
46
|
+
if (grants.length > 1 && !ownerEmail && !source) {
|
|
47
|
+
throw new Error(`Multiple source grants found for ${input.agentId}; pass --owner-email or --source to choose one`);
|
|
48
|
+
}
|
|
49
|
+
return grants[0];
|
|
50
|
+
}
|
|
51
|
+
async function envelopeForMboxMessage(rawMessage, grant) {
|
|
52
|
+
const parsed = await (0, mailparser_1.simpleParser)(rawMessage);
|
|
53
|
+
const mailFrom = parsed.from?.value?.[0]?.address;
|
|
54
|
+
return {
|
|
55
|
+
mailFrom: mailFrom ? (0, core_1.normalizeMailAddress)(mailFrom) : "",
|
|
56
|
+
rcptTo: [(0, core_1.normalizeMailAddress)(grant.aliasAddress)],
|
|
57
|
+
remoteAddress: "mbox-import",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
async function importMboxToStore(input) {
|
|
61
|
+
const agentId = input.agentId.toLowerCase();
|
|
62
|
+
const sourceGrant = findSourceGrant({
|
|
63
|
+
registry: input.registry,
|
|
64
|
+
agentId,
|
|
65
|
+
ownerEmail: input.ownerEmail,
|
|
66
|
+
source: input.source,
|
|
67
|
+
});
|
|
68
|
+
const resolved = (0, core_1.resolveMailAddress)(input.registry, sourceGrant.aliasAddress);
|
|
69
|
+
/* v8 ignore start -- findSourceGrant and resolveMailAddress share the same registry; this is a corruption guard. @preserve */
|
|
70
|
+
if (!resolved) {
|
|
71
|
+
throw new Error(`Source grant alias ${sourceGrant.aliasAddress} is not resolvable`);
|
|
72
|
+
}
|
|
73
|
+
/* v8 ignore stop */
|
|
74
|
+
let imported = 0;
|
|
75
|
+
let duplicates = 0;
|
|
76
|
+
const messages = [];
|
|
77
|
+
const rawMessages = splitMboxMessages(input.rawMbox);
|
|
78
|
+
for (const rawMessage of rawMessages) {
|
|
79
|
+
const result = await input.store.putRawMessage({
|
|
80
|
+
resolved,
|
|
81
|
+
envelope: await envelopeForMboxMessage(rawMessage, sourceGrant),
|
|
82
|
+
rawMime: rawMessage,
|
|
83
|
+
receivedAt: input.importedAt,
|
|
84
|
+
});
|
|
85
|
+
messages.push(result.message);
|
|
86
|
+
if (result.created)
|
|
87
|
+
imported += 1;
|
|
88
|
+
else
|
|
89
|
+
duplicates += 1;
|
|
90
|
+
}
|
|
91
|
+
(0, runtime_1.emitNervesEvent)({
|
|
92
|
+
component: "senses",
|
|
93
|
+
event: "senses.mail_mbox_imported",
|
|
94
|
+
message: "mbox mail imported",
|
|
95
|
+
meta: { agentId, scanned: rawMessages.length, imported, duplicates, grantId: sourceGrant.grantId },
|
|
96
|
+
});
|
|
97
|
+
return {
|
|
98
|
+
agentId,
|
|
99
|
+
sourceGrant,
|
|
100
|
+
scanned: rawMessages.length,
|
|
101
|
+
imported,
|
|
102
|
+
duplicates,
|
|
103
|
+
messages,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveOutboundTransport = resolveOutboundTransport;
|
|
37
|
+
exports.createMailDraft = createMailDraft;
|
|
38
|
+
exports.confirmMailDraftSend = confirmMailDraftSend;
|
|
39
|
+
exports.listMailOutboundRecords = listMailOutboundRecords;
|
|
40
|
+
const crypto = __importStar(require("node:crypto"));
|
|
41
|
+
const fs = __importStar(require("node:fs"));
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const runtime_1 = require("../nerves/runtime");
|
|
44
|
+
const core_1 = require("./core");
|
|
45
|
+
function isRecord(value) {
|
|
46
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
47
|
+
}
|
|
48
|
+
function textField(value, key) {
|
|
49
|
+
const raw = value[key];
|
|
50
|
+
return typeof raw === "string" ? raw.trim() : "";
|
|
51
|
+
}
|
|
52
|
+
function normalizeList(values) {
|
|
53
|
+
return values
|
|
54
|
+
.map((value) => value.trim())
|
|
55
|
+
.filter(Boolean)
|
|
56
|
+
.map(core_1.normalizeMailAddress);
|
|
57
|
+
}
|
|
58
|
+
function draftId() {
|
|
59
|
+
return `draft_${crypto.randomBytes(12).toString("hex")}`;
|
|
60
|
+
}
|
|
61
|
+
function ensureRecipients(to) {
|
|
62
|
+
if (to.length === 0)
|
|
63
|
+
throw new Error("at least one recipient is required");
|
|
64
|
+
}
|
|
65
|
+
function resolveOutboundTransport(config) {
|
|
66
|
+
const outbound = isRecord(config) && isRecord(config.outbound) ? config.outbound : null;
|
|
67
|
+
if (!outbound) {
|
|
68
|
+
throw new Error("outbound mail transport is not configured; human-required: set mailroom.outbound before confirmed sends");
|
|
69
|
+
}
|
|
70
|
+
const transport = textField(outbound, "transport");
|
|
71
|
+
if (transport === "local-sink") {
|
|
72
|
+
const sinkPath = textField(outbound, "sinkPath");
|
|
73
|
+
if (!sinkPath)
|
|
74
|
+
throw new Error("outbound local-sink transport is missing sinkPath");
|
|
75
|
+
return { kind: "local-sink", sinkPath };
|
|
76
|
+
}
|
|
77
|
+
if (transport === "azure-communication-services") {
|
|
78
|
+
const endpoint = textField(outbound, "endpoint");
|
|
79
|
+
if (!endpoint)
|
|
80
|
+
throw new Error("outbound Azure Communication Services transport is missing endpoint");
|
|
81
|
+
const senderAddress = textField(outbound, "senderAddress");
|
|
82
|
+
return {
|
|
83
|
+
kind: "azure-communication-services",
|
|
84
|
+
endpoint,
|
|
85
|
+
...(senderAddress ? { senderAddress } : {}),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
throw new Error("outbound mail transport is not configured; human-required: choose local-sink or azure-communication-services");
|
|
89
|
+
}
|
|
90
|
+
async function createMailDraft(input) {
|
|
91
|
+
const now = (input.now ?? (() => new Date()))().toISOString();
|
|
92
|
+
const to = normalizeList(input.to);
|
|
93
|
+
ensureRecipients(to);
|
|
94
|
+
const record = {
|
|
95
|
+
schemaVersion: 1,
|
|
96
|
+
id: draftId(),
|
|
97
|
+
agentId: input.agentId,
|
|
98
|
+
status: "draft",
|
|
99
|
+
from: (0, core_1.normalizeMailAddress)(input.from),
|
|
100
|
+
to,
|
|
101
|
+
cc: normalizeList(input.cc ?? []),
|
|
102
|
+
bcc: normalizeList(input.bcc ?? []),
|
|
103
|
+
subject: input.subject.trim(),
|
|
104
|
+
text: input.text,
|
|
105
|
+
actor: input.actor,
|
|
106
|
+
reason: input.reason,
|
|
107
|
+
createdAt: now,
|
|
108
|
+
updatedAt: now,
|
|
109
|
+
};
|
|
110
|
+
await input.store.upsertMailOutbound(record);
|
|
111
|
+
(0, runtime_1.emitNervesEvent)({
|
|
112
|
+
component: "senses",
|
|
113
|
+
event: "senses.mail_draft_created",
|
|
114
|
+
message: "mail draft created",
|
|
115
|
+
meta: { agentId: record.agentId, id: record.id, toCount: record.to.length },
|
|
116
|
+
});
|
|
117
|
+
return record;
|
|
118
|
+
}
|
|
119
|
+
function appendLocalSink(transport, record, sentAt) {
|
|
120
|
+
fs.mkdirSync(path.dirname(transport.sinkPath), { recursive: true });
|
|
121
|
+
const transportMessageId = `local_${crypto.randomBytes(10).toString("hex")}`;
|
|
122
|
+
fs.appendFileSync(transport.sinkPath, `${JSON.stringify({
|
|
123
|
+
schemaVersion: 1,
|
|
124
|
+
transportMessageId,
|
|
125
|
+
draftId: record.id,
|
|
126
|
+
agentId: record.agentId,
|
|
127
|
+
from: record.from,
|
|
128
|
+
to: record.to,
|
|
129
|
+
cc: record.cc,
|
|
130
|
+
bcc: record.bcc,
|
|
131
|
+
subject: record.subject,
|
|
132
|
+
text: record.text,
|
|
133
|
+
sentAt,
|
|
134
|
+
})}\n`, "utf-8");
|
|
135
|
+
return transportMessageId;
|
|
136
|
+
}
|
|
137
|
+
function transportSend(transport, record, sentAt) {
|
|
138
|
+
if (transport.kind === "local-sink")
|
|
139
|
+
return appendLocalSink(transport, record, sentAt);
|
|
140
|
+
throw new Error("Azure Communication Services outbound send is configured but not enabled on this machine; human-required setup is still needed");
|
|
141
|
+
}
|
|
142
|
+
async function confirmMailDraftSend(input) {
|
|
143
|
+
if (input.autonomous) {
|
|
144
|
+
throw new Error("Autonomous mail sending is disabled; create a draft and require explicit confirmation instead");
|
|
145
|
+
}
|
|
146
|
+
if (input.confirmation !== "CONFIRM_SEND") {
|
|
147
|
+
throw new Error("mail_send requires confirmation=CONFIRM_SEND before any outbound mail leaves the agent");
|
|
148
|
+
}
|
|
149
|
+
const draft = await input.store.getMailOutbound(input.draftId);
|
|
150
|
+
if (!draft || draft.agentId !== input.agentId)
|
|
151
|
+
throw new Error(`No draft found for ${input.draftId}`);
|
|
152
|
+
if (draft.status !== "draft")
|
|
153
|
+
throw new Error(`Draft ${input.draftId} is already ${draft.status}`);
|
|
154
|
+
const sentAt = (input.now ?? (() => new Date()))().toISOString();
|
|
155
|
+
const transportMessageId = transportSend(input.transport, draft, sentAt);
|
|
156
|
+
const sent = {
|
|
157
|
+
...draft,
|
|
158
|
+
status: "sent",
|
|
159
|
+
actor: input.actor,
|
|
160
|
+
reason: input.reason,
|
|
161
|
+
updatedAt: sentAt,
|
|
162
|
+
sentAt,
|
|
163
|
+
transport: input.transport.kind,
|
|
164
|
+
transportMessageId,
|
|
165
|
+
};
|
|
166
|
+
await input.store.upsertMailOutbound(sent);
|
|
167
|
+
(0, runtime_1.emitNervesEvent)({
|
|
168
|
+
component: "senses",
|
|
169
|
+
event: "senses.mail_draft_sent",
|
|
170
|
+
message: "mail draft sent",
|
|
171
|
+
meta: { agentId: sent.agentId, id: sent.id, transport: sent.transport },
|
|
172
|
+
});
|
|
173
|
+
return sent;
|
|
174
|
+
}
|
|
175
|
+
function listMailOutboundRecords(store, agentId) {
|
|
176
|
+
return store.listMailOutbound(agentId);
|
|
177
|
+
}
|