openryoko 0.9.4-ryoko.2
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/dist/bin/jimmy.d.ts +3 -0
- package/dist/bin/jimmy.d.ts.map +1 -0
- package/dist/bin/jimmy.js +149 -0
- package/dist/bin/jimmy.js.map +1 -0
- package/dist/package.json +54 -0
- package/dist/src/cli/__tests__/migrate.test.d.ts +2 -0
- package/dist/src/cli/__tests__/migrate.test.d.ts.map +1 -0
- package/dist/src/cli/__tests__/migrate.test.js +79 -0
- package/dist/src/cli/__tests__/migrate.test.js.map +1 -0
- package/dist/src/cli/chrome-allow.d.ts +5 -0
- package/dist/src/cli/chrome-allow.d.ts.map +1 -0
- package/dist/src/cli/chrome-allow.js +250 -0
- package/dist/src/cli/chrome-allow.js.map +1 -0
- package/dist/src/cli/create.d.ts +2 -0
- package/dist/src/cli/create.d.ts.map +1 -0
- package/dist/src/cli/create.js +72 -0
- package/dist/src/cli/create.js.map +1 -0
- package/dist/src/cli/instances.d.ts +14 -0
- package/dist/src/cli/instances.d.ts.map +1 -0
- package/dist/src/cli/instances.js +43 -0
- package/dist/src/cli/instances.js.map +1 -0
- package/dist/src/cli/list.d.ts +2 -0
- package/dist/src/cli/list.d.ts.map +1 -0
- package/dist/src/cli/list.js +38 -0
- package/dist/src/cli/list.js.map +1 -0
- package/dist/src/cli/migrate.d.ts +5 -0
- package/dist/src/cli/migrate.d.ts.map +1 -0
- package/dist/src/cli/migrate.js +222 -0
- package/dist/src/cli/migrate.js.map +1 -0
- package/dist/src/cli/nuke.d.ts +2 -0
- package/dist/src/cli/nuke.d.ts.map +1 -0
- package/dist/src/cli/nuke.js +91 -0
- package/dist/src/cli/nuke.js.map +1 -0
- package/dist/src/cli/remove.d.ts +4 -0
- package/dist/src/cli/remove.d.ts.map +1 -0
- package/dist/src/cli/remove.js +47 -0
- package/dist/src/cli/remove.js.map +1 -0
- package/dist/src/cli/setup.d.ts +4 -0
- package/dist/src/cli/setup.d.ts.map +1 -0
- package/dist/src/cli/setup.js +491 -0
- package/dist/src/cli/setup.js.map +1 -0
- package/dist/src/cli/skills.d.ts +28 -0
- package/dist/src/cli/skills.d.ts.map +1 -0
- package/dist/src/cli/skills.js +284 -0
- package/dist/src/cli/skills.js.map +1 -0
- package/dist/src/cli/start.d.ts +5 -0
- package/dist/src/cli/start.d.ts.map +1 -0
- package/dist/src/cli/start.js +34 -0
- package/dist/src/cli/start.js.map +1 -0
- package/dist/src/cli/status.d.ts +2 -0
- package/dist/src/cli/status.d.ts.map +1 -0
- package/dist/src/cli/status.js +69 -0
- package/dist/src/cli/status.js.map +1 -0
- package/dist/src/cli/stop.d.ts +2 -0
- package/dist/src/cli/stop.d.ts.map +1 -0
- package/dist/src/cli/stop.js +11 -0
- package/dist/src/cli/stop.js.map +1 -0
- package/dist/src/connectors/cron/index.d.ts +21 -0
- package/dist/src/connectors/cron/index.d.ts.map +1 -0
- package/dist/src/connectors/cron/index.js +75 -0
- package/dist/src/connectors/cron/index.js.map +1 -0
- package/dist/src/connectors/discord/format.d.ts +3 -0
- package/dist/src/connectors/discord/format.d.ts.map +1 -0
- package/dist/src/connectors/discord/format.js +33 -0
- package/dist/src/connectors/discord/format.js.map +1 -0
- package/dist/src/connectors/discord/index.d.ts +47 -0
- package/dist/src/connectors/discord/index.d.ts.map +1 -0
- package/dist/src/connectors/discord/index.js +308 -0
- package/dist/src/connectors/discord/index.js.map +1 -0
- package/dist/src/connectors/discord/remote.d.ts +33 -0
- package/dist/src/connectors/discord/remote.d.ts.map +1 -0
- package/dist/src/connectors/discord/remote.js +89 -0
- package/dist/src/connectors/discord/remote.js.map +1 -0
- package/dist/src/connectors/discord/threads.d.ts +5 -0
- package/dist/src/connectors/discord/threads.d.ts.map +1 -0
- package/dist/src/connectors/discord/threads.js +22 -0
- package/dist/src/connectors/discord/threads.js.map +1 -0
- package/dist/src/connectors/slack/__tests__/active-threads.test.d.ts +2 -0
- package/dist/src/connectors/slack/__tests__/active-threads.test.d.ts.map +1 -0
- package/dist/src/connectors/slack/__tests__/active-threads.test.js +57 -0
- package/dist/src/connectors/slack/__tests__/active-threads.test.js.map +1 -0
- package/dist/src/connectors/slack/__tests__/format.test.d.ts +2 -0
- package/dist/src/connectors/slack/__tests__/format.test.d.ts.map +1 -0
- package/dist/src/connectors/slack/__tests__/format.test.js +115 -0
- package/dist/src/connectors/slack/__tests__/format.test.js.map +1 -0
- package/dist/src/connectors/slack/__tests__/speaker.test.d.ts +2 -0
- package/dist/src/connectors/slack/__tests__/speaker.test.d.ts.map +1 -0
- package/dist/src/connectors/slack/__tests__/speaker.test.js +59 -0
- package/dist/src/connectors/slack/__tests__/speaker.test.js.map +1 -0
- package/dist/src/connectors/slack/__tests__/triage-prompt.test.d.ts +2 -0
- package/dist/src/connectors/slack/__tests__/triage-prompt.test.d.ts.map +1 -0
- package/dist/src/connectors/slack/__tests__/triage-prompt.test.js +102 -0
- package/dist/src/connectors/slack/__tests__/triage-prompt.test.js.map +1 -0
- package/dist/src/connectors/slack/__tests__/triage.test.d.ts +2 -0
- package/dist/src/connectors/slack/__tests__/triage.test.d.ts.map +1 -0
- package/dist/src/connectors/slack/__tests__/triage.test.js +88 -0
- package/dist/src/connectors/slack/__tests__/triage.test.js.map +1 -0
- package/dist/src/connectors/slack/active-threads.d.ts +39 -0
- package/dist/src/connectors/slack/active-threads.d.ts.map +1 -0
- package/dist/src/connectors/slack/active-threads.js +71 -0
- package/dist/src/connectors/slack/active-threads.js.map +1 -0
- package/dist/src/connectors/slack/format.d.ts +17 -0
- package/dist/src/connectors/slack/format.d.ts.map +1 -0
- package/dist/src/connectors/slack/format.js +85 -0
- package/dist/src/connectors/slack/format.js.map +1 -0
- package/dist/src/connectors/slack/index.d.ts +51 -0
- package/dist/src/connectors/slack/index.d.ts.map +1 -0
- package/dist/src/connectors/slack/index.js +562 -0
- package/dist/src/connectors/slack/index.js.map +1 -0
- package/dist/src/connectors/slack/speaker.d.ts +39 -0
- package/dist/src/connectors/slack/speaker.d.ts.map +1 -0
- package/dist/src/connectors/slack/speaker.js +30 -0
- package/dist/src/connectors/slack/speaker.js.map +1 -0
- package/dist/src/connectors/slack/threads.d.ts +12 -0
- package/dist/src/connectors/slack/threads.d.ts.map +1 -0
- package/dist/src/connectors/slack/threads.js +41 -0
- package/dist/src/connectors/slack/threads.js.map +1 -0
- package/dist/src/connectors/slack/threads.test.d.ts +2 -0
- package/dist/src/connectors/slack/threads.test.d.ts.map +1 -0
- package/dist/src/connectors/slack/threads.test.js +79 -0
- package/dist/src/connectors/slack/threads.test.js.map +1 -0
- package/dist/src/connectors/slack/triage-prompt.d.ts +50 -0
- package/dist/src/connectors/slack/triage-prompt.d.ts.map +1 -0
- package/dist/src/connectors/slack/triage-prompt.js +127 -0
- package/dist/src/connectors/slack/triage-prompt.js.map +1 -0
- package/dist/src/connectors/slack/triage.d.ts +41 -0
- package/dist/src/connectors/slack/triage.d.ts.map +1 -0
- package/dist/src/connectors/slack/triage.js +120 -0
- package/dist/src/connectors/slack/triage.js.map +1 -0
- package/dist/src/connectors/telegram/__tests__/connector.test.d.ts +2 -0
- package/dist/src/connectors/telegram/__tests__/connector.test.d.ts.map +1 -0
- package/dist/src/connectors/telegram/__tests__/connector.test.js +257 -0
- package/dist/src/connectors/telegram/__tests__/connector.test.js.map +1 -0
- package/dist/src/connectors/telegram/__tests__/format.test.d.ts +2 -0
- package/dist/src/connectors/telegram/__tests__/format.test.d.ts.map +1 -0
- package/dist/src/connectors/telegram/__tests__/format.test.js +79 -0
- package/dist/src/connectors/telegram/__tests__/format.test.js.map +1 -0
- package/dist/src/connectors/telegram/__tests__/threads.test.d.ts +2 -0
- package/dist/src/connectors/telegram/__tests__/threads.test.d.ts.map +1 -0
- package/dist/src/connectors/telegram/__tests__/threads.test.js +51 -0
- package/dist/src/connectors/telegram/__tests__/threads.test.js.map +1 -0
- package/dist/src/connectors/telegram/format.d.ts +12 -0
- package/dist/src/connectors/telegram/format.d.ts.map +1 -0
- package/dist/src/connectors/telegram/format.js +61 -0
- package/dist/src/connectors/telegram/format.js.map +1 -0
- package/dist/src/connectors/telegram/index.d.ts +28 -0
- package/dist/src/connectors/telegram/index.d.ts.map +1 -0
- package/dist/src/connectors/telegram/index.js +213 -0
- package/dist/src/connectors/telegram/index.js.map +1 -0
- package/dist/src/connectors/telegram/threads.d.ts +29 -0
- package/dist/src/connectors/telegram/threads.d.ts.map +1 -0
- package/dist/src/connectors/telegram/threads.js +26 -0
- package/dist/src/connectors/telegram/threads.js.map +1 -0
- package/dist/src/connectors/whatsapp/__tests__/format.test.d.ts +2 -0
- package/dist/src/connectors/whatsapp/__tests__/format.test.d.ts.map +1 -0
- package/dist/src/connectors/whatsapp/__tests__/format.test.js +70 -0
- package/dist/src/connectors/whatsapp/__tests__/format.test.js.map +1 -0
- package/dist/src/connectors/whatsapp/format.d.ts +12 -0
- package/dist/src/connectors/whatsapp/format.d.ts.map +1 -0
- package/dist/src/connectors/whatsapp/format.js +53 -0
- package/dist/src/connectors/whatsapp/format.js.map +1 -0
- package/dist/src/connectors/whatsapp/index.d.ts +42 -0
- package/dist/src/connectors/whatsapp/index.d.ts.map +1 -0
- package/dist/src/connectors/whatsapp/index.js +279 -0
- package/dist/src/connectors/whatsapp/index.js.map +1 -0
- package/dist/src/cron/jobs.d.ts +5 -0
- package/dist/src/cron/jobs.d.ts.map +1 -0
- package/dist/src/cron/jobs.js +23 -0
- package/dist/src/cron/jobs.js.map +1 -0
- package/dist/src/cron/runner.d.ts +4 -0
- package/dist/src/cron/runner.d.ts.map +1 -0
- package/dist/src/cron/runner.js +88 -0
- package/dist/src/cron/runner.js.map +1 -0
- package/dist/src/cron/scheduler.d.ts +8 -0
- package/dist/src/cron/scheduler.d.ts.map +1 -0
- package/dist/src/cron/scheduler.js +64 -0
- package/dist/src/cron/scheduler.js.map +1 -0
- package/dist/src/engines/__tests__/gemini.test.d.ts +2 -0
- package/dist/src/engines/__tests__/gemini.test.d.ts.map +1 -0
- package/dist/src/engines/__tests__/gemini.test.js +404 -0
- package/dist/src/engines/__tests__/gemini.test.js.map +1 -0
- package/dist/src/engines/claude.d.ts +20 -0
- package/dist/src/engines/claude.d.ts.map +1 -0
- package/dist/src/engines/claude.js +520 -0
- package/dist/src/engines/claude.js.map +1 -0
- package/dist/src/engines/codex.d.ts +15 -0
- package/dist/src/engines/codex.d.ts.map +1 -0
- package/dist/src/engines/codex.js +351 -0
- package/dist/src/engines/codex.js.map +1 -0
- package/dist/src/engines/gemini.d.ts +32 -0
- package/dist/src/engines/gemini.d.ts.map +1 -0
- package/dist/src/engines/gemini.js +328 -0
- package/dist/src/engines/gemini.js.map +1 -0
- package/dist/src/engines/mock.d.ts +16 -0
- package/dist/src/engines/mock.d.ts.map +1 -0
- package/dist/src/engines/mock.js +47 -0
- package/dist/src/engines/mock.js.map +1 -0
- package/dist/src/gateway/__tests__/api-last-n.test.d.ts +2 -0
- package/dist/src/gateway/__tests__/api-last-n.test.d.ts.map +1 -0
- package/dist/src/gateway/__tests__/api-last-n.test.js +32 -0
- package/dist/src/gateway/__tests__/api-last-n.test.js.map +1 -0
- package/dist/src/gateway/__tests__/costs.test.d.ts +2 -0
- package/dist/src/gateway/__tests__/costs.test.d.ts.map +1 -0
- package/dist/src/gateway/__tests__/costs.test.js +32 -0
- package/dist/src/gateway/__tests__/costs.test.js.map +1 -0
- package/dist/src/gateway/__tests__/org-hierarchy.test.d.ts +2 -0
- package/dist/src/gateway/__tests__/org-hierarchy.test.d.ts.map +1 -0
- package/dist/src/gateway/__tests__/org-hierarchy.test.js +161 -0
- package/dist/src/gateway/__tests__/org-hierarchy.test.js.map +1 -0
- package/dist/src/gateway/__tests__/org-update.test.d.ts +2 -0
- package/dist/src/gateway/__tests__/org-update.test.d.ts.map +1 -0
- package/dist/src/gateway/__tests__/org-update.test.js +99 -0
- package/dist/src/gateway/__tests__/org-update.test.js.map +1 -0
- package/dist/src/gateway/__tests__/org.test.d.ts +2 -0
- package/dist/src/gateway/__tests__/org.test.d.ts.map +1 -0
- package/dist/src/gateway/__tests__/org.test.js +77 -0
- package/dist/src/gateway/__tests__/org.test.js.map +1 -0
- package/dist/src/gateway/__tests__/services.test.d.ts +2 -0
- package/dist/src/gateway/__tests__/services.test.d.ts.map +1 -0
- package/dist/src/gateway/__tests__/services.test.js +153 -0
- package/dist/src/gateway/__tests__/services.test.js.map +1 -0
- package/dist/src/gateway/api.d.ts +19 -0
- package/dist/src/gateway/api.d.ts.map +1 -0
- package/dist/src/gateway/api.js +2261 -0
- package/dist/src/gateway/api.js.map +1 -0
- package/dist/src/gateway/budgets.d.ts +16 -0
- package/dist/src/gateway/budgets.d.ts.map +1 -0
- package/dist/src/gateway/budgets.js +39 -0
- package/dist/src/gateway/budgets.js.map +1 -0
- package/dist/src/gateway/costs.d.ts +19 -0
- package/dist/src/gateway/costs.d.ts.map +1 -0
- package/dist/src/gateway/costs.js +39 -0
- package/dist/src/gateway/costs.js.map +1 -0
- package/dist/src/gateway/daemon-entry.d.ts +2 -0
- package/dist/src/gateway/daemon-entry.d.ts.map +1 -0
- package/dist/src/gateway/daemon-entry.js +12 -0
- package/dist/src/gateway/daemon-entry.js.map +1 -0
- package/dist/src/gateway/files.d.ts +6 -0
- package/dist/src/gateway/files.d.ts.map +1 -0
- package/dist/src/gateway/files.js +442 -0
- package/dist/src/gateway/files.js.map +1 -0
- package/dist/src/gateway/goals.d.ts +11 -0
- package/dist/src/gateway/goals.d.ts.map +1 -0
- package/dist/src/gateway/goals.js +72 -0
- package/dist/src/gateway/goals.js.map +1 -0
- package/dist/src/gateway/lifecycle.d.ts +10 -0
- package/dist/src/gateway/lifecycle.d.ts.map +1 -0
- package/dist/src/gateway/lifecycle.js +152 -0
- package/dist/src/gateway/lifecycle.js.map +1 -0
- package/dist/src/gateway/org-hierarchy.d.ts +5 -0
- package/dist/src/gateway/org-hierarchy.d.ts.map +1 -0
- package/dist/src/gateway/org-hierarchy.js +174 -0
- package/dist/src/gateway/org-hierarchy.js.map +1 -0
- package/dist/src/gateway/org.d.ts +17 -0
- package/dist/src/gateway/org.d.ts.map +1 -0
- package/dist/src/gateway/org.js +136 -0
- package/dist/src/gateway/org.js.map +1 -0
- package/dist/src/gateway/server.d.ts +4 -0
- package/dist/src/gateway/server.d.ts.map +1 -0
- package/dist/src/gateway/server.js +764 -0
- package/dist/src/gateway/server.js.map +1 -0
- package/dist/src/gateway/services.d.ts +28 -0
- package/dist/src/gateway/services.d.ts.map +1 -0
- package/dist/src/gateway/services.js +112 -0
- package/dist/src/gateway/services.js.map +1 -0
- package/dist/src/gateway/watcher.d.ts +14 -0
- package/dist/src/gateway/watcher.d.ts.map +1 -0
- package/dist/src/gateway/watcher.js +111 -0
- package/dist/src/gateway/watcher.js.map +1 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp/gateway-server.d.ts +13 -0
- package/dist/src/mcp/gateway-server.d.ts.map +1 -0
- package/dist/src/mcp/gateway-server.js +376 -0
- package/dist/src/mcp/gateway-server.js.map +1 -0
- package/dist/src/mcp/resolver.d.ts +19 -0
- package/dist/src/mcp/resolver.d.ts.map +1 -0
- package/dist/src/mcp/resolver.js +159 -0
- package/dist/src/mcp/resolver.js.map +1 -0
- package/dist/src/sessions/__tests__/callbacks.test.d.ts +2 -0
- package/dist/src/sessions/__tests__/callbacks.test.d.ts.map +1 -0
- package/dist/src/sessions/__tests__/callbacks.test.js +154 -0
- package/dist/src/sessions/__tests__/callbacks.test.js.map +1 -0
- package/dist/src/sessions/callbacks.d.ts +31 -0
- package/dist/src/sessions/callbacks.d.ts.map +1 -0
- package/dist/src/sessions/callbacks.js +112 -0
- package/dist/src/sessions/callbacks.js.map +1 -0
- package/dist/src/sessions/context.d.ts +36 -0
- package/dist/src/sessions/context.d.ts.map +1 -0
- package/dist/src/sessions/context.js +741 -0
- package/dist/src/sessions/context.js.map +1 -0
- package/dist/src/sessions/fork.d.ts +30 -0
- package/dist/src/sessions/fork.d.ts.map +1 -0
- package/dist/src/sessions/fork.js +178 -0
- package/dist/src/sessions/fork.js.map +1 -0
- package/dist/src/sessions/manager.d.ts +27 -0
- package/dist/src/sessions/manager.d.ts.map +1 -0
- package/dist/src/sessions/manager.js +751 -0
- package/dist/src/sessions/manager.js.map +1 -0
- package/dist/src/sessions/queue.d.ts +36 -0
- package/dist/src/sessions/queue.d.ts.map +1 -0
- package/dist/src/sessions/queue.js +101 -0
- package/dist/src/sessions/queue.js.map +1 -0
- package/dist/src/sessions/queue.test.d.ts +2 -0
- package/dist/src/sessions/queue.test.d.ts.map +1 -0
- package/dist/src/sessions/queue.test.js +28 -0
- package/dist/src/sessions/queue.test.js.map +1 -0
- package/dist/src/sessions/registry.d.ts +116 -0
- package/dist/src/sessions/registry.d.ts.map +1 -0
- package/dist/src/sessions/registry.js +480 -0
- package/dist/src/sessions/registry.js.map +1 -0
- package/dist/src/sessions/registry.test.d.ts +2 -0
- package/dist/src/sessions/registry.test.d.ts.map +1 -0
- package/dist/src/sessions/registry.test.js +41 -0
- package/dist/src/sessions/registry.test.js.map +1 -0
- package/dist/src/shared/__tests__/rateLimit.test.d.ts +2 -0
- package/dist/src/shared/__tests__/rateLimit.test.d.ts.map +1 -0
- package/dist/src/shared/__tests__/rateLimit.test.js +108 -0
- package/dist/src/shared/__tests__/rateLimit.test.js.map +1 -0
- package/dist/src/shared/__tests__/usageAwareness.test.d.ts +2 -0
- package/dist/src/shared/__tests__/usageAwareness.test.d.ts.map +1 -0
- package/dist/src/shared/__tests__/usageAwareness.test.js +58 -0
- package/dist/src/shared/__tests__/usageAwareness.test.js.map +1 -0
- package/dist/src/shared/config.d.ts +3 -0
- package/dist/src/shared/config.d.ts.map +1 -0
- package/dist/src/shared/config.js +11 -0
- package/dist/src/shared/config.js.map +1 -0
- package/dist/src/shared/effort.d.ts +17 -0
- package/dist/src/shared/effort.d.ts.map +1 -0
- package/dist/src/shared/effort.js +44 -0
- package/dist/src/shared/effort.js.map +1 -0
- package/dist/src/shared/logger.d.ts +12 -0
- package/dist/src/shared/logger.d.ts.map +1 -0
- package/dist/src/shared/logger.js +35 -0
- package/dist/src/shared/logger.js.map +1 -0
- package/dist/src/shared/paths.d.ts +31 -0
- package/dist/src/shared/paths.d.ts.map +1 -0
- package/dist/src/shared/paths.js +92 -0
- package/dist/src/shared/paths.js.map +1 -0
- package/dist/src/shared/rateLimit.d.ts +20 -0
- package/dist/src/shared/rateLimit.d.ts.map +1 -0
- package/dist/src/shared/rateLimit.js +61 -0
- package/dist/src/shared/rateLimit.js.map +1 -0
- package/dist/src/shared/types.d.ts +448 -0
- package/dist/src/shared/types.d.ts.map +1 -0
- package/dist/src/shared/types.js +4 -0
- package/dist/src/shared/types.js.map +1 -0
- package/dist/src/shared/usageAwareness.d.ts +10 -0
- package/dist/src/shared/usageAwareness.d.ts.map +1 -0
- package/dist/src/shared/usageAwareness.js +69 -0
- package/dist/src/shared/usageAwareness.js.map +1 -0
- package/dist/src/shared/version.d.ts +15 -0
- package/dist/src/shared/version.d.ts.map +1 -0
- package/dist/src/shared/version.js +56 -0
- package/dist/src/shared/version.js.map +1 -0
- package/dist/src/stt/stt.d.ts +24 -0
- package/dist/src/stt/stt.d.ts.map +1 -0
- package/dist/src/stt/stt.js +203 -0
- package/dist/src/stt/stt.js.map +1 -0
- package/dist/web/404.html +1 -0
- package/dist/web/__next.__PAGE__.txt +9 -0
- package/dist/web/__next._full.txt +19 -0
- package/dist/web/__next._head.txt +6 -0
- package/dist/web/__next._index.txt +6 -0
- package/dist/web/__next._tree.txt +2 -0
- package/dist/web/_next/static/chunks/00yn.jp4tr9l6.js +62 -0
- package/dist/web/_next/static/chunks/0398g9fy2i2l..js +5 -0
- package/dist/web/_next/static/chunks/03~yq9q893hmn.js +1 -0
- package/dist/web/_next/static/chunks/07t-qdutaizlf.js +5 -0
- package/dist/web/_next/static/chunks/0_pxvi.u4tzw1.js +5 -0
- package/dist/web/_next/static/chunks/0dtbl8648b3u9.js +7 -0
- package/dist/web/_next/static/chunks/0e3pdjkorr5zl.js +2 -0
- package/dist/web/_next/static/chunks/0ewpxy-mzj3j3.js +1 -0
- package/dist/web/_next/static/chunks/0ihbb7~gq42g~.js +5 -0
- package/dist/web/_next/static/chunks/0j4uz-g9x1_~s.js +1 -0
- package/dist/web/_next/static/chunks/0mlo32yrc7ziu.css +1 -0
- package/dist/web/_next/static/chunks/0ru56x83x4rkk.js +1 -0
- package/dist/web/_next/static/chunks/0svvev77pb2gu.js +1 -0
- package/dist/web/_next/static/chunks/0tf9kpygstdls.js +1 -0
- package/dist/web/_next/static/chunks/0wzpea61sn2-k.js +5 -0
- package/dist/web/_next/static/chunks/0y3dnnq~kxyz_.js +1 -0
- package/dist/web/_next/static/chunks/0y~qqhmf2o7pt.js +1 -0
- package/dist/web/_next/static/chunks/0~6m1p5hnsx2f.js +1 -0
- package/dist/web/_next/static/chunks/10-liamt-ipcu.js +1 -0
- package/dist/web/_next/static/chunks/10l08hq.acixl.js +5 -0
- package/dist/web/_next/static/chunks/11rbefjn.e-3-.js +1 -0
- package/dist/web/_next/static/chunks/11rodb4s1x4of.js +1 -0
- package/dist/web/_next/static/chunks/12_uxtnrqhoo1.js +1 -0
- package/dist/web/_next/static/chunks/12h4dws.tz7yb.js +5 -0
- package/dist/web/_next/static/chunks/13juizw904g.e.js +1 -0
- package/dist/web/_next/static/chunks/14ge_q22f0n.f.js +1 -0
- package/dist/web/_next/static/chunks/16b0jvgccyt2i.js +5 -0
- package/dist/web/_next/static/chunks/17-u9c_weg12-.js +31 -0
- package/dist/web/_next/static/chunks/turbopack-0dt987bw_1nyf.js +1 -0
- package/dist/web/_next/static/media/apple-icon.0.wpl4.d-5bkf.jpg +0 -0
- package/dist/web/_next/static/media/icon.0.wpl4.d-5bkf.jpg +0 -0
- package/dist/web/_next/static/uwjABwQIFELOHhVlstvOe/_buildManifest.js +11 -0
- package/dist/web/_next/static/uwjABwQIFELOHhVlstvOe/_clientMiddlewareManifest.js +1 -0
- package/dist/web/_next/static/uwjABwQIFELOHhVlstvOe/_ssgManifest.js +1 -0
- package/dist/web/_not-found/__next._full.txt +17 -0
- package/dist/web/_not-found/__next._head.txt +6 -0
- package/dist/web/_not-found/__next._index.txt +6 -0
- package/dist/web/_not-found/__next._not-found.__PAGE__.txt +5 -0
- package/dist/web/_not-found/__next._not-found.txt +5 -0
- package/dist/web/_not-found/__next._tree.txt +2 -0
- package/dist/web/_not-found.html +1 -0
- package/dist/web/_not-found.txt +17 -0
- package/dist/web/apple-icon.jpg +0 -0
- package/dist/web/chat/__next._full.txt +21 -0
- package/dist/web/chat/__next._head.txt +6 -0
- package/dist/web/chat/__next._index.txt +6 -0
- package/dist/web/chat/__next._tree.txt +2 -0
- package/dist/web/chat/__next.chat.__PAGE__.txt +9 -0
- package/dist/web/chat/__next.chat.txt +5 -0
- package/dist/web/chat.html +1 -0
- package/dist/web/chat.txt +21 -0
- package/dist/web/cron/__next._full.txt +21 -0
- package/dist/web/cron/__next._head.txt +6 -0
- package/dist/web/cron/__next._index.txt +6 -0
- package/dist/web/cron/__next._tree.txt +2 -0
- package/dist/web/cron/__next.cron.__PAGE__.txt +9 -0
- package/dist/web/cron/__next.cron.txt +5 -0
- package/dist/web/cron.html +1 -0
- package/dist/web/cron.txt +21 -0
- package/dist/web/icon.jpg +0 -0
- package/dist/web/index.html +1 -0
- package/dist/web/index.txt +19 -0
- package/dist/web/kanban/__next._full.txt +21 -0
- package/dist/web/kanban/__next._head.txt +6 -0
- package/dist/web/kanban/__next._index.txt +6 -0
- package/dist/web/kanban/__next._tree.txt +2 -0
- package/dist/web/kanban/__next.kanban.__PAGE__.txt +9 -0
- package/dist/web/kanban/__next.kanban.txt +5 -0
- package/dist/web/kanban.html +1 -0
- package/dist/web/kanban.txt +21 -0
- package/dist/web/logs/__next._full.txt +21 -0
- package/dist/web/logs/__next._head.txt +6 -0
- package/dist/web/logs/__next._index.txt +6 -0
- package/dist/web/logs/__next._tree.txt +2 -0
- package/dist/web/logs/__next.logs.__PAGE__.txt +9 -0
- package/dist/web/logs/__next.logs.txt +5 -0
- package/dist/web/logs.html +7 -0
- package/dist/web/logs.txt +21 -0
- package/dist/web/org/__next._full.txt +21 -0
- package/dist/web/org/__next._head.txt +6 -0
- package/dist/web/org/__next._index.txt +6 -0
- package/dist/web/org/__next._tree.txt +2 -0
- package/dist/web/org/__next.org.__PAGE__.txt +9 -0
- package/dist/web/org/__next.org.txt +5 -0
- package/dist/web/org.html +1 -0
- package/dist/web/org.txt +21 -0
- package/dist/web/sessions/__next._full.txt +18 -0
- package/dist/web/sessions/__next._head.txt +6 -0
- package/dist/web/sessions/__next._index.txt +6 -0
- package/dist/web/sessions/__next._tree.txt +2 -0
- package/dist/web/sessions/__next.sessions.__PAGE__.txt +6 -0
- package/dist/web/sessions/__next.sessions.txt +5 -0
- package/dist/web/sessions.html +1 -0
- package/dist/web/sessions.txt +18 -0
- package/dist/web/settings/__next._full.txt +21 -0
- package/dist/web/settings/__next._head.txt +6 -0
- package/dist/web/settings/__next._index.txt +6 -0
- package/dist/web/settings/__next._tree.txt +2 -0
- package/dist/web/settings/__next.settings.__PAGE__.txt +9 -0
- package/dist/web/settings/__next.settings.txt +5 -0
- package/dist/web/settings.html +1 -0
- package/dist/web/settings.txt +21 -0
- package/dist/web/skills/__next._full.txt +21 -0
- package/dist/web/skills/__next._head.txt +6 -0
- package/dist/web/skills/__next._index.txt +6 -0
- package/dist/web/skills/__next._tree.txt +2 -0
- package/dist/web/skills/__next.skills.__PAGE__.txt +9 -0
- package/dist/web/skills/__next.skills.txt +5 -0
- package/dist/web/skills.html +1 -0
- package/dist/web/skills.txt +21 -0
- package/package.json +54 -0
- package/template/AGENTS.md +285 -0
- package/template/CLAUDE.md +285 -0
- package/template/config.default.yaml +71 -0
- package/template/docs/architecture.md +74 -0
- package/template/docs/connectors.md +72 -0
- package/template/docs/cron.md +137 -0
- package/template/docs/mcp.md +108 -0
- package/template/docs/org.md +105 -0
- package/template/docs/overview.md +39 -0
- package/template/docs/self-modification.md +65 -0
- package/template/docs/skills.md +58 -0
- package/template/knowledge/.gitkeep +0 -0
- package/template/migrations/.gitkeep +0 -0
- package/template/migrations/0.1.0/MIGRATION.md +25 -0
- package/template/migrations/0.2.0/MIGRATION.md +41 -0
- package/template/migrations/0.2.0/files/config.default.yaml +30 -0
- package/template/migrations/0.3.0/MIGRATION.md +57 -0
- package/template/migrations/0.3.0/files/config.default.yaml +62 -0
- package/template/migrations/0.3.0/files/docs/mcp.md +108 -0
- package/template/migrations/0.7.3/MIGRATION.md +63 -0
- package/template/migrations/0.7.3/files/AGENTS.md +188 -0
- package/template/migrations/0.7.3/files/CLAUDE.md +127 -0
- package/template/migrations/0.7.5/MIGRATION.md +78 -0
- package/template/migrations/0.8.0/MIGRATION.md +73 -0
- package/template/migrations/0.9.0/MIGRATION.md +82 -0
- package/template/skills/cron-manager/SKILL.md +127 -0
- package/template/skills/find-and-install/SKILL.md +92 -0
- package/template/skills/management/SKILL.md +226 -0
- package/template/skills/migrate/SKILL.md +154 -0
- package/template/skills/new/SKILL.md +19 -0
- package/template/skills/onboarding/SKILL.md +106 -0
- package/template/skills/self-heal/SKILL.md +114 -0
- package/template/skills/skill-creator/SKILL.md +112 -0
- package/template/skills/status/SKILL.md +19 -0
- package/template/skills/sync/SKILL.md +67 -0
- package/template/skills.json +3 -0
|
@@ -0,0 +1,764 @@
|
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { WebSocketServer } from "ws";
|
|
8
|
+
import { loadConfig } from "../shared/config.js";
|
|
9
|
+
import { configureLogger, logger } from "../shared/logger.js";
|
|
10
|
+
import { initDb, recoverStaleSessions, recoverStaleQueueItems, getInterruptedSessions, listSessions, updateSession } from "../sessions/registry.js";
|
|
11
|
+
import { SessionManager } from "../sessions/manager.js";
|
|
12
|
+
import { ClaudeEngine } from "../engines/claude.js";
|
|
13
|
+
import { CodexEngine } from "../engines/codex.js";
|
|
14
|
+
import { GeminiEngine } from "../engines/gemini.js";
|
|
15
|
+
import { handleApiRequest, resumePendingWebQueueItems } from "./api.js";
|
|
16
|
+
import { ensureFilesDir } from "./files.js";
|
|
17
|
+
import { initStt } from "../stt/stt.js";
|
|
18
|
+
import { startWatchers, stopWatchers, syncSkillSymlinks } from "./watcher.js";
|
|
19
|
+
import { SlackConnector } from "../connectors/slack/index.js";
|
|
20
|
+
import { DiscordConnector } from "../connectors/discord/index.js";
|
|
21
|
+
import { RemoteDiscordConnector } from "../connectors/discord/remote.js";
|
|
22
|
+
import { WhatsAppConnector } from "../connectors/whatsapp/index.js";
|
|
23
|
+
import { TelegramConnector } from "../connectors/telegram/index.js";
|
|
24
|
+
import { loadJobs } from "../cron/jobs.js";
|
|
25
|
+
import { startScheduler, reloadScheduler, stopScheduler } from "../cron/scheduler.js";
|
|
26
|
+
import { scanOrg } from "./org.js";
|
|
27
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
28
|
+
const __dirname = path.dirname(__filename);
|
|
29
|
+
const MIME_TYPES = {
|
|
30
|
+
".html": "text/html",
|
|
31
|
+
".js": "application/javascript",
|
|
32
|
+
".css": "text/css",
|
|
33
|
+
".json": "application/json",
|
|
34
|
+
".png": "image/png",
|
|
35
|
+
".svg": "image/svg+xml",
|
|
36
|
+
".ico": "image/x-icon",
|
|
37
|
+
".woff": "font/woff",
|
|
38
|
+
".woff2": "font/woff2",
|
|
39
|
+
};
|
|
40
|
+
function serveStatic(req, res, webDir) {
|
|
41
|
+
if (!fs.existsSync(webDir))
|
|
42
|
+
return false;
|
|
43
|
+
// Strip query string before resolving file path
|
|
44
|
+
const urlPath = (req.url || "/").split("?")[0];
|
|
45
|
+
let filePath = path.join(webDir, urlPath);
|
|
46
|
+
if (filePath.endsWith("/"))
|
|
47
|
+
filePath = path.join(filePath, "index.html");
|
|
48
|
+
// Prevent directory traversal
|
|
49
|
+
const resolved = path.resolve(filePath);
|
|
50
|
+
if (!resolved.startsWith(path.resolve(webDir))) {
|
|
51
|
+
res.writeHead(403);
|
|
52
|
+
res.end("Forbidden");
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (!fs.existsSync(resolved) || fs.statSync(resolved).isDirectory()) {
|
|
56
|
+
// Next.js static export produces /chat.html, /sessions.html, etc.
|
|
57
|
+
// Try appending .html before falling back to index.html
|
|
58
|
+
const htmlPath = resolved.endsWith("/")
|
|
59
|
+
? path.join(resolved, "index.html")
|
|
60
|
+
: resolved + ".html";
|
|
61
|
+
if (fs.existsSync(htmlPath) && !fs.statSync(htmlPath).isDirectory()) {
|
|
62
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
63
|
+
fs.createReadStream(htmlPath).pipe(res);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
// SPA fallback: serve index.html for non-API, non-WS routes
|
|
67
|
+
const indexPath = path.join(webDir, "index.html");
|
|
68
|
+
if (fs.existsSync(indexPath)) {
|
|
69
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
70
|
+
fs.createReadStream(indexPath).pipe(res);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const ext = path.extname(resolved);
|
|
76
|
+
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
77
|
+
res.writeHead(200, { "Content-Type": contentType });
|
|
78
|
+
fs.createReadStream(resolved).pipe(res);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
export async function startGateway(config) {
|
|
82
|
+
const bootId = randomUUID().slice(0, 8);
|
|
83
|
+
// Configure logging
|
|
84
|
+
configureLogger({
|
|
85
|
+
level: config.logging.level,
|
|
86
|
+
stdout: config.logging.stdout,
|
|
87
|
+
file: config.logging.file,
|
|
88
|
+
});
|
|
89
|
+
const gatewayName = config.portal?.portalName || "Ryoko";
|
|
90
|
+
logger.info(`Starting ${gatewayName} gateway (boot ${bootId}, pid ${process.pid})...`);
|
|
91
|
+
// Initialize database and recover any sessions stuck from a previous run
|
|
92
|
+
initDb();
|
|
93
|
+
ensureFilesDir();
|
|
94
|
+
const recovered = recoverStaleSessions();
|
|
95
|
+
if (recovered > 0) {
|
|
96
|
+
logger.info(`Recovered ${recovered} stale session(s) — marked as "interrupted" for resume`);
|
|
97
|
+
}
|
|
98
|
+
// Log resumable sessions so operators know what can be picked up
|
|
99
|
+
const resumable = getInterruptedSessions();
|
|
100
|
+
if (resumable.length > 0) {
|
|
101
|
+
logger.info(`${resumable.length} interrupted session(s) available for resume:`);
|
|
102
|
+
for (const s of resumable) {
|
|
103
|
+
logger.info(` - ${s.id} (engine: ${s.engine}, employee: ${s.employee || "none"}, engineSessionId: ${s.engineSessionId})`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const recoveredQueue = recoverStaleQueueItems();
|
|
107
|
+
if (recoveredQueue > 0) {
|
|
108
|
+
logger.info(`Recovered ${recoveredQueue} in-flight queue item(s) from previous run — reset to pending`);
|
|
109
|
+
}
|
|
110
|
+
// Set up engines
|
|
111
|
+
const claudeEngine = new ClaudeEngine();
|
|
112
|
+
const codexEngine = new CodexEngine();
|
|
113
|
+
const geminiEngine = new GeminiEngine();
|
|
114
|
+
const engines = new Map();
|
|
115
|
+
engines.set("claude", claudeEngine);
|
|
116
|
+
engines.set("codex", codexEngine);
|
|
117
|
+
engines.set("gemini", geminiEngine);
|
|
118
|
+
// Derive connector names from config
|
|
119
|
+
const connectorNames = [];
|
|
120
|
+
if (config.connectors?.slack?.appToken && config.connectors?.slack?.botToken) {
|
|
121
|
+
connectorNames.push("slack");
|
|
122
|
+
}
|
|
123
|
+
if (config.connectors?.discord?.botToken || config.connectors?.discord?.proxyVia) {
|
|
124
|
+
connectorNames.push("discord");
|
|
125
|
+
}
|
|
126
|
+
if (config.connectors?.telegram?.botToken) {
|
|
127
|
+
connectorNames.push("telegram");
|
|
128
|
+
}
|
|
129
|
+
if (config.connectors?.whatsapp) {
|
|
130
|
+
connectorNames.push("whatsapp");
|
|
131
|
+
}
|
|
132
|
+
// Session manager
|
|
133
|
+
const sessionManager = new SessionManager(config, engines, connectorNames);
|
|
134
|
+
// Build employee registry
|
|
135
|
+
let employeeRegistry = scanOrg();
|
|
136
|
+
logger.info(`Loaded ${employeeRegistry.size} employee(s) from org directory`);
|
|
137
|
+
// Start connectors
|
|
138
|
+
const connectors = [];
|
|
139
|
+
const connectorMap = new Map();
|
|
140
|
+
/** IDs of connectors created from config.connectors.instances[] (vs legacy top-level connectors) */
|
|
141
|
+
const instanceConnectorIds = new Set();
|
|
142
|
+
if (config.connectors?.slack?.appToken && config.connectors?.slack?.botToken) {
|
|
143
|
+
try {
|
|
144
|
+
const slack = new SlackConnector({
|
|
145
|
+
appToken: config.connectors.slack.appToken,
|
|
146
|
+
botToken: config.connectors.slack.botToken,
|
|
147
|
+
allowFrom: config.connectors.slack.allowFrom,
|
|
148
|
+
ignoreOldMessagesOnBoot: config.connectors.slack.ignoreOldMessagesOnBoot,
|
|
149
|
+
triage: config.connectors.slack.triage,
|
|
150
|
+
}, {
|
|
151
|
+
portalName: config.portal?.portalName,
|
|
152
|
+
operatorName: config.portal?.operatorName,
|
|
153
|
+
});
|
|
154
|
+
slack.onMessage((msg) => {
|
|
155
|
+
const routeOpts = {};
|
|
156
|
+
if (config.connectors.slack?.employee) {
|
|
157
|
+
const emp = employeeRegistry.get(config.connectors.slack.employee);
|
|
158
|
+
if (emp)
|
|
159
|
+
routeOpts.employee = emp;
|
|
160
|
+
}
|
|
161
|
+
sessionManager.route(msg, slack, routeOpts).catch((err) => {
|
|
162
|
+
logger.error(`Slack route error: ${err instanceof Error ? err.message : err}`);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
await slack.start();
|
|
166
|
+
connectors.push(slack);
|
|
167
|
+
connectorMap.set("slack", slack);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
logger.error(`Failed to start Slack connector: ${err instanceof Error ? err.message : err}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (config.connectors?.discord?.proxyVia) {
|
|
174
|
+
// Remote mode: proxy all Discord operations through the primary instance
|
|
175
|
+
try {
|
|
176
|
+
const discord = new RemoteDiscordConnector({
|
|
177
|
+
proxyVia: config.connectors.discord.proxyVia,
|
|
178
|
+
channelId: config.connectors.discord.channelId,
|
|
179
|
+
});
|
|
180
|
+
discord.onMessage((msg) => {
|
|
181
|
+
const routeOpts = {};
|
|
182
|
+
if (config.connectors.discord?.employee) {
|
|
183
|
+
const emp = employeeRegistry.get(config.connectors.discord.employee);
|
|
184
|
+
if (emp)
|
|
185
|
+
routeOpts.employee = emp;
|
|
186
|
+
}
|
|
187
|
+
sessionManager.route(msg, discord, routeOpts).catch((err) => {
|
|
188
|
+
logger.error(`Discord route error: ${err instanceof Error ? err.message : err}`);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
await discord.start();
|
|
192
|
+
connectors.push(discord);
|
|
193
|
+
connectorMap.set("discord", discord);
|
|
194
|
+
logger.info("Discord remote connector started");
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
logger.error(`Failed to start remote Discord connector: ${err instanceof Error ? err.message : err}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else if (config.connectors?.discord?.botToken) {
|
|
201
|
+
// Primary mode: direct Discord bot connection
|
|
202
|
+
try {
|
|
203
|
+
const discord = new DiscordConnector(config.connectors.discord);
|
|
204
|
+
discord.onMessage((msg) => {
|
|
205
|
+
const routeOpts = {};
|
|
206
|
+
if (config.connectors.discord?.employee) {
|
|
207
|
+
const emp = employeeRegistry.get(config.connectors.discord.employee);
|
|
208
|
+
if (emp)
|
|
209
|
+
routeOpts.employee = emp;
|
|
210
|
+
}
|
|
211
|
+
sessionManager.route(msg, discord, routeOpts).catch((err) => {
|
|
212
|
+
logger.error(`Discord route error: ${err instanceof Error ? err.message : err}`);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
await discord.start();
|
|
216
|
+
connectors.push(discord);
|
|
217
|
+
connectorMap.set("discord", discord);
|
|
218
|
+
logger.info("Discord connector started");
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
logger.error(`Failed to start Discord connector: ${err instanceof Error ? err.message : err}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else if (config.connectors?.discord?.proxyVia) {
|
|
225
|
+
try {
|
|
226
|
+
const discord = new RemoteDiscordConnector({ proxyVia: config.connectors.discord.proxyVia });
|
|
227
|
+
discord.onMessage((msg) => {
|
|
228
|
+
const routeOpts = {};
|
|
229
|
+
if (config.connectors.discord?.employee) {
|
|
230
|
+
const emp = employeeRegistry.get(config.connectors.discord.employee);
|
|
231
|
+
if (emp)
|
|
232
|
+
routeOpts.employee = emp;
|
|
233
|
+
}
|
|
234
|
+
sessionManager.route(msg, discord, routeOpts).catch((err) => {
|
|
235
|
+
logger.error(`Discord (remote) route error: ${err instanceof Error ? err.message : err}`);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
await discord.start();
|
|
239
|
+
connectors.push(discord);
|
|
240
|
+
connectorMap.set("discord", discord);
|
|
241
|
+
logger.info(`Discord connector started in remote mode (via ${config.connectors.discord.proxyVia})`);
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
logger.error(`Failed to start remote Discord connector: ${err instanceof Error ? err.message : err}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (config.connectors?.telegram?.botToken) {
|
|
248
|
+
try {
|
|
249
|
+
const telegram = new TelegramConnector({
|
|
250
|
+
botToken: config.connectors.telegram.botToken,
|
|
251
|
+
allowFrom: config.connectors.telegram.allowFrom,
|
|
252
|
+
ignoreOldMessagesOnBoot: config.connectors.telegram.ignoreOldMessagesOnBoot,
|
|
253
|
+
});
|
|
254
|
+
telegram.onMessage((msg) => {
|
|
255
|
+
const routeOpts = {};
|
|
256
|
+
if (config.connectors.telegram?.employee) {
|
|
257
|
+
const emp = employeeRegistry.get(config.connectors.telegram.employee);
|
|
258
|
+
if (emp)
|
|
259
|
+
routeOpts.employee = emp;
|
|
260
|
+
}
|
|
261
|
+
sessionManager.route(msg, telegram, routeOpts).catch((err) => {
|
|
262
|
+
logger.error(`Telegram route error: ${err instanceof Error ? err.message : err}`);
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
await telegram.start();
|
|
266
|
+
connectors.push(telegram);
|
|
267
|
+
connectorMap.set("telegram", telegram);
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
logger.error(`Failed to start Telegram connector: ${err instanceof Error ? err.message : err}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (config.connectors?.whatsapp) {
|
|
274
|
+
try {
|
|
275
|
+
const whatsapp = new WhatsAppConnector(config.connectors.whatsapp ?? {});
|
|
276
|
+
whatsapp.onMessage((msg) => {
|
|
277
|
+
const routeOpts = {};
|
|
278
|
+
if (config.connectors.whatsapp?.employee) {
|
|
279
|
+
const emp = employeeRegistry.get(config.connectors.whatsapp.employee);
|
|
280
|
+
if (emp)
|
|
281
|
+
routeOpts.employee = emp;
|
|
282
|
+
}
|
|
283
|
+
sessionManager.route(msg, whatsapp, routeOpts).catch((err) => {
|
|
284
|
+
logger.error(`WhatsApp route error: ${err instanceof Error ? err.message : err}`);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
await whatsapp.start();
|
|
288
|
+
connectors.push(whatsapp);
|
|
289
|
+
connectorMap.set("whatsapp", whatsapp);
|
|
290
|
+
logger.info("WhatsApp connector started (scan QR code if first run)");
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
logger.error(`Failed to start WhatsApp connector: ${err instanceof Error ? err.message : err}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// Process named connector instances (allows multiple connectors of the same type)
|
|
297
|
+
if (config.connectors?.instances) {
|
|
298
|
+
for (const instance of config.connectors.instances) {
|
|
299
|
+
const { id, type, employee, ...typeConfig } = instance;
|
|
300
|
+
if (!id || !type) {
|
|
301
|
+
logger.warn(`Skipping connector instance without id or type`);
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (connectorMap.has(id)) {
|
|
305
|
+
logger.warn(`Duplicate connector instance id "${id}", skipping`);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
try {
|
|
309
|
+
let connector;
|
|
310
|
+
switch (type) {
|
|
311
|
+
case "discord": {
|
|
312
|
+
const discordConfig = { ...typeConfig, id };
|
|
313
|
+
const discord = new DiscordConnector(discordConfig);
|
|
314
|
+
discord.onMessage((msg) => {
|
|
315
|
+
const routeOpts = {};
|
|
316
|
+
if (employee) {
|
|
317
|
+
const emp = employeeRegistry.get(employee);
|
|
318
|
+
if (emp)
|
|
319
|
+
routeOpts.employee = emp;
|
|
320
|
+
}
|
|
321
|
+
sessionManager.route(msg, discord, routeOpts).catch((err) => {
|
|
322
|
+
logger.error(`${id} route error: ${err instanceof Error ? err.message : err}`);
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
await discord.start();
|
|
326
|
+
connector = discord;
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
case "slack": {
|
|
330
|
+
const slackConfig = { ...typeConfig, id };
|
|
331
|
+
const slack = new SlackConnector(slackConfig, {
|
|
332
|
+
portalName: config.portal?.portalName,
|
|
333
|
+
operatorName: config.portal?.operatorName,
|
|
334
|
+
});
|
|
335
|
+
slack.onMessage((msg) => {
|
|
336
|
+
const routeOpts = {};
|
|
337
|
+
if (employee) {
|
|
338
|
+
const emp = employeeRegistry.get(employee);
|
|
339
|
+
if (emp)
|
|
340
|
+
routeOpts.employee = emp;
|
|
341
|
+
}
|
|
342
|
+
sessionManager.route(msg, slack, routeOpts).catch((err) => {
|
|
343
|
+
logger.error(`${id} route error: ${err instanceof Error ? err.message : err}`);
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
await slack.start();
|
|
347
|
+
connector = slack;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case "whatsapp": {
|
|
351
|
+
const whatsapp = new WhatsAppConnector({ ...typeConfig });
|
|
352
|
+
whatsapp.onMessage((msg) => {
|
|
353
|
+
const routeOpts = {};
|
|
354
|
+
if (employee) {
|
|
355
|
+
const emp = employeeRegistry.get(employee);
|
|
356
|
+
if (emp)
|
|
357
|
+
routeOpts.employee = emp;
|
|
358
|
+
}
|
|
359
|
+
sessionManager.route(msg, whatsapp, routeOpts).catch((err) => {
|
|
360
|
+
logger.error(`${id} route error: ${err instanceof Error ? err.message : err}`);
|
|
361
|
+
});
|
|
362
|
+
});
|
|
363
|
+
await whatsapp.start();
|
|
364
|
+
connector = whatsapp;
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
case "telegram": {
|
|
368
|
+
const telegramConfig = { ...typeConfig, id };
|
|
369
|
+
const tg = new TelegramConnector(telegramConfig);
|
|
370
|
+
tg.onMessage((msg) => {
|
|
371
|
+
const routeOpts = {};
|
|
372
|
+
if (employee) {
|
|
373
|
+
const emp = employeeRegistry.get(employee);
|
|
374
|
+
if (emp)
|
|
375
|
+
routeOpts.employee = emp;
|
|
376
|
+
}
|
|
377
|
+
sessionManager.route(msg, tg, routeOpts).catch((err) => {
|
|
378
|
+
logger.error(`${id} route error: ${err instanceof Error ? err.message : err}`);
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
await tg.start();
|
|
382
|
+
connector = tg;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
default:
|
|
386
|
+
logger.warn(`Unknown connector type "${type}" for instance "${id}"`);
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
connectors.push(connector);
|
|
390
|
+
connectorMap.set(id, connector);
|
|
391
|
+
instanceConnectorIds.add(id);
|
|
392
|
+
logger.info(`Connector instance "${id}" (type: ${type}, employee: ${employee || "default"}) started`);
|
|
393
|
+
}
|
|
394
|
+
catch (err) {
|
|
395
|
+
logger.error(`Failed to start connector instance "${id}": ${err instanceof Error ? err.message : err}`);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
sessionManager.setConnectorProvider(() => connectorMap);
|
|
400
|
+
// Reload connector instances from config (stop old instances, start new ones)
|
|
401
|
+
async function reloadConnectorInstances() {
|
|
402
|
+
const freshConfig = loadConfig();
|
|
403
|
+
const started = [];
|
|
404
|
+
const stopped = [];
|
|
405
|
+
const errors = [];
|
|
406
|
+
// Find instance-based connectors (keys that came from instances array)
|
|
407
|
+
const instanceIds = new Set();
|
|
408
|
+
if (freshConfig.connectors?.instances) {
|
|
409
|
+
for (const inst of freshConfig.connectors.instances) {
|
|
410
|
+
if (inst.id)
|
|
411
|
+
instanceIds.add(inst.id);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Stop old instance connectors that are no longer in config or need refresh
|
|
415
|
+
for (const [id, connector] of connectorMap.entries()) {
|
|
416
|
+
// Skip legacy (top-level) connectors — only reload instance-based ones
|
|
417
|
+
if (!instanceConnectorIds.has(id))
|
|
418
|
+
continue;
|
|
419
|
+
try {
|
|
420
|
+
await connector.stop();
|
|
421
|
+
connectorMap.delete(id);
|
|
422
|
+
instanceConnectorIds.delete(id);
|
|
423
|
+
const idx = connectors.indexOf(connector);
|
|
424
|
+
if (idx >= 0)
|
|
425
|
+
connectors.splice(idx, 1);
|
|
426
|
+
stopped.push(id);
|
|
427
|
+
logger.info(`Stopped connector instance "${id}" for reload`);
|
|
428
|
+
}
|
|
429
|
+
catch (err) {
|
|
430
|
+
errors.push(`Failed to stop ${id}: ${err instanceof Error ? err.message : err}`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
// Start new instances from fresh config
|
|
434
|
+
if (freshConfig.connectors?.instances) {
|
|
435
|
+
for (const instance of freshConfig.connectors.instances) {
|
|
436
|
+
const { id, type, employee, ...typeConfig } = instance;
|
|
437
|
+
if (!id || !type)
|
|
438
|
+
continue;
|
|
439
|
+
if (connectorMap.has(id))
|
|
440
|
+
continue;
|
|
441
|
+
try {
|
|
442
|
+
let connector;
|
|
443
|
+
switch (type) {
|
|
444
|
+
case "discord": {
|
|
445
|
+
const discordConfig = { ...typeConfig, id };
|
|
446
|
+
const discord = new DiscordConnector(discordConfig);
|
|
447
|
+
discord.onMessage((msg) => {
|
|
448
|
+
const routeOpts = {};
|
|
449
|
+
if (employee) {
|
|
450
|
+
const emp = employeeRegistry.get(employee);
|
|
451
|
+
if (emp)
|
|
452
|
+
routeOpts.employee = emp;
|
|
453
|
+
}
|
|
454
|
+
sessionManager.route(msg, discord, routeOpts).catch((err) => {
|
|
455
|
+
logger.error(`${id} route error: ${err instanceof Error ? err.message : err}`);
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
await discord.start();
|
|
459
|
+
connector = discord;
|
|
460
|
+
break;
|
|
461
|
+
}
|
|
462
|
+
case "slack": {
|
|
463
|
+
const slackConfig = { ...typeConfig, id };
|
|
464
|
+
const slack = new SlackConnector(slackConfig, {
|
|
465
|
+
portalName: config.portal?.portalName,
|
|
466
|
+
operatorName: config.portal?.operatorName,
|
|
467
|
+
});
|
|
468
|
+
slack.onMessage((msg) => {
|
|
469
|
+
const routeOpts = {};
|
|
470
|
+
if (employee) {
|
|
471
|
+
const emp = employeeRegistry.get(employee);
|
|
472
|
+
if (emp)
|
|
473
|
+
routeOpts.employee = emp;
|
|
474
|
+
}
|
|
475
|
+
sessionManager.route(msg, slack, routeOpts).catch((err) => {
|
|
476
|
+
logger.error(`${id} route error: ${err instanceof Error ? err.message : err}`);
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
await slack.start();
|
|
480
|
+
connector = slack;
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
case "whatsapp": {
|
|
484
|
+
const whatsapp = new WhatsAppConnector({ ...typeConfig });
|
|
485
|
+
whatsapp.onMessage((msg) => {
|
|
486
|
+
const routeOpts = {};
|
|
487
|
+
if (employee) {
|
|
488
|
+
const emp = employeeRegistry.get(employee);
|
|
489
|
+
if (emp)
|
|
490
|
+
routeOpts.employee = emp;
|
|
491
|
+
}
|
|
492
|
+
sessionManager.route(msg, whatsapp, routeOpts).catch((err) => {
|
|
493
|
+
logger.error(`${id} route error: ${err instanceof Error ? err.message : err}`);
|
|
494
|
+
});
|
|
495
|
+
});
|
|
496
|
+
await whatsapp.start();
|
|
497
|
+
connector = whatsapp;
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
500
|
+
case "telegram": {
|
|
501
|
+
const telegramConfig = { ...typeConfig, id };
|
|
502
|
+
const tg = new TelegramConnector(telegramConfig);
|
|
503
|
+
tg.onMessage((msg) => {
|
|
504
|
+
const routeOpts = {};
|
|
505
|
+
if (employee) {
|
|
506
|
+
const emp = employeeRegistry.get(employee);
|
|
507
|
+
if (emp)
|
|
508
|
+
routeOpts.employee = emp;
|
|
509
|
+
}
|
|
510
|
+
sessionManager.route(msg, tg, routeOpts).catch((err) => {
|
|
511
|
+
logger.error(`${id} route error: ${err instanceof Error ? err.message : err}`);
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
await tg.start();
|
|
515
|
+
connector = tg;
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
default:
|
|
519
|
+
errors.push(`Unknown connector type "${type}" for instance "${id}"`);
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
connectors.push(connector);
|
|
523
|
+
connectorMap.set(id, connector);
|
|
524
|
+
instanceConnectorIds.add(id);
|
|
525
|
+
started.push(id);
|
|
526
|
+
logger.info(`Connector instance "${id}" (type: ${type}, employee: ${employee || "default"}) started`);
|
|
527
|
+
}
|
|
528
|
+
catch (err) {
|
|
529
|
+
errors.push(`Failed to start "${id}": ${err instanceof Error ? err.message : err}`);
|
|
530
|
+
logger.error(`Failed to start connector instance "${id}": ${err instanceof Error ? err.message : err}`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return { started, stopped, errors };
|
|
535
|
+
}
|
|
536
|
+
// Start cron scheduler
|
|
537
|
+
const cronJobs = loadJobs();
|
|
538
|
+
startScheduler(cronJobs, sessionManager, config, connectorMap);
|
|
539
|
+
logger.info(`Loaded ${cronJobs.length} cron job(s)`);
|
|
540
|
+
// Mutable config reference for hot-reload
|
|
541
|
+
let currentConfig = config;
|
|
542
|
+
const startTime = Date.now();
|
|
543
|
+
// Broadcast function (defined early so apiContext can reference it)
|
|
544
|
+
const wsClients = new Set();
|
|
545
|
+
const emit = (event, payload) => {
|
|
546
|
+
const message = JSON.stringify({ event, payload, ts: Date.now() });
|
|
547
|
+
for (const client of wsClients) {
|
|
548
|
+
if (client.readyState === 1) {
|
|
549
|
+
try {
|
|
550
|
+
client.send(message);
|
|
551
|
+
}
|
|
552
|
+
catch (err) {
|
|
553
|
+
logger.warn(`WebSocket send failed, removing dead client: ${err instanceof Error ? err.message : err}`);
|
|
554
|
+
wsClients.delete(client);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
// API context
|
|
560
|
+
const apiContext = {
|
|
561
|
+
config: currentConfig,
|
|
562
|
+
sessionManager,
|
|
563
|
+
startTime,
|
|
564
|
+
getConfig: () => currentConfig,
|
|
565
|
+
emit,
|
|
566
|
+
connectors: connectorMap,
|
|
567
|
+
reloadConnectorInstances,
|
|
568
|
+
};
|
|
569
|
+
// Replay any pending web queue items (e.g. gateway restart mid-run)
|
|
570
|
+
resumePendingWebQueueItems(apiContext);
|
|
571
|
+
// Resolve web UI directory — bundled into dist/web/ by postbuild script
|
|
572
|
+
// At runtime __dirname is dist/src/gateway/, so ../../web resolves to dist/web/
|
|
573
|
+
const webDir = path.resolve(__dirname, "..", "..", "web");
|
|
574
|
+
// Create HTTP server
|
|
575
|
+
const server = http.createServer((req, res) => {
|
|
576
|
+
const url = req.url || "/";
|
|
577
|
+
// CORS headers for development
|
|
578
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
579
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
580
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
581
|
+
if (req.method === "OPTIONS") {
|
|
582
|
+
res.writeHead(204);
|
|
583
|
+
res.end();
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
// API routes
|
|
587
|
+
if (url.startsWith("/api/")) {
|
|
588
|
+
handleApiRequest(req, res, apiContext);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
// Static files for web UI
|
|
592
|
+
if (!serveStatic(req, res, webDir)) {
|
|
593
|
+
if (url === "/" || url === "/index.html") {
|
|
594
|
+
res.writeHead(503, { "Content-Type": "text/html" });
|
|
595
|
+
res.end("<html><body><h1>Web UI not built</h1><p>Run <code>pnpm build</code> from the project root to build the web UI.</p></body></html>");
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
599
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
// WebSocket server
|
|
604
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
605
|
+
wss.on("connection", (ws) => {
|
|
606
|
+
wsClients.add(ws);
|
|
607
|
+
logger.info(`WebSocket client connected (${wsClients.size} total)`);
|
|
608
|
+
ws.on("close", () => {
|
|
609
|
+
wsClients.delete(ws);
|
|
610
|
+
logger.info(`WebSocket client disconnected (${wsClients.size} total)`);
|
|
611
|
+
});
|
|
612
|
+
ws.on("error", (err) => {
|
|
613
|
+
logger.error(`WebSocket error: ${err.message}`);
|
|
614
|
+
wsClients.delete(ws);
|
|
615
|
+
});
|
|
616
|
+
});
|
|
617
|
+
server.on("upgrade", (req, socket, head) => {
|
|
618
|
+
if (req.url === "/ws") {
|
|
619
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
620
|
+
wss.emit("connection", ws, req);
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
socket.destroy();
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
// Sync skill symlinks to .claude/skills/ and .agents/skills/
|
|
628
|
+
syncSkillSymlinks();
|
|
629
|
+
// Initialize STT model symlinks
|
|
630
|
+
try {
|
|
631
|
+
initStt();
|
|
632
|
+
}
|
|
633
|
+
catch (err) {
|
|
634
|
+
logger.warn(`STT init skipped: ${err instanceof Error ? err.message : err}`);
|
|
635
|
+
}
|
|
636
|
+
// Start file watchers
|
|
637
|
+
startWatchers({
|
|
638
|
+
onConfigReload: () => {
|
|
639
|
+
try {
|
|
640
|
+
currentConfig = loadConfig();
|
|
641
|
+
apiContext.config = currentConfig;
|
|
642
|
+
logger.info("Config reloaded successfully");
|
|
643
|
+
emit("config:reloaded", {});
|
|
644
|
+
}
|
|
645
|
+
catch (err) {
|
|
646
|
+
logger.error(`Failed to reload config: ${err instanceof Error ? err.message : err}`);
|
|
647
|
+
}
|
|
648
|
+
},
|
|
649
|
+
onCronReload: () => {
|
|
650
|
+
const updatedJobs = loadJobs();
|
|
651
|
+
reloadScheduler(updatedJobs);
|
|
652
|
+
logger.info(`Cron jobs reloaded (${updatedJobs.length} job(s))`);
|
|
653
|
+
emit("cron:reloaded", {});
|
|
654
|
+
},
|
|
655
|
+
onOrgChange: () => {
|
|
656
|
+
employeeRegistry = scanOrg();
|
|
657
|
+
logger.info(`Org directory changed, reloaded ${employeeRegistry.size} employee(s)`);
|
|
658
|
+
emit("org:changed", {});
|
|
659
|
+
},
|
|
660
|
+
onSkillsChange: () => {
|
|
661
|
+
logger.info("Skills changed, notifying clients");
|
|
662
|
+
emit("skills:changed", {});
|
|
663
|
+
},
|
|
664
|
+
});
|
|
665
|
+
// Start listening
|
|
666
|
+
const port = config.gateway.port || 7777;
|
|
667
|
+
const host = config.gateway.host || "127.0.0.1";
|
|
668
|
+
await new Promise((resolve, reject) => {
|
|
669
|
+
server.on("error", (err) => {
|
|
670
|
+
if (err.code === "EADDRINUSE") {
|
|
671
|
+
const msg = `Port ${port} is already in use.`;
|
|
672
|
+
logger.error(msg);
|
|
673
|
+
console.error(`\nError: ${msg}`);
|
|
674
|
+
console.error(`\nTry: jinn start -p ${port + 1}`);
|
|
675
|
+
console.error(`Or update the port in config.yaml\n`);
|
|
676
|
+
process.exit(1);
|
|
677
|
+
}
|
|
678
|
+
reject(err);
|
|
679
|
+
});
|
|
680
|
+
server.listen(port, host, () => {
|
|
681
|
+
logger.info(`${gatewayName} gateway listening on http://${host}:${port} (boot ${bootId})`);
|
|
682
|
+
resolve();
|
|
683
|
+
});
|
|
684
|
+
});
|
|
685
|
+
// Notify connected WebSocket clients about interrupted sessions available for resume
|
|
686
|
+
if (resumable.length > 0) {
|
|
687
|
+
// Small delay to let WebSocket clients connect after server starts
|
|
688
|
+
setTimeout(() => {
|
|
689
|
+
emit("sessions:interrupted", {
|
|
690
|
+
count: resumable.length,
|
|
691
|
+
sessions: resumable.map((s) => ({
|
|
692
|
+
id: s.id,
|
|
693
|
+
engine: s.engine,
|
|
694
|
+
employee: s.employee,
|
|
695
|
+
title: s.title,
|
|
696
|
+
lastActivity: s.lastActivity,
|
|
697
|
+
})),
|
|
698
|
+
});
|
|
699
|
+
}, 1000);
|
|
700
|
+
}
|
|
701
|
+
// Prevent macOS from sleeping while the gateway is running
|
|
702
|
+
let caffeinate = null;
|
|
703
|
+
if (process.platform === "darwin") {
|
|
704
|
+
caffeinate = spawn("caffeinate", ["-s"], {
|
|
705
|
+
stdio: "ignore",
|
|
706
|
+
detached: false,
|
|
707
|
+
});
|
|
708
|
+
caffeinate.unref();
|
|
709
|
+
caffeinate.on("error", (err) => {
|
|
710
|
+
logger.warn(`caffeinate failed to start: ${err.message}`);
|
|
711
|
+
caffeinate = null;
|
|
712
|
+
});
|
|
713
|
+
logger.info("caffeinate started — macOS sleep prevention active");
|
|
714
|
+
}
|
|
715
|
+
// Return cleanup function
|
|
716
|
+
return async () => {
|
|
717
|
+
logger.info("Gateway cleanup starting...");
|
|
718
|
+
// Stop caffeinate
|
|
719
|
+
if (caffeinate && caffeinate.exitCode === null) {
|
|
720
|
+
caffeinate.kill();
|
|
721
|
+
logger.info("caffeinate stopped");
|
|
722
|
+
}
|
|
723
|
+
// Mark all running sessions as "interrupted" before killing engine processes.
|
|
724
|
+
// This preserves their engine_session_id so they can be resumed on next startup.
|
|
725
|
+
const runningSessions = listSessions({ status: "running" });
|
|
726
|
+
for (const session of runningSessions) {
|
|
727
|
+
updateSession(session.id, {
|
|
728
|
+
status: "interrupted",
|
|
729
|
+
lastActivity: new Date().toISOString(),
|
|
730
|
+
lastError: "Interrupted: gateway shutting down gracefully",
|
|
731
|
+
});
|
|
732
|
+
logger.info(`Marked session ${session.id} as interrupted for resume`);
|
|
733
|
+
}
|
|
734
|
+
// Terminate live engine subprocesses after marking sessions.
|
|
735
|
+
claudeEngine.killAll();
|
|
736
|
+
codexEngine.killAll();
|
|
737
|
+
// Stop cron scheduler
|
|
738
|
+
stopScheduler();
|
|
739
|
+
// Stop connectors
|
|
740
|
+
for (const connector of connectors) {
|
|
741
|
+
try {
|
|
742
|
+
await connector.stop();
|
|
743
|
+
}
|
|
744
|
+
catch (err) {
|
|
745
|
+
logger.error(`Failed to stop ${connector.name} connector: ${err instanceof Error ? err.message : err}`);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
// Stop watchers
|
|
749
|
+
await stopWatchers();
|
|
750
|
+
// Close WebSocket connections
|
|
751
|
+
for (const client of wsClients) {
|
|
752
|
+
client.close(1001, "Server shutting down");
|
|
753
|
+
}
|
|
754
|
+
wsClients.clear();
|
|
755
|
+
// Close WebSocket server
|
|
756
|
+
await new Promise((resolve) => wss.close(() => resolve()));
|
|
757
|
+
// Close HTTP server
|
|
758
|
+
await new Promise((resolve, reject) => {
|
|
759
|
+
server.close((err) => (err ? reject(err) : resolve()));
|
|
760
|
+
});
|
|
761
|
+
logger.info("Gateway shutdown complete");
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
//# sourceMappingURL=server.js.map
|