@rubytech/create-maxy-code 0.1.158 → 0.1.161
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/package.json +1 -1
- package/payload/platform/lib/admin-conversation-purge/dist/index.d.ts +1 -1
- package/payload/platform/lib/admin-conversation-purge/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/admin-conversation-purge/dist/index.js +4 -4
- package/payload/platform/lib/admin-conversation-purge/dist/index.js.map +1 -1
- package/payload/platform/lib/admin-conversation-purge/src/index.ts +5 -5
- package/payload/platform/lib/graph-search/src/__tests__/fulltext-coverage.test.ts +48 -17
- package/payload/platform/lib/graph-style/dist/index.js +2 -2
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +1 -1
- package/payload/platform/lib/graph-style/src/index.ts +2 -2
- package/payload/platform/lib/graph-trash/dist/index.js +1 -1
- package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-trash/src/index.ts +1 -1
- package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js +1 -1
- package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js.map +1 -1
- package/payload/platform/lib/graph-write/dist/conversation-provenance.d.ts +3 -3
- package/payload/platform/lib/graph-write/dist/conversation-provenance.js +5 -5
- package/payload/platform/lib/graph-write/dist/conversation-provenance.js.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +1 -1
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/__tests__/action-provenance-gate.test.ts +1 -1
- package/payload/platform/lib/graph-write/src/conversation-provenance.ts +8 -8
- package/payload/platform/lib/graph-write/src/index.ts +1 -1
- package/payload/platform/neo4j/schema.cypher +86 -46
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +8 -4
- package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +1 -1
- package/payload/platform/plugins/admin/hooks/__tests__/per-turn-graph-pass-gate.test.sh +361 -0
- package/payload/platform/plugins/admin/hooks/__tests__/pre-turn-graph-pass.test.sh +13 -13
- package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +1 -1
- package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +2 -2
- package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +102 -0
- package/payload/platform/plugins/admin/hooks/per-turn-graph-pass-gate.sh +106 -0
- package/payload/platform/plugins/admin/hooks/pre-turn-graph-pass.sh +15 -8
- package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +4 -4
- package/payload/platform/plugins/admin/mcp/dist/index.js +65 -24
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/business-profile/SKILL.md +1 -1
- package/payload/platform/plugins/admin/skills/session-management/SKILL.md +2 -2
- package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +5 -5
- package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md +6 -6
- package/payload/platform/plugins/business-assistant/references/profiling.md +1 -1
- package/payload/platform/plugins/contacts/PLUGIN.md +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +2 -2
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +3 -3
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js +2 -2
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js +4 -4
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js +10 -10
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js.map +1 -1
- package/payload/platform/plugins/docs/references/admin-session.md +6 -6
- package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
- package/payload/platform/plugins/docs/references/internals.md +5 -5
- package/payload/platform/plugins/docs/references/plugins-guide.md +6 -5
- package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
- package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/email/PLUGIN.md +19 -2
- package/payload/platform/plugins/email/mcp/dist/index.js +78 -0
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.d.ts +8 -0
- package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.js +177 -0
- package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/embedding.js +2 -2
- package/payload/platform/plugins/email/mcp/dist/lib/embedding.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts +6 -54
- package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/graph.js +12 -300
- package/payload/platform/plugins/email/mcp/dist/lib/graph.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts +23 -0
- package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js +15 -0
- package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-classify.d.ts +6 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-classify.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-classify.js +89 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-classify.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts +15 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js +49 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts +20 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js +91 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +32 -52
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
- package/payload/platform/plugins/email/references/email-reference.md +19 -83
- package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +87 -0
- package/payload/platform/plugins/linkedin-import/skills/linkedin-import/SKILL.md +10 -37
- package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/connections.md +1 -0
- package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +11 -2
- package/payload/platform/plugins/memory/bin/conversation-archive-ingest.mjs +139 -439
- package/payload/platform/plugins/memory/bin/conversation-archive-ingest.sh +15 -47
- package/payload/platform/plugins/memory/mcp/dist/index.js +197 -58
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js +43 -27
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.js +62 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js +5 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts +42 -25
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.js +23 -17
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.d.ts +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.js +61 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js +9 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +3 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +6 -6
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.d.ts +41 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.js +71 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.d.ts +18 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.js +31 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.d.ts +5 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js +162 -78
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js +3 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.js +6 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.js +141 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js +8 -8
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.js +86 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts +33 -34
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +94 -273
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.d.ts +43 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.js +96 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.d.ts +6 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.js +73 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js +4 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts +6 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +8 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +40 -5
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts +8 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js +25 -9
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +11 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.d.ts +28 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.js +46 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +26 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +11 -11
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/scripts/backfill-typed-edges.ts +1 -1
- package/payload/platform/plugins/memory/mcp/scripts/graph/fixture.cypher +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +5 -4
- package/payload/platform/plugins/memory/references/graph-primitives.md +1 -1
- package/payload/platform/plugins/memory/references/schema-base.md +8 -10
- package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +100 -116
- package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +74 -24
- package/payload/platform/plugins/memory/skills/conversational-memory/SKILL.md +1 -1
- package/payload/platform/plugins/notion-import/skills/notion-import/SKILL.md +1 -1
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/SKILL.md +1 -1
- package/payload/platform/plugins/substack-import/.claude-plugin/plugin.json +8 -0
- package/payload/platform/plugins/substack-import/PLUGIN.md +34 -0
- package/payload/platform/plugins/substack-import/skills/substack-import/SKILL.md +182 -0
- package/payload/platform/plugins/substack-import/skills/substack-import/references/archive-shape.md +68 -0
- package/payload/platform/plugins/substack-import/skills/substack-import/references/attachments.md +72 -0
- package/payload/platform/plugins/substack-import/skills/substack-import/references/engagement.md +61 -0
- package/payload/platform/plugins/substack-import/skills/substack-import/references/posts.md +80 -0
- package/payload/platform/plugins/substack-import/skills/substack-import/references/subscribers.md +74 -0
- package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +2 -2
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/index.js +2 -2
- package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/project-create.js +6 -6
- package/payload/platform/plugins/work/mcp/dist/tools/project-create.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/session-list.js +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/session-list.js.map +1 -1
- package/payload/platform/plugins/x-import/references/archive-shape.md +2 -2
- package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +4 -4
- package/payload/platform/scripts/admin-persist-audit.ts +18 -18
- package/payload/platform/scripts/identity-forbidden-token-check.mjs +2 -0
- package/payload/platform/scripts/seed-neo4j.sh +1 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js +3 -3
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +3 -3
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +4 -4
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +2 -0
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/templates/specialists/agents/archive-ingest-operator.md +45 -0
- package/payload/platform/templates/specialists/agents/database-operator.md +5 -17
- package/payload/platform/templates/specialists/agents/librarian.md +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/{chunk-AXOL2PPG.js → chunk-3TRIXQSJ.js} +101 -101
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{admin-3fLFD5h_.js → admin-Dal5FWaD.js} +2 -2
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Breg9-99.js → architectureDiagram-Q4EWVU46-Do2zYONG.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DXf1_673.js → blockDiagram-DXYQGD6D-DpIX_bRu.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CSZ36W4-.js → c4Diagram-AHTNJAMY-Cz335ZSY.js} +1 -1
- package/payload/server/public/assets/channel-PC4_IjI1.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-DsrLk2eK.js → chunk-336JU56O-Dmknn3Wo.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-JpNfNf81.js → chunk-426QAEUC-ClfGjizN.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-DmClEAD0.js → chunk-4TB4RGXK-BPKctJ5c.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-BI9blW3N.js → chunk-5FUZZQ4R-BWDCO9zw.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-BbgttEFO.js → chunk-5PVQY5BW-BE34_Db0.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-BX_LCFOx.js → chunk-EDXVE4YY-BysA-_6v.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-Bb7EoD0w.js → chunk-ENJZ2VHE-BMVyMsqA.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-DH8uQk-s.js → chunk-ICPOFSXX-C5KRdLV4.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-FH5kgXsw.js → chunk-OYMX7WX6-DVZD-AVc.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-D_ljlkHr.js → chunk-U2HBQHQK-DYmQdx8x.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-BX3EmZvm.js → chunk-X2U36JSP-DrZenIl3.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-Vu7-E93h.js → chunk-YZCP3GAM-CDuGbvMq.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-CwjhNPX5.js → chunk-ZZ45TVLE-COztbiu5.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-B_pMa-SX.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BdBAgF20.js +1 -0
- package/payload/server/public/assets/clone-CkNt9L9r.js +1 -0
- package/payload/server/public/assets/{dagre-Ce6gsj0C.js → dagre-Cv9Ib2OM.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-BaMGpsoy.js → dagre-KV5264BT-CoEd61KZ.js} +1 -1
- package/payload/server/public/assets/{data-BHASh0_Y.js → data-DbSORCl4.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-CHEE9rjq.js → diagram-5BDNPKRD-WXNzw3uW.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-C98sZLW1.js → diagram-G4DWMVQ6-C6IuQ2VV.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-DNvMGsTZ.js → diagram-MMDJMWI5-CdJdir5A.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-Cdte4IBa.js → diagram-TYMM5635-DxWKQH5T.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-C9VZsWXK.js → erDiagram-SMLLAGMA-C9fvs33K.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-tuP5fzzR.js → flowDiagram-DWJPFMVM-BO7Yrbqv.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-SJgRPUwx.js → ganttDiagram-T4ZO3ILL-CQJyWBZq.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DU_cI_50.js → gitGraphDiagram-UUTBAWPF-DZfQHrYw.js} +1 -1
- package/payload/server/public/assets/{graph-labels-DXlmm1og.js → graph-labels-BBB5jsZk.js} +1 -1
- package/payload/server/public/assets/{graph-BhEI09tF.js → graph-ys_joP2o.js} +1 -1
- package/payload/server/public/assets/{graphlib-D_nAsvmx.js → graphlib-C40H-Q5E.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-Cj2Y19m6.js → infoDiagram-42DDH7IO-CakfV5f9.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DMc1xq1y.js → ishikawaDiagram-UXIWVN3A-CPuBPyfa.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-C4CRAQma.js → journeyDiagram-VCZTEJTY-zpZm2Mmo.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CTr4AldU.js → kanban-definition-6JOO6SKY-DfJduQCo.js} +1 -1
- package/payload/server/public/assets/{line-Btlm_IAl.js → line-BpYQqO5R.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-DXFdj_y1.js → mermaid-parser.core-C5Mwi14D.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-DFBhoCr5.js → mermaid.core-D8qBtvvT.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-r9gVQybo.js → mindmap-definition-QFDTVHPH-Bli9JhIN.js} +1 -1
- package/payload/server/public/assets/{page-CDWu1Aft.js → page--bl5Y7ZI.js} +2 -2
- package/payload/server/public/assets/page-CwmZ76U7.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-CHKZjSaH.js → pieDiagram-DEJITSTG-MsLXTSLg.js} +1 -1
- package/payload/server/public/assets/{public-DyGWgfaZ.js → public-DltgEfA9.js} +2 -2
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CSGR1HJr.js → quadrantDiagram-34T5L4WZ-De1sh2K0.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DZ6hX9D6.js → requirementDiagram-MS252O5E-D5Sfg1t_.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DbZBKh0m.js → sankeyDiagram-XADWPNL6-DHA3LIbv.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BHHpb8dt.js → sequenceDiagram-FGHM5R23-BE_QlG1B.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DQ1jiLB4.js → stateDiagram-FHFEXIEX-NIwp3F4u.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-pfk2F6st.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BlGiEU7p.js → timeline-definition-GMOUNBTQ-CPE9jyDF.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-DmEH-hsB.js → vennDiagram-DHZGUBPP-CKfoyYmH.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-C7KJJ40d.js → wardleyDiagram-NUSXRM2D-B9yJek-o.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-JDnusCaa.js → xychartDiagram-5P7HB3ND-DuCcSLqX.js} +1 -1
- package/payload/server/public/data.html +3 -3
- package/payload/server/public/graph.html +3 -3
- package/payload/server/public/index.html +4 -4
- package/payload/server/public/public.html +1 -1
- package/payload/server/server.js +133 -133
- package/payload/server/public/assets/channel-BmZnt3PP.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-kmMLFUpV.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BV7Ae8ct.js +0 -1
- package/payload/server/public/assets/clone-B5eqoN9I.js +0 -1
- package/payload/server/public/assets/page-cyvshX4Z.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CByT2RzF.js +0 -1
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
1
|
import { getSession } from "./neo4j.js";
|
|
3
|
-
import { computeEmbedding } from "./embedding.js";
|
|
4
2
|
import neo4j from "neo4j-driver";
|
|
5
3
|
/**
|
|
6
4
|
* Strip RFC 2822 angle brackets from a Message-ID or In-Reply-To header.
|
|
@@ -15,304 +13,18 @@ export function stripAngleBrackets(value) {
|
|
|
15
13
|
}
|
|
16
14
|
return trimmed;
|
|
17
15
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return
|
|
21
|
-
.update(`email:${accountId}:${rootMessageId}`)
|
|
22
|
-
.digest("hex");
|
|
16
|
+
export async function getMessageEnvelope(_messageId, _accountId) {
|
|
17
|
+
// Task 442 — sourcing per-message envelopes from IMAP, not the graph.
|
|
18
|
+
return null;
|
|
23
19
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
.digest("hex");
|
|
29
|
-
}
|
|
30
|
-
function normaliseAddress(addr) {
|
|
31
|
-
return addr.trim().toLowerCase();
|
|
32
|
-
}
|
|
33
|
-
function renderMessageBlock(data, messageId) {
|
|
34
|
-
const headers = [
|
|
35
|
-
`Message-ID: ${messageId}`,
|
|
36
|
-
`From: ${data.fromName ? `${data.fromName} <${data.fromAddress}>` : data.fromAddress}`,
|
|
37
|
-
`To: ${data.toAddresses.join(", ")}`,
|
|
38
|
-
data.ccAddresses.length > 0 ? `Cc: ${data.ccAddresses.join(", ")}` : null,
|
|
39
|
-
`Date: ${data.receivedAt}`,
|
|
40
|
-
`Subject: ${data.subject}`,
|
|
41
|
-
]
|
|
42
|
-
.filter((line) => line !== null)
|
|
43
|
-
.join("\n");
|
|
44
|
-
return `--- BEGIN MESSAGE ---\n${headers}\n\n${data.bodyPreview}\n--- END MESSAGE ---`;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Find the thread KD that already contains the given message-id in its
|
|
48
|
-
* messageIds array, scoped to one account. Returns null when no match
|
|
49
|
-
* (the message starts a new thread or is an out-of-order reply whose
|
|
50
|
-
* parent thread has not yet been ingested).
|
|
51
|
-
*/
|
|
52
|
-
async function findThreadByMessageId(messageId, accountId) {
|
|
53
|
-
const session = getSession();
|
|
54
|
-
try {
|
|
55
|
-
const result = await session.run(`MATCH (kd:KnowledgeDocument {source: 'email', accountId: $accountId})
|
|
56
|
-
WHERE $messageId IN kd.messageIds
|
|
57
|
-
RETURN kd.attachmentId AS attachmentId, kd.body AS body,
|
|
58
|
-
kd.messageIds AS messageIds,
|
|
59
|
-
kd.messages AS messagesJson,
|
|
60
|
-
kd.firstReceivedAt AS firstReceivedAt,
|
|
61
|
-
kd.lastReceivedAt AS lastReceivedAt
|
|
62
|
-
LIMIT 1`, { messageId, accountId });
|
|
63
|
-
if (result.records.length === 0)
|
|
64
|
-
return null;
|
|
65
|
-
const record = result.records[0];
|
|
66
|
-
return {
|
|
67
|
-
attachmentId: record.get("attachmentId"),
|
|
68
|
-
body: record.get("body"),
|
|
69
|
-
messageIds: record.get("messageIds"),
|
|
70
|
-
messagesJson: record.get("messagesJson") ?? "[]",
|
|
71
|
-
firstReceivedAt: record.get("firstReceivedAt"),
|
|
72
|
-
lastReceivedAt: record.get("lastReceivedAt"),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
finally {
|
|
76
|
-
await session.close();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Ingest one IMAP message into the per-thread :KnowledgeDocument.
|
|
81
|
-
*
|
|
82
|
-
* - If the message's In-Reply-To points to a known thread KD, the
|
|
83
|
-
* message is appended (body grows, messageIds grows, lastReceivedAt
|
|
84
|
-
* advances).
|
|
85
|
-
* - Otherwise, a new thread KD is created with this message as root.
|
|
86
|
-
*
|
|
87
|
-
* Person, address-edge, anchor, and embedding writes always run.
|
|
88
|
-
* Discarded-screening messages skip embedding to keep vector search clean.
|
|
89
|
-
*/
|
|
90
|
-
export async function storeEmailMessage(data) {
|
|
91
|
-
const messageId = stripAngleBrackets(data.messageId) ?? `synthetic:${deriveFallbackAttachmentId(data)}`;
|
|
92
|
-
const inReplyTo = stripAngleBrackets(data.inReplyTo);
|
|
93
|
-
const existing = inReplyTo ? await findThreadByMessageId(inReplyTo, data.accountId) : null;
|
|
94
|
-
const attachmentId = existing
|
|
95
|
-
? existing.attachmentId
|
|
96
|
-
: deriveThreadAttachmentId(data.accountId, messageId);
|
|
97
|
-
// Already ingested? Idempotent skip — caught by messageIds-contains check.
|
|
98
|
-
if (existing && existing.messageIds.includes(messageId)) {
|
|
99
|
-
return { attachmentId, created: false, appended: false };
|
|
100
|
-
}
|
|
101
|
-
// Build new body + metadata (append or create).
|
|
102
|
-
const messageBlock = renderMessageBlock(data, messageId);
|
|
103
|
-
const newBody = existing ? `${existing.body}\n\n${messageBlock}` : messageBlock;
|
|
104
|
-
const newMessageIds = existing ? [...existing.messageIds, messageId] : [messageId];
|
|
105
|
-
const newEnvelope = {
|
|
106
|
-
messageId,
|
|
107
|
-
fromAddress: data.fromAddress,
|
|
108
|
-
fromName: data.fromName,
|
|
109
|
-
toAddresses: data.toAddresses,
|
|
110
|
-
ccAddresses: data.ccAddresses,
|
|
111
|
-
subject: data.subject,
|
|
112
|
-
receivedAt: data.receivedAt,
|
|
113
|
-
uid: data.uid,
|
|
114
|
-
mailbox: data.mailbox,
|
|
115
|
-
};
|
|
116
|
-
const existingMessages = existing
|
|
117
|
-
? JSON.parse(existing.messagesJson)
|
|
118
|
-
: [];
|
|
119
|
-
const newMessages = [...existingMessages, newEnvelope];
|
|
120
|
-
const newLastReceivedAt = existing && data.receivedAt < existing.lastReceivedAt
|
|
121
|
-
? existing.lastReceivedAt
|
|
122
|
-
: data.receivedAt;
|
|
123
|
-
const newFirstReceivedAt = existing && data.receivedAt > existing.firstReceivedAt
|
|
124
|
-
? existing.firstReceivedAt
|
|
125
|
-
: data.receivedAt;
|
|
126
|
-
// Embedding: skip discarded messages so vector search stays clean.
|
|
127
|
-
let embedding = [];
|
|
128
|
-
if (data.screening !== "discarded") {
|
|
129
|
-
const embeddingText = [data.subject, data.bodyPreview].filter(Boolean).join(" — ");
|
|
130
|
-
embedding = await computeEmbedding(embeddingText);
|
|
131
|
-
}
|
|
132
|
-
const nowIso = new Date().toISOString();
|
|
133
|
-
// Collect addresses for Person/edge MERGE. Sender first so :FROM gets a
|
|
134
|
-
// displayName when only the sender carries one.
|
|
135
|
-
const addressRows = [
|
|
136
|
-
{ address: data.fromAddress, displayName: data.fromName, edge: "FROM" },
|
|
137
|
-
...data.toAddresses.map((address) => ({
|
|
138
|
-
address,
|
|
139
|
-
displayName: null,
|
|
140
|
-
edge: "TO",
|
|
141
|
-
})),
|
|
142
|
-
...data.ccAddresses.map((address) => ({
|
|
143
|
-
address,
|
|
144
|
-
displayName: null,
|
|
145
|
-
edge: "CC",
|
|
146
|
-
})),
|
|
147
|
-
]
|
|
148
|
-
.filter((row) => row.address && row.address.length > 0)
|
|
149
|
-
.map((row) => ({ ...row, address: normaliseAddress(row.address) }));
|
|
150
|
-
const session = getSession();
|
|
151
|
-
try {
|
|
152
|
-
await session.run(`MERGE (kd:KnowledgeDocument {attachmentId: $attachmentId})
|
|
153
|
-
ON CREATE SET
|
|
154
|
-
kd.source = 'email',
|
|
155
|
-
kd.scope = 'admin',
|
|
156
|
-
kd.accountId = $accountId,
|
|
157
|
-
kd.subject = $subject,
|
|
158
|
-
kd.createdAt = $nowIso,
|
|
159
|
-
kd.firstReceivedAt = $firstReceivedAt,
|
|
160
|
-
kd.screening = $screening,
|
|
161
|
-
kd.screeningReason = $screeningReason,
|
|
162
|
-
kd.promptInjectionFlag = $promptInjectionFlag
|
|
163
|
-
SET kd.body = $body,
|
|
164
|
-
kd.messageIds = $messageIds,
|
|
165
|
-
kd.messages = $messagesJson,
|
|
166
|
-
kd.lastReceivedAt = $lastReceivedAt,
|
|
167
|
-
kd.updatedAt = $nowIso
|
|
168
|
-
WITH kd
|
|
169
|
-
MERGE (ea:EmailAccount {accountId: $accountId})
|
|
170
|
-
MERGE (kd)-[:RECEIVED_BY]->(ea)`, {
|
|
171
|
-
attachmentId,
|
|
172
|
-
accountId: data.accountId,
|
|
173
|
-
subject: data.subject,
|
|
174
|
-
body: newBody,
|
|
175
|
-
messageIds: newMessageIds,
|
|
176
|
-
messagesJson: JSON.stringify(newMessages),
|
|
177
|
-
firstReceivedAt: newFirstReceivedAt,
|
|
178
|
-
lastReceivedAt: newLastReceivedAt,
|
|
179
|
-
nowIso,
|
|
180
|
-
screening: data.screening ?? null,
|
|
181
|
-
screeningReason: data.screeningReason ?? null,
|
|
182
|
-
promptInjectionFlag: data.promptInjectionFlag ?? null,
|
|
183
|
-
});
|
|
184
|
-
// Persons + address edges. UNWIND so one round-trip handles every address.
|
|
185
|
-
if (addressRows.length > 0) {
|
|
186
|
-
await session.run(`UNWIND $rows AS row
|
|
187
|
-
MERGE (p:Person {email: row.address})
|
|
188
|
-
ON CREATE SET p.displayName = row.displayName,
|
|
189
|
-
p.scope = 'admin',
|
|
190
|
-
p.accountId = $accountId,
|
|
191
|
-
p.createdAt = $nowIso
|
|
192
|
-
WITH p, row
|
|
193
|
-
MATCH (kd:KnowledgeDocument {attachmentId: $attachmentId})
|
|
194
|
-
CALL {
|
|
195
|
-
WITH kd, p, row
|
|
196
|
-
WITH kd, p, row WHERE row.edge = 'FROM'
|
|
197
|
-
MERGE (kd)-[:FROM]->(p)
|
|
198
|
-
}
|
|
199
|
-
CALL {
|
|
200
|
-
WITH kd, p, row
|
|
201
|
-
WITH kd, p, row WHERE row.edge = 'TO'
|
|
202
|
-
MERGE (kd)-[:TO]->(p)
|
|
203
|
-
}
|
|
204
|
-
CALL {
|
|
205
|
-
WITH kd, p, row
|
|
206
|
-
WITH kd, p, row WHERE row.edge = 'CC'
|
|
207
|
-
MERGE (kd)-[:CC]->(p)
|
|
208
|
-
}`, { rows: addressRows, attachmentId, accountId: data.accountId, nowIso });
|
|
209
|
-
}
|
|
210
|
-
// Embedding written separately so the large vector doesn't go through the
|
|
211
|
-
// main MERGE params (some Neo4j versions reject very-large Cypher params).
|
|
212
|
-
if (embedding.length > 0) {
|
|
213
|
-
await session.run(`MATCH (kd:KnowledgeDocument {attachmentId: $attachmentId})
|
|
214
|
-
SET kd.embedding = $embedding`, { attachmentId, embedding });
|
|
215
|
-
}
|
|
216
|
-
return { attachmentId, created: !existing, appended: !!existing };
|
|
217
|
-
}
|
|
218
|
-
catch (err) {
|
|
219
|
-
if (err instanceof neo4j.Neo4jError &&
|
|
220
|
-
err.code === "Neo.ClientError.Schema.ConstraintValidationFailed") {
|
|
221
|
-
// Race: two concurrent writes for the same attachmentId. Treat as duplicate.
|
|
222
|
-
console.error(`[email-fetch] INFO: constraint caught duplicate attachmentId=${attachmentId} accountId=${data.accountId}`);
|
|
223
|
-
return { attachmentId, created: false, appended: false };
|
|
224
|
-
}
|
|
225
|
-
throw err;
|
|
226
|
-
}
|
|
227
|
-
finally {
|
|
228
|
-
await session.close();
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Ingest a batch of IMAP messages. Returns aggregate counts.
|
|
233
|
-
*
|
|
234
|
-
* Threads are intentionally not reordered — messages are processed in
|
|
235
|
-
* input order. Callers that want chronological transcript shape should
|
|
236
|
-
* pre-sort by `receivedAt` ascending.
|
|
237
|
-
*/
|
|
238
|
-
export async function storeEmailMessages(messages) {
|
|
239
|
-
let threadsCreated = 0;
|
|
240
|
-
let messagesAppended = 0;
|
|
241
|
-
let duplicates = 0;
|
|
242
|
-
for (const message of messages) {
|
|
243
|
-
const result = await storeEmailMessage(message);
|
|
244
|
-
if (result.created) {
|
|
245
|
-
threadsCreated++;
|
|
246
|
-
}
|
|
247
|
-
else if (result.appended) {
|
|
248
|
-
messagesAppended++;
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
duplicates++;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
return { threadsCreated, messagesAppended, duplicates };
|
|
255
|
-
}
|
|
256
|
-
// ---------------------------------------------------------------------------
|
|
257
|
-
// Read helpers — used by email-reply, email-read, email-search to look
|
|
258
|
-
// individual messages and threads back out of the KD model.
|
|
259
|
-
// ---------------------------------------------------------------------------
|
|
260
|
-
/**
|
|
261
|
-
* Look up a single message envelope by its Message-ID. Walks the thread
|
|
262
|
-
* KD's `messages` array (JSON-encoded). Returns null when the thread KD
|
|
263
|
-
* has not been ingested yet.
|
|
264
|
-
*/
|
|
265
|
-
export async function getMessageEnvelope(messageId, accountId) {
|
|
266
|
-
const normalised = stripAngleBrackets(messageId);
|
|
267
|
-
if (!normalised)
|
|
268
|
-
return null;
|
|
269
|
-
const thread = await findThreadByMessageId(normalised, accountId);
|
|
270
|
-
if (!thread)
|
|
271
|
-
return null;
|
|
272
|
-
const messages = JSON.parse(thread.messagesJson);
|
|
273
|
-
return messages.find((m) => m.messageId === normalised) ?? null;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Given a set of messageIds, locate each one inside its thread KD and
|
|
277
|
-
* report:
|
|
278
|
-
* - threadId — the thread KD's attachmentId
|
|
279
|
-
* - threadDepth — position of the message in the KD's messageIds array
|
|
280
|
-
* (0 = root). Useful for sorting search hits by thread
|
|
281
|
-
* position.
|
|
282
|
-
*
|
|
283
|
-
* Messages whose thread KD has not been ingested are absent from the map.
|
|
284
|
-
*/
|
|
285
|
-
export async function getThreadInfo(messageIds, accountId) {
|
|
286
|
-
if (messageIds.length === 0)
|
|
287
|
-
return new Map();
|
|
288
|
-
const normalised = messageIds
|
|
289
|
-
.map((mid) => stripAngleBrackets(mid))
|
|
290
|
-
.filter((mid) => mid !== null);
|
|
291
|
-
if (normalised.length === 0)
|
|
292
|
-
return new Map();
|
|
293
|
-
const session = getSession();
|
|
294
|
-
try {
|
|
295
|
-
// Index-of-mid is computed inline with a list comprehension so the query
|
|
296
|
-
// does not depend on the apoc plugin being installed.
|
|
297
|
-
const result = await session.run(`UNWIND $messageIds AS mid
|
|
298
|
-
MATCH (kd:KnowledgeDocument {source: 'email', accountId: $accountId})
|
|
299
|
-
WHERE mid IN kd.messageIds
|
|
300
|
-
WITH mid, kd.attachmentId AS threadId,
|
|
301
|
-
[i IN range(0, size(kd.messageIds) - 1) WHERE kd.messageIds[i] = mid | i][0] AS threadDepth
|
|
302
|
-
RETURN mid AS messageId, threadDepth, threadId`, { messageIds: normalised, accountId });
|
|
303
|
-
const map = new Map();
|
|
304
|
-
for (const record of result.records) {
|
|
305
|
-
const mid = record.get("messageId");
|
|
306
|
-
map.set(mid, {
|
|
307
|
-
messageId: mid,
|
|
308
|
-
threadDepth: neo4j.integer.toNumber(record.get("threadDepth")),
|
|
309
|
-
threadId: record.get("threadId"),
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
return map;
|
|
313
|
-
}
|
|
314
|
-
finally {
|
|
315
|
-
await session.close();
|
|
316
|
-
}
|
|
20
|
+
export async function getThreadInfo(_messageIds, _accountId) {
|
|
21
|
+
// Task 442 — per-message thread-depth lookup requires per-message nodes
|
|
22
|
+
// the new `:ConversationArchive` shape does not store.
|
|
23
|
+
return new Map();
|
|
317
24
|
}
|
|
25
|
+
// Re-export neo4j so consumers depending on the legacy module surface keep
|
|
26
|
+
// working without churn. The actual neo4j-driver usage is now in
|
|
27
|
+
// conversation-archive-dispatch.ts.
|
|
28
|
+
export { neo4j };
|
|
29
|
+
export { getSession };
|
|
318
30
|
//# sourceMappingURL=graph.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/lib/graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/lib/graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,MAAM,cAAc,CAAC;AAmCjC;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAoB;IACrD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACrD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAsBD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,UAAkB,EAClB,UAAkB;IAElB,sEAAsE;IACtE,OAAO,IAAI,CAAC;AACd,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAqB,EACrB,UAAkB;IAElB,wEAAwE;IACxE,uDAAuD;IACvD,OAAO,IAAI,GAAG,EAAE,CAAC;AACnB,CAAC;AAED,2EAA2E;AAC3E,iEAAiE;AACjE,oCAAoC;AACpC,OAAO,EAAE,KAAK,EAAE,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -134,7 +134,7 @@ export declare function searchMessages(config: EmailConfig, password: string, qu
|
|
|
134
134
|
beforeUid?: number;
|
|
135
135
|
}): Promise<PaginatedMessages>;
|
|
136
136
|
/**
|
|
137
|
-
* Result from an incremental email fetch performed by the email-fetch
|
|
137
|
+
* Result from an incremental email fetch performed by the email-fetch tool.
|
|
138
138
|
* Includes the raw envelope data needed for graph storage (not just display).
|
|
139
139
|
*/
|
|
140
140
|
export interface FetchedEmail {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory pending batch between email-fetch and email-ingest.
|
|
3
|
+
*
|
|
4
|
+
* email-fetch pulls new IMAP messages and stashes them here. email-ingest
|
|
5
|
+
* reads the stash, writes only the operator-approved subset, and clears it.
|
|
6
|
+
*
|
|
7
|
+
* State is per-MCP-server-process, keyed by accountId. The server runs for
|
|
8
|
+
* the lifetime of a session, so the two tools share state across turns
|
|
9
|
+
* within one conversation. Restart drops the batch — the operator just
|
|
10
|
+
* runs "check my emails" again, which is the intended human-in-the-loop
|
|
11
|
+
* cadence.
|
|
12
|
+
*/
|
|
13
|
+
import type { FetchedEmail } from "./imap.js";
|
|
14
|
+
export interface PendingBatch {
|
|
15
|
+
uidValidity: number;
|
|
16
|
+
maxUid: number;
|
|
17
|
+
recipientAddress: string;
|
|
18
|
+
messages: FetchedEmail[];
|
|
19
|
+
}
|
|
20
|
+
export declare function putBatch(accountId: string, batch: PendingBatch): void;
|
|
21
|
+
export declare function takeBatch(accountId: string): PendingBatch | null;
|
|
22
|
+
export declare function peekBatch(accountId: string): PendingBatch | null;
|
|
23
|
+
//# sourceMappingURL=ingest-batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-batch.d.ts","sourceRoot":"","sources":["../../src/lib/ingest-batch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAID,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAErE;AAED,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAKhE;AAED,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAEhE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const batches = new Map();
|
|
2
|
+
export function putBatch(accountId, batch) {
|
|
3
|
+
batches.set(accountId, batch);
|
|
4
|
+
}
|
|
5
|
+
export function takeBatch(accountId) {
|
|
6
|
+
const b = batches.get(accountId);
|
|
7
|
+
if (!b)
|
|
8
|
+
return null;
|
|
9
|
+
batches.delete(accountId);
|
|
10
|
+
return b;
|
|
11
|
+
}
|
|
12
|
+
export function peekBatch(accountId) {
|
|
13
|
+
return batches.get(accountId) ?? null;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ingest-batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-batch.js","sourceRoot":"","sources":["../../src/lib/ingest-batch.ts"],"names":[],"mappings":"AAqBA,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;AAEhD,MAAM,UAAU,QAAQ,CAAC,SAAiB,EAAE,KAAmB;IAC7D,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,SAAiB;IACzC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC1B,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,SAAiB;IACzC,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-classify.d.ts","sourceRoot":"","sources":["../../src/tools/email-classify.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAuCD,wBAAsB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CA8DhF"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { getSession } from "../lib/neo4j.js";
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// email-classify — operator-solicited reclassify for one email-thread
|
|
7
|
+
// :KnowledgeDocument keyed by its root Message-ID. Thin wrapper over the
|
|
8
|
+
// generic kd-classify primitive (memory plugin): derives the
|
|
9
|
+
// account-scoped attachmentId, runs the same body-growth gate, stages the
|
|
10
|
+
// thread body to a temp file, and returns a dispatch envelope the admin
|
|
11
|
+
// agent uses to hand off to the `librarian` specialist.
|
|
12
|
+
//
|
|
13
|
+
// The gate threshold and envelope shape mirror
|
|
14
|
+
// `platform/plugins/memory/mcp/src/lib/kd-classify-gate.ts`; the two copies
|
|
15
|
+
// are duplicated rather than cross-plugin-imported so each MCP process boots
|
|
16
|
+
// independently. Keep both aligned when the contract changes. Task 401.
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
const KD_CLASSIFY_GROWTH_THRESHOLD = 0.25;
|
|
19
|
+
function deriveThreadAttachmentId(accountId, rootMessageId) {
|
|
20
|
+
return createHash("sha256")
|
|
21
|
+
.update(`email:${accountId}:${rootMessageId}`)
|
|
22
|
+
.digest("hex");
|
|
23
|
+
}
|
|
24
|
+
async function readThread(accountId, attachmentId) {
|
|
25
|
+
const session = getSession();
|
|
26
|
+
try {
|
|
27
|
+
const result = await session.run(`MATCH (kd:KnowledgeDocument { source: 'email', accountId: $accountId, attachmentId: $attachmentId })
|
|
28
|
+
RETURN coalesce(size(kd.body), 0) AS bodyLen,
|
|
29
|
+
coalesce(kd.lastClassifiedBodyLength, 0) AS lastLen,
|
|
30
|
+
kd.body AS body`, { accountId, attachmentId });
|
|
31
|
+
if (result.records.length === 0)
|
|
32
|
+
return null;
|
|
33
|
+
const r = result.records[0];
|
|
34
|
+
return {
|
|
35
|
+
bodyLen: Number(r.get("bodyLen")),
|
|
36
|
+
lastClassifiedBodyLength: Number(r.get("lastLen")),
|
|
37
|
+
body: r.get("body") ?? "",
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
await session.close();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export async function emailClassify(params) {
|
|
45
|
+
const { accountId, rootMessageId } = params;
|
|
46
|
+
if (!rootMessageId.trim()) {
|
|
47
|
+
throw new Error("email-classify: rootMessageId is required.");
|
|
48
|
+
}
|
|
49
|
+
const attachmentId = deriveThreadAttachmentId(accountId, rootMessageId);
|
|
50
|
+
const meta = await readThread(accountId, attachmentId);
|
|
51
|
+
if (!meta) {
|
|
52
|
+
throw new Error(`email-classify: no email-thread :KnowledgeDocument for rootMessageId=${rootMessageId} in account ${accountId}. Have you run email-fetch + email-ingest first?`);
|
|
53
|
+
}
|
|
54
|
+
if (meta.bodyLen === 0) {
|
|
55
|
+
throw new Error(`email-classify: thread KD for rootMessageId=${rootMessageId} has empty body; cannot classify.`);
|
|
56
|
+
}
|
|
57
|
+
const lastLen = meta.lastClassifiedBodyLength;
|
|
58
|
+
const growthPct = lastLen > 0 ? (meta.bodyLen - lastLen) / lastLen : 1;
|
|
59
|
+
const isFirstClassify = lastLen <= 0;
|
|
60
|
+
const shouldProceed = isFirstClassify || growthPct >= KD_CLASSIFY_GROWTH_THRESHOLD;
|
|
61
|
+
process.stderr.write(`[email-classify] attachmentId=${attachmentId.slice(0, 12)} bodyLen=${meta.bodyLen} lastLen=${lastLen} growthPct=${growthPct.toFixed(3)} action=${shouldProceed ? "proceed" : "skip"}\n`);
|
|
62
|
+
if (!shouldProceed) {
|
|
63
|
+
const pctRounded = Math.round(growthPct * 100);
|
|
64
|
+
return `no classification needed (body grew ${pctRounded}% since last ingest; threshold ${Math.round(KD_CLASSIFY_GROWTH_THRESHOLD * 100)}%)`;
|
|
65
|
+
}
|
|
66
|
+
const accountDir = process.env.ACCOUNT_DIR;
|
|
67
|
+
if (!accountDir) {
|
|
68
|
+
throw new Error(`email-classify: ACCOUNT_DIR env not set; cannot stage thread body for librarian dispatch.`);
|
|
69
|
+
}
|
|
70
|
+
const tempFilePath = `${accountDir}/tmp/kd-classify-${attachmentId}.txt`;
|
|
71
|
+
await mkdir(dirname(tempFilePath), { recursive: true });
|
|
72
|
+
await writeFile(tempFilePath, meta.body, "utf-8");
|
|
73
|
+
const growthLabel = isFirstClassify
|
|
74
|
+
? "first classify"
|
|
75
|
+
: `${Math.round(growthPct * 100)}% growth since last ingest`;
|
|
76
|
+
return [
|
|
77
|
+
`Ready to classify email :KnowledgeDocument into sections.`,
|
|
78
|
+
`attachmentId: ${attachmentId}`,
|
|
79
|
+
`rootMessageId: ${rootMessageId}`,
|
|
80
|
+
`bodyLen: ${meta.bodyLen} chars (${growthLabel})`,
|
|
81
|
+
`tempFilePath: ${tempFilePath}`,
|
|
82
|
+
``,
|
|
83
|
+
`Next: dispatch the \`librarian\` specialist via the Task tool with this brief —`,
|
|
84
|
+
` "Ingest the document at ${tempFilePath} using mode=document, attachmentId=${attachmentId},`,
|
|
85
|
+
` anchor=LocalBusiness. The :KnowledgeDocument already exists and has source=email;`,
|
|
86
|
+
` memory-ingest will MERGE by attachmentId and write :Section children, replacing any prior."`,
|
|
87
|
+
].join("\n");
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=email-classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-classify.js","sourceRoot":"","sources":["../../src/tools/email-classify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface FetchParams {
|
|
2
|
+
accountId: string;
|
|
3
|
+
since_uid?: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* List new inbox messages since a UID high-water mark, without writing to
|
|
7
|
+
* the graph. Caches the batch in-memory so a follow-up email-ingest call
|
|
8
|
+
* can apply operator decisions.
|
|
9
|
+
*
|
|
10
|
+
* No classification, no embeddings, no graph writes. The operator triages
|
|
11
|
+
* by eye from the returned summary.
|
|
12
|
+
*/
|
|
13
|
+
export declare function emailFetch(params: FetchParams): Promise<string>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=email-fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-fetch.d.ts","sourceRoot":"","sources":["../../src/tools/email-fetch.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CA+CrE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { loadCredentials, readPollState } from "../lib/credentials.js";
|
|
2
|
+
import { fetchSinceUid } from "../lib/imap.js";
|
|
3
|
+
import { putBatch } from "../lib/ingest-batch.js";
|
|
4
|
+
/**
|
|
5
|
+
* List new inbox messages since a UID high-water mark, without writing to
|
|
6
|
+
* the graph. Caches the batch in-memory so a follow-up email-ingest call
|
|
7
|
+
* can apply operator decisions.
|
|
8
|
+
*
|
|
9
|
+
* No classification, no embeddings, no graph writes. The operator triages
|
|
10
|
+
* by eye from the returned summary.
|
|
11
|
+
*/
|
|
12
|
+
export async function emailFetch(params) {
|
|
13
|
+
const credResult = await loadCredentials(params.accountId);
|
|
14
|
+
if ("error" in credResult)
|
|
15
|
+
throw new Error(credResult.error);
|
|
16
|
+
const { config, password } = credResult.credentials;
|
|
17
|
+
const pollState = await readPollState(params.accountId);
|
|
18
|
+
const sinceUid = params.since_uid ?? pollState?.lastFetchedUid ?? 0;
|
|
19
|
+
const { uidValidity, emails, maxUid } = await fetchSinceUid(config, password, sinceUid, config.agentAddress);
|
|
20
|
+
console.error(`[email-fetch] tag=email-fetch listed=${emails.length} sinceUid=${sinceUid}`);
|
|
21
|
+
if (emails.length === 0) {
|
|
22
|
+
return `No new messages since UID ${sinceUid}.`;
|
|
23
|
+
}
|
|
24
|
+
// Stash for the follow-up email-ingest call.
|
|
25
|
+
putBatch(params.accountId, {
|
|
26
|
+
uidValidity,
|
|
27
|
+
maxUid,
|
|
28
|
+
recipientAddress: config.agentAddress,
|
|
29
|
+
messages: emails,
|
|
30
|
+
});
|
|
31
|
+
const lines = emails.map((m) => {
|
|
32
|
+
const header = [
|
|
33
|
+
`UID: ${m.uid}`,
|
|
34
|
+
`Message-ID: ${m.messageId ?? "(missing)"}`,
|
|
35
|
+
`From: ${m.fromName ? `${m.fromName} <${m.fromAddress}>` : m.fromAddress}`,
|
|
36
|
+
`Subject: ${m.subject}`,
|
|
37
|
+
`Date: ${m.date}`,
|
|
38
|
+
].join("\n");
|
|
39
|
+
const body = m.bodyPreview ? `\n\n${m.bodyPreview}` : "";
|
|
40
|
+
return `${header}${body}\n---`;
|
|
41
|
+
}).join("\n\n");
|
|
42
|
+
const footer = [
|
|
43
|
+
"",
|
|
44
|
+
`Listed ${emails.length} new message(s) since UID ${sinceUid}. Nothing has been written to the graph.`,
|
|
45
|
+
`Call email-ingest with a disposition ("ingest" or "discard") for every Message-ID above to apply the operator's decisions.`,
|
|
46
|
+
].join("\n");
|
|
47
|
+
return `${lines}\n${footer}`;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=email-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-fetch.js","sourceRoot":"","sources":["../../src/tools/email-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAOlD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAmB;IAClD,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3D,IAAI,OAAO,IAAI,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC7D,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC;IAEpD,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,IAAI,SAAS,EAAE,cAAc,IAAI,CAAC,CAAC;IAEpE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACzD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,YAAY,CAChD,CAAC;IAEF,OAAO,CAAC,KAAK,CACX,wCAAwC,MAAM,CAAC,MAAM,aAAa,QAAQ,EAAE,CAC7E,CAAC;IAEF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,6BAA6B,QAAQ,GAAG,CAAC;IAClD,CAAC;IAED,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE;QACzB,WAAW;QACX,MAAM;QACN,gBAAgB,EAAE,MAAM,CAAC,YAAY;QACrC,QAAQ,EAAE,MAAM;KACjB,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG;YACb,QAAQ,CAAC,CAAC,GAAG,EAAE;YACf,eAAe,CAAC,CAAC,SAAS,IAAI,WAAW,EAAE;YAC3C,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YAC1E,YAAY,CAAC,CAAC,OAAO,EAAE;YACvB,SAAS,CAAC,CAAC,IAAI,EAAE;SAClB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,OAAO,GAAG,MAAM,GAAG,IAAI,OAAO,CAAC;IACjC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,MAAM,GAAG;QACb,EAAE;QACF,UAAU,MAAM,CAAC,MAAM,6BAA6B,QAAQ,0CAA0C;QACtG,4HAA4H;KAC7H,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO,GAAG,KAAK,KAAK,MAAM,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface IngestDecision {
|
|
2
|
+
messageId: string;
|
|
3
|
+
disposition: "ingest" | "discard";
|
|
4
|
+
}
|
|
5
|
+
interface IngestParams {
|
|
6
|
+
accountId: string;
|
|
7
|
+
decisions: IngestDecision[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Apply operator decisions to the most recent email-fetch batch.
|
|
11
|
+
*
|
|
12
|
+
* - Every pending message must have a decision; missing IDs cause refusal
|
|
13
|
+
* so messages never silently fall through the high-water mark.
|
|
14
|
+
* - Only "ingest" entries are written to the graph; "discard" entries
|
|
15
|
+
* advance the high-water mark without persisting anything.
|
|
16
|
+
* - The cached batch is consumed (taken, not peeked) only on success.
|
|
17
|
+
*/
|
|
18
|
+
export declare function emailIngest(params: IngestParams): Promise<string>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=email-ingest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-ingest.d.ts","sourceRoot":"","sources":["../../src/tools/email-ingest.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,QAAQ,GAAG,SAAS,CAAC;CACnC;AAED,UAAU,YAAY;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAMD;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAuFvE"}
|