@cohortapp/agent-sdk 2.3.0
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/.claude/commands/init-agent.md +104 -0
- package/.claude/commands/init-maestro.md +1187 -0
- package/.claude/settings.json +161 -0
- package/.env.example +216 -0
- package/README.md +632 -0
- package/agents/browser-operator/agent.md +52 -0
- package/agents/calendar-ops/agent.md +50 -0
- package/agents/communications/agent.md +96 -0
- package/agents/decision-log/agent.md +65 -0
- package/agents/desktop-operator/agent.md +59 -0
- package/agents/gmail-operator/agent.md +62 -0
- package/agents/inbound-dispatcher/agent.md +66 -0
- package/agents/inbox-processor/agent.md +39 -0
- package/agents/pmo-execution/agent.md +60 -0
- package/agents/session-spawner/agent.md +64 -0
- package/agents/slack-operator/agent.md +60 -0
- package/agents/whatsapp-operator/agent.md +60 -0
- package/agents/workflow-automation/agent.md +61 -0
- package/archetypes/altitudes/c-suite.yaml +58 -0
- package/archetypes/altitudes/founder.yaml +68 -0
- package/archetypes/altitudes/senior-manager.yaml +63 -0
- package/archetypes/altitudes/svp.yaml +60 -0
- package/archetypes/altitudes/vp.yaml +50 -0
- package/archetypes/archetype.schema.json +77 -0
- package/archetypes/base.yaml +47 -0
- package/archetypes/capabilities/commercial-leader.yaml +159 -0
- package/archetypes/capabilities/compliance-officer.yaml +159 -0
- package/archetypes/capabilities/executive-operator.yaml +169 -0
- package/archetypes/capabilities/finance-leader.yaml +162 -0
- package/archetypes/capabilities/operations-leader.yaml +154 -0
- package/archetypes/capabilities/product-leader.yaml +148 -0
- package/archetypes/capabilities/technical-leader.yaml +146 -0
- package/archetypes/functions/commercial-leader.yaml +62 -0
- package/archetypes/functions/compliance-officer.yaml +64 -0
- package/archetypes/functions/executive-operator.yaml +70 -0
- package/archetypes/functions/finance-leader.yaml +70 -0
- package/archetypes/functions/operations-leader.yaml +62 -0
- package/archetypes/functions/product-leader.yaml +61 -0
- package/archetypes/functions/technical-leader.yaml +57 -0
- package/bin/cohort-mcp.mjs +81 -0
- package/bin/maestro.mjs +3516 -0
- package/bin/maestro.test.mjs +1015 -0
- package/desktop-control/README.md +56 -0
- package/desktop-control/app-profiles/gmail.yaml +120 -0
- package/desktop-control/app-profiles/slack.yaml +315 -0
- package/desktop-control/app-profiles/whatsapp.yaml +107 -0
- package/docs/architecture/agent-topology.md +2239 -0
- package/docs/architecture/archetype-agent-factory.md +110 -0
- package/docs/architecture/collective-memory-and-org-mesh.md +115 -0
- package/docs/architecture/continuous-monitoring.md +221 -0
- package/docs/architecture/mcp-capability-map.md +585 -0
- package/docs/architecture/system-architecture.md +1272 -0
- package/docs/company-context/README.md +40 -0
- package/docs/guides/agent-persona-setup.md +600 -0
- package/docs/guides/agents-observe-setup.md +64 -0
- package/docs/guides/billing-console-keys.md +88 -0
- package/docs/guides/ccxray-diagnostics.md +65 -0
- package/docs/guides/channel-bus.md +127 -0
- package/docs/guides/claude-mem-setup.md +79 -0
- package/docs/guides/claude-pace-setup.md +56 -0
- package/docs/guides/claudraband-sessions.md +98 -0
- package/docs/guides/clawteam-swarm.md +116 -0
- package/docs/guides/code-review-graph-setup.md +86 -0
- package/docs/guides/email-setup.md +431 -0
- package/docs/guides/mac-mini.md +119 -0
- package/docs/guides/media-generation-setup.md +349 -0
- package/docs/guides/model-routing.md +162 -0
- package/docs/guides/observability-otel.md +265 -0
- package/docs/guides/org-onboarding.md +132 -0
- package/docs/guides/outbound-governance-setup.md +437 -0
- package/docs/guides/pdf-generation-setup.md +315 -0
- package/docs/guides/poller-daemon-setup.md +563 -0
- package/docs/guides/rag-context-setup.md +459 -0
- package/docs/guides/self-optimization-pattern.md +82 -0
- package/docs/guides/setup-wizard.md +178 -0
- package/docs/guides/slack-setup.md +350 -0
- package/docs/guides/telegram-setup.md +227 -0
- package/docs/guides/twilio-subaccounts-setup.md +223 -0
- package/docs/guides/verification.md +128 -0
- package/docs/guides/voice-mode.md +188 -0
- package/docs/guides/voice-sms-setup.md +698 -0
- package/docs/guides/webhook-relay-setup.md +349 -0
- package/docs/guides/whatsapp-setup.md +288 -0
- package/docs/prompts/board-pack-cover-template.md +36 -0
- package/docs/prompts/decision-recommendation-template.md +88 -0
- package/docs/prompts/followup-message-template.md +141 -0
- package/docs/prompts/investor-letter-template.md +52 -0
- package/docs/prompts/morning-brief-template.md +82 -0
- package/docs/prompts/presentation-template.md +58 -0
- package/docs/prompts/weekly-strategic-memo-template.md +104 -0
- package/docs/research/hallucinated-tool-output-investigation.md +151 -0
- package/docs/runbooks/backup-restore.md +205 -0
- package/docs/runbooks/cohort-cutover.md +129 -0
- package/docs/runbooks/fleet-operations.md +200 -0
- package/docs/runbooks/incident-response.md +226 -0
- package/docs/runbooks/mac-mini-bootstrap.md +431 -0
- package/docs/runbooks/perpetual-operations.md +509 -0
- package/docs/runbooks/recovery-and-failover.md +260 -0
- package/framework-features.json +267 -0
- package/ingest/README.md +87 -0
- package/lib/action-executor.js +689 -0
- package/lib/action-executor.test.mjs +871 -0
- package/lib/agent-root.mjs +37 -0
- package/lib/archetype.mjs +236 -0
- package/lib/archetype.test.mjs +132 -0
- package/lib/autonomy.mjs +114 -0
- package/lib/autonomy.test.mjs +66 -0
- package/lib/backlog.mjs +358 -0
- package/lib/backlog.test.mjs +266 -0
- package/lib/budget-guard.mjs +279 -0
- package/lib/budget-guard.test.mjs +291 -0
- package/lib/cadence-bus-schedule.test.mjs +194 -0
- package/lib/cadence-bus.mjs +1120 -0
- package/lib/cadence-bus.test.mjs +720 -0
- package/lib/cadences.mjs +205 -0
- package/lib/cadences.test.mjs +125 -0
- package/lib/capability.mjs +154 -0
- package/lib/capability.test.mjs +78 -0
- package/lib/channels/base-adapter.mjs +719 -0
- package/lib/channels/base-adapter.test.mjs +590 -0
- package/lib/channels/channel.mjs +128 -0
- package/lib/channels/channels.test.mjs +371 -0
- package/lib/channels/contract.mjs +215 -0
- package/lib/channels/contract.test.mjs +137 -0
- package/lib/channels/conversation-resolver.mjs +95 -0
- package/lib/channels/gmail/adapter.mjs +87 -0
- package/lib/channels/inbox-item.mjs +255 -0
- package/lib/channels/inbox-item.test.mjs +335 -0
- package/lib/channels/index.mjs +94 -0
- package/lib/channels/orgmail/adapter.mjs +353 -0
- package/lib/channels/orgmail/adapter.test.mjs +311 -0
- package/lib/channels/pairing.mjs +363 -0
- package/lib/channels/pairing.test.mjs +270 -0
- package/lib/channels/registry.mjs +164 -0
- package/lib/channels/slack/adapter.mjs +317 -0
- package/lib/channels/slack-adapter.test.mjs +212 -0
- package/lib/channels/sms/adapter.mjs +43 -0
- package/lib/channels/telegram/adapter.mjs +432 -0
- package/lib/channels/telegram-adapter.test.mjs +306 -0
- package/lib/channels/voice/adapter.mjs +301 -0
- package/lib/channels/voice/adapter.test.mjs +278 -0
- package/lib/channels/whatsapp/adapter-baileys.mjs +587 -0
- package/lib/channels/whatsapp/adapter-baileys.test.mjs +359 -0
- package/lib/channels/whatsapp/adapter-twilio.mjs +65 -0
- package/lib/channels/whatsapp/baileys-typing.test.mjs +154 -0
- package/lib/charter.mjs +256 -0
- package/lib/charter.test.mjs +89 -0
- package/lib/claude-bin.mjs +134 -0
- package/lib/claude-bin.test.mjs +75 -0
- package/lib/collective/capture.mjs +185 -0
- package/lib/collective/capture.test.mjs +121 -0
- package/lib/collective/cards.mjs +201 -0
- package/lib/collective/cards.test.mjs +114 -0
- package/lib/collective/config.mjs +186 -0
- package/lib/collective/config.test.mjs +123 -0
- package/lib/collective/global-config.mjs +113 -0
- package/lib/collective/global-config.test.mjs +75 -0
- package/lib/collective/presence.mjs +201 -0
- package/lib/collective/presence.test.mjs +95 -0
- package/lib/collective/recall.mjs +215 -0
- package/lib/collective/recall.test.mjs +116 -0
- package/lib/comms/send-gate.mjs +554 -0
- package/lib/comms/send-gate.test.mjs +577 -0
- package/lib/comms.mjs +67 -0
- package/lib/comms.test.mjs +41 -0
- package/lib/diagnostics/alerts.mjs +424 -0
- package/lib/diagnostics/alerts.test.mjs +318 -0
- package/lib/diagnostics/backup-freshness.mjs +188 -0
- package/lib/diagnostics/backup-freshness.test.mjs +185 -0
- package/lib/diagnostics/counters.mjs +269 -0
- package/lib/diagnostics/counters.test.mjs +206 -0
- package/lib/diagnostics/events.mjs +188 -0
- package/lib/diagnostics/events.test.mjs +290 -0
- package/lib/diagnostics/otel.mjs +237 -0
- package/lib/diagnostics/otel.test.mjs +196 -0
- package/lib/diagnostics/trace.mjs +216 -0
- package/lib/diagnostics/trace.test.mjs +251 -0
- package/lib/env-compat.mjs +74 -0
- package/lib/env-compat.test.mjs +104 -0
- package/lib/feature-init.mjs +331 -0
- package/lib/fs-atomic.mjs +112 -0
- package/lib/fs-atomic.test.mjs +72 -0
- package/lib/fs-ownership.mjs +111 -0
- package/lib/fs-ownership.test.mjs +158 -0
- package/lib/hooks/bus.mjs +347 -0
- package/lib/hooks/bus.test.mjs +387 -0
- package/lib/index.js +16 -0
- package/lib/learning/config.mjs +106 -0
- package/lib/learning/config.test.mjs +75 -0
- package/lib/learning/counters.mjs +156 -0
- package/lib/learning/counters.test.mjs +69 -0
- package/lib/learning/curator-consolidate.test.mjs +238 -0
- package/lib/learning/curator.mjs +453 -0
- package/lib/learning/curator.test.mjs +106 -0
- package/lib/learning/log.mjs +40 -0
- package/lib/learning/reflect.mjs +534 -0
- package/lib/learning/reflect.test.mjs +0 -0
- package/lib/learning/session-index.mjs +352 -0
- package/lib/learning/session-index.test.mjs +125 -0
- package/lib/learning/skill-writer.mjs +474 -0
- package/lib/learning/skill-writer.test.mjs +210 -0
- package/lib/mcp/server.mjs +328 -0
- package/lib/mcp/server.test.mjs +400 -0
- package/lib/model-router/auth-profiles.mjs +758 -0
- package/lib/model-router/auth-profiles.test.mjs +580 -0
- package/lib/model-router/catalog/anthropic.yaml +153 -0
- package/lib/model-router/catalog/deepseek.yaml +86 -0
- package/lib/model-router/catalog/moonshot.yaml +81 -0
- package/lib/model-router/catalog/qwen.yaml +114 -0
- package/lib/model-router/catalog.mjs +925 -0
- package/lib/model-router/catalog.test.mjs +385 -0
- package/lib/model-router/economics.mjs +564 -0
- package/lib/model-router/economics.test.mjs +344 -0
- package/lib/model-router/failover.mjs +298 -0
- package/lib/model-router/failover.test.mjs +439 -0
- package/lib/model-router/health.mjs +453 -0
- package/lib/model-router/health.test.mjs +338 -0
- package/lib/model-router/integration-coverage.test.mjs +829 -0
- package/lib/model-router/integration.test.mjs +564 -0
- package/lib/model-router/ledger.mjs +402 -0
- package/lib/model-router/ledger.test.mjs +382 -0
- package/lib/model-router/llm-task.mjs +515 -0
- package/lib/model-router/llm-task.test.mjs +392 -0
- package/lib/model-router/org-credentials.mjs +260 -0
- package/lib/model-router/org-credentials.test.mjs +265 -0
- package/lib/model-router/pricing-refresh.mjs +463 -0
- package/lib/model-router/pricing-refresh.test.mjs +286 -0
- package/lib/model-router/reconcile.mjs +429 -0
- package/lib/model-router/reconcile.test.mjs +316 -0
- package/lib/model-router/repair.mjs +471 -0
- package/lib/model-router/repair.test.mjs +180 -0
- package/lib/model-router/resolve.mjs +1206 -0
- package/lib/model-router/spawn.mjs +497 -0
- package/lib/model-router/spawn.test.mjs +425 -0
- package/lib/model-router/taxonomy.mjs +893 -0
- package/lib/model-router/taxonomy.test.mjs +410 -0
- package/lib/model-router.mjs +677 -0
- package/lib/model-router.test.mjs +907 -0
- package/lib/org/activity.mjs +211 -0
- package/lib/org/activity.test.mjs +134 -0
- package/lib/org/approvals.mjs +448 -0
- package/lib/org/approvals.test.mjs +216 -0
- package/lib/org/awareness.mjs +222 -0
- package/lib/org/awareness.test.mjs +159 -0
- package/lib/org/board.mjs +229 -0
- package/lib/org/board.test.mjs +177 -0
- package/lib/org/bootstrap-context.mjs +169 -0
- package/lib/org/bootstrap-context.test.mjs +153 -0
- package/lib/org/client.mjs +1628 -0
- package/lib/org/client.test.mjs +1107 -0
- package/lib/org/cohort-client.mjs +67 -0
- package/lib/org/cohort-client.test.mjs +126 -0
- package/lib/org/cost-sync.mjs +227 -0
- package/lib/org/cost-sync.test.mjs +153 -0
- package/lib/org/doctor.mjs +212 -0
- package/lib/org/doctor.test.mjs +212 -0
- package/lib/org/handoff.mjs +293 -0
- package/lib/org/handoff.test.mjs +269 -0
- package/lib/org/integration-tools.mjs +182 -0
- package/lib/org/integration-tools.test.mjs +160 -0
- package/lib/org/keys.mjs +131 -0
- package/lib/org/keys.test.mjs +92 -0
- package/lib/org/knowledge.mjs +463 -0
- package/lib/org/knowledge.test.mjs +319 -0
- package/lib/org/leases.mjs +335 -0
- package/lib/org/leases.test.mjs +235 -0
- package/lib/org/mesh-integration.test.mjs +127 -0
- package/lib/org/mesh.mjs +459 -0
- package/lib/org/mesh.test.mjs +345 -0
- package/lib/org/messaging.mjs +503 -0
- package/lib/org/messaging.test.mjs +238 -0
- package/lib/org/policy.mjs +345 -0
- package/lib/org/policy.test.mjs +237 -0
- package/lib/org/protocol.checksum +1 -0
- package/lib/org/protocol.checksum.test.mjs +90 -0
- package/lib/org/protocol.mjs +967 -0
- package/lib/org/protocol.test.mjs +264 -0
- package/lib/org/registry.mjs +194 -0
- package/lib/org/registry.test.mjs +100 -0
- package/lib/org/tool-surface-integration.test.mjs +120 -0
- package/lib/org/tool-surface.mjs +2535 -0
- package/lib/org/tool-surface.test.mjs +589 -0
- package/lib/org/ui-parity.mjs +3236 -0
- package/lib/org/ui-parity.test.mjs +348 -0
- package/lib/org/verify.mjs +176 -0
- package/lib/org/verify.test.mjs +194 -0
- package/lib/rag/embed.mjs +188 -0
- package/lib/rag/indexer.mjs +425 -0
- package/lib/rag/rag.test.mjs +505 -0
- package/lib/rag/search.mjs +475 -0
- package/lib/rate-guard.mjs +246 -0
- package/lib/rate-guard.test.mjs +201 -0
- package/lib/render.mjs +112 -0
- package/lib/render.test.mjs +68 -0
- package/lib/resource-governor.mjs +297 -0
- package/lib/resource-governor.test.mjs +262 -0
- package/lib/scheduling/dynamic-jobs.mjs +675 -0
- package/lib/scheduling/dynamic-jobs.test.mjs +344 -0
- package/lib/scheduling/jitter.mjs +0 -0
- package/lib/scheduling/jitter.test.mjs +140 -0
- package/lib/secrets/broker.mjs +315 -0
- package/lib/secrets/broker.test.mjs +280 -0
- package/lib/secrets/providers.mjs +461 -0
- package/lib/secrets/providers.test.mjs +274 -0
- package/lib/security/audit-engine.mjs +684 -0
- package/lib/security/audit-engine.test.mjs +389 -0
- package/lib/security/coerce-args.mjs +552 -0
- package/lib/security/coerce-args.test.mjs +281 -0
- package/lib/security/dangerous-tools.mjs +97 -0
- package/lib/security/dangerous-tools.test.mjs +68 -0
- package/lib/security/external-content.mjs +145 -0
- package/lib/security/external-content.test.mjs +67 -0
- package/lib/security/redact.mjs +592 -0
- package/lib/security/redact.test.mjs +441 -0
- package/lib/security/secret-equal.mjs +73 -0
- package/lib/security/secret-equal.test.mjs +55 -0
- package/lib/session-permissions.mjs +101 -0
- package/lib/session-permissions.test.mjs +100 -0
- package/lib/setup/claude-probe.mjs +74 -0
- package/lib/setup/completeness.mjs +175 -0
- package/lib/setup/completeness.test.mjs +110 -0
- package/lib/setup/context-pack.mjs +173 -0
- package/lib/setup/context-pack.test.mjs +89 -0
- package/lib/setup/enrich.mjs +277 -0
- package/lib/setup/enrich.test.mjs +115 -0
- package/lib/setup/enroll-from-cohort.mjs +441 -0
- package/lib/setup/enroll-from-cohort.test.mjs +233 -0
- package/lib/setup/integration.test.mjs +162 -0
- package/lib/setup/io.mjs +360 -0
- package/lib/setup/io.test.mjs +77 -0
- package/lib/setup/run-generator.mjs +81 -0
- package/lib/setup/runner.mjs +244 -0
- package/lib/setup/runner.test.mjs +132 -0
- package/lib/setup/sections/comms.mjs +173 -0
- package/lib/setup/sections/company.mjs +120 -0
- package/lib/setup/sections/enrich.mjs +138 -0
- package/lib/setup/sections/identity.mjs +182 -0
- package/lib/setup/sections/identity.test.mjs +140 -0
- package/lib/setup/sections/learning.mjs +153 -0
- package/lib/setup/sections/learning.test.mjs +81 -0
- package/lib/setup/sections/messaging.mjs +219 -0
- package/lib/setup/sections/messaging.test.mjs +127 -0
- package/lib/setup/sections/model.mjs +102 -0
- package/lib/setup/sections/operating-model.mjs +78 -0
- package/lib/setup/sections/org.mjs +475 -0
- package/lib/setup/sections/org.test.mjs +313 -0
- package/lib/setup/sections/orgmail.mjs +173 -0
- package/lib/setup/sections/orgmail.test.mjs +118 -0
- package/lib/setup/sections/recovery.mjs +159 -0
- package/lib/setup/sections/recovery.test.mjs +98 -0
- package/lib/setup/sections/tools.mjs +132 -0
- package/lib/setup/sections/verify.mjs +97 -0
- package/lib/setup/sot.mjs +205 -0
- package/lib/setup/sot.test.mjs +81 -0
- package/lib/setup/state.mjs +151 -0
- package/lib/setup/state.test.mjs +92 -0
- package/lib/singleton.js +229 -0
- package/lib/singleton.test.mjs +135 -0
- package/lib/telemetry/alerts.mjs +216 -0
- package/lib/telemetry/alerts.test.mjs +109 -0
- package/lib/telemetry/collect.mjs +512 -0
- package/lib/telemetry/collect.test.mjs +202 -0
- package/lib/tool-definitions-integration.test.mjs +83 -0
- package/lib/tool-definitions.js +738 -0
- package/lib/tool-definitions.test.mjs +437 -0
- package/lib/util/fetch-timeout.mjs +136 -0
- package/lib/util/fetch-timeout.test.mjs +202 -0
- package/lib/util/reconnect.mjs +343 -0
- package/lib/util/reconnect.test.mjs +369 -0
- package/lib/util/unhandled.mjs +205 -0
- package/lib/util/unhandled.test.mjs +216 -0
- package/lib/voice/context-loader.mjs +466 -0
- package/lib/voice/index.mjs +100 -0
- package/lib/voice/openai-realtime.mjs +510 -0
- package/lib/voice/outbound.mjs +542 -0
- package/lib/voice/outbound.test.mjs +69 -0
- package/lib/voice/post-call-brief.mjs +428 -0
- package/lib/voice/provider.mjs +52 -0
- package/lib/voice/session-rotation.mjs +257 -0
- package/lib/voice/stt.mjs +161 -0
- package/lib/voice/stt.test.mjs +226 -0
- package/lib/voice/tool-bridge.mjs +370 -0
- package/lib/voice/tts.mjs +104 -0
- package/lib/voice/twilio-sip-bridge.mjs +288 -0
- package/lib/voice/voice.test.mjs +990 -0
- package/mcp/README.md +80 -0
- package/package.json +151 -0
- package/plugins/maestro-skills/plugin.json +139 -0
- package/plugins/maestro-skills/skills/agents-observe.md +110 -0
- package/plugins/maestro-skills/skills/board-deck.md +68 -0
- package/plugins/maestro-skills/skills/books-close.md +77 -0
- package/plugins/maestro-skills/skills/brand-steward.md +121 -0
- package/plugins/maestro-skills/skills/calendar-plan.md +57 -0
- package/plugins/maestro-skills/skills/call-working-sessions.md +124 -0
- package/plugins/maestro-skills/skills/ccxray-diagnostics.md +91 -0
- package/plugins/maestro-skills/skills/claude-pace.md +61 -0
- package/plugins/maestro-skills/skills/code-review-graph.md +99 -0
- package/plugins/maestro-skills/skills/crm-pipeline.md +65 -0
- package/plugins/maestro-skills/skills/decision-brief.md +89 -0
- package/plugins/maestro-skills/skills/directory-hygiene.md +125 -0
- package/plugins/maestro-skills/skills/draft-comms.md +84 -0
- package/plugins/maestro-skills/skills/evening-wrap.md +53 -0
- package/plugins/maestro-skills/skills/files-find.md +65 -0
- package/plugins/maestro-skills/skills/generative-ui.md +228 -0
- package/plugins/maestro-skills/skills/hiring-triage.md +74 -0
- package/plugins/maestro-skills/skills/inbox-triage.md +61 -0
- package/plugins/maestro-skills/skills/mail-triage.md +86 -0
- package/plugins/maestro-skills/skills/morning-brief.md +54 -0
- package/plugins/maestro-skills/skills/native-artifacts.md +157 -0
- package/plugins/maestro-skills/skills/org-board.md +133 -0
- package/plugins/maestro-skills/skills/org-credential.md +68 -0
- package/plugins/maestro-skills/skills/org-recall.md +81 -0
- package/plugins/maestro-skills/skills/pipeline-review.md +76 -0
- package/plugins/maestro-skills/skills/regulatory-status.md +81 -0
- package/plugins/maestro-skills/skills/router-why.md +78 -0
- package/plugins/maestro-skills/skills/schedule-meeting.md +91 -0
- package/plugins/maestro-skills/skills/session-search.md +71 -0
- package/plugins/maestro-skills/skills/set-reminder.md +93 -0
- package/plugins/maestro-skills/skills/slack-followup.md +64 -0
- package/plugins/maestro-skills/skills/team-activity.md +86 -0
- package/plugins/maestro-skills/skills/weekly-memo.md +70 -0
- package/policies/action-classification.yaml +114 -0
- package/policies/ai-disclosure.yaml +294 -0
- package/policies/communication-style.md +139 -0
- package/policies/information-barriers.yaml +118 -0
- package/policies/prompt-injection-defence.yaml +138 -0
- package/public/assets/icon-dark.png +0 -0
- package/public/assets/icon-dark.svg +9 -0
- package/public/assets/icon-light.svg +9 -0
- package/public/assets/logo-dark.svg +15 -0
- package/public/assets/logo-light.svg +15 -0
- package/scaffold/.mcp.json +7 -0
- package/scaffold/CLAUDE.md +368 -0
- package/scaffold/config/agent.json +55 -0
- package/scaffold/config/agent.ts +76 -0
- package/scaffold/config/agent.ts.example +89 -0
- package/scaffold/config/alerts.yaml +23 -0
- package/scaffold/config/allowlist.yaml.example +25 -0
- package/scaffold/config/caller-id-map.yaml +46 -0
- package/scaffold/config/collective.yaml +49 -0
- package/scaffold/config/company.json +20 -0
- package/scaffold/config/known-agents.json +6 -0
- package/scaffold/config/learning.yaml +55 -0
- package/scaffold/config/model-routing.yaml.example +104 -0
- package/scaffold/config/org.yaml +25 -0
- package/scaffold/config/orgmail.yaml.example +19 -0
- package/scaffold/config/recovery.yaml +72 -0
- package/scaffold/config/secrets.yaml +27 -0
- package/scaffold/config/slack.yaml.example +35 -0
- package/scaffold/config/telegram.yaml.example +38 -0
- package/scaffold/config/voice.yaml.example +89 -0
- package/scaffold/config/whatsapp.yaml.example +39 -0
- package/schedules/README.md +49 -0
- package/schedules/triggers/backlog-executor.md +102 -0
- package/schedules/triggers/brand-steward.md +72 -0
- package/schedules/triggers/daily-evening-wrap.md +159 -0
- package/schedules/triggers/daily-midday-sweep.md +58 -0
- package/schedules/triggers/daily-morning-brief.md +55 -0
- package/schedules/triggers/directory-hygiene.md +81 -0
- package/schedules/triggers/dynamic-jobs.md +40 -0
- package/schedules/triggers/inbox-processor.md +115 -0
- package/schedules/triggers/meeting-action-capture.md +60 -0
- package/schedules/triggers/meeting-prep.md +69 -0
- package/schedules/triggers/messaging-inbound.md +50 -0
- package/schedules/triggers/org-pulse.md +24 -0
- package/schedules/triggers/quarterly-self-assessment.md +54 -0
- package/schedules/triggers/weekly-engineering-health.md +37 -0
- package/schedules/triggers/weekly-execution.md +65 -0
- package/schedules/triggers/weekly-hiring.md +53 -0
- package/schedules/triggers/weekly-priorities.md +38 -0
- package/schedules/triggers/weekly-strategic-memo.md +124 -0
- package/scripts/archive-email.sh +55 -0
- package/scripts/cadence/cadence-status.mjs +36 -0
- package/scripts/cadence/enqueue-cadence-tick.mjs +174 -0
- package/scripts/cadence/enqueue-cadence-tick.test.mjs +187 -0
- package/scripts/cadence/launchd-cadence-wrapper.sh +85 -0
- package/scripts/cadence/launchd-cloud-relay-wrapper.sh +95 -0
- package/scripts/cadence/launchd-socket-mode-wrapper.sh +95 -0
- package/scripts/ci/check-docs-accuracy.mjs +493 -0
- package/scripts/ci/check-docs-accuracy.test.mjs +409 -0
- package/scripts/ci/check-exports-exist.mjs +140 -0
- package/scripts/ci/check-files-exist.mjs +107 -0
- package/scripts/ci/check-no-build-artifacts.mjs +111 -0
- package/scripts/ci/check-no-build-artifacts.test.mjs +71 -0
- package/scripts/ci/check-no-confidential.mjs +198 -0
- package/scripts/ci/check-no-conflict-markers.mjs +169 -0
- package/scripts/ci/check-no-residual-identity.mjs +163 -0
- package/scripts/ci/check-no-residual-identity.test.mjs +89 -0
- package/scripts/ci/check-tarball-fidelity.mjs +205 -0
- package/scripts/ci/check-unresolved-tokens.mjs +83 -0
- package/scripts/ci/check.mjs +109 -0
- package/scripts/ci/check.test.mjs +194 -0
- package/scripts/ci/run-coverage.mjs +82 -0
- package/scripts/ci/run-tests.mjs +71 -0
- package/scripts/cloud-relay/README.md +59 -0
- package/scripts/cloud-relay/index.mjs +233 -0
- package/scripts/cloud-relay/package.json +15 -0
- package/scripts/cloud-relay/railway.json +13 -0
- package/scripts/cloud-relay/voice/README.md +94 -0
- package/scripts/cloud-relay/voice/package-lock.json +39 -0
- package/scripts/cloud-relay/voice/package.json +16 -0
- package/scripts/cloud-relay/voice/railway.json +13 -0
- package/scripts/cloud-relay/voice/server.mjs +532 -0
- package/scripts/collective/hook-runner.mjs +211 -0
- package/scripts/collective/hook-runner.test.mjs +90 -0
- package/scripts/collective/org-pulse.mjs +72 -0
- package/scripts/collective/org-sync.mjs +61 -0
- package/scripts/collective/recall.mjs +45 -0
- package/scripts/collective/who.mjs +30 -0
- package/scripts/comms-monitor.sh +288 -0
- package/scripts/configure-whatsapp-sandbox.sh +201 -0
- package/scripts/continuous-monitor.sh +91 -0
- package/scripts/cost/fleet-digest.mjs +407 -0
- package/scripts/cost/fleet-digest.test.mjs +207 -0
- package/scripts/cost/track-claude-usage.mjs +169 -0
- package/scripts/daemon/agent-daemon.mjs +989 -0
- package/scripts/daemon/agent-daemon.test.mjs +525 -0
- package/scripts/daemon/cadence-consumer-governance.test.mjs +220 -0
- package/scripts/daemon/cadence-consumer.mjs +1080 -0
- package/scripts/daemon/cadence-consumer.test.mjs +770 -0
- package/scripts/daemon/cadence-handlers.mjs +1121 -0
- package/scripts/daemon/cadence-handlers.test.mjs +617 -0
- package/scripts/daemon/classifier.mjs +704 -0
- package/scripts/daemon/classifier.test.mjs +238 -0
- package/scripts/daemon/classify-kind.mjs +54 -0
- package/scripts/daemon/classify-kind.test.mjs +40 -0
- package/scripts/daemon/context-compiler.mjs +605 -0
- package/scripts/daemon/context-compiler.test.mjs +300 -0
- package/scripts/daemon/dispatcher-cooldown.test.mjs +122 -0
- package/scripts/daemon/dispatcher-governance.test.mjs +886 -0
- package/scripts/daemon/dispatcher.mjs +1516 -0
- package/scripts/daemon/health.mjs +72 -0
- package/scripts/daemon/inbox-deferral.mjs +210 -0
- package/scripts/daemon/inbox-deferral.test.mjs +242 -0
- package/scripts/daemon/integration.test.mjs +149 -0
- package/scripts/daemon/launchd-wrapper-generic.sh +96 -0
- package/scripts/daemon/launchd-wrapper-slack-events.sh +37 -0
- package/scripts/daemon/launchd-wrapper.sh +91 -0
- package/scripts/daemon/lib/session-router.mjs +274 -0
- package/scripts/daemon/lib/session-router.test.mjs +295 -0
- package/scripts/daemon/maestro-daemon.mjs +275 -0
- package/scripts/daemon/prompt-builder.mjs +685 -0
- package/scripts/daemon/prompt-builder.test.mjs +213 -0
- package/scripts/daemon/responder.mjs +854 -0
- package/scripts/daemon/session-lock.mjs +721 -0
- package/scripts/daemon/session-lock.test.mjs +252 -0
- package/scripts/daemon/session-outcomes.mjs +640 -0
- package/scripts/daemon/session-outcomes.test.mjs +533 -0
- package/scripts/daemon/typing-registry.mjs +90 -0
- package/scripts/daemon/typing-registry.test.mjs +77 -0
- package/scripts/daemon/voice-webhook-server.mjs +804 -0
- package/scripts/decisions/capture-decision.mjs +116 -0
- package/scripts/disclosure_assessment.py +873 -0
- package/scripts/disclosure_boundaries.py +562 -0
- package/scripts/email-signature-principal.html +52 -0
- package/scripts/email-signature.html +60 -0
- package/scripts/email_quote_thread.py +167 -0
- package/scripts/email_thread_dedup.py +362 -0
- package/scripts/emergency-stop.sh +81 -0
- package/scripts/healthcheck.sh +116 -0
- package/scripts/hooks/block-mcp-cohort-send.sh +15 -0
- package/scripts/hooks/block-mcp-slack-send.sh +7 -0
- package/scripts/hooks/post-action-log.sh +126 -0
- package/scripts/hooks/pre-send-audit.sh +174 -0
- package/scripts/hooks/pre-send-audit.test.mjs +215 -0
- package/scripts/hooks/session-end-log.sh +27 -0
- package/scripts/hooks/session-start-banner.sh +115 -0
- package/scripts/huddle/audio-bridge.mjs +664 -0
- package/scripts/huddle/boot-slack-cdp.sh +102 -0
- package/scripts/huddle/huddle-controller.mjs +942 -0
- package/scripts/huddle/huddle-server.mjs +1229 -0
- package/scripts/huddle/launch-slack.sh +232 -0
- package/scripts/huddle/openai-realtime-bridge.mjs +462 -0
- package/scripts/huddle/package-lock.json +62 -0
- package/scripts/huddle/package.json +22 -0
- package/scripts/huddle/setup-audio.sh +239 -0
- package/scripts/huddle/start-call.mjs +318 -0
- package/scripts/huddle/test-pipeline.mjs +263 -0
- package/scripts/learning/consolidate-skills.mjs +72 -0
- package/scripts/learning/session-search.mjs +125 -0
- package/scripts/llm_email_dedup.py +442 -0
- package/scripts/local-triggers/generate-plists.sh +432 -0
- package/scripts/local-triggers/generate-plists.test.mjs +413 -0
- package/scripts/local-triggers/install-all.sh +49 -0
- package/scripts/local-triggers/plists/.gitkeep +0 -0
- package/scripts/local-triggers/run-trigger.sh +63 -0
- package/scripts/local-triggers/templates/rag-reindex.plist.template +47 -0
- package/scripts/local-triggers/templates/voice-relay-poller.plist.template +54 -0
- package/scripts/local-triggers/templates/voice-tunnel.plist.template +55 -0
- package/scripts/local-triggers/templates/voice-webhook.plist.template +51 -0
- package/scripts/maintenance/backup-to-cloud.sh +124 -0
- package/scripts/maintenance/health-check.sh +377 -0
- package/scripts/media-generation/README.md +105 -0
- package/scripts/media-generation/gemini-image-client.mjs +173 -0
- package/scripts/media-generation/generate-assets.mjs +289 -0
- package/scripts/media-generation/veo-video-client.mjs +219 -0
- package/scripts/org/send-orgmail.mjs +227 -0
- package/scripts/outbound-dedup-cleanup.sh +43 -0
- package/scripts/outbound-dedup.sh +477 -0
- package/scripts/outbound_dedup.py +115 -0
- package/scripts/parse-voice-transcript.mjs +481 -0
- package/scripts/pdf-generation/README.md +63 -0
- package/scripts/pdf-generation/build-document.mjs +247 -0
- package/scripts/pdf-generation/templates/board-pack.latex +136 -0
- package/scripts/pdf-generation/templates/corporate-letter.latex +126 -0
- package/scripts/pdf-generation/templates/memo.latex +114 -0
- package/scripts/poll-slack-events.sh +35 -0
- package/scripts/poller/calendar-poller.mjs +12 -0
- package/scripts/poller/gmail-poller.mjs +192 -0
- package/scripts/poller/imap-client.mjs +289 -0
- package/scripts/poller/inbox-scan-poller.mjs +156 -0
- package/scripts/poller/inbox-scan-poller.test.mjs +231 -0
- package/scripts/poller/index.mjs +73 -0
- package/scripts/poller/intra-session-check.mjs +285 -0
- package/scripts/poller/lib/cloud-relay-dedup.mjs +88 -0
- package/scripts/poller/lib/cloud-relay-dedup.test.mjs +133 -0
- package/scripts/poller/lib/slash-command-handlers.mjs +177 -0
- package/scripts/poller/secondary-gmail-poller.mjs +132 -0
- package/scripts/poller/slack-cloud-relay-client.mjs +368 -0
- package/scripts/poller/slack-poller.mjs +854 -0
- package/scripts/poller/slack-socket-mode.mjs +917 -0
- package/scripts/poller/slack-socket-mode.test.mjs +753 -0
- package/scripts/poller/trigger.mjs +75 -0
- package/scripts/poller/utils.mjs +371 -0
- package/scripts/poller/voice-cloud-relay-client.mjs +179 -0
- package/scripts/poller/voice-poller.mjs +236 -0
- package/scripts/poller-launchd/install.sh +66 -0
- package/scripts/poller-launchd/poller.plist.template +40 -0
- package/scripts/poller-launchd/whatsapp-handler.plist.template +39 -0
- package/scripts/post-interaction-indexer.py +1598 -0
- package/scripts/pre-draft-context.py +994 -0
- package/scripts/pre_draft_lookup.py +258 -0
- package/scripts/rag/build-index.mjs +47 -0
- package/scripts/rag/ingest.mjs +111 -0
- package/scripts/rag/search.mjs +119 -0
- package/scripts/rag-indexer.py +629 -0
- package/scripts/restore-from-backup.sh +248 -0
- package/scripts/restore-from-backup.test.mjs +178 -0
- package/scripts/resume-operations.sh +80 -0
- package/scripts/search-secondary-inbox.py +181 -0
- package/scripts/secondary-inbox-poller.py +437 -0
- package/scripts/self-optimization/compute-metrics.py +398 -0
- package/scripts/send-email-as-principal.py +369 -0
- package/scripts/send-email-threaded.py +392 -0
- package/scripts/send-email-with-attachment.py +377 -0
- package/scripts/send-email.sh +131 -0
- package/scripts/send-sms.sh +175 -0
- package/scripts/send-whatsapp.sh +292 -0
- package/scripts/session-start.sh +106 -0
- package/scripts/setup/boot-claude-session.sh +94 -0
- package/scripts/setup/configure-macos.sh +674 -0
- package/scripts/setup/configure-twilio-sip-trunk.mjs +207 -0
- package/scripts/setup/configure-voice-tunnel.mjs +182 -0
- package/scripts/setup/generate-agent-env.mjs +92 -0
- package/scripts/setup/generate-agent-package-json.mjs +222 -0
- package/scripts/setup/generate-agent-package-json.test.mjs +143 -0
- package/scripts/setup/generate-autonomy.mjs +60 -0
- package/scripts/setup/generate-backlog.mjs +101 -0
- package/scripts/setup/generate-cadences.mjs +92 -0
- package/scripts/setup/generate-capability.mjs +162 -0
- package/scripts/setup/generate-charter.mjs +76 -0
- package/scripts/setup/generate-comms.mjs +59 -0
- package/scripts/setup/generate-company.mjs +92 -0
- package/scripts/setup/init-agent.sh +547 -0
- package/scripts/setup/init-agent.test.mjs +151 -0
- package/scripts/setup/init-archetype.mjs +74 -0
- package/scripts/setup/init-backup.mjs +54 -0
- package/scripts/setup/init-cadence-bus.mjs +60 -0
- package/scripts/setup/init-channel-bus.mjs +46 -0
- package/scripts/setup/init-cost-tracking.mjs +45 -0
- package/scripts/setup/init-decision-capture.mjs +66 -0
- package/scripts/setup/init-known-agents.mjs +57 -0
- package/scripts/setup/init-learning.mjs +70 -0
- package/scripts/setup/init-memory-executive.mjs +45 -0
- package/scripts/setup/init-model-router.mjs +124 -0
- package/scripts/setup/init-rag.mjs +174 -0
- package/scripts/setup/init-session-router.mjs +38 -0
- package/scripts/setup/init-slack-socket-mode.mjs +260 -0
- package/scripts/setup/init-telegram.mjs +165 -0
- package/scripts/setup/init-voice-realtime.mjs +204 -0
- package/scripts/setup/init-whatsapp-baileys.mjs +77 -0
- package/scripts/setup/install-dev-tools.sh +150 -0
- package/scripts/setup/lib/install-plist.mjs +95 -0
- package/scripts/setup/migrate-agent-to-sot.mjs +192 -0
- package/scripts/setup/render-environment-yaml.mjs +133 -0
- package/scripts/slack-events-ctl.sh +177 -0
- package/scripts/slack-events-server.mjs +1045 -0
- package/scripts/slack-react.mjs +89 -0
- package/scripts/slack-responded.sh +232 -0
- package/scripts/slack-send.sh +287 -0
- package/scripts/slack-typing.mjs +196 -0
- package/scripts/slack-upload-v2.py +95 -0
- package/scripts/sms-handler.mjs +450 -0
- package/scripts/spawn-session.sh +120 -0
- package/scripts/sync-protocol.mjs +217 -0
- package/scripts/system-verify.sh +184 -0
- package/scripts/test-email-thread-dedup.py +239 -0
- package/scripts/test-information-barriers.py +484 -0
- package/scripts/test-llm-email-dedup.py +251 -0
- package/scripts/test-pre-draft-integration.py +203 -0
- package/scripts/test-rag-phase2.sh +442 -0
- package/scripts/test-rag-search.sh +251 -0
- package/scripts/test-voice-parser.mjs +316 -0
- package/scripts/user-context-search.py +659 -0
- package/scripts/validate_outbound.py +1504 -0
- package/scripts/watchdog/ai.maestro.memory-watchdog.plist +41 -0
- package/scripts/watchdog/force-reboot.sh +157 -0
- package/scripts/watchdog/memory-watchdog.sh +473 -0
- package/scripts/whatsapp-handler.mjs +538 -0
- package/teams/desktop-operations.yaml +34 -0
- package/teams/executive-office.yaml +27 -0
- package/teams/legal-and-regulatory.yaml +24 -0
- package/teams/platform-and-engineering.yaml +23 -0
- package/teams/strategy-and-growth.yaml +29 -0
- package/workflows/continuous/backlog-executor.yaml +141 -0
- package/workflows/continuous/inbound-monitor.yaml +168 -0
- package/workflows/daily/applicant-triage.yaml +197 -0
- package/workflows/daily/comms-triage.yaml +80 -0
- package/workflows/daily/evening-wrap.yaml +105 -0
- package/workflows/daily/morning-brief.yaml +164 -0
- package/workflows/daily/slack-followup-sweep.yaml +87 -0
- package/workflows/event-driven/README.md +50 -0
- package/workflows/event-driven/agent-failure-investigation.yaml +137 -0
- package/workflows/event-driven/pr-review.yaml +107 -0
- package/workflows/monthly/board-readiness.yaml +76 -0
- package/workflows/quarterly/strategic-scenario-analysis.yaml +85 -0
- package/workflows/session-protocol.md +171 -0
- package/workflows/weekly/engineering-health.yaml +154 -0
- package/workflows/weekly/hiring-review.yaml +169 -0
- package/workflows/weekly/rollup-pipeline-review.yaml +76 -0
- package/workflows/weekly/strategic-memo.yaml +79 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* context-compiler.mjs — Pre-compiles all relevant context for a daemon-spawned session.
|
|
4
|
+
*
|
|
5
|
+
* Single export: compileContext(item, classResult, options)
|
|
6
|
+
*
|
|
7
|
+
* Assembles sender profile, disclosure boundaries, conversation history,
|
|
8
|
+
* active sessions, and sent-message registry into a single context block.
|
|
9
|
+
* Filters history entries by information barrier domains.
|
|
10
|
+
*
|
|
11
|
+
* Adaptive token budget: 12K for critical/high, 8K for normal, 4K for low.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { readFileSync, readdirSync } from "fs";
|
|
15
|
+
import { join } from "path";
|
|
16
|
+
import { isEnabled as orgEnabled, loadOrgConfig } from "../../lib/org/client.mjs";
|
|
17
|
+
import { recall as orgRecall } from "../../lib/org/knowledge.mjs";
|
|
18
|
+
|
|
19
|
+
const AGENT_REPO_DIR = process.env.__TEST_AGENT_DIR || process.env.AGENT_DIR || join(new URL(".", import.meta.url).pathname, "../..");
|
|
20
|
+
const SESSION_DIR = process.env.__TEST_SESSION_DIR || join(AGENT_REPO_DIR, "state", "sessions");
|
|
21
|
+
const CHARS_PER_TOKEN = 4;
|
|
22
|
+
|
|
23
|
+
// ── Org shared-memory (central store via knowledge.* RPC) ───────────
|
|
24
|
+
// The compiled context draws not only from local files but from the org's
|
|
25
|
+
// shared, ACL'd memory plane. Bounded so a large recall can never blow up the
|
|
26
|
+
// prompt: at most this many facts, each truncated. The SERVER enforces ACL —
|
|
27
|
+
// we render exactly what recall() returns.
|
|
28
|
+
const ORG_RECALL_MAX_FACTS = 6;
|
|
29
|
+
const ORG_RECALL_FACT_CHARS = 400;
|
|
30
|
+
|
|
31
|
+
// ── Token budgets by priority ──────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
const TOKEN_BUDGETS = {
|
|
34
|
+
critical: 12000,
|
|
35
|
+
high: 12000,
|
|
36
|
+
normal: 8000,
|
|
37
|
+
low: 4000,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Fixed allocations (in tokens)
|
|
41
|
+
const ALLOC = {
|
|
42
|
+
profile: 500,
|
|
43
|
+
boundaries: 300,
|
|
44
|
+
active_sessions: 300,
|
|
45
|
+
sent_registry: 500,
|
|
46
|
+
org_memory: 600,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// History gets 60% of remaining budget
|
|
50
|
+
const HISTORY_SHARE = 0.6;
|
|
51
|
+
|
|
52
|
+
// ── Helpers ────────────────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Extract Slack channel ID from item metadata.
|
|
56
|
+
*/
|
|
57
|
+
function extractChannelId(item) {
|
|
58
|
+
if (!item) return null;
|
|
59
|
+
if (item.channel_id) return item.channel_id;
|
|
60
|
+
if (item.raw_ref) {
|
|
61
|
+
const match = item.raw_ref.match(/slack:([DC][A-Z0-9]+):/);
|
|
62
|
+
if (match) return match[1];
|
|
63
|
+
}
|
|
64
|
+
if (item.channel && /^[DC][A-Z0-9]{8,}$/.test(item.channel)) return item.channel;
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Read a YAML file and truncate to a character budget. Returns null if missing.
|
|
70
|
+
*/
|
|
71
|
+
function loadUserProfile(senderSlug, budgetTokens) {
|
|
72
|
+
if (!senderSlug) return null;
|
|
73
|
+
try {
|
|
74
|
+
const filePath = join(AGENT_REPO_DIR, "memory", "profiles", "users", `${senderSlug}.yaml`);
|
|
75
|
+
let raw = readFileSync(filePath, "utf-8");
|
|
76
|
+
const charBudget = budgetTokens * CHARS_PER_TOKEN;
|
|
77
|
+
if (raw.length > charBudget) {
|
|
78
|
+
raw = raw.substring(0, charBudget) + "\n...(truncated)";
|
|
79
|
+
}
|
|
80
|
+
return raw;
|
|
81
|
+
} catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ── Domain / disclosure helpers ────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Parse domain descriptions from information-barriers.yaml using regex.
|
|
90
|
+
* Returns a Map of domain -> description.
|
|
91
|
+
*/
|
|
92
|
+
function loadDomainDescriptions() {
|
|
93
|
+
try {
|
|
94
|
+
const filePath = join(AGENT_REPO_DIR, "policies", "information-barriers.yaml");
|
|
95
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
96
|
+
const map = new Map();
|
|
97
|
+
const regex = /^\s{2}([\w-]+):\s*\n\s+description:\s*"(.+?)"/gm;
|
|
98
|
+
let match;
|
|
99
|
+
while ((match = regex.exec(raw)) !== null) {
|
|
100
|
+
map.set(match[1], match[2]);
|
|
101
|
+
}
|
|
102
|
+
return map;
|
|
103
|
+
} catch {
|
|
104
|
+
return new Map();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get all domain names except "public".
|
|
110
|
+
*/
|
|
111
|
+
function getAllDomains() {
|
|
112
|
+
const descriptions = loadDomainDescriptions();
|
|
113
|
+
return [...descriptions.keys()].filter((d) => d !== "public");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Common words to exclude from keyword matching (4+ chars)
|
|
117
|
+
const COMMON_WORDS = new Set([
|
|
118
|
+
"this", "that", "with", "from", "have", "been", "will", "more", "when",
|
|
119
|
+
"were", "some", "them", "than", "each", "make", "like", "over", "such",
|
|
120
|
+
"take", "only", "come", "into", "also", "back", "after", "would", "what",
|
|
121
|
+
"your", "about", "could", "their", "which", "other", "there", "first",
|
|
122
|
+
"does", "these", "should", "through", "where", "being", "those",
|
|
123
|
+
"between", "before", "under", "still",
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Build a map of domain -> keyword array from domain descriptions.
|
|
128
|
+
* Words must be 4+ chars and not in the common-words exclusion list.
|
|
129
|
+
*/
|
|
130
|
+
function buildDomainKeywords() {
|
|
131
|
+
const descriptions = loadDomainDescriptions();
|
|
132
|
+
const result = new Map();
|
|
133
|
+
for (const [domain, desc] of descriptions) {
|
|
134
|
+
if (domain === "public") continue;
|
|
135
|
+
const words = desc
|
|
136
|
+
.toLowerCase()
|
|
137
|
+
.replace(/[^a-z0-9\s-]/g, "")
|
|
138
|
+
.split(/\s+/)
|
|
139
|
+
.filter((w) => w.length >= 4 && !COMMON_WORDS.has(w));
|
|
140
|
+
// Deduplicate
|
|
141
|
+
result.set(domain, [...new Set(words)]);
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Returns true if the text matches 2+ keywords from any forbidden domain.
|
|
148
|
+
*/
|
|
149
|
+
function matchesForbiddenDomain(text, forbiddenDomains, domainKeywords) {
|
|
150
|
+
if (!forbiddenDomains || forbiddenDomains.length === 0) return false;
|
|
151
|
+
if (!text) return false;
|
|
152
|
+
const lower = text.toLowerCase();
|
|
153
|
+
for (const domain of forbiddenDomains) {
|
|
154
|
+
const keywords = domainKeywords.get(domain);
|
|
155
|
+
if (!keywords) continue;
|
|
156
|
+
let hits = 0;
|
|
157
|
+
for (const kw of keywords) {
|
|
158
|
+
if (lower.includes(kw)) {
|
|
159
|
+
hits++;
|
|
160
|
+
if (hits >= 2) return true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Load disclosure boundaries for a sender.
|
|
169
|
+
* Returns { boundariesSection, forbiddenDomains }.
|
|
170
|
+
*/
|
|
171
|
+
function loadDisclosureBoundaries(senderSlug, budgetTokens) {
|
|
172
|
+
// Attempt to load profile
|
|
173
|
+
let privilegeLevel = null;
|
|
174
|
+
let excludedDomains = [];
|
|
175
|
+
|
|
176
|
+
if (senderSlug) {
|
|
177
|
+
try {
|
|
178
|
+
const filePath = join(AGENT_REPO_DIR, "memory", "profiles", "users", `${senderSlug}.yaml`);
|
|
179
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
180
|
+
|
|
181
|
+
// Extract privilege_level via regex
|
|
182
|
+
const privMatch = raw.match(/privilege_level:\s*(\S+)/);
|
|
183
|
+
if (privMatch) privilegeLevel = privMatch[1];
|
|
184
|
+
|
|
185
|
+
// Extract excluded_domains list
|
|
186
|
+
const exclMatch = raw.match(/excluded_domains:\s*\n((?:\s+-\s+\S+\n?)*)/);
|
|
187
|
+
if (exclMatch) {
|
|
188
|
+
excludedDomains = exclMatch[1]
|
|
189
|
+
.split("\n")
|
|
190
|
+
.map((line) => line.replace(/^\s*-\s*/, "").trim())
|
|
191
|
+
.filter(Boolean);
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
// No profile — unknown sender
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// CEO gets no restrictions
|
|
199
|
+
if (privilegeLevel === "ceo") {
|
|
200
|
+
return { boundariesSection: null, forbiddenDomains: [] };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// No profile or unknown → restrict to "public" only (forbid all other domains)
|
|
204
|
+
let forbiddenDomains;
|
|
205
|
+
if (!privilegeLevel) {
|
|
206
|
+
forbiddenDomains = getAllDomains();
|
|
207
|
+
} else {
|
|
208
|
+
// Has profile with explicit excluded_domains
|
|
209
|
+
forbiddenDomains = excludedDomains.length > 0 ? excludedDomains : [];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (forbiddenDomains.length === 0) {
|
|
213
|
+
return { boundariesSection: null, forbiddenDomains: [] };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Build human-readable section
|
|
217
|
+
const descriptions = loadDomainDescriptions();
|
|
218
|
+
const lines = ["DO NOT mention or disclose information related to:"];
|
|
219
|
+
for (const domain of forbiddenDomains) {
|
|
220
|
+
const desc = descriptions.get(domain) || domain;
|
|
221
|
+
lines.push(`- ${domain}: ${desc}`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
let section = lines.join("\n");
|
|
225
|
+
const charBudget = budgetTokens * CHARS_PER_TOKEN;
|
|
226
|
+
if (section.length > charBudget) {
|
|
227
|
+
section = section.substring(0, charBudget) + "\n...(truncated)";
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return { boundariesSection: section, forbiddenDomains };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ── Conversation history ───────────────────────────────────────────
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Load conversation history from interaction logs, filtered by disclosure boundaries.
|
|
237
|
+
*/
|
|
238
|
+
function loadConversationHistory(senderSlug, channelId, budgetTokens, forbiddenDomains) {
|
|
239
|
+
const candidateDirs = [];
|
|
240
|
+
if (channelId) candidateDirs.push(join(AGENT_REPO_DIR, "memory", "interactions", "slack", channelId));
|
|
241
|
+
if (senderSlug) {
|
|
242
|
+
candidateDirs.push(join(AGENT_REPO_DIR, "memory", "interactions", "slack", `dm-${senderSlug}`));
|
|
243
|
+
candidateDirs.push(join(AGENT_REPO_DIR, "memory", "interactions", "slack", senderSlug));
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const entries = [];
|
|
247
|
+
const seenKeys = new Set();
|
|
248
|
+
|
|
249
|
+
for (const dir of candidateDirs) {
|
|
250
|
+
try {
|
|
251
|
+
const files = readdirSync(dir)
|
|
252
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
253
|
+
.sort()
|
|
254
|
+
.reverse()
|
|
255
|
+
.slice(0, 3); // Today + yesterday + day before
|
|
256
|
+
|
|
257
|
+
for (const file of files) {
|
|
258
|
+
try {
|
|
259
|
+
const content = readFileSync(join(dir, file), "utf-8").trim();
|
|
260
|
+
if (!content) continue;
|
|
261
|
+
const lines = content.split("\n").filter(Boolean);
|
|
262
|
+
for (const line of lines) {
|
|
263
|
+
try {
|
|
264
|
+
const entry = JSON.parse(line);
|
|
265
|
+
// Deduplicate by ts:from key
|
|
266
|
+
const dedupKey = `${entry.ts || ""}:${entry.from || entry.sender || ""}`;
|
|
267
|
+
if (seenKeys.has(dedupKey)) continue;
|
|
268
|
+
seenKeys.add(dedupKey);
|
|
269
|
+
entries.push(entry);
|
|
270
|
+
} catch { /* skip malformed lines */ }
|
|
271
|
+
}
|
|
272
|
+
} catch { /* skip unreadable files */ }
|
|
273
|
+
}
|
|
274
|
+
} catch { /* dir doesn't exist — try next */ }
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (entries.length === 0) return null;
|
|
278
|
+
|
|
279
|
+
// Sort chronologically
|
|
280
|
+
entries.sort((a, b) => {
|
|
281
|
+
const tsA = a.ts || a.received_at || a.timestamp || "";
|
|
282
|
+
const tsB = b.ts || b.received_at || b.timestamp || "";
|
|
283
|
+
return tsA.localeCompare(tsB);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// Filter by disclosure boundaries
|
|
287
|
+
const domainKeywords = buildDomainKeywords();
|
|
288
|
+
const filtered = entries.filter((entry) => {
|
|
289
|
+
const text = entry.content || entry.text || "";
|
|
290
|
+
return !matchesForbiddenDomain(text, forbiddenDomains, domainKeywords);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (filtered.length === 0) return null;
|
|
294
|
+
|
|
295
|
+
// Truncate to character budget — most recent messages prioritised (iterate from end)
|
|
296
|
+
const charBudget = budgetTokens * CHARS_PER_TOKEN;
|
|
297
|
+
const outputLines = [];
|
|
298
|
+
let totalChars = 0;
|
|
299
|
+
|
|
300
|
+
for (let i = filtered.length - 1; i >= 0; i--) {
|
|
301
|
+
const entry = filtered[i];
|
|
302
|
+
const from = entry.from || entry.sender || entry.user_name || "unknown";
|
|
303
|
+
const text = entry.content || entry.text || "(no text)";
|
|
304
|
+
const ts = entry.received_at || entry.timestamp || entry.processed_at || entry.ts || "";
|
|
305
|
+
const responded = entry.response_sent ? " [Responded]" : "";
|
|
306
|
+
const line = `[${ts}] ${from}: ${text.substring(0, 500)}${responded}`;
|
|
307
|
+
|
|
308
|
+
if (totalChars + line.length > charBudget) break;
|
|
309
|
+
outputLines.unshift(line);
|
|
310
|
+
totalChars += line.length;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return outputLines.length > 0 ? outputLines.join("\n") : null;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ── Active sessions ────────────────────────────────────────────────
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Load active sessions and format as bullet list.
|
|
320
|
+
*/
|
|
321
|
+
function loadActiveSessions(budgetTokens) {
|
|
322
|
+
try {
|
|
323
|
+
const filePath = join(SESSION_DIR, "active.json");
|
|
324
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
325
|
+
const data = JSON.parse(raw);
|
|
326
|
+
|
|
327
|
+
// data may be an object with session entries or an array
|
|
328
|
+
const sessions = Array.isArray(data) ? data : Object.values(data);
|
|
329
|
+
if (sessions.length === 0) return null;
|
|
330
|
+
|
|
331
|
+
const lines = [];
|
|
332
|
+
const charBudget = budgetTokens * CHARS_PER_TOKEN;
|
|
333
|
+
let totalChars = 0;
|
|
334
|
+
|
|
335
|
+
for (const sess of sessions) {
|
|
336
|
+
const id = sess.sessionId || sess.id || "unknown";
|
|
337
|
+
const summary = sess.summary || sess.task || "no summary";
|
|
338
|
+
const model = sess.model || "unknown";
|
|
339
|
+
const sender = sess.sender || sess.owner || "unknown";
|
|
340
|
+
const started = sess.startTime || sess.started_at || "";
|
|
341
|
+
let age = "";
|
|
342
|
+
if (started) {
|
|
343
|
+
const ms = Date.now() - new Date(started).getTime();
|
|
344
|
+
const mins = Math.round(ms / 60000);
|
|
345
|
+
age = `${mins}m ago`;
|
|
346
|
+
}
|
|
347
|
+
const line = `- ${id}: ${summary} (model=${model}, sender=${sender}${age ? ", " + age : ""})`;
|
|
348
|
+
if (totalChars + line.length > charBudget) break;
|
|
349
|
+
lines.push(line);
|
|
350
|
+
totalChars += line.length;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return lines.length > 0 ? lines.join("\n") : null;
|
|
354
|
+
} catch {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ── Sent registry ──────────────────────────────────────────────────
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Load recent sent-registry entries for the same channel.
|
|
363
|
+
*/
|
|
364
|
+
function loadSentRegistry(channelId, budgetTokens) {
|
|
365
|
+
if (!channelId) return null;
|
|
366
|
+
try {
|
|
367
|
+
const filePath = join(SESSION_DIR, "sent-registry.jsonl");
|
|
368
|
+
const raw = readFileSync(filePath, "utf-8").trim();
|
|
369
|
+
if (!raw) return null;
|
|
370
|
+
|
|
371
|
+
const allLines = raw.split("\n").filter(Boolean);
|
|
372
|
+
const matching = [];
|
|
373
|
+
for (const line of allLines) {
|
|
374
|
+
try {
|
|
375
|
+
const entry = JSON.parse(line);
|
|
376
|
+
if (entry.channelId === channelId || entry.channel_id === channelId || entry.channel === channelId) {
|
|
377
|
+
matching.push(entry);
|
|
378
|
+
}
|
|
379
|
+
} catch { /* skip malformed */ }
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Take last 20
|
|
383
|
+
const recent = matching.slice(-20);
|
|
384
|
+
if (recent.length === 0) return null;
|
|
385
|
+
|
|
386
|
+
const charBudget = budgetTokens * CHARS_PER_TOKEN;
|
|
387
|
+
const lines = [];
|
|
388
|
+
let totalChars = 0;
|
|
389
|
+
|
|
390
|
+
for (const entry of recent) {
|
|
391
|
+
const ts = entry.timestamp || entry.sent_at || "";
|
|
392
|
+
const type = entry.type || entry.action || "message";
|
|
393
|
+
const preview = (entry.preview || entry.content || entry.text || "").substring(0, 100);
|
|
394
|
+
const line = `[${ts}] (${type}) ${preview}`;
|
|
395
|
+
if (totalChars + line.length > charBudget) break;
|
|
396
|
+
lines.push(line);
|
|
397
|
+
totalChars += line.length;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return lines.length > 0 ? lines.join("\n") : null;
|
|
401
|
+
} catch {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// ── Org shared memory ──────────────────────────────────────────────
|
|
407
|
+
|
|
408
|
+
// Cached org config (config/org.yaml) — read once per process. undefined until loaded.
|
|
409
|
+
let cachedOrgCfg;
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Load the org config for the recall binding, cached for the process. Returns {}
|
|
413
|
+
* on any error so callers can null-check uniformly — the org binding must never
|
|
414
|
+
* take down the daemon's main path.
|
|
415
|
+
*/
|
|
416
|
+
function loadCachedOrgCfg() {
|
|
417
|
+
if (cachedOrgCfg !== undefined) return cachedOrgCfg;
|
|
418
|
+
try {
|
|
419
|
+
cachedOrgCfg = loadOrgConfig(AGENT_REPO_DIR) || {};
|
|
420
|
+
} catch {
|
|
421
|
+
cachedOrgCfg = {};
|
|
422
|
+
}
|
|
423
|
+
return cachedOrgCfg;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/** For tests: reset the cached org config so a fresh config/org.yaml is re-read. */
|
|
427
|
+
export function _resetOrgCfgCache() {
|
|
428
|
+
cachedOrgCfg = undefined;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Derive a short recall query from the item / classification being processed.
|
|
433
|
+
* Prefers the classifier summary, then subject, then a slice of the body.
|
|
434
|
+
*/
|
|
435
|
+
function recallQueryFor(item, classResult, queueItem) {
|
|
436
|
+
const parts = [];
|
|
437
|
+
if (classResult && classResult.summary) parts.push(String(classResult.summary));
|
|
438
|
+
if (item && item.subject) parts.push(String(item.subject));
|
|
439
|
+
if (queueItem && queueItem.title) parts.push(String(queueItem.title));
|
|
440
|
+
if (parts.length === 0 && item && item.content) parts.push(String(item.content).slice(0, 200));
|
|
441
|
+
return parts.join(" — ").trim();
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Read the org's shared memory (central store, `knowledge.search` RPC) for this
|
|
446
|
+
* item's topic and render it as a bounded, clearly-delimited section, or null
|
|
447
|
+
* when disabled / nothing relevant came back. Fail-open: never throws. The
|
|
448
|
+
* SERVER enforces ACL — we render exactly what recall() returns.
|
|
449
|
+
*
|
|
450
|
+
* @param {object} item
|
|
451
|
+
* @param {object} classResult
|
|
452
|
+
* @param {number} budgetTokens
|
|
453
|
+
* @param {object} [opts] - { cfg?, recallImpl?, queueItem? } — injectable for tests
|
|
454
|
+
* @returns {Promise<string|null>}
|
|
455
|
+
*/
|
|
456
|
+
async function loadOrgMemory(item, classResult, budgetTokens, opts = {}) {
|
|
457
|
+
try {
|
|
458
|
+
const cfg = opts.cfg !== undefined ? opts.cfg : loadCachedOrgCfg();
|
|
459
|
+
if (!orgEnabled(cfg)) return null;
|
|
460
|
+
const query = recallQueryFor(item, classResult, opts.queueItem);
|
|
461
|
+
if (!query) return null;
|
|
462
|
+
|
|
463
|
+
const recallImpl = opts.recallImpl || orgRecall;
|
|
464
|
+
const facts = await recallImpl(query, { cfg, limit: ORG_RECALL_MAX_FACTS });
|
|
465
|
+
if (!Array.isArray(facts) || facts.length === 0) return null;
|
|
466
|
+
|
|
467
|
+
const charBudget = budgetTokens * CHARS_PER_TOKEN;
|
|
468
|
+
const lines = [
|
|
469
|
+
"Facts the org already knows that may bear on this item (ACL-filtered by the",
|
|
470
|
+
"server; treat as trusted internal context):",
|
|
471
|
+
];
|
|
472
|
+
let n = 0;
|
|
473
|
+
let totalChars = lines.join("\n").length;
|
|
474
|
+
for (const f of facts) {
|
|
475
|
+
if (n >= ORG_RECALL_MAX_FACTS) break;
|
|
476
|
+
const textRaw = typeof f === "string" ? f : (f && (f.text || f.content || f.body) || "");
|
|
477
|
+
const text = String(textRaw).trim();
|
|
478
|
+
if (!text) continue;
|
|
479
|
+
const clipped = text.length > ORG_RECALL_FACT_CHARS ? `${text.slice(0, ORG_RECALL_FACT_CHARS)}…` : text;
|
|
480
|
+
const id = f && typeof f === "object" && f.id != null ? ` [${String(f.id)}]` : "";
|
|
481
|
+
const line = `- ${clipped}${id}`;
|
|
482
|
+
if (totalChars + line.length > charBudget) break;
|
|
483
|
+
lines.push(line);
|
|
484
|
+
totalChars += line.length;
|
|
485
|
+
n += 1;
|
|
486
|
+
}
|
|
487
|
+
return n > 0 ? lines.join("\n") : null;
|
|
488
|
+
} catch {
|
|
489
|
+
// Fail-open: org recall must never take down the context build.
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// ── Main export ────────────────────────────────────────────────────
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Compile all relevant context for a daemon session.
|
|
498
|
+
*
|
|
499
|
+
* @param {object} item - The inbox item or queue item being processed
|
|
500
|
+
* @param {object} classResult - Classification result with at least .priority
|
|
501
|
+
* @param {object} [options] - Optional overrides
|
|
502
|
+
* @returns {{ contextBlock: string, tokenBudget: number, tokenEstimate: number }}
|
|
503
|
+
*/
|
|
504
|
+
export async function compileContext(item, classResult, options = {}) {
|
|
505
|
+
try {
|
|
506
|
+
// Step 1 — Budget
|
|
507
|
+
const priority = classResult?.priority || "normal";
|
|
508
|
+
const tokenBudget = TOKEN_BUDGETS[priority] || TOKEN_BUDGETS.normal;
|
|
509
|
+
|
|
510
|
+
const senderSlug = item?.sender
|
|
511
|
+
? item.sender.replace(/\s+/g, "-").toLowerCase()
|
|
512
|
+
: null;
|
|
513
|
+
const channelId = extractChannelId(item);
|
|
514
|
+
|
|
515
|
+
// Step 2 — User profile
|
|
516
|
+
const profileText = loadUserProfile(senderSlug, ALLOC.profile);
|
|
517
|
+
|
|
518
|
+
// Step 3 — Disclosure boundaries
|
|
519
|
+
const { boundariesSection, forbiddenDomains } = loadDisclosureBoundaries(senderSlug, ALLOC.boundaries);
|
|
520
|
+
|
|
521
|
+
// Step 4 — Conversation history
|
|
522
|
+
const fixedTokens = ALLOC.profile + ALLOC.boundaries + ALLOC.active_sessions + ALLOC.sent_registry + ALLOC.org_memory;
|
|
523
|
+
const remainingTokens = tokenBudget - fixedTokens;
|
|
524
|
+
const historyBudget = Math.floor(remainingTokens * HISTORY_SHARE);
|
|
525
|
+
const historyText = loadConversationHistory(senderSlug, channelId, historyBudget, forbiddenDomains);
|
|
526
|
+
|
|
527
|
+
// Step 5 — Active sessions
|
|
528
|
+
const sessionsText = loadActiveSessions(ALLOC.active_sessions);
|
|
529
|
+
|
|
530
|
+
// Step 6 — Sent registry
|
|
531
|
+
const sentText = loadSentRegistry(channelId, ALLOC.sent_registry);
|
|
532
|
+
|
|
533
|
+
// Step 6b — Org shared memory (central store via knowledge.* RPC). Routed
|
|
534
|
+
// alongside the local reads; bounded + fail-open (a disabled/unreachable
|
|
535
|
+
// server or empty recall injects nothing). The `cfg`/`recallImpl` overrides
|
|
536
|
+
// let tests drive this deterministically without a live server.
|
|
537
|
+
const orgMemoryText = await loadOrgMemory(item, classResult, ALLOC.org_memory, {
|
|
538
|
+
cfg: options.orgCfg,
|
|
539
|
+
recallImpl: options.orgRecall,
|
|
540
|
+
queueItem: options.queueItem,
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
// Step 7 — Assemble
|
|
544
|
+
const sections = [];
|
|
545
|
+
sections.push("--- COMPILED CONTEXT (do not repeat verbatim) ---");
|
|
546
|
+
sections.push("");
|
|
547
|
+
|
|
548
|
+
if (profileText) {
|
|
549
|
+
sections.push("## Sender Profile");
|
|
550
|
+
sections.push(profileText);
|
|
551
|
+
sections.push("");
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (boundariesSection) {
|
|
555
|
+
sections.push("## Disclosure Boundaries");
|
|
556
|
+
sections.push(boundariesSection);
|
|
557
|
+
sections.push("");
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
if (orgMemoryText) {
|
|
561
|
+
sections.push("## Org Shared Memory");
|
|
562
|
+
sections.push(orgMemoryText);
|
|
563
|
+
sections.push("");
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
sections.push("## Conversation History (most recent last)");
|
|
567
|
+
sections.push(historyText || "No prior conversation history found.");
|
|
568
|
+
sections.push("");
|
|
569
|
+
|
|
570
|
+
if (sessionsText) {
|
|
571
|
+
sections.push("## Active Sessions");
|
|
572
|
+
sections.push(sessionsText);
|
|
573
|
+
sections.push("");
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (sentText) {
|
|
577
|
+
sections.push("## Already Sent");
|
|
578
|
+
sections.push(sentText);
|
|
579
|
+
sections.push("");
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
sections.push("--- END CONTEXT ---");
|
|
583
|
+
|
|
584
|
+
const contextBlock = sections.join("\n");
|
|
585
|
+
const tokenEstimate = Math.ceil(contextBlock.length / CHARS_PER_TOKEN);
|
|
586
|
+
|
|
587
|
+
return { contextBlock, tokenBudget, tokenEstimate };
|
|
588
|
+
} catch (err) {
|
|
589
|
+
// Never throw — return minimal context on error
|
|
590
|
+
const tokenBudget = TOKEN_BUDGETS[classResult?.priority] || TOKEN_BUDGETS.normal;
|
|
591
|
+
const contextBlock = [
|
|
592
|
+
"--- COMPILED CONTEXT (do not repeat verbatim) ---",
|
|
593
|
+
"",
|
|
594
|
+
"## Conversation History (most recent last)",
|
|
595
|
+
"No prior conversation history found.",
|
|
596
|
+
"",
|
|
597
|
+
"--- END CONTEXT ---",
|
|
598
|
+
].join("\n");
|
|
599
|
+
return {
|
|
600
|
+
contextBlock,
|
|
601
|
+
tokenBudget,
|
|
602
|
+
tokenEstimate: Math.ceil(contextBlock.length / CHARS_PER_TOKEN),
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
}
|