@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,463 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/org/knowledge.mjs — agent-facing shared-memory API over the Cohort
|
|
3
|
+
* knowledge plane (SPEC-org-server §4.7).
|
|
4
|
+
*
|
|
5
|
+
* THE compounding-collaboration lever. Where lib/learning/ and lib/collective/
|
|
6
|
+
* give one agent a memory of its OWN sessions, this module gives every agent a
|
|
7
|
+
* window into the ORG's shared, ACL'd knowledge: a fact promoted by agent A is
|
|
8
|
+
* retrievable by agent B inside the ACL, invisible outside it. It is the org-wide
|
|
9
|
+
* RAG source an agent's context-assembly can consult — `recall(query)` pulls the
|
|
10
|
+
* shared facts the server's RLS floor permits, and `remember(fact)` lands new
|
|
11
|
+
* shared knowledge for everyone else.
|
|
12
|
+
*
|
|
13
|
+
* The verb surface is deliberately small and human:
|
|
14
|
+
* - remember(fact, {group}) → knowledge.append (episodes; commutes) or
|
|
15
|
+
* knowledge.replace (CAS) when {id, expectedVersion}
|
|
16
|
+
* - recall(query, {group?}) → knowledge.search → the ACL-visible facts
|
|
17
|
+
* - forget(id, {reason?}) → knowledge.invalidate (tombstone, NEVER delete)
|
|
18
|
+
* - rewrite(id, text, …) → knowledge.rewrite (designated-owner-only)
|
|
19
|
+
* - upsertContact / contacts → contacts.upsert / contacts.list
|
|
20
|
+
* - recordMeeting / meetings → meetings.record / meetings.list
|
|
21
|
+
*
|
|
22
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
23
|
+
* THE SERVER IS AUTHORITATIVE FOR ACL. This is load-bearing and non-negotiable.
|
|
24
|
+
*
|
|
25
|
+
* This module NEVER decides what an agent may read or write. It does not inspect
|
|
26
|
+
* a fact's `group`, does not know which barrier:<cell> the agent holds, and does
|
|
27
|
+
* NOT filter `recall()` results. The non-bypassable RLS floor — org/unit group
|
|
28
|
+
* membership, `barrier:<cell>` DENY-OVERRIDE (never returned unless explicitly
|
|
29
|
+
* granted, even to an org/unit member), and participant-derived ACLs — lives in
|
|
30
|
+
* the server's query layer (the SQLite/Postgres-RLS floor every read passes
|
|
31
|
+
* through). The agent's groups derive from its VERIFIED identity, not from
|
|
32
|
+
* anything this client sends. `recall()` renders exactly what the server chose to
|
|
33
|
+
* return; the `{group}` argument is a SCOPING HINT to the server, never a filter
|
|
34
|
+
* the client enforces. If you want to narrow a search, the server still applies
|
|
35
|
+
* the floor on top of your hint — a hint can only ever shrink, never widen, what
|
|
36
|
+
* comes back.
|
|
37
|
+
*
|
|
38
|
+
* Every `recall()` is a SIDE-EFFECTING, AUDITED retrieval: the server appends a
|
|
39
|
+
* 'knowledge' org_events row {agent, query, returned_ids, groups_considered} —
|
|
40
|
+
* the regulator-facing read-audit trail. There is no "silent" read of the plane.
|
|
41
|
+
* ──────────────────────────────────────────────────────────────────────────
|
|
42
|
+
*
|
|
43
|
+
* G16 (zero-LLM-in-the-coordination-loop): NOTHING here makes an LLM call. These
|
|
44
|
+
* are pure parameter shaping + a fail-open HTTP round-trip. Episode CONSOLIDATION
|
|
45
|
+
* (the optional ingest worker that distils episodes into facts) is the only LLM
|
|
46
|
+
* consumer in the plane and lives server-side, OUT of this synchronous path.
|
|
47
|
+
*
|
|
48
|
+
* Fail-open by design: a disabled/unreachable server makes `remember/forget`
|
|
49
|
+
* a no-op `{ok:false, skipped}` and `recall/contacts/meetings` return `[]` —
|
|
50
|
+
* never a throw — so the org knowledge binding can never take down the agent's
|
|
51
|
+
* main path. `fetchImpl` is injectable everywhere for deterministic tests.
|
|
52
|
+
*
|
|
53
|
+
* Node builtins only (global fetch on Node 20). ESM.
|
|
54
|
+
*
|
|
55
|
+
* @module lib/org/knowledge
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
"use strict";
|
|
59
|
+
|
|
60
|
+
import {
|
|
61
|
+
isEnabled,
|
|
62
|
+
configFromAgent,
|
|
63
|
+
knowledgeAppend,
|
|
64
|
+
knowledgeReplace,
|
|
65
|
+
knowledgeRewrite,
|
|
66
|
+
knowledgeInvalidate,
|
|
67
|
+
knowledgeSearch,
|
|
68
|
+
contactsUpsert,
|
|
69
|
+
contactsList,
|
|
70
|
+
meetingsRecord,
|
|
71
|
+
meetingsList,
|
|
72
|
+
} from "./client.mjs";
|
|
73
|
+
import { KNOWLEDGE_GROUP_KINDS } from "./protocol.mjs";
|
|
74
|
+
|
|
75
|
+
/** Default cap on facts returned by a single recall (the server may cap lower). */
|
|
76
|
+
const DEFAULT_RECALL_LIMIT = 20;
|
|
77
|
+
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Group hints (the server is still authoritative — these are advisory shapes)
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Normalise a group hint to a `group_id` string of the form the plane uses:
|
|
84
|
+
* `org` | `unit:<id>` | `barrier:<cell>` (KNOWLEDGE_GROUP_KINDS). Accepts either
|
|
85
|
+
* a ready string or a `{kind, id}` object. Returns undefined when nothing usable
|
|
86
|
+
* is given (the server then picks the group from the caller's verified identity).
|
|
87
|
+
*
|
|
88
|
+
* This is a SHAPE helper only — emitting `barrier:<cell>` here does NOT grant the
|
|
89
|
+
* agent that cell. The server still deny-overrides any barrier group the agent's
|
|
90
|
+
* verified identity was not explicitly granted.
|
|
91
|
+
*
|
|
92
|
+
* @param {string|{kind?:string,id?:string,cell?:string}|undefined} group
|
|
93
|
+
* @returns {string|undefined}
|
|
94
|
+
*/
|
|
95
|
+
export function normalizeGroup(group) {
|
|
96
|
+
if (group == null) return undefined;
|
|
97
|
+
if (typeof group === "string") {
|
|
98
|
+
const s = group.trim();
|
|
99
|
+
if (!s) return undefined;
|
|
100
|
+
if (s === "org") return "org";
|
|
101
|
+
// Already in `kind:rest` form, or a bare unit/barrier id we leave to the server.
|
|
102
|
+
if (s.includes(":")) {
|
|
103
|
+
const kind = s.split(":", 1)[0];
|
|
104
|
+
return KNOWLEDGE_GROUP_KINDS.includes(kind) ? s : undefined;
|
|
105
|
+
}
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
if (typeof group === "object") {
|
|
109
|
+
const kind = group.kind ? String(group.kind) : "";
|
|
110
|
+
if (kind === "org") return "org";
|
|
111
|
+
const id = group.id != null ? String(group.id) : (group.cell != null ? String(group.cell) : "");
|
|
112
|
+
if ((kind === "unit" || kind === "barrier") && id) return `${kind}:${id}`;
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// remember — land shared knowledge (append episode, or CAS-replace a fact)
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Remember a fact into the org's shared knowledge plane.
|
|
123
|
+
*
|
|
124
|
+
* Default path is `knowledge.append` — an episode, the SOLE shared-write
|
|
125
|
+
* primitive; it COMMUTES, so concurrent appends from different agents both land
|
|
126
|
+
* with no coordination. When the caller supplies `{id, expectedVersion}` it's an
|
|
127
|
+
* update to an existing fact and routes to `knowledge.replace` (compare-and-swap
|
|
128
|
+
* on the version; a stale CAS comes back as a CONFLICT frame). Use `rewrite()`
|
|
129
|
+
* (not this) for an owner-only in-place rewrite.
|
|
130
|
+
*
|
|
131
|
+
* The `group` is a HINT only; the server assigns/validates the fact's group from
|
|
132
|
+
* the caller's verified identity subject to the RLS floor. Never throws; returns
|
|
133
|
+
* a benign skipped result when the integration is disabled.
|
|
134
|
+
*
|
|
135
|
+
* @param {string|{text:string,...}} fact the episode text, or a fact object
|
|
136
|
+
* @param {object} opts - {
|
|
137
|
+
* cfg, group?, id?, expectedVersion?, kind?, participants?, provenance?,
|
|
138
|
+
* links?, refs?, idempotencyKey?, fetchImpl?
|
|
139
|
+
* }
|
|
140
|
+
* @returns {Promise<{ok:boolean, skipped?:boolean, mode?:'append'|'replace', id?:string, result?:any, error?:object}>}
|
|
141
|
+
*/
|
|
142
|
+
export async function remember(fact, opts = {}) {
|
|
143
|
+
if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
|
|
144
|
+
const params = factToParams(fact, opts);
|
|
145
|
+
if (!params.text && !params.id) return { ok: false, skipped: false, error: { code: "BAD_REQUEST", message: "empty fact" } };
|
|
146
|
+
|
|
147
|
+
const c = configFromAgent(opts.cfg);
|
|
148
|
+
const tx = { base: c.base, token: c.token, fetchImpl: opts.fetchImpl };
|
|
149
|
+
|
|
150
|
+
// {id, expectedVersion} ⇒ CAS replace of an existing fact; otherwise append.
|
|
151
|
+
const isReplace = !!(params.id && (opts.expectedVersion != null || params.expectedVersion != null));
|
|
152
|
+
if (isReplace) {
|
|
153
|
+
const replaceParams = { ...params, expectedVersion: opts.expectedVersion ?? params.expectedVersion };
|
|
154
|
+
const frame = await knowledgeReplace(replaceParams, { ...tx, idempotencyKey: opts.idempotencyKey });
|
|
155
|
+
return shapeWrite(frame, "replace", params.id);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const frame = await knowledgeAppend(params, {
|
|
159
|
+
...tx,
|
|
160
|
+
idempotencyKey: opts.idempotencyKey || (params.id ? `knowledge.append:${params.id}` : undefined),
|
|
161
|
+
});
|
|
162
|
+
return shapeWrite(frame, "append", params.id);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Rewrite a fact in place (knowledge.rewrite) — DESIGNATED-OWNER-ONLY. Distinct
|
|
167
|
+
* from remember()'s CAS path: rewrite is the owner asserting authorship, not a
|
|
168
|
+
* versioned update; the server enforces ownership and rejects a non-owner. Use
|
|
169
|
+
* sparingly — most updates should append (provenance-preserving) or CAS-replace.
|
|
170
|
+
*
|
|
171
|
+
* @param {string} id
|
|
172
|
+
* @param {string|{text:string,...}} fact
|
|
173
|
+
* @param {object} opts - { cfg, group?, provenance?, idempotencyKey?, fetchImpl? }
|
|
174
|
+
* @returns {Promise<{ok:boolean, skipped?:boolean, mode?:'rewrite', id?:string, result?:any, error?:object}>}
|
|
175
|
+
*/
|
|
176
|
+
export async function rewrite(id, fact, opts = {}) {
|
|
177
|
+
if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
|
|
178
|
+
if (!id) return { ok: false, skipped: false, error: { code: "BAD_REQUEST", message: "missing id" } };
|
|
179
|
+
const params = { ...factToParams(fact, opts), id: String(id) };
|
|
180
|
+
const c = configFromAgent(opts.cfg);
|
|
181
|
+
const frame = await knowledgeRewrite(params, {
|
|
182
|
+
base: c.base, token: c.token, idempotencyKey: opts.idempotencyKey, fetchImpl: opts.fetchImpl,
|
|
183
|
+
});
|
|
184
|
+
return shapeWrite(frame, "rewrite", params.id);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
// recall — the org-RAG read (ACL-floored by the server; the client never filters)
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Recall shared knowledge for a query — the org-wide RAG source. Calls
|
|
193
|
+
* `knowledge.search` and returns the facts the SERVER chose to return after
|
|
194
|
+
* applying the non-bypassable RLS floor. The client performs NO ACL filtering:
|
|
195
|
+
* whatever facts come back are, by construction, the ones this agent's verified
|
|
196
|
+
* groups may see (barrier:<cell> deny-override already applied server-side).
|
|
197
|
+
*
|
|
198
|
+
* This is the call an agent's context-assembly makes to pull org knowledge into a
|
|
199
|
+
* prompt — drop it alongside the local lib/collective recall. Because every
|
|
200
|
+
* retrieval is audited server-side (org_events family 'knowledge'), do not loop
|
|
201
|
+
* it gratuitously; one query per context build is the intended cadence.
|
|
202
|
+
*
|
|
203
|
+
* The `{group}` option is a scoping HINT to the server (it can only shrink the
|
|
204
|
+
* result, never widen it past the floor). `lexical` flags that a keyword/lexical
|
|
205
|
+
* match was requested — an acceptable phase-4 stand-in for vector search, which
|
|
206
|
+
* the server notes; ranking/embedding is the server's job either way.
|
|
207
|
+
*
|
|
208
|
+
* Fail-open: a disabled/unreachable server yields []. Never throws.
|
|
209
|
+
*
|
|
210
|
+
* @param {string} query natural-language or keyword query
|
|
211
|
+
* @param {object} opts - {
|
|
212
|
+
* cfg, group?, limit?, kind?, includeInvalid?, lexical?, idempotencyKey?, fetchImpl?
|
|
213
|
+
* }
|
|
214
|
+
* @returns {Promise<object[]>} the ACL-visible facts (server-filtered), or []
|
|
215
|
+
*/
|
|
216
|
+
export async function recall(query, opts = {}) {
|
|
217
|
+
const r = await recallDetailed(query, opts);
|
|
218
|
+
return r.facts;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Like recall(), but returns the full retrieval envelope the server reported:
|
|
223
|
+
* `{ ok, facts, returnedIds, groupsConsidered }`. `returnedIds`/`groupsConsidered`
|
|
224
|
+
* mirror the read-audit row the server wrote — useful for surfacing provenance
|
|
225
|
+
* (e.g. "answered from facts X,Y across groups org,unit:eng") without a second
|
|
226
|
+
* call, and for the cascade/blast-radius drill. Still does no client-side ACL
|
|
227
|
+
* filtering. Fail-open: yields `{ok:false, facts:[]}`.
|
|
228
|
+
*
|
|
229
|
+
* @param {string} query
|
|
230
|
+
* @param {object} opts - see recall()
|
|
231
|
+
* @returns {Promise<{ok:boolean, facts:object[], returnedIds:string[], groupsConsidered:string[], error?:object}>}
|
|
232
|
+
*/
|
|
233
|
+
export async function recallDetailed(query, opts = {}) {
|
|
234
|
+
const empty = { ok: false, facts: [], returnedIds: [], groupsConsidered: [] };
|
|
235
|
+
if (!isEnabled(opts.cfg)) return empty;
|
|
236
|
+
const q = query == null ? "" : String(query);
|
|
237
|
+
if (!q.trim()) return empty;
|
|
238
|
+
|
|
239
|
+
const params = { query: q };
|
|
240
|
+
const group = normalizeGroup(opts.group);
|
|
241
|
+
if (group) params.group = group;
|
|
242
|
+
params.limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : DEFAULT_RECALL_LIMIT;
|
|
243
|
+
if (opts.kind) params.kind = String(opts.kind);
|
|
244
|
+
if (opts.includeInvalid) params.includeInvalid = true;
|
|
245
|
+
if (opts.lexical) params.lexical = true;
|
|
246
|
+
|
|
247
|
+
const c = configFromAgent(opts.cfg);
|
|
248
|
+
const frame = await knowledgeSearch(params, {
|
|
249
|
+
base: c.base, token: c.token, idempotencyKey: opts.idempotencyKey, fetchImpl: opts.fetchImpl,
|
|
250
|
+
});
|
|
251
|
+
if (!frame || !frame.ok) {
|
|
252
|
+
return { ok: false, facts: [], returnedIds: [], groupsConsidered: [], error: frame && frame.error };
|
|
253
|
+
}
|
|
254
|
+
const result = frame.result || {};
|
|
255
|
+
// Render WHATEVER the server returned. We do NOT re-derive, re-sort, or filter
|
|
256
|
+
// by group — the server already applied the RLS floor. We only coerce shapes.
|
|
257
|
+
const facts = pickArray(result, ["facts", "results", "items"]);
|
|
258
|
+
const returnedIds = Array.isArray(result.returned_ids)
|
|
259
|
+
? result.returned_ids.map(String)
|
|
260
|
+
: facts.map((f) => (f && (f.id != null ? String(f.id) : null))).filter(Boolean);
|
|
261
|
+
const groupsConsidered = Array.isArray(result.groups_considered) ? result.groups_considered.map(String) : [];
|
|
262
|
+
return { ok: true, facts, returnedIds, groupsConsidered };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ---------------------------------------------------------------------------
|
|
266
|
+
// forget — invalidate (tombstone), never hard-delete
|
|
267
|
+
// ---------------------------------------------------------------------------
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Forget a fact — INVALIDATE, DON'T DELETE. Routes to `knowledge.invalidate`:
|
|
271
|
+
* the server marks the fact invalid (provenance + tombstone) and excludes it from
|
|
272
|
+
* future recall, but the ROW PERSISTS for audit and the cascade/blast-radius
|
|
273
|
+
* drill (provenance can still enumerate everyone who read the bad fact). There is
|
|
274
|
+
* no client-side delete and no server hard-delete in this plane.
|
|
275
|
+
*
|
|
276
|
+
* Fail-open: disabled ⇒ `{ok:false, skipped:true}`. Never throws.
|
|
277
|
+
*
|
|
278
|
+
* @param {string} id the fact id to invalidate
|
|
279
|
+
* @param {object} opts - { cfg, reason?, supersededBy?, idempotencyKey?, fetchImpl? }
|
|
280
|
+
* @returns {Promise<{ok:boolean, skipped?:boolean, id?:string, result?:any, error?:object}>}
|
|
281
|
+
*/
|
|
282
|
+
export async function forget(id, opts = {}) {
|
|
283
|
+
if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
|
|
284
|
+
if (!id) return { ok: false, skipped: false, error: { code: "BAD_REQUEST", message: "missing id" } };
|
|
285
|
+
const c = configFromAgent(opts.cfg);
|
|
286
|
+
const params = { id: String(id) };
|
|
287
|
+
if (opts.reason) params.reason = String(opts.reason);
|
|
288
|
+
if (opts.supersededBy) params.supersededBy = String(opts.supersededBy);
|
|
289
|
+
const frame = await knowledgeInvalidate(params, {
|
|
290
|
+
base: c.base,
|
|
291
|
+
token: c.token,
|
|
292
|
+
idempotencyKey: opts.idempotencyKey || `knowledge.invalidate:${params.id}`,
|
|
293
|
+
fetchImpl: opts.fetchImpl,
|
|
294
|
+
});
|
|
295
|
+
return shapeWrite(frame, "invalidate", params.id);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
299
|
+
// contacts + meetings (ACL-filtered registries on the same plane)
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Upsert an org contact into the shared registry (contacts.upsert). Idempotent.
|
|
304
|
+
* ACL-filtered on read by the server like every other knowledge surface. Fail-open.
|
|
305
|
+
* @param {object} contact - { id?, name?, emails?, phones?, handles?, org?, group?, fields? }
|
|
306
|
+
* @param {object} opts - { cfg, idempotencyKey?, fetchImpl? }
|
|
307
|
+
* @returns {Promise<{ok:boolean, skipped?:boolean, id?:string, result?:any, error?:object}>}
|
|
308
|
+
*/
|
|
309
|
+
export async function upsertContact(contact, opts = {}) {
|
|
310
|
+
if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
|
|
311
|
+
const c = configFromAgent(opts.cfg);
|
|
312
|
+
const params = contact && typeof contact === "object" ? { ...contact } : {};
|
|
313
|
+
const group = normalizeGroup(params.group);
|
|
314
|
+
if (group) params.group = group; else delete params.group;
|
|
315
|
+
const frame = await contactsUpsert(params, {
|
|
316
|
+
base: c.base,
|
|
317
|
+
token: c.token,
|
|
318
|
+
idempotencyKey: opts.idempotencyKey || (params.id ? `contacts.upsert:${params.id}` : undefined),
|
|
319
|
+
fetchImpl: opts.fetchImpl,
|
|
320
|
+
});
|
|
321
|
+
return shapeWrite(frame, "contact", params.id, "contacts.upsert");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* List org contacts the agent may see (contacts.list). The SERVER ACL-filters;
|
|
326
|
+
* the client renders the list as-is. Returns [] when disabled or on failure.
|
|
327
|
+
* @param {object} opts - { cfg, q?, group?, limit?, fetchImpl? }
|
|
328
|
+
* @returns {Promise<object[]>}
|
|
329
|
+
*/
|
|
330
|
+
export async function listContacts(opts = {}) {
|
|
331
|
+
if (!isEnabled(opts.cfg)) return [];
|
|
332
|
+
const c = configFromAgent(opts.cfg);
|
|
333
|
+
return contactsList({
|
|
334
|
+
base: c.base, token: c.token, fetchImpl: opts.fetchImpl,
|
|
335
|
+
q: opts.q, group: normalizeGroup(opts.group), limit: opts.limit,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Record a meeting into the shared registry (meetings.record). Idempotent. The
|
|
341
|
+
* server derives a participant ACL for the meeting fact. Fail-open.
|
|
342
|
+
* @param {object} meeting - { id?, title?, at?, participants?, notes?, group?, refs?, fields? }
|
|
343
|
+
* @param {object} opts - { cfg, idempotencyKey?, fetchImpl? }
|
|
344
|
+
* @returns {Promise<{ok:boolean, skipped?:boolean, id?:string, result?:any, error?:object}>}
|
|
345
|
+
*/
|
|
346
|
+
export async function recordMeeting(meeting, opts = {}) {
|
|
347
|
+
if (!isEnabled(opts.cfg)) return { ok: false, skipped: true };
|
|
348
|
+
const c = configFromAgent(opts.cfg);
|
|
349
|
+
const params = meeting && typeof meeting === "object" ? { ...meeting } : {};
|
|
350
|
+
const group = normalizeGroup(params.group);
|
|
351
|
+
if (group) params.group = group; else delete params.group;
|
|
352
|
+
const frame = await meetingsRecord(params, {
|
|
353
|
+
base: c.base,
|
|
354
|
+
token: c.token,
|
|
355
|
+
idempotencyKey: opts.idempotencyKey || (params.id ? `meetings.record:${params.id}` : undefined),
|
|
356
|
+
fetchImpl: opts.fetchImpl,
|
|
357
|
+
});
|
|
358
|
+
return shapeWrite(frame, "meeting", params.id, "meetings.record");
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* List org meetings the agent may see (meetings.list). The SERVER ACL-filters
|
|
363
|
+
* (participant-derived). Returns [] when disabled or on failure.
|
|
364
|
+
* @param {object} opts - { cfg, q?, group?, since?, limit?, fetchImpl? }
|
|
365
|
+
* @returns {Promise<object[]>}
|
|
366
|
+
*/
|
|
367
|
+
export async function listMeetings(opts = {}) {
|
|
368
|
+
if (!isEnabled(opts.cfg)) return [];
|
|
369
|
+
const c = configFromAgent(opts.cfg);
|
|
370
|
+
return meetingsList({
|
|
371
|
+
base: c.base, token: c.token, fetchImpl: opts.fetchImpl,
|
|
372
|
+
q: opts.q, group: normalizeGroup(opts.group), since: opts.since, limit: opts.limit,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// ---------------------------------------------------------------------------
|
|
377
|
+
// internals (pure shaping)
|
|
378
|
+
// ---------------------------------------------------------------------------
|
|
379
|
+
|
|
380
|
+
/** Coerce a fact arg (string text or fact object) + opts into the wire params. */
|
|
381
|
+
function factToParams(fact, opts = {}) {
|
|
382
|
+
const base = typeof fact === "string" ? { text: fact } : (fact && typeof fact === "object" ? { ...fact } : {});
|
|
383
|
+
// Pull through the structured options without letting opts plumbing leak.
|
|
384
|
+
if (opts.id != null && base.id == null) base.id = opts.id;
|
|
385
|
+
if (opts.kind != null && base.kind == null) base.kind = opts.kind;
|
|
386
|
+
if (opts.participants != null && base.participants == null) base.participants = opts.participants;
|
|
387
|
+
if (opts.provenance != null && base.provenance == null) base.provenance = opts.provenance;
|
|
388
|
+
if (opts.links != null && base.links == null) base.links = opts.links;
|
|
389
|
+
if (opts.refs != null && base.refs == null) base.refs = opts.refs;
|
|
390
|
+
if (opts.expectedVersion != null && base.expectedVersion == null) base.expectedVersion = opts.expectedVersion;
|
|
391
|
+
const group = normalizeGroup(opts.group != null ? opts.group : base.group);
|
|
392
|
+
if (group) base.group = group; else delete base.group;
|
|
393
|
+
if (base.id != null) base.id = String(base.id);
|
|
394
|
+
return base;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** Methods that have already emitted their one-shot "server does not implement" warning. */
|
|
398
|
+
const _unimplementedWarned = new Set();
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Loudly, ONCE per method, surface that the org server has no handler for a
|
|
402
|
+
* write the agent attempted (dispatch returns NOT_FOUND). Silently swallowing
|
|
403
|
+
* this (as the old wrappers did) hides a real capability gap — the doctor and
|
|
404
|
+
* the operator need to see it. Fail-open: writing the warning never throws.
|
|
405
|
+
* @param {string} method the wire method (e.g. "contacts.upsert")
|
|
406
|
+
*/
|
|
407
|
+
function warnUnimplemented(method) {
|
|
408
|
+
if (_unimplementedWarned.has(method)) return;
|
|
409
|
+
_unimplementedWarned.add(method);
|
|
410
|
+
try {
|
|
411
|
+
// eslint-disable-next-line no-console
|
|
412
|
+
console.warn(
|
|
413
|
+
`[maestro/org] the org server does not implement ${method} (NOT_FOUND) — ` +
|
|
414
|
+
`this write was dropped. Upgrade Cohort or run \`maestro doctor\` for detail.`
|
|
415
|
+
);
|
|
416
|
+
} catch { /* fail-open */ }
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Normalise a write res frame into the module's `{ok, mode, id, result|error}`
|
|
421
|
+
* shape. When the server returns NOT_FOUND (the method's handler lane is not
|
|
422
|
+
* built), the result is flagged `unimplemented:true` AND a one-shot warning is
|
|
423
|
+
* emitted, so a genuine capability gap is never swallowed silently.
|
|
424
|
+
* @param {object} frame the res frame
|
|
425
|
+
* @param {string} mode the surface label (e.g. "contact", "meeting")
|
|
426
|
+
* @param {string} [id]
|
|
427
|
+
* @param {string} [method] the wire method, for the unimplemented warning
|
|
428
|
+
*/
|
|
429
|
+
function shapeWrite(frame, mode, id, method) {
|
|
430
|
+
const ok = !!(frame && frame.ok);
|
|
431
|
+
const result = ok ? (frame.result ?? null) : undefined;
|
|
432
|
+
const resolvedId = (result && result.id) || id || undefined;
|
|
433
|
+
if (ok) return { ok: true, mode, id: resolvedId, result };
|
|
434
|
+
const error = (frame && frame.error) || { code: "INTERNAL", message: "no frame" };
|
|
435
|
+
if (error.code === "NOT_FOUND") {
|
|
436
|
+
if (method) warnUnimplemented(method);
|
|
437
|
+
return { ok: false, mode, id: resolvedId, unimplemented: true, error };
|
|
438
|
+
}
|
|
439
|
+
return { ok: false, mode, id: resolvedId, error };
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/** Return the first array found under the given keys, else []. */
|
|
443
|
+
function pickArray(obj, keys) {
|
|
444
|
+
if (Array.isArray(obj)) return obj;
|
|
445
|
+
if (!obj || typeof obj !== "object") return [];
|
|
446
|
+
for (const k of keys) if (Array.isArray(obj[k])) return obj[k];
|
|
447
|
+
return [];
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export const _internals = { factToParams, shapeWrite, pickArray, DEFAULT_RECALL_LIMIT };
|
|
451
|
+
|
|
452
|
+
export default {
|
|
453
|
+
remember,
|
|
454
|
+
rewrite,
|
|
455
|
+
recall,
|
|
456
|
+
recallDetailed,
|
|
457
|
+
forget,
|
|
458
|
+
upsertContact,
|
|
459
|
+
listContacts,
|
|
460
|
+
recordMeeting,
|
|
461
|
+
listMeetings,
|
|
462
|
+
normalizeGroup,
|
|
463
|
+
};
|