@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,503 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/org/messaging.mjs — the maestro seam for posting / @mentioning / calling
|
|
3
|
+
* ON Cohort (SP10).
|
|
4
|
+
*
|
|
5
|
+
* Why this exists
|
|
6
|
+
* ---------------
|
|
7
|
+
* The org protocol froze a `messaging.*` / `calling.*` surface (protocol.mjs)
|
|
8
|
+
* so a fleet of agents can participate in the org's OWN human messaging app —
|
|
9
|
+
* post a message, @mention a teammate, react, read channel history, and join /
|
|
10
|
+
* start a call — exactly as they already do on Slack/Telegram/WhatsApp. This
|
|
11
|
+
* module is the agent-side helper layer over that surface. It is to messaging
|
|
12
|
+
* what cost-sync.mjs is to cost.report: a thin, fail-open wrapper over
|
|
13
|
+
* lib/org/client.call/read that adds the cross-cutting policy + telemetry the
|
|
14
|
+
* raw RPC must not skip.
|
|
15
|
+
*
|
|
16
|
+
* Three invariants this layer enforces (and the raw client.call cannot):
|
|
17
|
+
*
|
|
18
|
+
* 1. EVERY outbound message runs lib/comms/send-gate.screenOutbound BEFORE the
|
|
19
|
+
* messaging.send RPC. A blocked message (banned phrase / AI-disclosure /
|
|
20
|
+
* information barrier / off-allowlist) is NOT sent — sendMessage returns a
|
|
21
|
+
* blocked frame and never touches the wire. This closes the same gap the
|
|
22
|
+
* send-gate closes for the channel adapters: the org messaging path is just
|
|
23
|
+
* another real send path, so it must run the one shared chokepoint.
|
|
24
|
+
*
|
|
25
|
+
* 2. After a successful send we emit `afterSend` on the typed hook bus
|
|
26
|
+
* (lib/hooks/bus.getHookBus) so audit/delivery-receipt subscribers observe
|
|
27
|
+
* the org messaging path like every other send. afterSend is observe-only
|
|
28
|
+
* (never cancellable) — the cancellable gate already ran in step 1.
|
|
29
|
+
*
|
|
30
|
+
* 3. We attribute the send to the cost ledger with `source: "messaging"` so the
|
|
31
|
+
* org rollup can see how much messaging the agent does. A plain message send
|
|
32
|
+
* is a ZERO-token, zero-LLM action, so the attributed row carries 0 spend —
|
|
33
|
+
* it is a COUNT/attribution row, not an LLM-spend row (the G16 honesty line
|
|
34
|
+
* stays intact: messaging is not an LLM-in-the-loop cost).
|
|
35
|
+
*
|
|
36
|
+
* Wire shape (frozen in protocol.mjs):
|
|
37
|
+
* messaging.send / .react / .edit — POST /v1/messaging.* (Bearer + x-org-protocol,
|
|
38
|
+
* x-idempotency-key on send — idempotent on the
|
|
39
|
+
* client-supplied message id).
|
|
40
|
+
* messaging.history / .channels — POST /v1/messaging.* (read scope, non-mutating).
|
|
41
|
+
* calling.start / .join / .invite / .end — POST /v1/calling.* (calling.write scope).
|
|
42
|
+
*
|
|
43
|
+
* Fail-open by design: a disabled/unreachable org server yields an error frame,
|
|
44
|
+
* never a throw — so the messaging path can never take down the agent. The
|
|
45
|
+
* send-gate, hook bus, and ledger are all injectable for deterministic tests.
|
|
46
|
+
*
|
|
47
|
+
* Node builtins + the existing maestro libs only. ESM.
|
|
48
|
+
*
|
|
49
|
+
* @module lib/org/messaging
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
"use strict";
|
|
53
|
+
|
|
54
|
+
import { isEnabled, configFromAgent, call, read } from "./client.mjs";
|
|
55
|
+
import { errFrame } from "./protocol.mjs";
|
|
56
|
+
import { screenOutbound } from "../comms/send-gate.mjs";
|
|
57
|
+
import { getHookBus } from "../hooks/bus.mjs";
|
|
58
|
+
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Internal helpers
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolve the {base, token} the RPC needs from an agent cfg, or null when the
|
|
65
|
+
* org integration is disabled / unconfigured (so the caller fails open).
|
|
66
|
+
* @param {object} cfg
|
|
67
|
+
* @returns {{base:string, token:string}|null}
|
|
68
|
+
*/
|
|
69
|
+
function resolveOrg(cfg) {
|
|
70
|
+
if (!isEnabled(cfg)) return null;
|
|
71
|
+
const c = configFromAgent(cfg);
|
|
72
|
+
if (!c.base) return null;
|
|
73
|
+
return { base: c.base, token: c.token };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** A best-effort agent id for ledger attribution (never throws). */
|
|
77
|
+
function agentIdOf(cfg) {
|
|
78
|
+
const n = (cfg && cfg.org && cfg.org.cohort) || {};
|
|
79
|
+
return n.agentId || n.id || (cfg && cfg.identity && cfg.identity.id) || (cfg && cfg.agentId) || null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Attribute a messaging action to the cost ledger with source="messaging".
|
|
84
|
+
* A message send is zero-token / zero-LLM, so the attributed row carries 0
|
|
85
|
+
* spend — it's a COUNT row, not an LLM-spend row. Fail-open and fully optional:
|
|
86
|
+
* the write is best-effort (writeLedgerRow never throws) and entirely skipped
|
|
87
|
+
* when an injected `ledger:null` opts out (tests / read-only callers).
|
|
88
|
+
*
|
|
89
|
+
* @param {object} o - { cfg, agentRoot, action, channel }
|
|
90
|
+
* @param {object} deps - { ledgerImpl?, catalog? } injectable for tests
|
|
91
|
+
*/
|
|
92
|
+
async function attributeMessaging(o, deps = {}) {
|
|
93
|
+
// Opt-out: an explicit `ledgerImpl: null` (or false) disables attribution.
|
|
94
|
+
if (Object.prototype.hasOwnProperty.call(deps, "ledgerImpl") && !deps.ledgerImpl) return;
|
|
95
|
+
try {
|
|
96
|
+
const writeLedgerRow =
|
|
97
|
+
deps.ledgerImpl || (await import("../model-router/ledger.mjs")).writeLedgerRow;
|
|
98
|
+
// No model is involved in a plain message send, so the catalog is empty and
|
|
99
|
+
// the row prices to $0 (estimated_usd:0). The attribution is the `source`.
|
|
100
|
+
writeLedgerRow(
|
|
101
|
+
deps.catalog || {},
|
|
102
|
+
{
|
|
103
|
+
agent: agentIdOf(o.cfg),
|
|
104
|
+
source: "messaging",
|
|
105
|
+
task_class: o.action || "messaging.send",
|
|
106
|
+
lane: o.channel || null,
|
|
107
|
+
inputTokens: 0,
|
|
108
|
+
outputTokens: 0,
|
|
109
|
+
exitReason: "ok",
|
|
110
|
+
},
|
|
111
|
+
{ agentRoot: o.agentRoot, now: deps.now }
|
|
112
|
+
);
|
|
113
|
+
} catch {
|
|
114
|
+
/* fail-open: attribution must never block or break a send */
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Emit afterSend on the hook bus (observe-only; never throws). */
|
|
119
|
+
async function emitAfterSend(ctx, deps = {}) {
|
|
120
|
+
try {
|
|
121
|
+
const bus = deps.hookBus || getHookBus();
|
|
122
|
+
await bus.emit("afterSend", ctx);
|
|
123
|
+
} catch {
|
|
124
|
+
/* fail-open: a broken subscriber must never break the send */
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// Messaging — send / react / history / channels
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Post a message to an org channel ON Cohort (messaging.send). THE outbound
|
|
134
|
+
* primitive — it runs the shared send-gate BEFORE the wire, emits afterSend on
|
|
135
|
+
* success, and attributes a source="messaging" ledger row.
|
|
136
|
+
*
|
|
137
|
+
* Flow:
|
|
138
|
+
* 1. resolve org enrollment (disabled ⇒ fail-open error frame, no send).
|
|
139
|
+
* 2. screenOutbound({channel, recipient:channel, text:body}) — a BLOCK returns
|
|
140
|
+
* a frame `{ok:false, error:{code:"FORBIDDEN_SCOPE"|"BAD_REQUEST", message}}`
|
|
141
|
+
* and the message is NEVER sent (no client.call).
|
|
142
|
+
* 3. messaging.send RPC (Bearer + x-org-protocol + x-idempotency-key from the
|
|
143
|
+
* client-supplied message id, so a retried send dedupes server-side).
|
|
144
|
+
* 4. on ok: emit afterSend + attribute the ledger row.
|
|
145
|
+
*
|
|
146
|
+
* @param {object} params
|
|
147
|
+
* @param {string} params.channel org channel id to post into
|
|
148
|
+
* @param {string} params.body the message text
|
|
149
|
+
* @param {string[]} [params.mentions] agent/user ids to @mention
|
|
150
|
+
* @param {string} [params.idempotencyId] stable client message id (idempotency key)
|
|
151
|
+
* @param {string} [params.threadId] reply within a thread
|
|
152
|
+
* @param {object} o - {
|
|
153
|
+
* cfg, agentRoot?, fetchImpl?,
|
|
154
|
+
* jurisdiction?, firstContact?, internalDomains?, allowlist?, // → send-gate
|
|
155
|
+
* gateImpl?, hookBus?, ledgerImpl?, catalog?, now? // → test seams
|
|
156
|
+
* }
|
|
157
|
+
* @returns {Promise<object>} res frame {ok:true,result}|{ok:false,error,blocked?}
|
|
158
|
+
*/
|
|
159
|
+
export async function sendMessage(params = {}, o = {}) {
|
|
160
|
+
const channel = params.channel != null ? String(params.channel) : "";
|
|
161
|
+
const body = params.body != null ? String(params.body) : "";
|
|
162
|
+
if (!channel) return errFrame("BAD_REQUEST", "missing channel");
|
|
163
|
+
if (!body) return errFrame("BAD_REQUEST", "missing body");
|
|
164
|
+
|
|
165
|
+
// (2) The one shared outbound chokepoint — runs BEFORE the wire.
|
|
166
|
+
const gate = o.gateImpl || screenOutbound;
|
|
167
|
+
let screened;
|
|
168
|
+
try {
|
|
169
|
+
screened = await gate({
|
|
170
|
+
channel: "cohort",
|
|
171
|
+
recipient: channel,
|
|
172
|
+
text: body,
|
|
173
|
+
agentRoot: o.agentRoot || process.cwd(),
|
|
174
|
+
jurisdiction: o.jurisdiction,
|
|
175
|
+
firstContact: o.firstContact !== undefined ? o.firstContact : false,
|
|
176
|
+
internalDomains: o.internalDomains || [],
|
|
177
|
+
allowlist: o.allowlist,
|
|
178
|
+
});
|
|
179
|
+
} catch (err) {
|
|
180
|
+
// A gate fault is fail-CLOSED for an outbound message: never send when we
|
|
181
|
+
// could not screen it (mirrors the send-gate's own external posture).
|
|
182
|
+
return { ...errFrame("INTERNAL", `send-gate error: ${err && err.message ? err.message : String(err)}`), blocked: true };
|
|
183
|
+
}
|
|
184
|
+
if (!screened || !screened.allow) {
|
|
185
|
+
// A blocked message is NOT sent. Surface the policy reason; mark blocked so
|
|
186
|
+
// the caller can distinguish a policy refusal from a transport failure.
|
|
187
|
+
return { ...errFrame("FORBIDDEN_SCOPE", screened && screened.reason ? screened.reason : "blocked by send-gate"), blocked: true };
|
|
188
|
+
}
|
|
189
|
+
const text = screened.redactedText != null ? screened.redactedText : body;
|
|
190
|
+
|
|
191
|
+
// (1) org resolution AFTER the gate so a policy violation is caught even when
|
|
192
|
+
// the org is disabled (defence: the gate is the one chokepoint).
|
|
193
|
+
const org = resolveOrg(o.cfg);
|
|
194
|
+
if (!org) return errFrame("BAD_REQUEST", "org messaging disabled or unconfigured");
|
|
195
|
+
|
|
196
|
+
// (3) the wire — idempotent on the client message id.
|
|
197
|
+
const idempotencyId = params.idempotencyId != null ? String(params.idempotencyId) : "";
|
|
198
|
+
const wire = {
|
|
199
|
+
channel,
|
|
200
|
+
body: text,
|
|
201
|
+
...(Array.isArray(params.mentions) && params.mentions.length ? { mentions: params.mentions.map(String) } : {}),
|
|
202
|
+
...(params.threadId != null ? { threadId: String(params.threadId) } : {}),
|
|
203
|
+
...(idempotencyId ? { id: idempotencyId } : {}),
|
|
204
|
+
};
|
|
205
|
+
const frame = await call("messaging.send", wire, {
|
|
206
|
+
base: org.base,
|
|
207
|
+
token: org.token,
|
|
208
|
+
idempotencyKey: idempotencyId || undefined,
|
|
209
|
+
fetchImpl: o.fetchImpl,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// (4) on success: observe-only afterSend + source="messaging" attribution.
|
|
213
|
+
if (frame && frame.ok) {
|
|
214
|
+
await emitAfterSend(
|
|
215
|
+
{ channel: "cohort", recipient: channel, text, mentions: wire.mentions || [], result: frame.result, source: "messaging" },
|
|
216
|
+
o
|
|
217
|
+
);
|
|
218
|
+
await attributeMessaging({ cfg: o.cfg, agentRoot: o.agentRoot, action: "messaging.send", channel }, o);
|
|
219
|
+
}
|
|
220
|
+
return frame;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* React to a message ON Cohort (messaging.react). A reaction is not a content
|
|
225
|
+
* send, so it does NOT run the banned-phrase send-gate (there is no prose to
|
|
226
|
+
* screen) — but it is still attributed (source="messaging") and fail-open.
|
|
227
|
+
* @param {object} params - { channel, messageId, emoji }
|
|
228
|
+
* @param {object} o - { cfg, agentRoot?, fetchImpl?, ... test seams }
|
|
229
|
+
* @returns {Promise<object>} res frame
|
|
230
|
+
*/
|
|
231
|
+
export async function reactMessage(params = {}, o = {}) {
|
|
232
|
+
const channel = params.channel != null ? String(params.channel) : "";
|
|
233
|
+
const messageId = params.messageId != null ? String(params.messageId) : "";
|
|
234
|
+
const emoji = params.emoji != null ? String(params.emoji) : "";
|
|
235
|
+
if (!channel || !messageId || !emoji) return errFrame("BAD_REQUEST", "missing channel, messageId, or emoji");
|
|
236
|
+
|
|
237
|
+
const org = resolveOrg(o.cfg);
|
|
238
|
+
if (!org) return errFrame("BAD_REQUEST", "org messaging disabled or unconfigured");
|
|
239
|
+
|
|
240
|
+
const frame = await call("messaging.react", { channel, messageId, emoji }, {
|
|
241
|
+
base: org.base,
|
|
242
|
+
token: org.token,
|
|
243
|
+
idempotencyKey: o.idempotencyKey,
|
|
244
|
+
fetchImpl: o.fetchImpl,
|
|
245
|
+
});
|
|
246
|
+
if (frame && frame.ok) {
|
|
247
|
+
await attributeMessaging({ cfg: o.cfg, agentRoot: o.agentRoot, action: "messaging.react", channel }, o);
|
|
248
|
+
}
|
|
249
|
+
return frame;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Fetch recent channel history ON Cohort (messaging.history). Read-scope,
|
|
254
|
+
* non-mutating. Returns the messages array, or [] on any failure (fail-open).
|
|
255
|
+
* @param {object} params - { channel, since?, cursor?, limit? }
|
|
256
|
+
* @param {object} o - { cfg, fetchImpl? }
|
|
257
|
+
* @returns {Promise<object[]>}
|
|
258
|
+
*/
|
|
259
|
+
export async function fetchHistory(params = {}, o = {}) {
|
|
260
|
+
const channel = params.channel != null ? String(params.channel) : "";
|
|
261
|
+
if (!channel) return [];
|
|
262
|
+
const org = resolveOrg(o.cfg);
|
|
263
|
+
if (!org) return [];
|
|
264
|
+
|
|
265
|
+
const frame = await call(
|
|
266
|
+
"messaging.history",
|
|
267
|
+
{
|
|
268
|
+
channel,
|
|
269
|
+
...(params.since != null ? { since: params.since } : {}),
|
|
270
|
+
...(params.cursor != null ? { cursor: params.cursor } : {}),
|
|
271
|
+
...(Number.isFinite(params.limit) ? { limit: params.limit } : {}),
|
|
272
|
+
},
|
|
273
|
+
{ base: org.base, token: org.token, fetchImpl: o.fetchImpl }
|
|
274
|
+
);
|
|
275
|
+
if (!frame || !frame.ok || !frame.result) return [];
|
|
276
|
+
const r = frame.result;
|
|
277
|
+
if (Array.isArray(r)) return r;
|
|
278
|
+
if (Array.isArray(r.messages)) return r.messages;
|
|
279
|
+
if (Array.isArray(r.items)) return r.items;
|
|
280
|
+
return [];
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* List the org channels visible to this agent (messaging.channels). Read-scope.
|
|
285
|
+
* Returns the channels array, or [] on any failure (fail-open).
|
|
286
|
+
* @param {object} o - { cfg, fetchImpl? }
|
|
287
|
+
* @returns {Promise<object[]>}
|
|
288
|
+
*/
|
|
289
|
+
export async function listChannels(o = {}) {
|
|
290
|
+
const org = resolveOrg(o.cfg);
|
|
291
|
+
if (!org) return [];
|
|
292
|
+
const frame = await call("messaging.channels", {}, { base: org.base, token: org.token, fetchImpl: o.fetchImpl });
|
|
293
|
+
if (!frame || !frame.ok || !frame.result) return [];
|
|
294
|
+
const r = frame.result;
|
|
295
|
+
if (Array.isArray(r)) return r;
|
|
296
|
+
if (Array.isArray(r.channels)) return r.channels;
|
|
297
|
+
return [];
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
// Calling — start / join
|
|
302
|
+
// ---------------------------------------------------------------------------
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Start a call ON Cohort (calling.start). calling.write scope. Attributed
|
|
306
|
+
* (source="messaging") and fail-open. There is no prose to screen, so the
|
|
307
|
+
* banned-phrase send-gate does not run — but an `invitees` list is passed
|
|
308
|
+
* through so the server can ring participants.
|
|
309
|
+
* @param {object} params - { channel?, invitees?, topic?, idempotencyId? }
|
|
310
|
+
* @param {object} o - { cfg, agentRoot?, fetchImpl?, ... test seams }
|
|
311
|
+
* @returns {Promise<object>} res frame {ok:true,result:{callId,...}}|{ok:false,error}
|
|
312
|
+
*/
|
|
313
|
+
export async function initiateCall(params = {}, o = {}) {
|
|
314
|
+
const org = resolveOrg(o.cfg);
|
|
315
|
+
if (!org) return errFrame("BAD_REQUEST", "org calling disabled or unconfigured");
|
|
316
|
+
const idempotencyId = params.idempotencyId != null ? String(params.idempotencyId) : "";
|
|
317
|
+
const wire = {
|
|
318
|
+
...(params.channel != null ? { channel: String(params.channel) } : {}),
|
|
319
|
+
...(Array.isArray(params.invitees) && params.invitees.length ? { invitees: params.invitees.map(String) } : {}),
|
|
320
|
+
...(params.topic != null ? { topic: String(params.topic) } : {}),
|
|
321
|
+
...(idempotencyId ? { id: idempotencyId } : {}),
|
|
322
|
+
};
|
|
323
|
+
const frame = await call("calling.start", wire, {
|
|
324
|
+
base: org.base,
|
|
325
|
+
token: org.token,
|
|
326
|
+
idempotencyKey: idempotencyId || undefined,
|
|
327
|
+
fetchImpl: o.fetchImpl,
|
|
328
|
+
});
|
|
329
|
+
if (frame && frame.ok) {
|
|
330
|
+
await attributeMessaging({ cfg: o.cfg, agentRoot: o.agentRoot, action: "calling.start", channel: wire.channel || null }, o);
|
|
331
|
+
}
|
|
332
|
+
return frame;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Join an existing call ON Cohort (calling.join). calling.write scope.
|
|
337
|
+
* Attributed (source="messaging") and fail-open.
|
|
338
|
+
* @param {object} params - { callId }
|
|
339
|
+
* @param {object} o - { cfg, agentRoot?, fetchImpl?, ... test seams }
|
|
340
|
+
* @returns {Promise<object>} res frame
|
|
341
|
+
*/
|
|
342
|
+
export async function joinCall(params = {}, o = {}) {
|
|
343
|
+
const callId = params.callId != null ? String(params.callId) : "";
|
|
344
|
+
if (!callId) return errFrame("BAD_REQUEST", "missing callId");
|
|
345
|
+
const org = resolveOrg(o.cfg);
|
|
346
|
+
if (!org) return errFrame("BAD_REQUEST", "org calling disabled or unconfigured");
|
|
347
|
+
const frame = await call("calling.join", { callId }, {
|
|
348
|
+
base: org.base,
|
|
349
|
+
token: org.token,
|
|
350
|
+
idempotencyKey: o.idempotencyKey,
|
|
351
|
+
fetchImpl: o.fetchImpl,
|
|
352
|
+
});
|
|
353
|
+
if (frame && frame.ok) {
|
|
354
|
+
await attributeMessaging({ cfg: o.cfg, agentRoot: o.agentRoot, action: "calling.join", channel: callId }, o);
|
|
355
|
+
}
|
|
356
|
+
return frame;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ---------------------------------------------------------------------------
|
|
360
|
+
// Inbound — pull new messages / @mentions / call-invites for THIS agent
|
|
361
|
+
// ---------------------------------------------------------------------------
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Pull org events newer than `cursor` that are DIRECTED AT this agent — new
|
|
365
|
+
* messages in a channel it is in, @mentions, and call-invites — and project them
|
|
366
|
+
* onto the unified MessageEvent contract so the existing daemon inbox pipeline
|
|
367
|
+
* (classifier → dispatcher → responder) reacts to them like any other channel.
|
|
368
|
+
*
|
|
369
|
+
* This is the read leg the inbound cadence handler drives. It is pure over the
|
|
370
|
+
* injected fetch: the handler decides whether to escalate and where to write the
|
|
371
|
+
* resulting items. The cursor advance is the caller's responsibility (returned
|
|
372
|
+
* here as `nextCursor`) so a crash never loses or double-delivers events.
|
|
373
|
+
*
|
|
374
|
+
* Mention detection: an event whose `mentions[]` (or `mentioned_agents[]`)
|
|
375
|
+
* includes this agent's id, OR a DM-kind event addressed to it, counts as
|
|
376
|
+
* directed. We do NOT include the agent's own outbound echoes (`from` == self).
|
|
377
|
+
*
|
|
378
|
+
* @param {object} o - { cfg, agentId?, cursor?, limit?, fetchImpl? }
|
|
379
|
+
* @returns {Promise<{events:object[], nextCursor:(number|string|null)}>}
|
|
380
|
+
*/
|
|
381
|
+
export async function pullInbound(o = {}) {
|
|
382
|
+
const org = resolveOrg(o.cfg);
|
|
383
|
+
if (!org) return { events: [], nextCursor: o.cursor ?? null };
|
|
384
|
+
const me = o.agentId || agentIdOf(o.cfg);
|
|
385
|
+
|
|
386
|
+
const cursor = o.cursor ?? 0;
|
|
387
|
+
const limit = Number.isFinite(o.limit) ? o.limit : 200;
|
|
388
|
+
const path = `events?cursor=${encodeURIComponent(cursor)}&limit=${encodeURIComponent(limit)}&family=messaging,calling`;
|
|
389
|
+
const r = await read(path, { base: org.base, token: org.token, fetchImpl: o.fetchImpl });
|
|
390
|
+
if (!r.ok || !r.payload) return { events: [], nextCursor: cursor };
|
|
391
|
+
|
|
392
|
+
const raw = Array.isArray(r.payload) ? r.payload : (Array.isArray(r.payload.events) ? r.payload.events : []);
|
|
393
|
+
let maxSeq = cursor;
|
|
394
|
+
const events = [];
|
|
395
|
+
for (const ev of raw) {
|
|
396
|
+
if (ev && (ev.seq != null) && Number.isFinite(Number(ev.seq))) {
|
|
397
|
+
maxSeq = Math.max(Number(maxSeq) || 0, Number(ev.seq));
|
|
398
|
+
}
|
|
399
|
+
const directed = isDirectedAtAgent(ev, me);
|
|
400
|
+
if (!directed) continue;
|
|
401
|
+
events.push(toMessageEvent(ev, me));
|
|
402
|
+
}
|
|
403
|
+
return { events, nextCursor: raw.length ? maxSeq : cursor };
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Decide whether an org event is directed at this agent (an inbound it should
|
|
408
|
+
* react to) vs ambient chatter / its own echo. Pure.
|
|
409
|
+
* @param {object} ev @param {string} me agent id
|
|
410
|
+
* @returns {boolean}
|
|
411
|
+
*/
|
|
412
|
+
export function isDirectedAtAgent(ev, me) {
|
|
413
|
+
if (!ev || typeof ev !== "object") return false;
|
|
414
|
+
const family = ev.family || (ev.kind ? String(ev.kind).split(".")[0] : "");
|
|
415
|
+
if (family && family !== "messaging" && family !== "calling") return false;
|
|
416
|
+
const p = ev.payload || ev;
|
|
417
|
+
const from = String(p.from || p.author || p.sender || (ev.actor || "")).trim();
|
|
418
|
+
if (me && from && from === String(me)) return false; // ignore own echoes
|
|
419
|
+
|
|
420
|
+
const mentions = []
|
|
421
|
+
.concat(Array.isArray(p.mentions) ? p.mentions : [])
|
|
422
|
+
.concat(Array.isArray(p.mentioned_agents) ? p.mentioned_agents : [])
|
|
423
|
+
.map((m) => String(m));
|
|
424
|
+
if (me && mentions.includes(String(me))) return true;
|
|
425
|
+
|
|
426
|
+
// A DM / direct call-invite addressed to this agent is directed even with no
|
|
427
|
+
// explicit @mention.
|
|
428
|
+
const to = []
|
|
429
|
+
.concat(Array.isArray(p.to) ? p.to : (p.to != null ? [p.to] : []))
|
|
430
|
+
.concat(Array.isArray(p.invitees) ? p.invitees : [])
|
|
431
|
+
.map((t) => String(t));
|
|
432
|
+
if (me && to.includes(String(me))) return true;
|
|
433
|
+
|
|
434
|
+
const kind = String(p.kind || ev.kind || "").toLowerCase();
|
|
435
|
+
if (kind.includes("dm") || kind.includes("invite") || family === "calling") {
|
|
436
|
+
return !me || to.includes(String(me)) || mentions.includes(String(me)) || to.length === 0;
|
|
437
|
+
}
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Project an org messaging/calling event onto the unified MessageEvent contract
|
|
443
|
+
* (lib/channels/contract.MessageEvent) so eventToInboxItem can serialise it into
|
|
444
|
+
* the legacy inbox pipeline unchanged. Pure.
|
|
445
|
+
* @param {object} ev @param {string} me
|
|
446
|
+
* @returns {object} MessageEvent
|
|
447
|
+
*/
|
|
448
|
+
export function toMessageEvent(ev, me) {
|
|
449
|
+
const p = (ev && ev.payload) || ev || {};
|
|
450
|
+
const family = ev.family || (ev.kind ? String(ev.kind).split(".")[0] : "messaging");
|
|
451
|
+
const isCall = family === "calling";
|
|
452
|
+
const channelId = String(p.channel || p.channelId || p.callId || "");
|
|
453
|
+
const messageId = String(p.id || p.messageId || ev.entity_id || ev.seq || "");
|
|
454
|
+
const fromId = String(p.from || p.author || p.sender || ev.actor || "");
|
|
455
|
+
const text = isCall
|
|
456
|
+
? (p.topic ? `Call invite: ${p.topic}` : "Call invite")
|
|
457
|
+
: (p.body != null ? String(p.body) : (p.text != null ? String(p.text) : ""));
|
|
458
|
+
|
|
459
|
+
return {
|
|
460
|
+
channel: "cohort",
|
|
461
|
+
message_id: messageId,
|
|
462
|
+
id: messageId ? `cohort-${messageId}` : undefined,
|
|
463
|
+
thread_id: p.threadId != null ? String(p.threadId) : "",
|
|
464
|
+
from: { id: fromId, name: String(p.fromName || p.authorName || fromId) },
|
|
465
|
+
text,
|
|
466
|
+
timestamp: ev.at || p.at || new Date().toISOString(),
|
|
467
|
+
kind: isCall ? "call" : "message",
|
|
468
|
+
subject: isCall ? "Cohort call invite" : "Cohort message",
|
|
469
|
+
channel_id: channelId,
|
|
470
|
+
channel_label: String(p.channelName || channelId || "cohort"),
|
|
471
|
+
sender: String(p.fromName || fromId),
|
|
472
|
+
priority_signals: {
|
|
473
|
+
from_ceo: false,
|
|
474
|
+
tagged_urgent: false,
|
|
475
|
+
contains_deadline: false,
|
|
476
|
+
mentions_agent: !!(me && []
|
|
477
|
+
.concat(Array.isArray(p.mentions) ? p.mentions : [])
|
|
478
|
+
.concat(Array.isArray(p.mentioned_agents) ? p.mentioned_agents : [])
|
|
479
|
+
.map(String)
|
|
480
|
+
.includes(String(me))),
|
|
481
|
+
},
|
|
482
|
+
raw_ref: `cohort:${channelId}:${messageId}`,
|
|
483
|
+
ingest_source: "cohort",
|
|
484
|
+
source: {
|
|
485
|
+
channel: "cohort",
|
|
486
|
+
chatId: channelId,
|
|
487
|
+
threadRef: p.threadId != null ? String(p.threadId) : undefined,
|
|
488
|
+
userScope: isCall ? "channel" : (channelId ? "channel" : "dm"),
|
|
489
|
+
},
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export default {
|
|
494
|
+
sendMessage,
|
|
495
|
+
reactMessage,
|
|
496
|
+
fetchHistory,
|
|
497
|
+
listChannels,
|
|
498
|
+
initiateCall,
|
|
499
|
+
joinCall,
|
|
500
|
+
pullInbound,
|
|
501
|
+
isDirectedAtAgent,
|
|
502
|
+
toMessageEvent,
|
|
503
|
+
};
|