@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,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-telegram.mjs — Idempotent init for the Telegram channel (grammY).
|
|
4
|
+
*
|
|
5
|
+
* Mirrors init-whatsapp-baileys.mjs + init-slack-socket-mode.mjs:
|
|
6
|
+
* 1. Walks the operator through creating a bot with @BotFather.
|
|
7
|
+
* 2. Prompts for the bot token → appends TELEGRAM_BOT_TOKEN to .env
|
|
8
|
+
* (never overwrites an existing value; skips the prompt off-TTY).
|
|
9
|
+
* 3. Validates the token via the Telegram getMe API (no grammy needed).
|
|
10
|
+
* 4. Activates config/telegram.yaml from the scaffold example.
|
|
11
|
+
* 5. Checks for the optional `grammy` package and prints an install hint.
|
|
12
|
+
*
|
|
13
|
+
* Opt-in: grammY is a dynamic dependency, so the daemon only loads Telegram
|
|
14
|
+
* when config/telegram.yaml exists. Safe to re-run.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { dirname, join, resolve } from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync, copyFileSync } from "node:fs";
|
|
20
|
+
import { createInterface } from "node:readline/promises";
|
|
21
|
+
|
|
22
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
24
|
+
const MAESTRO_ROOT = process.env.MAESTRO_ROOT || resolve(__dirname, "..", "..");
|
|
25
|
+
|
|
26
|
+
const ok = (m) => process.stdout.write(`[init-telegram] ✓ ${m}\n`);
|
|
27
|
+
const warn = (m) => process.stdout.write(`[init-telegram] ⚠ ${m}\n`);
|
|
28
|
+
const info = (m) => process.stdout.write(`[init-telegram] ${m}\n`);
|
|
29
|
+
const fail = (m) => process.stderr.write(`[init-telegram] ✗ ${m}\n`);
|
|
30
|
+
|
|
31
|
+
function printWalkthrough() {
|
|
32
|
+
process.stdout.write(`
|
|
33
|
+
================================================================================
|
|
34
|
+
Telegram Setup — create a bot with @BotFather
|
|
35
|
+
================================================================================
|
|
36
|
+
|
|
37
|
+
Telegram gives the agent realtime DMs/groups via long-polling (no public
|
|
38
|
+
webhook, runs inside the daemon). You need a bot token from BotFather.
|
|
39
|
+
|
|
40
|
+
Step 1 — Create the bot
|
|
41
|
+
Open Telegram, message @BotFather, send: /newbot
|
|
42
|
+
Choose a display name and a username ending in "bot".
|
|
43
|
+
BotFather replies with an HTTP API token like: 123456789:ABCdef...
|
|
44
|
+
|
|
45
|
+
Step 2 — (optional) Let the bot read all group messages
|
|
46
|
+
@BotFather → /setprivacy → pick your bot → Disable.
|
|
47
|
+
(Otherwise the bot only sees @mentions, replies, and commands in groups.)
|
|
48
|
+
|
|
49
|
+
Step 3 — Paste the token below, or add it manually to ${join(AGENT_DIR, ".env")}:
|
|
50
|
+
TELEGRAM_BOT_TOKEN=123456789:ABCdef...
|
|
51
|
+
|
|
52
|
+
================================================================================
|
|
53
|
+
`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function readEnv(envPath) {
|
|
57
|
+
if (!existsSync(envPath)) return {};
|
|
58
|
+
const map = {};
|
|
59
|
+
for (const line of readFileSync(envPath, "utf-8").split("\n")) {
|
|
60
|
+
const m = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
|
|
61
|
+
if (m) map[m[1]] = m[2].trim().replace(/^["']|["']$/g, "");
|
|
62
|
+
}
|
|
63
|
+
return map;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function appendEnvLine(envPath, key, value) {
|
|
67
|
+
if (!existsSync(envPath)) { writeFileSync(envPath, `${key}=${value}\n`); return; }
|
|
68
|
+
const body = readFileSync(envPath, "utf-8");
|
|
69
|
+
const suffix = body.endsWith("\n") ? "" : "\n";
|
|
70
|
+
appendFileSync(envPath, `${suffix}${key}=${value}\n`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function promptForToken() {
|
|
74
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
75
|
+
try {
|
|
76
|
+
const answer = await rl.question("Paste your TELEGRAM_BOT_TOKEN (digits:ABC…), or press ENTER to skip: ");
|
|
77
|
+
return answer.trim();
|
|
78
|
+
} finally {
|
|
79
|
+
rl.close();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Validate a token via the Telegram getMe API. Returns { ok, username?, error? }. */
|
|
84
|
+
async function validateToken(token) {
|
|
85
|
+
try {
|
|
86
|
+
const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);
|
|
87
|
+
const body = await res.json();
|
|
88
|
+
if (body.ok && body.result?.username) return { ok: true, username: body.result.username };
|
|
89
|
+
return { ok: false, error: body.description || "getMe returned not-ok" };
|
|
90
|
+
} catch (err) {
|
|
91
|
+
return { ok: false, error: err.message };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function ensureTokenInEnv() {
|
|
96
|
+
const envPath = join(AGENT_DIR, ".env");
|
|
97
|
+
const env = readEnv(envPath);
|
|
98
|
+
const existing = env.TELEGRAM_BOT_TOKEN || "";
|
|
99
|
+
if (/^\d+:[\w-]+$/.test(existing)) {
|
|
100
|
+
ok("TELEGRAM_BOT_TOKEN already set in .env");
|
|
101
|
+
return existing;
|
|
102
|
+
}
|
|
103
|
+
if (!process.stdin.isTTY) {
|
|
104
|
+
warn("TELEGRAM_BOT_TOKEN missing and stdin is non-interactive — skipping prompt.");
|
|
105
|
+
info(`Add it manually to ${envPath}: TELEGRAM_BOT_TOKEN=123456789:ABC…`);
|
|
106
|
+
return "";
|
|
107
|
+
}
|
|
108
|
+
const token = await promptForToken();
|
|
109
|
+
if (!token) {
|
|
110
|
+
warn("No token provided — skipping. Add it manually before starting the daemon.");
|
|
111
|
+
return "";
|
|
112
|
+
}
|
|
113
|
+
if (!/^\d+:[\w-]+$/.test(token)) {
|
|
114
|
+
fail(`Token doesn't look like a Telegram bot token (digits:ABC…) — got '${token.slice(0, 8)}…'. Skipping.`);
|
|
115
|
+
return "";
|
|
116
|
+
}
|
|
117
|
+
appendEnvLine(envPath, "TELEGRAM_BOT_TOKEN", token);
|
|
118
|
+
ok(`TELEGRAM_BOT_TOKEN appended to ${envPath}`);
|
|
119
|
+
return token;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function activateGateFile() {
|
|
123
|
+
const exampleSrc = join(MAESTRO_ROOT, "scaffold/config/telegram.yaml.example");
|
|
124
|
+
const cfgDir = join(AGENT_DIR, "config");
|
|
125
|
+
mkdirSync(cfgDir, { recursive: true });
|
|
126
|
+
const activePath = join(cfgDir, "telegram.yaml");
|
|
127
|
+
if (existsSync(activePath)) { ok("config/telegram.yaml already present"); return; }
|
|
128
|
+
if (!existsSync(exampleSrc)) { warn(`scaffold/config/telegram.yaml.example missing in ${MAESTRO_ROOT}`); return; }
|
|
129
|
+
copyFileSync(exampleSrc, activePath);
|
|
130
|
+
ok("activated config/telegram.yaml from scaffold");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function checkGrammy() {
|
|
134
|
+
const pkg = join(AGENT_DIR, "node_modules/grammy/package.json");
|
|
135
|
+
if (existsSync(pkg)) { ok("grammy npm package present in agent"); }
|
|
136
|
+
else {
|
|
137
|
+
warn("grammy npm package NOT present in agent");
|
|
138
|
+
info(` Install with: cd ${AGENT_DIR} && npm i grammy`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function main() {
|
|
143
|
+
printWalkthrough();
|
|
144
|
+
const token = await ensureTokenInEnv();
|
|
145
|
+
|
|
146
|
+
if (token) {
|
|
147
|
+
const v = await validateToken(token);
|
|
148
|
+
if (v.ok) ok(`token valid — bot is @${v.username}`);
|
|
149
|
+
else warn(`token validation failed: ${v.error}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
activateGateFile();
|
|
153
|
+
checkGrammy();
|
|
154
|
+
|
|
155
|
+
info("DM pairing is default-deny: unknown senders must `pair <code>` first.");
|
|
156
|
+
info("Seed allowlisted ids in config/allowlist.yaml under `telegram:` or pair at runtime.");
|
|
157
|
+
ok("init-telegram complete");
|
|
158
|
+
info("Verify with: maestro doctor (and DM the bot once the daemon is running)");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
main().catch((err) => {
|
|
162
|
+
fail(`unexpected error: ${err.message}`);
|
|
163
|
+
process.stderr.write(`${err.stack}\n`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
});
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-voice-realtime.mjs — Idempotent init step for the voice-realtime feature.
|
|
4
|
+
*
|
|
5
|
+
* Sets up the OpenAI Realtime voice channel for an agent. Safe to run
|
|
6
|
+
* repeatedly — every step checks state and only acts on what's missing.
|
|
7
|
+
*
|
|
8
|
+
* What this installs (v2, post-1.12.20):
|
|
9
|
+
* 1. Copy scaffold/config/voice.yaml.example → config/voice.yaml.disabled
|
|
10
|
+
* (operator activates by renaming to .yaml once configured).
|
|
11
|
+
* 2. Patch .env.example with voice-related placeholders (OpenAI key, Twilio,
|
|
12
|
+
* cloud-relay URL + tokens).
|
|
13
|
+
* 3. Install ~/Library/LaunchAgents/ai.maestro.<firstname>-voice-webhook.plist
|
|
14
|
+
* from scripts/local-triggers/templates/ (uses the agent's own copy of
|
|
15
|
+
* voice-webhook-server.mjs — no MAESTRO_ROOT runtime dep).
|
|
16
|
+
* 4. Install ai.maestro.<firstname>-voice-relay-poller.plist for the
|
|
17
|
+
* Railway-fronted SIP poll loop.
|
|
18
|
+
* 5. Verify a recent enough `openai` npm package is available.
|
|
19
|
+
* 6. Create logs/voice/{sessions,outbound-audio} + state/voice/.
|
|
20
|
+
* 7. Print next-step checklist (Twilio SIP trunk, OpenAI dashboard config).
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { dirname, join, resolve } from "node:path";
|
|
24
|
+
import { fileURLToPath } from "node:url";
|
|
25
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from "node:fs";
|
|
26
|
+
|
|
27
|
+
import { installPlist, bootInLaunchd } from "./lib/install-plist.mjs";
|
|
28
|
+
|
|
29
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
31
|
+
// MAESTRO_ROOT here is only used to find the scaffold/ directory which lives
|
|
32
|
+
// inside the npm package install location. At runtime the agent uses its own
|
|
33
|
+
// colocated copies under AGENT_DIR/lib + scripts. Setting MAESTRO_ROOT explicitly
|
|
34
|
+
// only matters during `npx @cohortapp/agent-sdk init/upgrade` invocation.
|
|
35
|
+
const MAESTRO_ROOT = process.env.MAESTRO_ROOT || resolve(__dirname, "..", "..");
|
|
36
|
+
|
|
37
|
+
const args = new Set(process.argv.slice(2));
|
|
38
|
+
const skipPlists = args.has("--skip-plists");
|
|
39
|
+
const skipBoot = args.has("--skip-boot");
|
|
40
|
+
|
|
41
|
+
const ok = (m) => process.stdout.write(`[init-voice-realtime] ✓ ${m}\n`);
|
|
42
|
+
const warn = (m) => process.stdout.write(`[init-voice-realtime] ⚠ ${m}\n`);
|
|
43
|
+
const info = (m) => process.stdout.write(`[init-voice-realtime] · ${m}\n`);
|
|
44
|
+
|
|
45
|
+
// Resolve agent's first name from config/agent.json — needed for plist labels.
|
|
46
|
+
function loadFirstname() {
|
|
47
|
+
const agentJsonPath = join(AGENT_DIR, "config/agent.json");
|
|
48
|
+
if (existsSync(agentJsonPath)) {
|
|
49
|
+
try {
|
|
50
|
+
const j = JSON.parse(readFileSync(agentJsonPath, "utf-8"));
|
|
51
|
+
const n = j.firstName || j.fullName?.split(/\s+/)[0] || "";
|
|
52
|
+
return n.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
53
|
+
} catch { /* fall through */ }
|
|
54
|
+
}
|
|
55
|
+
return "agent";
|
|
56
|
+
}
|
|
57
|
+
const firstname = loadFirstname();
|
|
58
|
+
|
|
59
|
+
// ── 1. Place the disabled config file ──────────────────────────────────────
|
|
60
|
+
// The scaffold lives inside the npm package install dir, not the agent repo,
|
|
61
|
+
// so when this script is invoked via `npx @cohortapp/agent-sdk init` MAESTRO_ROOT
|
|
62
|
+
// points at the npx cache and finds scaffold/. When invoked directly inside
|
|
63
|
+
// an already-bootstrapped agent repo, scaffold/ is absent — that's fine
|
|
64
|
+
// PROVIDED config/voice.yaml{,.disabled} is already in place. Only error if
|
|
65
|
+
// both are missing (which means the agent never went through the wizard).
|
|
66
|
+
const exampleSrc = join(MAESTRO_ROOT, "scaffold/config/voice.yaml.example");
|
|
67
|
+
const cfgDir = join(AGENT_DIR, "config");
|
|
68
|
+
mkdirSync(cfgDir, { recursive: true });
|
|
69
|
+
|
|
70
|
+
const activePath = join(cfgDir, "voice.yaml");
|
|
71
|
+
const disabledPath = join(cfgDir, "voice.yaml.disabled");
|
|
72
|
+
|
|
73
|
+
if (existsSync(activePath)) {
|
|
74
|
+
ok("config/voice.yaml is already in place");
|
|
75
|
+
} else if (existsSync(disabledPath)) {
|
|
76
|
+
info("config/voice.yaml.disabled is present; rename to config/voice.yaml to activate.");
|
|
77
|
+
} else if (existsSync(exampleSrc)) {
|
|
78
|
+
copyFileSync(exampleSrc, disabledPath);
|
|
79
|
+
ok("placed scaffold/voice.yaml.example at config/voice.yaml.disabled");
|
|
80
|
+
} else {
|
|
81
|
+
warn(`No voice.yaml present and scaffold/config/voice.yaml.example not found at ${MAESTRO_ROOT}.`);
|
|
82
|
+
warn("Either run `npx @cohortapp/agent-sdk init voice-realtime` (uses scaffold from npm package)");
|
|
83
|
+
warn("or create config/voice.yaml manually using docs/guides/voice-mode.md as a reference.");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ── 2. Patch .env.example with all voice-stack vars ───────────────────────
|
|
88
|
+
const envExamplePath = join(AGENT_DIR, ".env.example");
|
|
89
|
+
if (existsSync(envExamplePath)) {
|
|
90
|
+
let body = readFileSync(envExamplePath, "utf-8");
|
|
91
|
+
let changed = false;
|
|
92
|
+
const placeholders = [
|
|
93
|
+
["OPENAI_API_KEY", "OpenAI API key — required for voice; also used as classifier fallback"],
|
|
94
|
+
["OPENAI_SAFETY_IDENTIFIER", "Optional hashed-user-id for OpenAI safety telemetry"],
|
|
95
|
+
["OPENAI_WEBHOOK_SECRET", "OpenAI webhook signing secret (Settings → Webhooks → realtime.call.incoming)"],
|
|
96
|
+
["TWILIO_ACCOUNT_SID", "Twilio account SID — required if using Twilio SIP/voice"],
|
|
97
|
+
["TWILIO_AUTH_TOKEN", "Twilio auth token"],
|
|
98
|
+
["TWILIO_SIP_TRUNK_SID", "Twilio Elastic SIP Trunk SID for native OpenAI SIP integration"],
|
|
99
|
+
["VOICE_RELAY_URL", "Cloud-relay base URL (Railway-deployed). e.g. https://<name>.up.railway.app"],
|
|
100
|
+
["VOICE_RELAY_POLL_TOKEN", "Bearer token for polling the cloud-relay drain endpoint"],
|
|
101
|
+
["VOICE_TWIML_TOKEN", "Bearer token Twilio presents when fetching the TwiML for Media Streams outbound"],
|
|
102
|
+
["VOICE_BROWSER_TOKEN", "Bearer token required to mint browser-side voice/test session"],
|
|
103
|
+
];
|
|
104
|
+
for (const [key, comment] of placeholders) {
|
|
105
|
+
if (!new RegExp(`^${key}=`, "m").test(body)) {
|
|
106
|
+
if (!body.endsWith("\n")) body += "\n";
|
|
107
|
+
body += `\n# ${comment}\n${key}=\n`;
|
|
108
|
+
changed = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (changed) {
|
|
112
|
+
writeFileSync(envExamplePath, body);
|
|
113
|
+
ok("appended voice env-var placeholders to .env.example");
|
|
114
|
+
} else {
|
|
115
|
+
info(".env.example already has voice env-var placeholders");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ── 3. Sanity-check the `openai` package ───────────────────────────────────
|
|
120
|
+
try {
|
|
121
|
+
const candidatePkg = [
|
|
122
|
+
join(AGENT_DIR, "node_modules/openai/package.json"),
|
|
123
|
+
join(MAESTRO_ROOT, "node_modules/openai/package.json"),
|
|
124
|
+
].find((p) => existsSync(p));
|
|
125
|
+
if (candidatePkg) {
|
|
126
|
+
const v = JSON.parse(readFileSync(candidatePkg, "utf-8")).version;
|
|
127
|
+
const major = parseInt(v.split(".")[0], 10);
|
|
128
|
+
if (major >= 6) ok(`openai@${v} detected — Realtime helpers available`);
|
|
129
|
+
else warn(`openai@${v} is below 6.x; install latest with: npm i openai`);
|
|
130
|
+
} else {
|
|
131
|
+
info("openai npm package not installed — run `npm i openai` in the agent repo");
|
|
132
|
+
}
|
|
133
|
+
} catch (err) {
|
|
134
|
+
warn(`unable to verify openai package: ${err.message}`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ── 4. Create transcript / audit dirs ──────────────────────────────────────
|
|
138
|
+
for (const d of [
|
|
139
|
+
"logs/voice/sessions",
|
|
140
|
+
"logs/voice",
|
|
141
|
+
"state/voice",
|
|
142
|
+
"state/voice/outbound-audio",
|
|
143
|
+
"state/voice/outbound-briefs",
|
|
144
|
+
"state/inbox/voice",
|
|
145
|
+
]) {
|
|
146
|
+
const full = join(AGENT_DIR, d);
|
|
147
|
+
if (!existsSync(full)) {
|
|
148
|
+
mkdirSync(full, { recursive: true });
|
|
149
|
+
ok(`created ${d}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ── 5. Install voice plists + boot them ────────────────────────────────────
|
|
154
|
+
if (skipPlists) {
|
|
155
|
+
info("--skip-plists set — leaving ~/Library/LaunchAgents/ untouched");
|
|
156
|
+
} else {
|
|
157
|
+
// Templates live inside the agent's *own* copy of scripts/local-triggers/
|
|
158
|
+
// (shipped via `npx @cohortapp/agent-sdk upgrade`), so we don't fall back into
|
|
159
|
+
// a MAESTRO_ROOT lookup. The plist installer hard-fails on missing files.
|
|
160
|
+
const templatesDir = join(AGENT_DIR, "scripts/local-triggers/templates");
|
|
161
|
+
const plists = [
|
|
162
|
+
{ template: "voice-webhook.plist.template", label: "voice-webhook" },
|
|
163
|
+
{ template: "voice-relay-poller.plist.template", label: "voice-relay-poller" },
|
|
164
|
+
];
|
|
165
|
+
for (const { template, label } of plists) {
|
|
166
|
+
const templatePath = join(templatesDir, template);
|
|
167
|
+
if (!existsSync(templatePath)) {
|
|
168
|
+
warn(`template not found: ${templatePath} — skipping ${label}`);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const { installedPath, changed, label: full } = installPlist({
|
|
173
|
+
templatePath,
|
|
174
|
+
firstname,
|
|
175
|
+
agentRoot: AGENT_DIR,
|
|
176
|
+
label,
|
|
177
|
+
});
|
|
178
|
+
ok(`${changed ? "installed" : "no-op (up-to-date)"} ${full} → ${installedPath}`);
|
|
179
|
+
if (!skipBoot && changed) {
|
|
180
|
+
try {
|
|
181
|
+
bootInLaunchd(installedPath);
|
|
182
|
+
ok(`booted ${full}`);
|
|
183
|
+
} catch (err) {
|
|
184
|
+
warn(`bootstrap failed for ${full}: ${err.message}`);
|
|
185
|
+
warn(` retry with: launchctl bootstrap gui/$(id -u) "${installedPath}"`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} catch (err) {
|
|
189
|
+
warn(`failed to install ${label}: ${err.message}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ── 6. Print operator next-steps ───────────────────────────────────────────
|
|
195
|
+
ok("done");
|
|
196
|
+
info("Next steps:");
|
|
197
|
+
info(" 1. Add OPENAI_API_KEY (+ OPENAI_WEBHOOK_SECRET, VOICE_RELAY_*, TWILIO_*) to .env");
|
|
198
|
+
info(" 2. Edit config/voice.yaml.disabled (choose inbound mode + tools) and rename → config/voice.yaml");
|
|
199
|
+
info(" 3. Deploy cloud-relay to Railway (one-time): cd scripts/cloud-relay/voice && railway up");
|
|
200
|
+
info(" • Set OPENAI_API_KEY + OPENAI_WEBHOOK_SECRET + VOICE_RELAY_POLL_TOKEN on Railway");
|
|
201
|
+
info(" • Point the OpenAI realtime.call.incoming webhook at <railway-url>/openai/realtime/incoming");
|
|
202
|
+
info(" 4. Configure Twilio Elastic SIP Trunk: node scripts/setup/configure-twilio-sip-trunk.mjs");
|
|
203
|
+
info(" 5. Reload services: launchctl kickstart -k gui/$(id -u)/ai.maestro.<name>-voice-webhook");
|
|
204
|
+
info("Runbook: docs/guides/voice-mode.md");
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* init-whatsapp-baileys.mjs — Idempotent init for WhatsApp(Baileys).
|
|
4
|
+
*
|
|
5
|
+
* This is opt-in (auto: false) because Baileys violates WhatsApp ToS
|
|
6
|
+
* for business use. The wizard:
|
|
7
|
+
* 1. Places config/whatsapp.yaml.disabled if no whatsapp.yaml exists.
|
|
8
|
+
* 2. Creates state/whatsapp/{auth,audio,outbound}/ for Baileys state.
|
|
9
|
+
* 3. Checks for the `baileys` npm package in the agent's node_modules
|
|
10
|
+
* and prints an install hint if missing.
|
|
11
|
+
* 4. Prints the QR-code instructions.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { dirname, join, resolve } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
import { existsSync, mkdirSync, copyFileSync } from "node:fs";
|
|
17
|
+
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const AGENT_DIR = process.env.AGENT_ROOT || process.env.AGENT_DIR || resolve(__dirname, "..", "..");
|
|
20
|
+
const MAESTRO_ROOT = process.env.MAESTRO_ROOT || resolve(__dirname, "..", "..");
|
|
21
|
+
|
|
22
|
+
const ok = (m) => process.stdout.write(`[init-whatsapp-baileys] ✓ ${m}\n`);
|
|
23
|
+
const warn = (m) => process.stdout.write(`[init-whatsapp-baileys] ⚠ ${m}\n`);
|
|
24
|
+
const info = (m) => process.stdout.write(`[init-whatsapp-baileys] · ${m}\n`);
|
|
25
|
+
|
|
26
|
+
const exampleSrc = join(MAESTRO_ROOT, "scaffold/config/whatsapp.yaml.example");
|
|
27
|
+
if (!existsSync(exampleSrc)) {
|
|
28
|
+
warn(`scaffold/config/whatsapp.yaml.example missing in ${MAESTRO_ROOT}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const cfgDir = join(AGENT_DIR, "config");
|
|
33
|
+
mkdirSync(cfgDir, { recursive: true });
|
|
34
|
+
|
|
35
|
+
const activePath = join(cfgDir, "whatsapp.yaml");
|
|
36
|
+
const disabledPath = join(cfgDir, "whatsapp.yaml.disabled");
|
|
37
|
+
|
|
38
|
+
if (existsSync(activePath)) {
|
|
39
|
+
ok("config/whatsapp.yaml already present");
|
|
40
|
+
} else if (existsSync(disabledPath)) {
|
|
41
|
+
info("config/whatsapp.yaml.disabled present; rename to activate");
|
|
42
|
+
} else {
|
|
43
|
+
copyFileSync(exampleSrc, disabledPath);
|
|
44
|
+
ok("placed scaffold/whatsapp.yaml.example at config/whatsapp.yaml.disabled");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
for (const d of [
|
|
48
|
+
"state/whatsapp/auth",
|
|
49
|
+
"state/whatsapp/audio",
|
|
50
|
+
"state/whatsapp/outbound",
|
|
51
|
+
]) {
|
|
52
|
+
const full = join(AGENT_DIR, d);
|
|
53
|
+
if (!existsSync(full)) {
|
|
54
|
+
mkdirSync(full, { recursive: true });
|
|
55
|
+
ok(`created ${d}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check for baileys
|
|
60
|
+
const pkg1 = join(AGENT_DIR, "node_modules/baileys/package.json");
|
|
61
|
+
const pkg2 = join(AGENT_DIR, "node_modules/@whiskeysockets/baileys/package.json");
|
|
62
|
+
if (existsSync(pkg1) || existsSync(pkg2)) {
|
|
63
|
+
ok("baileys npm package present in agent");
|
|
64
|
+
} else {
|
|
65
|
+
warn("baileys npm package NOT present in agent");
|
|
66
|
+
info(" Install with: cd " + AGENT_DIR + " && npm i baileys");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
info("First-run flow once the daemon starts the channel:");
|
|
70
|
+
info(" 1. Daemon prints QR text into state/whatsapp/auth/pending-qr.txt");
|
|
71
|
+
info(" 2. Operator renders QR (e.g. `cat … | qrencode -t ANSI`) and scans");
|
|
72
|
+
info(" 3. WhatsApp Web → Linked Devices → maestro session is now active");
|
|
73
|
+
info(" 4. Auth persists across restarts; do not lose state/whatsapp/auth/");
|
|
74
|
+
warn("REMINDER: Baileys violates WhatsApp ToS for business use. For");
|
|
75
|
+
warn("production / business deployments, use transport: twilio instead.");
|
|
76
|
+
|
|
77
|
+
ok("done");
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# install-dev-tools.sh — Install and configure approved dev tooling for Maestro agents
|
|
3
|
+
#
|
|
4
|
+
# Approved tools (audited 2026-04-18 from #dev-tooling channel):
|
|
5
|
+
# - claude-pace — Rate limit status line tracker (Bash plugin)
|
|
6
|
+
# - agents-observe — Multi-agent observability dashboard (CC plugin)
|
|
7
|
+
# - ccxray — Claude Code token/cost observability proxy
|
|
8
|
+
# - ClawTeam — Git worktree swarm orchestrator (CLI)
|
|
9
|
+
# - code-review-graph — Tree-sitter codebase knowledge graph (MCP)
|
|
10
|
+
#
|
|
11
|
+
# Skipped:
|
|
12
|
+
# - Superset — GUI-only, Elastic License v2, not automatable
|
|
13
|
+
# - claudraband — Evaluate later; overlaps with maestro session mgmt
|
|
14
|
+
#
|
|
15
|
+
# Usage: ./scripts/setup/install-dev-tools.sh [--all | --tool <name>]
|
|
16
|
+
# Examples:
|
|
17
|
+
# ./scripts/setup/install-dev-tools.sh --all
|
|
18
|
+
# ./scripts/setup/install-dev-tools.sh --tool claude-pace
|
|
19
|
+
# ./scripts/setup/install-dev-tools.sh --tool ccxray
|
|
20
|
+
|
|
21
|
+
set -e
|
|
22
|
+
|
|
23
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
24
|
+
AGENT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
25
|
+
|
|
26
|
+
# ── Helpers ──────────────────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
info() { echo " [INFO] $1"; }
|
|
29
|
+
ok() { echo " [OK] $1"; }
|
|
30
|
+
skip() { echo " [SKIP] $1"; }
|
|
31
|
+
fail() { echo " [FAIL] $1" >&2; }
|
|
32
|
+
|
|
33
|
+
# ── Tool installers ─────────────────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
install_claude_pace() {
|
|
36
|
+
info "Installing claude-pace (rate limit status line tracker)..."
|
|
37
|
+
if command -v claude >/dev/null 2>&1; then
|
|
38
|
+
# Install as Claude Code plugin
|
|
39
|
+
claude plugin install claude-pace 2>/dev/null && ok "claude-pace plugin installed" || {
|
|
40
|
+
info "Plugin install failed, trying npx setup..."
|
|
41
|
+
npx claude-pace setup 2>/dev/null && ok "claude-pace configured via npx" || skip "claude-pace: manual setup needed — see https://github.com/Astro-Han/claude-pace"
|
|
42
|
+
}
|
|
43
|
+
else
|
|
44
|
+
skip "claude-pace: Claude Code CLI not found"
|
|
45
|
+
fi
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
install_agents_observe() {
|
|
49
|
+
info "Installing agents-observe (multi-agent observability dashboard)..."
|
|
50
|
+
if command -v claude >/dev/null 2>&1; then
|
|
51
|
+
claude plugin install agents-observe 2>/dev/null && ok "agents-observe plugin installed" || {
|
|
52
|
+
info "Plugin install failed, trying npm global..."
|
|
53
|
+
npm install -g agents-observe 2>/dev/null && ok "agents-observe installed globally" || skip "agents-observe: manual setup needed — see https://github.com/simple10/agents-observe"
|
|
54
|
+
}
|
|
55
|
+
else
|
|
56
|
+
skip "agents-observe: Claude Code CLI not found"
|
|
57
|
+
fi
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
install_ccxray() {
|
|
61
|
+
info "Installing ccxray (Claude Code token/cost observability)..."
|
|
62
|
+
# ccxray is zero-install via npx — just verify it's accessible
|
|
63
|
+
if npx ccxray --version >/dev/null 2>&1; then
|
|
64
|
+
ok "ccxray available via npx"
|
|
65
|
+
else
|
|
66
|
+
info "ccxray will be available via: npx ccxray claude"
|
|
67
|
+
ok "ccxray: zero-install, run with 'npx ccxray claude' when needed"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Create a convenience wrapper
|
|
71
|
+
cat > "$AGENT_DIR/scripts/ccxray-session.sh" << 'WRAPPER'
|
|
72
|
+
#!/bin/bash
|
|
73
|
+
# Launch Claude Code through ccxray observability proxy
|
|
74
|
+
# Usage: ./scripts/ccxray-session.sh [claude args...]
|
|
75
|
+
exec npx ccxray claude "$@"
|
|
76
|
+
WRAPPER
|
|
77
|
+
chmod +x "$AGENT_DIR/scripts/ccxray-session.sh"
|
|
78
|
+
ok "Created scripts/ccxray-session.sh convenience wrapper"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
install_clawteam() {
|
|
82
|
+
info "Installing ClawTeam (git worktree swarm orchestrator)..."
|
|
83
|
+
if command -v pip3 >/dev/null 2>&1; then
|
|
84
|
+
pip3 install clawteam 2>/dev/null && ok "ClawTeam installed via pip" || {
|
|
85
|
+
info "pip install failed, trying git clone..."
|
|
86
|
+
if [ ! -d "$HOME/.clawteam" ]; then
|
|
87
|
+
git clone https://github.com/win4r/ClawTeam-OpenClaw.git "$HOME/.clawteam" 2>/dev/null && ok "ClawTeam cloned to ~/.clawteam" || skip "ClawTeam: manual setup needed — see https://github.com/win4r/ClawTeam-OpenClaw"
|
|
88
|
+
else
|
|
89
|
+
ok "ClawTeam already present at ~/.clawteam"
|
|
90
|
+
fi
|
|
91
|
+
}
|
|
92
|
+
else
|
|
93
|
+
skip "ClawTeam: pip3 not found"
|
|
94
|
+
fi
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
install_code_review_graph() {
|
|
98
|
+
info "Installing code-review-graph (Tree-sitter codebase knowledge graph)..."
|
|
99
|
+
if npx code-review-graph --version >/dev/null 2>&1; then
|
|
100
|
+
ok "code-review-graph available via npx"
|
|
101
|
+
else
|
|
102
|
+
npm install -g code-review-graph 2>/dev/null && ok "code-review-graph installed globally" || {
|
|
103
|
+
info "code-review-graph: available via npx when needed"
|
|
104
|
+
ok "Run with: npx code-review-graph"
|
|
105
|
+
}
|
|
106
|
+
fi
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# ── Main ─────────────────────────────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
echo "=========================================="
|
|
112
|
+
echo " Maestro Dev Tooling Installer"
|
|
113
|
+
echo " Agent dir: $AGENT_DIR"
|
|
114
|
+
echo "=========================================="
|
|
115
|
+
echo ""
|
|
116
|
+
|
|
117
|
+
TOOL="${2:-}"
|
|
118
|
+
case "${1:-}" in
|
|
119
|
+
--all)
|
|
120
|
+
install_claude_pace
|
|
121
|
+
install_agents_observe
|
|
122
|
+
install_ccxray
|
|
123
|
+
install_clawteam
|
|
124
|
+
install_code_review_graph
|
|
125
|
+
;;
|
|
126
|
+
--tool)
|
|
127
|
+
case "$TOOL" in
|
|
128
|
+
claude-pace) install_claude_pace ;;
|
|
129
|
+
agents-observe) install_agents_observe ;;
|
|
130
|
+
ccxray) install_ccxray ;;
|
|
131
|
+
clawteam) install_clawteam ;;
|
|
132
|
+
code-review-graph) install_code_review_graph ;;
|
|
133
|
+
*) echo "Unknown tool: $TOOL"; echo "Available: claude-pace, agents-observe, ccxray, clawteam, code-review-graph"; exit 1 ;;
|
|
134
|
+
esac
|
|
135
|
+
;;
|
|
136
|
+
*)
|
|
137
|
+
echo "Usage: $0 [--all | --tool <name>]"
|
|
138
|
+
echo ""
|
|
139
|
+
echo "Available tools:"
|
|
140
|
+
echo " claude-pace — Rate limit status line tracker"
|
|
141
|
+
echo " agents-observe — Multi-agent observability dashboard"
|
|
142
|
+
echo " ccxray — Token/cost observability proxy"
|
|
143
|
+
echo " clawteam — Git worktree swarm orchestrator"
|
|
144
|
+
echo " code-review-graph — Tree-sitter codebase knowledge graph"
|
|
145
|
+
exit 0
|
|
146
|
+
;;
|
|
147
|
+
esac
|
|
148
|
+
|
|
149
|
+
echo ""
|
|
150
|
+
echo "Done. See docs/guides/dev-tooling.md for usage details."
|