@fidelios/server 0.0.1
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/adapters/codex-models.d.ts +4 -0
- package/dist/adapters/codex-models.d.ts.map +1 -0
- package/dist/adapters/codex-models.js +98 -0
- package/dist/adapters/codex-models.js.map +1 -0
- package/dist/adapters/cursor-models.d.ts +13 -0
- package/dist/adapters/cursor-models.d.ts.map +1 -0
- package/dist/adapters/cursor-models.js +148 -0
- package/dist/adapters/cursor-models.js.map +1 -0
- package/dist/adapters/http/execute.d.ts +3 -0
- package/dist/adapters/http/execute.d.ts.map +1 -0
- package/dist/adapters/http/execute.js +39 -0
- package/dist/adapters/http/execute.js.map +1 -0
- package/dist/adapters/http/index.d.ts +3 -0
- package/dist/adapters/http/index.d.ts.map +1 -0
- package/dist/adapters/http/index.js +20 -0
- package/dist/adapters/http/index.js.map +1 -0
- package/dist/adapters/http/test.d.ts +3 -0
- package/dist/adapters/http/test.d.ts.map +1 -0
- package/dist/adapters/http/test.js +106 -0
- package/dist/adapters/http/test.js.map +1 -0
- package/dist/adapters/index.d.ts +4 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +3 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/process/execute.d.ts +3 -0
- package/dist/adapters/process/execute.d.ts.map +1 -0
- package/dist/adapters/process/execute.js +63 -0
- package/dist/adapters/process/execute.js.map +1 -0
- package/dist/adapters/process/index.d.ts +3 -0
- package/dist/adapters/process/index.d.ts.map +1 -0
- package/dist/adapters/process/index.js +23 -0
- package/dist/adapters/process/index.js.map +1 -0
- package/dist/adapters/process/test.d.ts +3 -0
- package/dist/adapters/process/test.d.ts.map +1 -0
- package/dist/adapters/process/test.js +77 -0
- package/dist/adapters/process/test.js.map +1 -0
- package/dist/adapters/registry.d.ts +14 -0
- package/dist/adapters/registry.d.ts.map +1 -0
- package/dist/adapters/registry.js +164 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/types.d.ts +2 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/adapters/utils.d.ts +10 -0
- package/dist/adapters/utils.d.ts.map +1 -0
- package/dist/adapters/utils.js +14 -0
- package/dist/adapters/utils.js.map +1 -0
- package/dist/agent-auth-jwt.d.ts +14 -0
- package/dist/agent-auth-jwt.d.ts.map +1 -0
- package/dist/agent-auth-jwt.js +117 -0
- package/dist/agent-auth-jwt.js.map +1 -0
- package/dist/app.d.ts +25 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +265 -0
- package/dist/app.js.map +1 -0
- package/dist/attachment-types.d.ts +33 -0
- package/dist/attachment-types.d.ts.map +1 -0
- package/dist/attachment-types.js +67 -0
- package/dist/attachment-types.js.map +1 -0
- package/dist/auth/better-auth.d.ts +24 -0
- package/dist/auth/better-auth.d.ts.map +1 -0
- package/dist/auth/better-auth.js +108 -0
- package/dist/auth/better-auth.js.map +1 -0
- package/dist/board-claim.d.ts +23 -0
- package/dist/board-claim.d.ts.map +1 -0
- package/dist/board-claim.js +115 -0
- package/dist/board-claim.js.map +1 -0
- package/dist/config-file.d.ts +3 -0
- package/dist/config-file.d.ts.map +1 -0
- package/dist/config-file.js +16 -0
- package/dist/config-file.js.map +1 -0
- package/dist/config.d.ts +45 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +171 -0
- package/dist/config.js.map +1 -0
- package/dist/dev-server-status.d.ts +27 -0
- package/dist/dev-server-status.d.ts.map +1 -0
- package/dist/dev-server-status.js +70 -0
- package/dist/dev-server-status.js.map +1 -0
- package/dist/dev-watch-ignore.d.ts +2 -0
- package/dist/dev-watch-ignore.d.ts.map +1 -0
- package/dist/dev-watch-ignore.js +33 -0
- package/dist/dev-watch-ignore.js.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -0
- package/dist/home-paths.d.ts +17 -0
- package/dist/home-paths.d.ts.map +1 -0
- package/dist/home-paths.js +75 -0
- package/dist/home-paths.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +642 -0
- package/dist/index.js.map +1 -0
- package/dist/log-redaction.d.ts +11 -0
- package/dist/log-redaction.d.ts.map +1 -0
- package/dist/log-redaction.js +118 -0
- package/dist/log-redaction.js.map +1 -0
- package/dist/middleware/auth.d.ts +12 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +144 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/board-mutation-guard.d.ts +3 -0
- package/dist/middleware/board-mutation-guard.d.ts.map +1 -0
- package/dist/middleware/board-mutation-guard.js +59 -0
- package/dist/middleware/board-mutation-guard.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +17 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +37 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/index.d.ts +4 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +4 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/logger.d.ts +4 -0
- package/dist/middleware/logger.d.ts.map +1 -0
- package/dist/middleware/logger.js +87 -0
- package/dist/middleware/logger.js.map +1 -0
- package/dist/middleware/private-hostname-guard.d.ts +11 -0
- package/dist/middleware/private-hostname-guard.d.ts.map +1 -0
- package/dist/middleware/private-hostname-guard.js +78 -0
- package/dist/middleware/private-hostname-guard.js.map +1 -0
- package/dist/middleware/validate.d.ts +4 -0
- package/dist/middleware/validate.d.ts.map +1 -0
- package/dist/middleware/validate.js +7 -0
- package/dist/middleware/validate.js.map +1 -0
- package/dist/onboarding-assets/ceo/AGENTS.md +54 -0
- package/dist/onboarding-assets/ceo/HEARTBEAT.md +72 -0
- package/dist/onboarding-assets/ceo/SOUL.md +33 -0
- package/dist/onboarding-assets/ceo/TOOLS.md +3 -0
- package/dist/onboarding-assets/default/AGENTS.md +3 -0
- package/dist/paths.d.ts +3 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +31 -0
- package/dist/paths.js.map +1 -0
- package/dist/realtime/live-events-ws.d.ts +28 -0
- package/dist/realtime/live-events-ws.d.ts.map +1 -0
- package/dist/realtime/live-events-ws.js +187 -0
- package/dist/realtime/live-events-ws.js.map +1 -0
- package/dist/redaction.d.ts +4 -0
- package/dist/redaction.d.ts.map +1 -0
- package/dist/redaction.js +63 -0
- package/dist/redaction.js.map +1 -0
- package/dist/routes/access.d.ts +61 -0
- package/dist/routes/access.d.ts.map +1 -0
- package/dist/routes/access.js +2265 -0
- package/dist/routes/access.js.map +1 -0
- package/dist/routes/activity.d.ts +3 -0
- package/dist/routes/activity.d.ts.map +1 -0
- package/dist/routes/activity.js +78 -0
- package/dist/routes/activity.js.map +1 -0
- package/dist/routes/agents.d.ts +3 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +1828 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/approvals.d.ts +3 -0
- package/dist/routes/approvals.d.ts.map +1 -0
- package/dist/routes/approvals.js +275 -0
- package/dist/routes/approvals.js.map +1 -0
- package/dist/routes/assets.d.ts +4 -0
- package/dist/routes/assets.d.ts.map +1 -0
- package/dist/routes/assets.js +309 -0
- package/dist/routes/assets.js.map +1 -0
- package/dist/routes/authz.d.ts +16 -0
- package/dist/routes/authz.d.ts.map +1 -0
- package/dist/routes/authz.js +47 -0
- package/dist/routes/authz.js.map +1 -0
- package/dist/routes/companies.d.ts +4 -0
- package/dist/routes/companies.d.ts.map +1 -0
- package/dist/routes/companies.js +303 -0
- package/dist/routes/companies.js.map +1 -0
- package/dist/routes/company-skills.d.ts +3 -0
- package/dist/routes/company-skills.d.ts.map +1 -0
- package/dist/routes/company-skills.js +228 -0
- package/dist/routes/company-skills.js.map +1 -0
- package/dist/routes/costs.d.ts +3 -0
- package/dist/routes/costs.d.ts.map +1 -0
- package/dist/routes/costs.js +268 -0
- package/dist/routes/costs.js.map +1 -0
- package/dist/routes/dashboard.d.ts +3 -0
- package/dist/routes/dashboard.d.ts.map +1 -0
- package/dist/routes/dashboard.js +15 -0
- package/dist/routes/dashboard.js.map +1 -0
- package/dist/routes/execution-workspaces.d.ts +3 -0
- package/dist/routes/execution-workspaces.d.ts.map +1 -0
- package/dist/routes/execution-workspaces.js +165 -0
- package/dist/routes/execution-workspaces.js.map +1 -0
- package/dist/routes/goals.d.ts +3 -0
- package/dist/routes/goals.d.ts.map +1 -0
- package/dist/routes/goals.js +95 -0
- package/dist/routes/goals.js.map +1 -0
- package/dist/routes/health.d.ts +9 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +69 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/index.d.ts +18 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +18 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/instance-settings.d.ts +3 -0
- package/dist/routes/instance-settings.d.ts.map +1 -0
- package/dist/routes/instance-settings.js +71 -0
- package/dist/routes/instance-settings.js.map +1 -0
- package/dist/routes/issues-checkout-wakeup.d.ts +9 -0
- package/dist/routes/issues-checkout-wakeup.d.ts.map +1 -0
- package/dist/routes/issues-checkout-wakeup.js +12 -0
- package/dist/routes/issues-checkout-wakeup.js.map +1 -0
- package/dist/routes/issues.d.ts +4 -0
- package/dist/routes/issues.d.ts.map +1 -0
- package/dist/routes/issues.js +1520 -0
- package/dist/routes/issues.js.map +1 -0
- package/dist/routes/llms.d.ts +3 -0
- package/dist/routes/llms.d.ts.map +1 -0
- package/dist/routes/llms.js +78 -0
- package/dist/routes/llms.js.map +1 -0
- package/dist/routes/org-chart-svg.d.ts +25 -0
- package/dist/routes/org-chart-svg.d.ts.map +1 -0
- package/dist/routes/org-chart-svg.js +656 -0
- package/dist/routes/org-chart-svg.js.map +1 -0
- package/dist/routes/plugin-ui-static.d.ts +69 -0
- package/dist/routes/plugin-ui-static.d.ts.map +1 -0
- package/dist/routes/plugin-ui-static.js +411 -0
- package/dist/routes/plugin-ui-static.js.map +1 -0
- package/dist/routes/plugins.d.ts +120 -0
- package/dist/routes/plugins.d.ts.map +1 -0
- package/dist/routes/plugins.js +1784 -0
- package/dist/routes/plugins.js.map +1 -0
- package/dist/routes/projects.d.ts +3 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +257 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/routines.d.ts +3 -0
- package/dist/routes/routines.d.ts.map +1 -0
- package/dist/routes/routines.js +277 -0
- package/dist/routes/routines.js.map +1 -0
- package/dist/routes/secrets.d.ts +3 -0
- package/dist/routes/secrets.d.ts.map +1 -0
- package/dist/routes/secrets.js +128 -0
- package/dist/routes/secrets.js.map +1 -0
- package/dist/routes/sidebar-badges.d.ts +3 -0
- package/dist/routes/sidebar-badges.d.ts.map +1 -0
- package/dist/routes/sidebar-badges.js +45 -0
- package/dist/routes/sidebar-badges.js.map +1 -0
- package/dist/secrets/external-stub-providers.d.ts +5 -0
- package/dist/secrets/external-stub-providers.d.ts.map +1 -0
- package/dist/secrets/external-stub-providers.js +21 -0
- package/dist/secrets/external-stub-providers.js.map +1 -0
- package/dist/secrets/local-encrypted-provider.d.ts +3 -0
- package/dist/secrets/local-encrypted-provider.d.ts.map +1 -0
- package/dist/secrets/local-encrypted-provider.js +116 -0
- package/dist/secrets/local-encrypted-provider.js.map +1 -0
- package/dist/secrets/provider-registry.d.ts +5 -0
- package/dist/secrets/provider-registry.d.ts.map +1 -0
- package/dist/secrets/provider-registry.js +20 -0
- package/dist/secrets/provider-registry.js.map +1 -0
- package/dist/secrets/types.d.ts +21 -0
- package/dist/secrets/types.d.ts.map +1 -0
- package/dist/secrets/types.js +2 -0
- package/dist/secrets/types.js.map +1 -0
- package/dist/services/access.d.ts +113 -0
- package/dist/services/access.d.ts.map +1 -0
- package/dist/services/access.js +247 -0
- package/dist/services/access.js.map +1 -0
- package/dist/services/activity-log.d.ts +17 -0
- package/dist/services/activity-log.d.ts.map +1 -0
- package/dist/services/activity-log.js +74 -0
- package/dist/services/activity-log.js.map +1 -0
- package/dist/services/activity.d.ts +764 -0
- package/dist/services/activity.d.ts.map +1 -0
- package/dist/services/activity.js +105 -0
- package/dist/services/activity.js.map +1 -0
- package/dist/services/agent-instructions.d.ts +91 -0
- package/dist/services/agent-instructions.d.ts.map +1 -0
- package/dist/services/agent-instructions.js +580 -0
- package/dist/services/agent-instructions.js.map +1 -0
- package/dist/services/agent-permissions.d.ts +6 -0
- package/dist/services/agent-permissions.d.ts.map +1 -0
- package/dist/services/agent-permissions.js +18 -0
- package/dist/services/agent-permissions.js.map +1 -0
- package/dist/services/agents.d.ts +1670 -0
- package/dist/services/agents.d.ts.map +1 -0
- package/dist/services/agents.js +566 -0
- package/dist/services/agents.js.map +1 -0
- package/dist/services/approvals.d.ts +546 -0
- package/dist/services/approvals.d.ts.map +1 -0
- package/dist/services/approvals.js +212 -0
- package/dist/services/approvals.js.map +1 -0
- package/dist/services/assets.d.ts +33 -0
- package/dist/services/assets.d.ts.map +1 -0
- package/dist/services/assets.js +17 -0
- package/dist/services/assets.js.map +1 -0
- package/dist/services/board-auth.d.ts +234 -0
- package/dist/services/board-auth.d.ts.map +1 -0
- package/dist/services/board-auth.js +295 -0
- package/dist/services/board-auth.js.map +1 -0
- package/dist/services/budgets.d.ts +38 -0
- package/dist/services/budgets.d.ts.map +1 -0
- package/dist/services/budgets.js +784 -0
- package/dist/services/budgets.js.map +1 -0
- package/dist/services/companies.d.ts +124 -0
- package/dist/services/companies.d.ts.map +1 -0
- package/dist/services/companies.js +256 -0
- package/dist/services/companies.js.map +1 -0
- package/dist/services/company-export-readme.d.ts +17 -0
- package/dist/services/company-export-readme.d.ts.map +1 -0
- package/dist/services/company-export-readme.js +148 -0
- package/dist/services/company-export-readme.js.map +1 -0
- package/dist/services/company-portability.d.ts +23 -0
- package/dist/services/company-portability.d.ts.map +1 -0
- package/dist/services/company-portability.js +3739 -0
- package/dist/services/company-portability.js.map +1 -0
- package/dist/services/company-skills.d.ts +77 -0
- package/dist/services/company-skills.d.ts.map +1 -0
- package/dist/services/company-skills.js +2042 -0
- package/dist/services/company-skills.js.map +1 -0
- package/dist/services/costs.d.ts +114 -0
- package/dist/services/costs.d.ts.map +1 -0
- package/dist/services/costs.js +294 -0
- package/dist/services/costs.js.map +1 -0
- package/dist/services/cron.d.ts +80 -0
- package/dist/services/cron.d.ts.map +1 -0
- package/dist/services/cron.js +300 -0
- package/dist/services/cron.js.map +1 -0
- package/dist/services/dashboard.d.ts +26 -0
- package/dist/services/dashboard.d.ts.map +1 -0
- package/dist/services/dashboard.js +98 -0
- package/dist/services/dashboard.js.map +1 -0
- package/dist/services/default-agent-instructions.d.ts +9 -0
- package/dist/services/default-agent-instructions.d.ts.map +1 -0
- package/dist/services/default-agent-instructions.js +20 -0
- package/dist/services/default-agent-instructions.js.map +1 -0
- package/dist/services/documents.d.ts +164 -0
- package/dist/services/documents.d.ts.map +1 -0
- package/dist/services/documents.js +382 -0
- package/dist/services/documents.js.map +1 -0
- package/dist/services/execution-workspace-policy.d.ts +21 -0
- package/dist/services/execution-workspace-policy.d.ts.map +1 -0
- package/dist/services/execution-workspace-policy.js +177 -0
- package/dist/services/execution-workspace-policy.js.map +1 -0
- package/dist/services/execution-workspaces.d.ts +19 -0
- package/dist/services/execution-workspaces.d.ts.map +1 -0
- package/dist/services/execution-workspaces.js +87 -0
- package/dist/services/execution-workspaces.js.map +1 -0
- package/dist/services/finance.d.ts +93 -0
- package/dist/services/finance.d.ts.map +1 -0
- package/dist/services/finance.js +120 -0
- package/dist/services/finance.js.map +1 -0
- package/dist/services/goals.d.ts +433 -0
- package/dist/services/goals.d.ts.map +1 -0
- package/dist/services/goals.js +54 -0
- package/dist/services/goals.js.map +1 -0
- package/dist/services/heartbeat-run-summary.d.ts +2 -0
- package/dist/services/heartbeat-run-summary.d.ts.map +1 -0
- package/dist/services/heartbeat-run-summary.js +30 -0
- package/dist/services/heartbeat-run-summary.js.map +1 -0
- package/dist/services/heartbeat.d.ts +812 -0
- package/dist/services/heartbeat.d.ts.map +1 -0
- package/dist/services/heartbeat.js +3156 -0
- package/dist/services/heartbeat.js.map +1 -0
- package/dist/services/hire-hook.d.ts +14 -0
- package/dist/services/hire-hook.d.ts.map +1 -0
- package/dist/services/hire-hook.js +85 -0
- package/dist/services/hire-hook.js.map +1 -0
- package/dist/services/index.d.ts +33 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +33 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/instance-settings.d.ts +11 -0
- package/dist/services/instance-settings.d.ts.map +1 -0
- package/dist/services/instance-settings.js +116 -0
- package/dist/services/instance-settings.js.map +1 -0
- package/dist/services/issue-approvals.d.ts +56 -0
- package/dist/services/issue-approvals.d.ts.map +1 -0
- package/dist/services/issue-approvals.js +153 -0
- package/dist/services/issue-approvals.js.map +1 -0
- package/dist/services/issue-assignment-wakeup.d.ts +29 -0
- package/dist/services/issue-assignment-wakeup.d.ts.map +1 -0
- package/dist/services/issue-assignment-wakeup.js +22 -0
- package/dist/services/issue-assignment-wakeup.js.map +1 -0
- package/dist/services/issue-goal-fallback.d.ts +18 -0
- package/dist/services/issue-goal-fallback.d.ts.map +1 -0
- package/dist/services/issue-goal-fallback.js +33 -0
- package/dist/services/issue-goal-fallback.js.map +1 -0
- package/dist/services/issues.d.ts +560 -0
- package/dist/services/issues.d.ts.map +1 -0
- package/dist/services/issues.js +1478 -0
- package/dist/services/issues.js.map +1 -0
- package/dist/services/live-events.d.ts +17 -0
- package/dist/services/live-events.d.ts.map +1 -0
- package/dist/services/live-events.js +33 -0
- package/dist/services/live-events.js.map +1 -0
- package/dist/services/plugin-capability-validator.d.ts +108 -0
- package/dist/services/plugin-capability-validator.d.ts.map +1 -0
- package/dist/services/plugin-capability-validator.js +268 -0
- package/dist/services/plugin-capability-validator.js.map +1 -0
- package/dist/services/plugin-config-validator.d.ts +26 -0
- package/dist/services/plugin-config-validator.d.ts.map +1 -0
- package/dist/services/plugin-config-validator.js +41 -0
- package/dist/services/plugin-config-validator.js.map +1 -0
- package/dist/services/plugin-dev-watcher.d.ts +30 -0
- package/dist/services/plugin-dev-watcher.d.ts.map +1 -0
- package/dist/services/plugin-dev-watcher.js +241 -0
- package/dist/services/plugin-dev-watcher.js.map +1 -0
- package/dist/services/plugin-event-bus.d.ts +149 -0
- package/dist/services/plugin-event-bus.d.ts.map +1 -0
- package/dist/services/plugin-event-bus.js +258 -0
- package/dist/services/plugin-event-bus.js.map +1 -0
- package/dist/services/plugin-host-service-cleanup.d.ts +14 -0
- package/dist/services/plugin-host-service-cleanup.d.ts.map +1 -0
- package/dist/services/plugin-host-service-cleanup.js +37 -0
- package/dist/services/plugin-host-service-cleanup.js.map +1 -0
- package/dist/services/plugin-host-services.d.ts +13 -0
- package/dist/services/plugin-host-services.d.ts.map +1 -0
- package/dist/services/plugin-host-services.js +969 -0
- package/dist/services/plugin-host-services.js.map +1 -0
- package/dist/services/plugin-job-coordinator.d.ts +81 -0
- package/dist/services/plugin-job-coordinator.d.ts.map +1 -0
- package/dist/services/plugin-job-coordinator.js +172 -0
- package/dist/services/plugin-job-coordinator.js.map +1 -0
- package/dist/services/plugin-job-scheduler.d.ts +163 -0
- package/dist/services/plugin-job-scheduler.d.ts.map +1 -0
- package/dist/services/plugin-job-scheduler.js +454 -0
- package/dist/services/plugin-job-scheduler.js.map +1 -0
- package/dist/services/plugin-job-store.d.ts +208 -0
- package/dist/services/plugin-job-store.d.ts.map +1 -0
- package/dist/services/plugin-job-store.js +350 -0
- package/dist/services/plugin-job-store.js.map +1 -0
- package/dist/services/plugin-lifecycle.d.ts +203 -0
- package/dist/services/plugin-lifecycle.d.ts.map +1 -0
- package/dist/services/plugin-lifecycle.js +476 -0
- package/dist/services/plugin-lifecycle.js.map +1 -0
- package/dist/services/plugin-loader.d.ts +441 -0
- package/dist/services/plugin-loader.d.ts.map +1 -0
- package/dist/services/plugin-loader.js +1192 -0
- package/dist/services/plugin-loader.js.map +1 -0
- package/dist/services/plugin-log-retention.d.ts +20 -0
- package/dist/services/plugin-log-retention.d.ts.map +1 -0
- package/dist/services/plugin-log-retention.js +63 -0
- package/dist/services/plugin-log-retention.js.map +1 -0
- package/dist/services/plugin-manifest-validator.d.ts +79 -0
- package/dist/services/plugin-manifest-validator.d.ts.map +1 -0
- package/dist/services/plugin-manifest-validator.js +84 -0
- package/dist/services/plugin-manifest-validator.js.map +1 -0
- package/dist/services/plugin-registry.d.ts +2542 -0
- package/dist/services/plugin-registry.d.ts.map +1 -0
- package/dist/services/plugin-registry.js +539 -0
- package/dist/services/plugin-registry.js.map +1 -0
- package/dist/services/plugin-runtime-sandbox.d.ts +40 -0
- package/dist/services/plugin-runtime-sandbox.d.ts.map +1 -0
- package/dist/services/plugin-runtime-sandbox.js +154 -0
- package/dist/services/plugin-runtime-sandbox.js.map +1 -0
- package/dist/services/plugin-secrets-handler.d.ts +81 -0
- package/dist/services/plugin-secrets-handler.d.ts.map +1 -0
- package/dist/services/plugin-secrets-handler.js +275 -0
- package/dist/services/plugin-secrets-handler.js.map +1 -0
- package/dist/services/plugin-state-store.d.ts +92 -0
- package/dist/services/plugin-state-store.d.ts.map +1 -0
- package/dist/services/plugin-state-store.js +190 -0
- package/dist/services/plugin-state-store.js.map +1 -0
- package/dist/services/plugin-stream-bus.d.ts +29 -0
- package/dist/services/plugin-stream-bus.d.ts.map +1 -0
- package/dist/services/plugin-stream-bus.js +48 -0
- package/dist/services/plugin-stream-bus.js.map +1 -0
- package/dist/services/plugin-tool-dispatcher.d.ts +180 -0
- package/dist/services/plugin-tool-dispatcher.d.ts.map +1 -0
- package/dist/services/plugin-tool-dispatcher.js +224 -0
- package/dist/services/plugin-tool-dispatcher.js.map +1 -0
- package/dist/services/plugin-tool-registry.d.ts +192 -0
- package/dist/services/plugin-tool-registry.d.ts.map +1 -0
- package/dist/services/plugin-tool-registry.js +224 -0
- package/dist/services/plugin-tool-registry.js.map +1 -0
- package/dist/services/plugin-worker-manager.d.ts +260 -0
- package/dist/services/plugin-worker-manager.d.ts.map +1 -0
- package/dist/services/plugin-worker-manager.js +835 -0
- package/dist/services/plugin-worker-manager.js.map +1 -0
- package/dist/services/projects.d.ts +87 -0
- package/dist/services/projects.d.ts.map +1 -0
- package/dist/services/projects.js +656 -0
- package/dist/services/projects.js.map +1 -0
- package/dist/services/quota-windows.d.ts +9 -0
- package/dist/services/quota-windows.d.ts.map +1 -0
- package/dist/services/quota-windows.js +56 -0
- package/dist/services/quota-windows.js.map +1 -0
- package/dist/services/routines.d.ts +135 -0
- package/dist/services/routines.d.ts.map +1 -0
- package/dist/services/routines.js +1105 -0
- package/dist/services/routines.js.map +1 -0
- package/dist/services/run-log-store.d.ts +34 -0
- package/dist/services/run-log-store.d.ts.map +1 -0
- package/dist/services/run-log-store.js +109 -0
- package/dist/services/run-log-store.js.map +1 -0
- package/dist/services/secrets.d.ts +511 -0
- package/dist/services/secrets.d.ts.map +1 -0
- package/dist/services/secrets.js +289 -0
- package/dist/services/secrets.js.map +1 -0
- package/dist/services/sidebar-badges.d.ts +9 -0
- package/dist/services/sidebar-badges.d.ts.map +1 -0
- package/dist/services/sidebar-badges.js +33 -0
- package/dist/services/sidebar-badges.js.map +1 -0
- package/dist/services/work-products.d.ts +14 -0
- package/dist/services/work-products.d.ts.map +1 -0
- package/dist/services/work-products.js +100 -0
- package/dist/services/work-products.js.map +1 -0
- package/dist/services/workspace-operation-log-store.d.ts +33 -0
- package/dist/services/workspace-operation-log-store.d.ts.map +1 -0
- package/dist/services/workspace-operation-log-store.js +110 -0
- package/dist/services/workspace-operation-log-store.js.map +1 -0
- package/dist/services/workspace-operations.d.ts +44 -0
- package/dist/services/workspace-operations.d.ts.map +1 -0
- package/dist/services/workspace-operations.js +211 -0
- package/dist/services/workspace-operations.js.map +1 -0
- package/dist/services/workspace-runtime.d.ts +164 -0
- package/dist/services/workspace-runtime.d.ts.map +1 -0
- package/dist/services/workspace-runtime.js +1235 -0
- package/dist/services/workspace-runtime.js.map +1 -0
- package/dist/startup-banner.d.ts +31 -0
- package/dist/startup-banner.d.ts.map +1 -0
- package/dist/startup-banner.js +117 -0
- package/dist/startup-banner.js.map +1 -0
- package/dist/storage/index.d.ts +6 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +29 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/local-disk-provider.d.ts +3 -0
- package/dist/storage/local-disk-provider.d.ts.map +1 -0
- package/dist/storage/local-disk-provider.js +79 -0
- package/dist/storage/local-disk-provider.js.map +1 -0
- package/dist/storage/provider-registry.d.ts +4 -0
- package/dist/storage/provider-registry.d.ts.map +1 -0
- package/dist/storage/provider-registry.js +15 -0
- package/dist/storage/provider-registry.js.map +1 -0
- package/dist/storage/s3-provider.d.ts +11 -0
- package/dist/storage/s3-provider.d.ts.map +1 -0
- package/dist/storage/s3-provider.js +123 -0
- package/dist/storage/s3-provider.js.map +1 -0
- package/dist/storage/service.d.ts +3 -0
- package/dist/storage/service.d.ts.map +1 -0
- package/dist/storage/service.js +120 -0
- package/dist/storage/service.js.map +1 -0
- package/dist/storage/types.d.ts +55 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/ui-branding.d.ts +13 -0
- package/dist/ui-branding.d.ts.map +1 -0
- package/dist/ui-branding.js +187 -0
- package/dist/ui-branding.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/dist/worktree-config.d.ts +19 -0
- package/dist/worktree-config.d.ts.map +1 -0
- package/dist/worktree-config.js +365 -0
- package/dist/worktree-config.js.map +1 -0
- package/package.json +95 -0
- package/ui-dist/android-chrome-192x192.png +0 -0
- package/ui-dist/android-chrome-512x512.png +0 -0
- package/ui-dist/apple-touch-icon.png +0 -0
- package/ui-dist/assets/_basePickBy-BB1S19s0.js +1 -0
- package/ui-dist/assets/_baseUniq-BNk0p-bq.js +1 -0
- package/ui-dist/assets/apl-B4CMkyY2.js +1 -0
- package/ui-dist/assets/arc-Ds13x1NW.js +1 -0
- package/ui-dist/assets/architectureDiagram-VXUJARFQ-D8Br-_jt.js +36 -0
- package/ui-dist/assets/asciiarmor-Df11BRmG.js +1 -0
- package/ui-dist/assets/asn1-EdZsLKOL.js +1 -0
- package/ui-dist/assets/asterisk-B-8jnY81.js +1 -0
- package/ui-dist/assets/blockDiagram-VD42YOAC-CCYsAhQ5.js +122 -0
- package/ui-dist/assets/brainfuck-C4LP7Hcl.js +1 -0
- package/ui-dist/assets/c4Diagram-YG6GDRKO-CsrnTJYB.js +10 -0
- package/ui-dist/assets/channel-Df4ReTUQ.js +1 -0
- package/ui-dist/assets/chunk-4BX2VUAB-s-S3bm2a.js +1 -0
- package/ui-dist/assets/chunk-55IACEB6-AlPeSG3C.js +1 -0
- package/ui-dist/assets/chunk-B4BG7PRW-Dlv3zmp0.js +165 -0
- package/ui-dist/assets/chunk-DI55MBZ5-y3Hfc2F6.js +220 -0
- package/ui-dist/assets/chunk-FMBD7UC4-ZbmFZ8uD.js +15 -0
- package/ui-dist/assets/chunk-QN33PNHL-g7XrAaL5.js +1 -0
- package/ui-dist/assets/chunk-QZHKN3VN-DQz2X_ZR.js +1 -0
- package/ui-dist/assets/chunk-TZMSLE5B-NRbDhryd.js +1 -0
- package/ui-dist/assets/classDiagram-2ON5EDUG-CdLb01dH.js +1 -0
- package/ui-dist/assets/classDiagram-v2-WZHVMYZB-CdLb01dH.js +1 -0
- package/ui-dist/assets/clike-B9uivgTg.js +1 -0
- package/ui-dist/assets/clojure-BMjYHr_A.js +1 -0
- package/ui-dist/assets/clone-ycTwxHSX.js +1 -0
- package/ui-dist/assets/cmake-BQqOBYOt.js +1 -0
- package/ui-dist/assets/cobol-CWcv1MsR.js +1 -0
- package/ui-dist/assets/coffeescript-S37ZYGWr.js +1 -0
- package/ui-dist/assets/commonlisp-DBKNyK5s.js +1 -0
- package/ui-dist/assets/cose-bilkent-S5V4N54A-CifA3UGC.js +1 -0
- package/ui-dist/assets/crystal-SjHAIU92.js +1 -0
- package/ui-dist/assets/css-BnMrqG3P.js +1 -0
- package/ui-dist/assets/cypher-C_CwsFkJ.js +1 -0
- package/ui-dist/assets/cytoscape.esm-BQaXIfA_.js +331 -0
- package/ui-dist/assets/d-pRatUO7H.js +1 -0
- package/ui-dist/assets/dagre-6UL2VRFP-Cy4_402x.js +4 -0
- package/ui-dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/ui-dist/assets/diagram-PSM6KHXK-CUA-Vqxe.js +24 -0
- package/ui-dist/assets/diagram-QEK2KX5R-D763Ackt.js +43 -0
- package/ui-dist/assets/diagram-S2PKOQOG-Cu1xEKHt.js +24 -0
- package/ui-dist/assets/diff-DbItnlRl.js +1 -0
- package/ui-dist/assets/dockerfile-BKs6k2Af.js +1 -0
- package/ui-dist/assets/dtd-DF_7sFjM.js +1 -0
- package/ui-dist/assets/dylan-DwRh75JA.js +1 -0
- package/ui-dist/assets/ebnf-CDyGwa7X.js +1 -0
- package/ui-dist/assets/ecl-Cabwm37j.js +1 -0
- package/ui-dist/assets/eiffel-CnydiIhH.js +1 -0
- package/ui-dist/assets/elm-vLlmbW-K.js +1 -0
- package/ui-dist/assets/erDiagram-Q2GNP2WA-9RlN9oCi.js +60 -0
- package/ui-dist/assets/erlang-BNw1qcRV.js +1 -0
- package/ui-dist/assets/factor-kuTfRLto.js +1 -0
- package/ui-dist/assets/fcl-Kvtd6kyn.js +1 -0
- package/ui-dist/assets/flowDiagram-NV44I4VS-Ddv1tq-H.js +162 -0
- package/ui-dist/assets/forth-Ffai-XNe.js +1 -0
- package/ui-dist/assets/fortran-DYz_wnZ1.js +1 -0
- package/ui-dist/assets/ganttDiagram-JELNMOA3-DAw7UfVT.js +267 -0
- package/ui-dist/assets/gas-Bneqetm1.js +1 -0
- package/ui-dist/assets/gherkin-heZmZLOM.js +1 -0
- package/ui-dist/assets/gitGraphDiagram-V2S2FVAM-CLPkzwpF.js +65 -0
- package/ui-dist/assets/graph-B1ThnnK5.js +1 -0
- package/ui-dist/assets/groovy-D9Dt4D0W.js +1 -0
- package/ui-dist/assets/haskell-Cw1EW3IL.js +1 -0
- package/ui-dist/assets/haxe-H-WmDvRZ.js +1 -0
- package/ui-dist/assets/http-DBlCnlav.js +1 -0
- package/ui-dist/assets/idl-BEugSyMb.js +1 -0
- package/ui-dist/assets/index-0DYmQxT3.js +2 -0
- package/ui-dist/assets/index-1BRIjwwa.js +1 -0
- package/ui-dist/assets/index-4pxn9bje.js +1 -0
- package/ui-dist/assets/index-B02pjBpR.js +7 -0
- package/ui-dist/assets/index-BGjMkZzC.js +1 -0
- package/ui-dist/assets/index-BHsjaYJ1.js +1 -0
- package/ui-dist/assets/index-BTwpjL-6.js +1 -0
- package/ui-dist/assets/index-BZ72uG4K.js +6 -0
- package/ui-dist/assets/index-BpC8VHcj.js +3 -0
- package/ui-dist/assets/index-BrvXvCkd.js +1 -0
- package/ui-dist/assets/index-CEBcI-2f.js +1 -0
- package/ui-dist/assets/index-CkmjCahV.js +1 -0
- package/ui-dist/assets/index-Cp84QmJD.css +1 -0
- package/ui-dist/assets/index-CpVjtxma.js +1 -0
- package/ui-dist/assets/index-D3AJPUjv.js +1 -0
- package/ui-dist/assets/index-DRkeP4vs.js +13 -0
- package/ui-dist/assets/index-DXeNhnre.js +1180 -0
- package/ui-dist/assets/index-DXvXmooU.js +1 -0
- package/ui-dist/assets/index-DZdwValG.js +1 -0
- package/ui-dist/assets/index-DbWj5-qO.js +1 -0
- package/ui-dist/assets/index-DbcKBTbp.js +1 -0
- package/ui-dist/assets/index-DdAQdjTR.js +1 -0
- package/ui-dist/assets/index-DlImcHKo.js +1 -0
- package/ui-dist/assets/index-X9LdJDbl.js +1 -0
- package/ui-dist/assets/infoDiagram-HS3SLOUP-CbJm6kuq.js +2 -0
- package/ui-dist/assets/init-Gi6I4Gst.js +1 -0
- package/ui-dist/assets/javascript-iXu5QeM3.js +1 -0
- package/ui-dist/assets/journeyDiagram-XKPGCS4Q-CeNVFpGu.js +139 -0
- package/ui-dist/assets/julia-DuME0IfC.js +1 -0
- package/ui-dist/assets/kanban-definition-3W4ZIXB7-DRqPoDRI.js +89 -0
- package/ui-dist/assets/katex-O9d3_IXG.js +261 -0
- package/ui-dist/assets/layout-CZTKj8OD.js +1 -0
- package/ui-dist/assets/linear-BDJjeIco.js +1 -0
- package/ui-dist/assets/livescript-BwQOo05w.js +1 -0
- package/ui-dist/assets/lua-BgMRiT3U.js +1 -0
- package/ui-dist/assets/mathematica-DTrFuWx2.js +1 -0
- package/ui-dist/assets/mbox-CNhZ1qSd.js +1 -0
- package/ui-dist/assets/mermaid.core-B5v7dPHY.js +256 -0
- package/ui-dist/assets/mindmap-definition-VGOIOE7T-zjw0AyzL.js +68 -0
- package/ui-dist/assets/mirc-CjQqDB4T.js +1 -0
- package/ui-dist/assets/mllike-CXdrOF99.js +1 -0
- package/ui-dist/assets/modelica-Dc1JOy9r.js +1 -0
- package/ui-dist/assets/mscgen-BA5vi2Kp.js +1 -0
- package/ui-dist/assets/mumps-BT43cFF4.js +1 -0
- package/ui-dist/assets/nginx-DdIZxoE0.js +1 -0
- package/ui-dist/assets/nsis-LdVXkNf5.js +1 -0
- package/ui-dist/assets/ntriples-BfvgReVJ.js +1 -0
- package/ui-dist/assets/octave-Ck1zUtKM.js +1 -0
- package/ui-dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/ui-dist/assets/oz-BzwKVEFT.js +1 -0
- package/ui-dist/assets/pascal--L3eBynH.js +1 -0
- package/ui-dist/assets/perl-CdXCOZ3F.js +1 -0
- package/ui-dist/assets/pieDiagram-ADFJNKIX-ojNQ8Ukr.js +30 -0
- package/ui-dist/assets/pig-CevX1Tat.js +1 -0
- package/ui-dist/assets/powershell-CFHJl5sT.js +1 -0
- package/ui-dist/assets/properties-C78fOPTZ.js +1 -0
- package/ui-dist/assets/protobuf-ChK-085T.js +1 -0
- package/ui-dist/assets/pug-DeIclll2.js +1 -0
- package/ui-dist/assets/puppet-DMA9R1ak.js +1 -0
- package/ui-dist/assets/python-BuPzkPfP.js +1 -0
- package/ui-dist/assets/q-pXgVlZs6.js +1 -0
- package/ui-dist/assets/quadrantDiagram-AYHSOK5B-B8K2F86x.js +7 -0
- package/ui-dist/assets/r-B6wPVr8A.js +1 -0
- package/ui-dist/assets/requirementDiagram-UZGBJVZJ-DA_Bjcpk.js +64 -0
- package/ui-dist/assets/rpm-CTu-6PCP.js +1 -0
- package/ui-dist/assets/ruby-B2Rjki9n.js +1 -0
- package/ui-dist/assets/sankeyDiagram-TZEHDZUN-yQfMgroQ.js +10 -0
- package/ui-dist/assets/sas-B4kiWyti.js +1 -0
- package/ui-dist/assets/scheme-C41bIUwD.js +1 -0
- package/ui-dist/assets/sequenceDiagram-WL72ISMW-CWQm0UQc.js +145 -0
- package/ui-dist/assets/shell-CjFT_Tl9.js +1 -0
- package/ui-dist/assets/sieve-C3Gn_uJK.js +1 -0
- package/ui-dist/assets/simple-mode-GW_nhZxv.js +1 -0
- package/ui-dist/assets/smalltalk-CnHTOXQT.js +1 -0
- package/ui-dist/assets/solr-DehyRSwq.js +1 -0
- package/ui-dist/assets/sparql-DkYu6x3z.js +1 -0
- package/ui-dist/assets/spreadsheet-BCZA_wO0.js +1 -0
- package/ui-dist/assets/sql-D0XecflT.js +1 -0
- package/ui-dist/assets/stateDiagram-FKZM4ZOC-C9L_ELvE.js +1 -0
- package/ui-dist/assets/stateDiagram-v2-4FDKWEC3-D3i22gRM.js +1 -0
- package/ui-dist/assets/stex-C3f8Ysf7.js +1 -0
- package/ui-dist/assets/stylus-B533Al4x.js +1 -0
- package/ui-dist/assets/swift-BzpIVaGY.js +1 -0
- package/ui-dist/assets/tcl-DVfN8rqt.js +1 -0
- package/ui-dist/assets/textile-CnDTJFAw.js +1 -0
- package/ui-dist/assets/tiddlywiki-DO-Gjzrf.js +1 -0
- package/ui-dist/assets/tiki-DGYXhP31.js +1 -0
- package/ui-dist/assets/timeline-definition-IT6M3QCI-Bfva-2zq.js +61 -0
- package/ui-dist/assets/toml-Bm5Em-hy.js +1 -0
- package/ui-dist/assets/treemap-GDKQZRPO-6wTQWQt4.js +162 -0
- package/ui-dist/assets/troff-wAsdV37c.js +1 -0
- package/ui-dist/assets/ttcn-CfJYG6tj.js +1 -0
- package/ui-dist/assets/ttcn-cfg-B9xdYoR4.js +1 -0
- package/ui-dist/assets/turtle-B1tBg_DP.js +1 -0
- package/ui-dist/assets/vb-CmGdzxic.js +1 -0
- package/ui-dist/assets/vbscript-BuJXcnF6.js +1 -0
- package/ui-dist/assets/velocity-D8B20fx6.js +1 -0
- package/ui-dist/assets/verilog-C6RDOZhf.js +1 -0
- package/ui-dist/assets/vhdl-lSbBsy5d.js +1 -0
- package/ui-dist/assets/webidl-ZXfAyPTL.js +1 -0
- package/ui-dist/assets/xquery-DzFWVndE.js +1 -0
- package/ui-dist/assets/xychartDiagram-PRI3JC2R-DNsmIw3v.js +7 -0
- package/ui-dist/assets/yacas-BJ4BC0dw.js +1 -0
- package/ui-dist/assets/z80-Hz9HOZM7.js +1 -0
- package/ui-dist/brands/opencode-logo-dark-square.svg +18 -0
- package/ui-dist/brands/opencode-logo-light-square.svg +18 -0
- package/ui-dist/favicon-16x16.png +0 -0
- package/ui-dist/favicon-32x32.png +0 -0
- package/ui-dist/favicon.ico +0 -0
- package/ui-dist/favicon.svg +9 -0
- package/ui-dist/index.html +48 -0
- package/ui-dist/site.webmanifest +30 -0
- package/ui-dist/sw.js +42 -0
- package/ui-dist/worktree-favicon-16x16.png +0 -0
- package/ui-dist/worktree-favicon-32x32.png +0 -0
- package/ui-dist/worktree-favicon.ico +0 -0
- package/ui-dist/worktree-favicon.svg +9 -0
|
@@ -0,0 +1,969 @@
|
|
|
1
|
+
import { pluginLogs, agentTaskSessions as agentTaskSessionsTable } from "@fidelios/db";
|
|
2
|
+
import { eq, and, like, desc } from "drizzle-orm";
|
|
3
|
+
import { companyService } from "./companies.js";
|
|
4
|
+
import { agentService } from "./agents.js";
|
|
5
|
+
import { projectService } from "./projects.js";
|
|
6
|
+
import { issueService } from "./issues.js";
|
|
7
|
+
import { goalService } from "./goals.js";
|
|
8
|
+
import { documentService } from "./documents.js";
|
|
9
|
+
import { heartbeatService } from "./heartbeat.js";
|
|
10
|
+
import { subscribeCompanyLiveEvents } from "./live-events.js";
|
|
11
|
+
import { randomUUID } from "node:crypto";
|
|
12
|
+
import { activityService } from "./activity.js";
|
|
13
|
+
import { costService } from "./costs.js";
|
|
14
|
+
import { assetService } from "./assets.js";
|
|
15
|
+
import { pluginRegistryService } from "./plugin-registry.js";
|
|
16
|
+
import { pluginStateStore } from "./plugin-state-store.js";
|
|
17
|
+
import { createPluginSecretsHandler } from "./plugin-secrets-handler.js";
|
|
18
|
+
import { logActivity } from "./activity-log.js";
|
|
19
|
+
import { lookup as dnsLookup } from "node:dns/promises";
|
|
20
|
+
import { request as httpRequest } from "node:http";
|
|
21
|
+
import { request as httpsRequest } from "node:https";
|
|
22
|
+
import { isIP } from "node:net";
|
|
23
|
+
import { logger } from "../middleware/logger.js";
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// SSRF protection for plugin HTTP fetch
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/** Maximum time (ms) a plugin fetch request may take before being aborted. */
|
|
28
|
+
const PLUGIN_FETCH_TIMEOUT_MS = 30_000;
|
|
29
|
+
/** Maximum time (ms) to wait for a DNS lookup before aborting. */
|
|
30
|
+
const DNS_LOOKUP_TIMEOUT_MS = 5_000;
|
|
31
|
+
/** Only these protocols are allowed for plugin HTTP requests. */
|
|
32
|
+
const ALLOWED_PROTOCOLS = new Set(["http:", "https:"]);
|
|
33
|
+
/**
|
|
34
|
+
* Check if an IP address is in a private/reserved range (RFC 1918, loopback,
|
|
35
|
+
* link-local, etc.) that plugins should never be able to reach.
|
|
36
|
+
*
|
|
37
|
+
* Handles IPv4-mapped IPv6 addresses (e.g. ::ffff:127.0.0.1) which Node's
|
|
38
|
+
* dns.lookup may return depending on OS configuration.
|
|
39
|
+
*/
|
|
40
|
+
function isPrivateIP(ip) {
|
|
41
|
+
const lower = ip.toLowerCase();
|
|
42
|
+
// Unwrap IPv4-mapped IPv6 addresses (::ffff:x.x.x.x) and re-check as IPv4
|
|
43
|
+
const v4MappedMatch = lower.match(/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
|
|
44
|
+
if (v4MappedMatch && v4MappedMatch[1])
|
|
45
|
+
return isPrivateIP(v4MappedMatch[1]);
|
|
46
|
+
// IPv4 patterns
|
|
47
|
+
if (ip.startsWith("10."))
|
|
48
|
+
return true;
|
|
49
|
+
if (ip.startsWith("172.")) {
|
|
50
|
+
const second = parseInt(ip.split(".")[1], 10);
|
|
51
|
+
if (second >= 16 && second <= 31)
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
if (ip.startsWith("192.168."))
|
|
55
|
+
return true;
|
|
56
|
+
if (ip.startsWith("127."))
|
|
57
|
+
return true; // loopback
|
|
58
|
+
if (ip.startsWith("169.254."))
|
|
59
|
+
return true; // link-local
|
|
60
|
+
if (ip === "0.0.0.0")
|
|
61
|
+
return true;
|
|
62
|
+
// IPv6 patterns
|
|
63
|
+
if (lower === "::1")
|
|
64
|
+
return true; // loopback
|
|
65
|
+
if (lower.startsWith("fc") || lower.startsWith("fd"))
|
|
66
|
+
return true; // ULA
|
|
67
|
+
if (lower.startsWith("fe80"))
|
|
68
|
+
return true; // link-local
|
|
69
|
+
if (lower === "::")
|
|
70
|
+
return true;
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
async function validateAndResolveFetchUrl(urlString) {
|
|
74
|
+
let parsed;
|
|
75
|
+
try {
|
|
76
|
+
parsed = new URL(urlString);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
throw new Error(`Invalid URL: ${urlString}`);
|
|
80
|
+
}
|
|
81
|
+
if (!ALLOWED_PROTOCOLS.has(parsed.protocol)) {
|
|
82
|
+
throw new Error(`Disallowed protocol "${parsed.protocol}" — only http: and https: are permitted`);
|
|
83
|
+
}
|
|
84
|
+
// Resolve the hostname to an IP and check for private ranges.
|
|
85
|
+
// We pin the resolved IP into the URL to eliminate the TOCTOU window
|
|
86
|
+
// between DNS resolution here and the second resolution fetch() would do.
|
|
87
|
+
const originalHostname = parsed.hostname.replace(/^\[|\]$/g, ""); // strip IPv6 brackets
|
|
88
|
+
const hostHeader = parsed.host; // includes port if non-default
|
|
89
|
+
// Race the DNS lookup against a timeout to prevent indefinite hangs
|
|
90
|
+
// when DNS is misconfigured or unresponsive.
|
|
91
|
+
const dnsPromise = dnsLookup(originalHostname, { all: true });
|
|
92
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
93
|
+
setTimeout(() => reject(new Error(`DNS lookup timed out after ${DNS_LOOKUP_TIMEOUT_MS}ms for ${originalHostname}`)), DNS_LOOKUP_TIMEOUT_MS);
|
|
94
|
+
});
|
|
95
|
+
try {
|
|
96
|
+
const results = await Promise.race([dnsPromise, timeoutPromise]);
|
|
97
|
+
if (results.length === 0) {
|
|
98
|
+
throw new Error(`DNS resolution returned no results for ${originalHostname}`);
|
|
99
|
+
}
|
|
100
|
+
// Filter to only non-private IPs instead of rejecting the entire request
|
|
101
|
+
// when some IPs are private. This handles multi-homed hosts that resolve
|
|
102
|
+
// to both private and public addresses.
|
|
103
|
+
const safeResults = results.filter((entry) => !isPrivateIP(entry.address));
|
|
104
|
+
if (safeResults.length === 0) {
|
|
105
|
+
throw new Error(`All resolved IPs for ${originalHostname} are in private/reserved ranges`);
|
|
106
|
+
}
|
|
107
|
+
const resolved = safeResults[0];
|
|
108
|
+
return {
|
|
109
|
+
parsedUrl: parsed,
|
|
110
|
+
resolvedAddress: resolved.address,
|
|
111
|
+
hostHeader,
|
|
112
|
+
tlsServername: parsed.protocol === "https:" && isIP(originalHostname) === 0
|
|
113
|
+
? originalHostname
|
|
114
|
+
: undefined,
|
|
115
|
+
useTls: parsed.protocol === "https:",
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
// Re-throw our own errors; wrap DNS failures
|
|
120
|
+
if (err instanceof Error && (err.message.startsWith("All resolved IPs") ||
|
|
121
|
+
err.message.startsWith("DNS resolution returned") ||
|
|
122
|
+
err.message.startsWith("DNS lookup timed out")))
|
|
123
|
+
throw err;
|
|
124
|
+
throw new Error(`DNS resolution failed for ${originalHostname}: ${err.message}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function buildPinnedRequestOptions(target, init) {
|
|
128
|
+
const headers = new Headers(init?.headers);
|
|
129
|
+
const method = init?.method ?? "GET";
|
|
130
|
+
const body = init?.body === undefined || init?.body === null
|
|
131
|
+
? undefined
|
|
132
|
+
: typeof init.body === "string"
|
|
133
|
+
? init.body
|
|
134
|
+
: String(init.body);
|
|
135
|
+
headers.set("Host", target.hostHeader);
|
|
136
|
+
if (body !== undefined && !headers.has("content-length") && !headers.has("transfer-encoding")) {
|
|
137
|
+
headers.set("content-length", String(Buffer.byteLength(body)));
|
|
138
|
+
}
|
|
139
|
+
const pathname = `${target.parsedUrl.pathname}${target.parsedUrl.search}`;
|
|
140
|
+
const auth = target.parsedUrl.username || target.parsedUrl.password
|
|
141
|
+
? `${decodeURIComponent(target.parsedUrl.username)}:${decodeURIComponent(target.parsedUrl.password)}`
|
|
142
|
+
: undefined;
|
|
143
|
+
return {
|
|
144
|
+
options: {
|
|
145
|
+
protocol: target.parsedUrl.protocol,
|
|
146
|
+
host: target.resolvedAddress,
|
|
147
|
+
port: target.parsedUrl.port
|
|
148
|
+
? Number(target.parsedUrl.port)
|
|
149
|
+
: target.useTls
|
|
150
|
+
? 443
|
|
151
|
+
: 80,
|
|
152
|
+
path: pathname,
|
|
153
|
+
method,
|
|
154
|
+
headers: Object.fromEntries(headers.entries()),
|
|
155
|
+
auth,
|
|
156
|
+
servername: target.tlsServername,
|
|
157
|
+
},
|
|
158
|
+
body,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
async function executePinnedHttpRequest(target, init, signal) {
|
|
162
|
+
const { options, body } = buildPinnedRequestOptions(target, init);
|
|
163
|
+
const response = await new Promise((resolve, reject) => {
|
|
164
|
+
const requestFn = target.useTls ? httpsRequest : httpRequest;
|
|
165
|
+
const req = requestFn({ ...options, signal }, resolve);
|
|
166
|
+
req.on("error", reject);
|
|
167
|
+
if (body !== undefined) {
|
|
168
|
+
req.write(body);
|
|
169
|
+
}
|
|
170
|
+
req.end();
|
|
171
|
+
});
|
|
172
|
+
const MAX_RESPONSE_BODY_BYTES = 200 * 1024 * 1024; // 200 MB
|
|
173
|
+
const chunks = [];
|
|
174
|
+
let totalBytes = 0;
|
|
175
|
+
await new Promise((resolve, reject) => {
|
|
176
|
+
response.on("data", (chunk) => {
|
|
177
|
+
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
178
|
+
totalBytes += buf.length;
|
|
179
|
+
if (totalBytes > MAX_RESPONSE_BODY_BYTES) {
|
|
180
|
+
chunks.length = 0;
|
|
181
|
+
response.destroy(new Error(`Response body exceeded ${MAX_RESPONSE_BODY_BYTES} bytes`));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
chunks.push(buf);
|
|
185
|
+
});
|
|
186
|
+
response.on("end", resolve);
|
|
187
|
+
response.on("error", reject);
|
|
188
|
+
});
|
|
189
|
+
const headers = {};
|
|
190
|
+
for (const [key, value] of Object.entries(response.headers)) {
|
|
191
|
+
if (Array.isArray(value)) {
|
|
192
|
+
headers[key] = value.join(", ");
|
|
193
|
+
}
|
|
194
|
+
else if (value !== undefined) {
|
|
195
|
+
headers[key] = value;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
status: response.statusCode ?? 500,
|
|
200
|
+
statusText: response.statusMessage ?? "",
|
|
201
|
+
headers,
|
|
202
|
+
body: Buffer.concat(chunks).toString("utf8"),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
206
|
+
const PATH_LIKE_PATTERN = /[\\/]/;
|
|
207
|
+
const WINDOWS_DRIVE_PATH_PATTERN = /^[A-Za-z]:[\\/]/;
|
|
208
|
+
function looksLikePath(value) {
|
|
209
|
+
const normalized = value.trim();
|
|
210
|
+
return (PATH_LIKE_PATTERN.test(normalized)
|
|
211
|
+
|| WINDOWS_DRIVE_PATH_PATTERN.test(normalized)) && !UUID_PATTERN.test(normalized);
|
|
212
|
+
}
|
|
213
|
+
function sanitizeWorkspaceText(value) {
|
|
214
|
+
const trimmed = value.trim();
|
|
215
|
+
if (!trimmed || UUID_PATTERN.test(trimmed))
|
|
216
|
+
return "";
|
|
217
|
+
return trimmed;
|
|
218
|
+
}
|
|
219
|
+
function sanitizeWorkspacePath(cwd) {
|
|
220
|
+
if (!cwd)
|
|
221
|
+
return "";
|
|
222
|
+
return looksLikePath(cwd) ? cwd.trim() : "";
|
|
223
|
+
}
|
|
224
|
+
function sanitizeWorkspaceName(name, fallbackPath) {
|
|
225
|
+
const safeName = sanitizeWorkspaceText(name);
|
|
226
|
+
if (safeName && !looksLikePath(safeName)) {
|
|
227
|
+
return safeName;
|
|
228
|
+
}
|
|
229
|
+
const normalized = fallbackPath.trim().replace(/[\\/]+$/, "");
|
|
230
|
+
const segments = normalized.split(/[\\/]/).filter(Boolean);
|
|
231
|
+
return segments[segments.length - 1] ?? "Workspace";
|
|
232
|
+
}
|
|
233
|
+
// ---------------------------------------------------------------------------
|
|
234
|
+
// Buffered plugin log writes
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
/** How many buffered log entries trigger an immediate flush. */
|
|
237
|
+
const LOG_BUFFER_FLUSH_SIZE = 100;
|
|
238
|
+
/** How often (ms) the buffer is flushed regardless of size. */
|
|
239
|
+
const LOG_BUFFER_FLUSH_INTERVAL_MS = 5_000;
|
|
240
|
+
/** Max length for a single plugin log message (bytes/chars). */
|
|
241
|
+
const MAX_LOG_MESSAGE_LENGTH = 10_000;
|
|
242
|
+
/** Max serialised JSON size for plugin log meta objects. */
|
|
243
|
+
const MAX_LOG_META_JSON_LENGTH = 50_000;
|
|
244
|
+
/** Max length for a metric name. */
|
|
245
|
+
const MAX_METRIC_NAME_LENGTH = 500;
|
|
246
|
+
/** Pino reserved field names that plugins must not overwrite. */
|
|
247
|
+
const PINO_RESERVED_KEYS = new Set([
|
|
248
|
+
"level",
|
|
249
|
+
"time",
|
|
250
|
+
"pid",
|
|
251
|
+
"hostname",
|
|
252
|
+
"msg",
|
|
253
|
+
"v",
|
|
254
|
+
]);
|
|
255
|
+
/** Truncate a string to `max` characters, appending a marker if truncated. */
|
|
256
|
+
function truncStr(s, max) {
|
|
257
|
+
if (s.length <= max)
|
|
258
|
+
return s;
|
|
259
|
+
return s.slice(0, max) + "...[truncated]";
|
|
260
|
+
}
|
|
261
|
+
/** Sanitise a plugin-supplied meta object: enforce size limit and strip reserved keys. */
|
|
262
|
+
function sanitiseMeta(meta) {
|
|
263
|
+
if (meta == null)
|
|
264
|
+
return null;
|
|
265
|
+
// Strip pino reserved keys
|
|
266
|
+
const cleaned = {};
|
|
267
|
+
for (const [k, v] of Object.entries(meta)) {
|
|
268
|
+
if (!PINO_RESERVED_KEYS.has(k)) {
|
|
269
|
+
cleaned[k] = v;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Enforce total serialised size
|
|
273
|
+
let json;
|
|
274
|
+
try {
|
|
275
|
+
json = JSON.stringify(cleaned);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return { _sanitised: true, _error: "meta was not JSON-serialisable" };
|
|
279
|
+
}
|
|
280
|
+
if (json.length > MAX_LOG_META_JSON_LENGTH) {
|
|
281
|
+
return { _sanitised: true, _error: `meta exceeded ${MAX_LOG_META_JSON_LENGTH} chars` };
|
|
282
|
+
}
|
|
283
|
+
return cleaned;
|
|
284
|
+
}
|
|
285
|
+
const _logBuffer = [];
|
|
286
|
+
/**
|
|
287
|
+
* Flush all buffered log entries to the database in a single batch insert per
|
|
288
|
+
* unique db instance. Errors are swallowed with a console.error fallback so
|
|
289
|
+
* flushing never crashes the process.
|
|
290
|
+
*/
|
|
291
|
+
export async function flushPluginLogBuffer() {
|
|
292
|
+
if (_logBuffer.length === 0)
|
|
293
|
+
return;
|
|
294
|
+
// Drain the buffer atomically so concurrent flushes don't double-insert.
|
|
295
|
+
const entries = _logBuffer.splice(0, _logBuffer.length);
|
|
296
|
+
// Group entries by db identity so multi-db scenarios are handled correctly.
|
|
297
|
+
const byDb = new Map();
|
|
298
|
+
for (const entry of entries) {
|
|
299
|
+
const group = byDb.get(entry.db);
|
|
300
|
+
if (group) {
|
|
301
|
+
group.push(entry);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
byDb.set(entry.db, [entry]);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
for (const [dbInstance, group] of byDb) {
|
|
308
|
+
const values = group.map((e) => ({
|
|
309
|
+
pluginId: e.pluginId,
|
|
310
|
+
level: e.level,
|
|
311
|
+
message: e.message,
|
|
312
|
+
meta: e.meta,
|
|
313
|
+
}));
|
|
314
|
+
try {
|
|
315
|
+
await dbInstance.insert(pluginLogs).values(values);
|
|
316
|
+
}
|
|
317
|
+
catch (err) {
|
|
318
|
+
try {
|
|
319
|
+
logger.warn({ err, count: values.length }, "Failed to batch-persist plugin logs to DB");
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
console.error("[plugin-host-services] Batch log flush failed:", err);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/** Interval handle for the periodic log flush. */
|
|
328
|
+
const _logFlushInterval = setInterval(() => {
|
|
329
|
+
flushPluginLogBuffer().catch((err) => {
|
|
330
|
+
console.error("[plugin-host-services] Periodic log flush error:", err);
|
|
331
|
+
});
|
|
332
|
+
}, LOG_BUFFER_FLUSH_INTERVAL_MS);
|
|
333
|
+
// Allow the interval to be unref'd so it doesn't keep the process alive in tests.
|
|
334
|
+
if (_logFlushInterval.unref)
|
|
335
|
+
_logFlushInterval.unref();
|
|
336
|
+
/**
|
|
337
|
+
* buildHostServices — creates a concrete implementation of the `HostServices`
|
|
338
|
+
* interface for a specific plugin.
|
|
339
|
+
*
|
|
340
|
+
* This implementation delegates to the core FideliOS domain services,
|
|
341
|
+
* providing the bridge between the plugin worker's SDK and the host platform.
|
|
342
|
+
*
|
|
343
|
+
* @param db - Database connection instance.
|
|
344
|
+
* @param pluginId - The UUID of the plugin installation record.
|
|
345
|
+
* @param pluginKey - The unique identifier from the plugin manifest (e.g., "acme.linear").
|
|
346
|
+
* @param eventBus - The system-wide event bus for publishing plugin events.
|
|
347
|
+
* @returns An object implementing the HostServices interface for the plugin SDK.
|
|
348
|
+
*/
|
|
349
|
+
/** Maximum time (ms) to keep a session event subscription alive before forcing cleanup. */
|
|
350
|
+
const SESSION_EVENT_SUBSCRIPTION_TIMEOUT_MS = 30 * 60 * 1_000; // 30 minutes
|
|
351
|
+
export function buildHostServices(db, pluginId, pluginKey, eventBus, notifyWorker) {
|
|
352
|
+
const registry = pluginRegistryService(db);
|
|
353
|
+
const stateStore = pluginStateStore(db);
|
|
354
|
+
const secretsHandler = createPluginSecretsHandler({ db, pluginId });
|
|
355
|
+
const companies = companyService(db);
|
|
356
|
+
const agents = agentService(db);
|
|
357
|
+
const heartbeat = heartbeatService(db);
|
|
358
|
+
const projects = projectService(db);
|
|
359
|
+
const issues = issueService(db);
|
|
360
|
+
const documents = documentService(db);
|
|
361
|
+
const goals = goalService(db);
|
|
362
|
+
const activity = activityService(db);
|
|
363
|
+
const costs = costService(db);
|
|
364
|
+
const assets = assetService(db);
|
|
365
|
+
const scopedBus = eventBus.forPlugin(pluginKey);
|
|
366
|
+
// Track active session event subscriptions for cleanup
|
|
367
|
+
const activeSubscriptions = new Set();
|
|
368
|
+
let disposed = false;
|
|
369
|
+
const ensureCompanyId = (companyId) => {
|
|
370
|
+
if (!companyId)
|
|
371
|
+
throw new Error("companyId is required for this operation");
|
|
372
|
+
return companyId;
|
|
373
|
+
};
|
|
374
|
+
const parseWindowValue = (value) => {
|
|
375
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
376
|
+
return Math.max(0, Math.floor(value));
|
|
377
|
+
}
|
|
378
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
379
|
+
const parsed = Number(value);
|
|
380
|
+
if (Number.isFinite(parsed)) {
|
|
381
|
+
return Math.max(0, Math.floor(parsed));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return null;
|
|
385
|
+
};
|
|
386
|
+
const applyWindow = (rows, params) => {
|
|
387
|
+
const offset = parseWindowValue(params?.offset) ?? 0;
|
|
388
|
+
const limit = parseWindowValue(params?.limit);
|
|
389
|
+
if (limit == null)
|
|
390
|
+
return rows.slice(offset);
|
|
391
|
+
return rows.slice(offset, offset + limit);
|
|
392
|
+
};
|
|
393
|
+
/**
|
|
394
|
+
* Plugins are instance-wide in the current runtime. Company IDs are still
|
|
395
|
+
* required for company-scoped data access, but there is no per-company
|
|
396
|
+
* availability gate to enforce here.
|
|
397
|
+
*/
|
|
398
|
+
const ensurePluginAvailableForCompany = async (_companyId) => { };
|
|
399
|
+
const inCompany = (record, companyId) => Boolean(record && record.companyId === companyId);
|
|
400
|
+
const requireInCompany = (entityName, record, companyId) => {
|
|
401
|
+
if (!inCompany(record, companyId)) {
|
|
402
|
+
throw new Error(`${entityName} not found`);
|
|
403
|
+
}
|
|
404
|
+
return record;
|
|
405
|
+
};
|
|
406
|
+
return {
|
|
407
|
+
config: {
|
|
408
|
+
async get() {
|
|
409
|
+
const configRow = await registry.getConfig(pluginId);
|
|
410
|
+
return configRow?.configJson ?? {};
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
state: {
|
|
414
|
+
async get(params) {
|
|
415
|
+
return stateStore.get(pluginId, params.scopeKind, params.stateKey, {
|
|
416
|
+
scopeId: params.scopeId,
|
|
417
|
+
namespace: params.namespace,
|
|
418
|
+
});
|
|
419
|
+
},
|
|
420
|
+
async set(params) {
|
|
421
|
+
await stateStore.set(pluginId, {
|
|
422
|
+
scopeKind: params.scopeKind,
|
|
423
|
+
scopeId: params.scopeId,
|
|
424
|
+
namespace: params.namespace,
|
|
425
|
+
stateKey: params.stateKey,
|
|
426
|
+
value: params.value,
|
|
427
|
+
});
|
|
428
|
+
},
|
|
429
|
+
async delete(params) {
|
|
430
|
+
await stateStore.delete(pluginId, params.scopeKind, params.stateKey, {
|
|
431
|
+
scopeId: params.scopeId,
|
|
432
|
+
namespace: params.namespace,
|
|
433
|
+
});
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
entities: {
|
|
437
|
+
async upsert(params) {
|
|
438
|
+
return registry.upsertEntity(pluginId, params);
|
|
439
|
+
},
|
|
440
|
+
async list(params) {
|
|
441
|
+
return registry.listEntities(pluginId, params);
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
events: {
|
|
445
|
+
async emit(params) {
|
|
446
|
+
if (params.companyId) {
|
|
447
|
+
await ensurePluginAvailableForCompany(params.companyId);
|
|
448
|
+
}
|
|
449
|
+
await scopedBus.emit(params.name, params.companyId, params.payload);
|
|
450
|
+
},
|
|
451
|
+
async subscribe(params) {
|
|
452
|
+
const handler = async (event) => {
|
|
453
|
+
if (notifyWorker) {
|
|
454
|
+
notifyWorker("onEvent", { event });
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
if (params.filter) {
|
|
458
|
+
scopedBus.subscribe(params.eventPattern, params.filter, handler);
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
scopedBus.subscribe(params.eventPattern, handler);
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
http: {
|
|
466
|
+
async fetch(params) {
|
|
467
|
+
// SSRF protection: validate protocol whitelist + block private IPs.
|
|
468
|
+
// Resolve once, then connect directly to that IP to prevent DNS rebinding.
|
|
469
|
+
const target = await validateAndResolveFetchUrl(params.url);
|
|
470
|
+
const controller = new AbortController();
|
|
471
|
+
const timeout = setTimeout(() => controller.abort(), PLUGIN_FETCH_TIMEOUT_MS);
|
|
472
|
+
try {
|
|
473
|
+
const init = params.init;
|
|
474
|
+
return await executePinnedHttpRequest(target, init, controller.signal);
|
|
475
|
+
}
|
|
476
|
+
finally {
|
|
477
|
+
clearTimeout(timeout);
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
secrets: {
|
|
482
|
+
async resolve(params) {
|
|
483
|
+
return secretsHandler.resolve(params);
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
activity: {
|
|
487
|
+
async log(params) {
|
|
488
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
489
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
490
|
+
await logActivity(db, {
|
|
491
|
+
companyId,
|
|
492
|
+
actorType: "system",
|
|
493
|
+
actorId: pluginId,
|
|
494
|
+
action: params.message,
|
|
495
|
+
entityType: params.entityType ?? "plugin",
|
|
496
|
+
entityId: params.entityId ?? pluginId,
|
|
497
|
+
details: params.metadata,
|
|
498
|
+
});
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
metrics: {
|
|
502
|
+
async write(params) {
|
|
503
|
+
const safeName = truncStr(String(params.name ?? ""), MAX_METRIC_NAME_LENGTH);
|
|
504
|
+
logger.debug({ pluginId, name: safeName, value: params.value, tags: params.tags }, "Plugin metric write");
|
|
505
|
+
// Persist metrics to plugin_logs via the batch buffer (same path as
|
|
506
|
+
// logger.log) so they benefit from batched writes and are flushed
|
|
507
|
+
// reliably on shutdown. Using level "metric" makes them queryable
|
|
508
|
+
// alongside regular logs via the same API (§26).
|
|
509
|
+
_logBuffer.push({
|
|
510
|
+
db,
|
|
511
|
+
pluginId,
|
|
512
|
+
level: "metric",
|
|
513
|
+
message: safeName,
|
|
514
|
+
meta: sanitiseMeta({ value: params.value, tags: params.tags ?? null }),
|
|
515
|
+
});
|
|
516
|
+
if (_logBuffer.length >= LOG_BUFFER_FLUSH_SIZE) {
|
|
517
|
+
flushPluginLogBuffer().catch((err) => {
|
|
518
|
+
console.error("[plugin-host-services] Triggered metric flush failed:", err);
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
logger: {
|
|
524
|
+
async log(params) {
|
|
525
|
+
const { level, meta } = params;
|
|
526
|
+
const safeMessage = truncStr(String(params.message ?? ""), MAX_LOG_MESSAGE_LENGTH);
|
|
527
|
+
const safeMeta = sanitiseMeta(meta);
|
|
528
|
+
const pluginLogger = logger.child({ service: "plugin-worker", pluginId });
|
|
529
|
+
const logFields = {
|
|
530
|
+
...safeMeta,
|
|
531
|
+
pluginLogLevel: level,
|
|
532
|
+
pluginTimestamp: new Date().toISOString(),
|
|
533
|
+
};
|
|
534
|
+
if (level === "error")
|
|
535
|
+
pluginLogger.error(logFields, `[plugin] ${safeMessage}`);
|
|
536
|
+
else if (level === "warn")
|
|
537
|
+
pluginLogger.warn(logFields, `[plugin] ${safeMessage}`);
|
|
538
|
+
else if (level === "debug")
|
|
539
|
+
pluginLogger.debug(logFields, `[plugin] ${safeMessage}`);
|
|
540
|
+
else
|
|
541
|
+
pluginLogger.info(logFields, `[plugin] ${safeMessage}`);
|
|
542
|
+
// Persist to plugin_logs table via the module-level batch buffer (§26.1).
|
|
543
|
+
// Fire-and-forget — logging should never block the worker.
|
|
544
|
+
_logBuffer.push({
|
|
545
|
+
db,
|
|
546
|
+
pluginId,
|
|
547
|
+
level: level ?? "info",
|
|
548
|
+
message: safeMessage,
|
|
549
|
+
meta: safeMeta,
|
|
550
|
+
});
|
|
551
|
+
if (_logBuffer.length >= LOG_BUFFER_FLUSH_SIZE) {
|
|
552
|
+
flushPluginLogBuffer().catch((err) => {
|
|
553
|
+
console.error("[plugin-host-services] Triggered log flush failed:", err);
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
companies: {
|
|
559
|
+
async list(params) {
|
|
560
|
+
return applyWindow((await companies.list()), params);
|
|
561
|
+
},
|
|
562
|
+
async get(params) {
|
|
563
|
+
await ensurePluginAvailableForCompany(params.companyId);
|
|
564
|
+
return (await companies.getById(params.companyId));
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
projects: {
|
|
568
|
+
async list(params) {
|
|
569
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
570
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
571
|
+
return applyWindow((await projects.list(companyId)), params);
|
|
572
|
+
},
|
|
573
|
+
async get(params) {
|
|
574
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
575
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
576
|
+
const project = await projects.getById(params.projectId);
|
|
577
|
+
return (inCompany(project, companyId) ? project : null);
|
|
578
|
+
},
|
|
579
|
+
async listWorkspaces(params) {
|
|
580
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
581
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
582
|
+
const project = await projects.getById(params.projectId);
|
|
583
|
+
if (!inCompany(project, companyId))
|
|
584
|
+
return [];
|
|
585
|
+
const rows = await projects.listWorkspaces(params.projectId);
|
|
586
|
+
return rows.map((row) => {
|
|
587
|
+
const path = sanitizeWorkspacePath(row.cwd);
|
|
588
|
+
const name = sanitizeWorkspaceName(row.name, path);
|
|
589
|
+
return {
|
|
590
|
+
id: row.id,
|
|
591
|
+
projectId: row.projectId,
|
|
592
|
+
name,
|
|
593
|
+
path,
|
|
594
|
+
isPrimary: row.isPrimary,
|
|
595
|
+
createdAt: row.createdAt.toISOString(),
|
|
596
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
597
|
+
};
|
|
598
|
+
});
|
|
599
|
+
},
|
|
600
|
+
async getPrimaryWorkspace(params) {
|
|
601
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
602
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
603
|
+
const project = await projects.getById(params.projectId);
|
|
604
|
+
if (!inCompany(project, companyId))
|
|
605
|
+
return null;
|
|
606
|
+
const row = project.primaryWorkspace;
|
|
607
|
+
const path = sanitizeWorkspacePath(project.codebase.effectiveLocalFolder);
|
|
608
|
+
const name = sanitizeWorkspaceName(row?.name ?? project.name, path);
|
|
609
|
+
return {
|
|
610
|
+
id: row?.id ?? `${project.id}:managed`,
|
|
611
|
+
projectId: project.id,
|
|
612
|
+
name,
|
|
613
|
+
path,
|
|
614
|
+
isPrimary: true,
|
|
615
|
+
createdAt: (row?.createdAt ?? project.createdAt).toISOString(),
|
|
616
|
+
updatedAt: (row?.updatedAt ?? project.updatedAt).toISOString(),
|
|
617
|
+
};
|
|
618
|
+
},
|
|
619
|
+
async getWorkspaceForIssue(params) {
|
|
620
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
621
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
622
|
+
const issue = await issues.getById(params.issueId);
|
|
623
|
+
if (!inCompany(issue, companyId))
|
|
624
|
+
return null;
|
|
625
|
+
const projectId = issue.projectId;
|
|
626
|
+
if (!projectId)
|
|
627
|
+
return null;
|
|
628
|
+
const project = await projects.getById(projectId);
|
|
629
|
+
if (!inCompany(project, companyId))
|
|
630
|
+
return null;
|
|
631
|
+
const row = project.primaryWorkspace;
|
|
632
|
+
const path = sanitizeWorkspacePath(project.codebase.effectiveLocalFolder);
|
|
633
|
+
const name = sanitizeWorkspaceName(row?.name ?? project.name, path);
|
|
634
|
+
return {
|
|
635
|
+
id: row?.id ?? `${project.id}:managed`,
|
|
636
|
+
projectId: project.id,
|
|
637
|
+
name,
|
|
638
|
+
path,
|
|
639
|
+
isPrimary: true,
|
|
640
|
+
createdAt: (row?.createdAt ?? project.createdAt).toISOString(),
|
|
641
|
+
updatedAt: (row?.updatedAt ?? project.updatedAt).toISOString(),
|
|
642
|
+
};
|
|
643
|
+
},
|
|
644
|
+
},
|
|
645
|
+
issues: {
|
|
646
|
+
async list(params) {
|
|
647
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
648
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
649
|
+
return applyWindow((await issues.list(companyId, params)), params);
|
|
650
|
+
},
|
|
651
|
+
async get(params) {
|
|
652
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
653
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
654
|
+
const issue = await issues.getById(params.issueId);
|
|
655
|
+
return (inCompany(issue, companyId) ? issue : null);
|
|
656
|
+
},
|
|
657
|
+
async create(params) {
|
|
658
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
659
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
660
|
+
return (await issues.create(companyId, params));
|
|
661
|
+
},
|
|
662
|
+
async update(params) {
|
|
663
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
664
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
665
|
+
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
|
|
666
|
+
return (await issues.update(params.issueId, params.patch));
|
|
667
|
+
},
|
|
668
|
+
async listComments(params) {
|
|
669
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
670
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
671
|
+
if (!inCompany(await issues.getById(params.issueId), companyId))
|
|
672
|
+
return [];
|
|
673
|
+
return (await issues.listComments(params.issueId));
|
|
674
|
+
},
|
|
675
|
+
async createComment(params) {
|
|
676
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
677
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
678
|
+
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
|
|
679
|
+
return (await issues.addComment(params.issueId, params.body, {}));
|
|
680
|
+
},
|
|
681
|
+
},
|
|
682
|
+
issueDocuments: {
|
|
683
|
+
async list(params) {
|
|
684
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
685
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
686
|
+
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
|
|
687
|
+
const rows = await documents.listIssueDocuments(params.issueId);
|
|
688
|
+
return rows;
|
|
689
|
+
},
|
|
690
|
+
async get(params) {
|
|
691
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
692
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
693
|
+
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
|
|
694
|
+
const doc = await documents.getIssueDocumentByKey(params.issueId, params.key);
|
|
695
|
+
return (doc ?? null);
|
|
696
|
+
},
|
|
697
|
+
async upsert(params) {
|
|
698
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
699
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
700
|
+
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
|
|
701
|
+
const result = await documents.upsertIssueDocument({
|
|
702
|
+
issueId: params.issueId,
|
|
703
|
+
key: params.key,
|
|
704
|
+
body: params.body,
|
|
705
|
+
title: params.title ?? null,
|
|
706
|
+
format: params.format ?? "markdown",
|
|
707
|
+
changeSummary: params.changeSummary ?? null,
|
|
708
|
+
});
|
|
709
|
+
return result.document;
|
|
710
|
+
},
|
|
711
|
+
async delete(params) {
|
|
712
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
713
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
714
|
+
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
|
|
715
|
+
await documents.deleteIssueDocument(params.issueId, params.key);
|
|
716
|
+
},
|
|
717
|
+
},
|
|
718
|
+
agents: {
|
|
719
|
+
async list(params) {
|
|
720
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
721
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
722
|
+
const rows = await agents.list(companyId);
|
|
723
|
+
return applyWindow(rows.filter((agent) => !params.status || agent.status === params.status), params);
|
|
724
|
+
},
|
|
725
|
+
async get(params) {
|
|
726
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
727
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
728
|
+
const agent = await agents.getById(params.agentId);
|
|
729
|
+
return (inCompany(agent, companyId) ? agent : null);
|
|
730
|
+
},
|
|
731
|
+
async pause(params) {
|
|
732
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
733
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
734
|
+
const agent = await agents.getById(params.agentId);
|
|
735
|
+
requireInCompany("Agent", agent, companyId);
|
|
736
|
+
return (await agents.pause(params.agentId));
|
|
737
|
+
},
|
|
738
|
+
async resume(params) {
|
|
739
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
740
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
741
|
+
const agent = await agents.getById(params.agentId);
|
|
742
|
+
requireInCompany("Agent", agent, companyId);
|
|
743
|
+
return (await agents.resume(params.agentId));
|
|
744
|
+
},
|
|
745
|
+
async invoke(params) {
|
|
746
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
747
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
748
|
+
const agent = await agents.getById(params.agentId);
|
|
749
|
+
requireInCompany("Agent", agent, companyId);
|
|
750
|
+
const run = await heartbeat.wakeup(params.agentId, {
|
|
751
|
+
source: "automation",
|
|
752
|
+
triggerDetail: "system",
|
|
753
|
+
reason: params.reason ?? null,
|
|
754
|
+
payload: { prompt: params.prompt },
|
|
755
|
+
requestedByActorType: "system",
|
|
756
|
+
requestedByActorId: pluginId,
|
|
757
|
+
});
|
|
758
|
+
if (!run)
|
|
759
|
+
throw new Error("Agent wakeup was skipped by heartbeat policy");
|
|
760
|
+
return { runId: run.id };
|
|
761
|
+
},
|
|
762
|
+
},
|
|
763
|
+
goals: {
|
|
764
|
+
async list(params) {
|
|
765
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
766
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
767
|
+
const rows = await goals.list(companyId);
|
|
768
|
+
return applyWindow(rows.filter((goal) => (!params.level || goal.level === params.level) &&
|
|
769
|
+
(!params.status || goal.status === params.status)), params);
|
|
770
|
+
},
|
|
771
|
+
async get(params) {
|
|
772
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
773
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
774
|
+
const goal = await goals.getById(params.goalId);
|
|
775
|
+
return (inCompany(goal, companyId) ? goal : null);
|
|
776
|
+
},
|
|
777
|
+
async create(params) {
|
|
778
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
779
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
780
|
+
return (await goals.create(companyId, {
|
|
781
|
+
title: params.title,
|
|
782
|
+
description: params.description,
|
|
783
|
+
level: params.level,
|
|
784
|
+
status: params.status,
|
|
785
|
+
parentId: params.parentId,
|
|
786
|
+
ownerAgentId: params.ownerAgentId,
|
|
787
|
+
}));
|
|
788
|
+
},
|
|
789
|
+
async update(params) {
|
|
790
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
791
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
792
|
+
requireInCompany("Goal", await goals.getById(params.goalId), companyId);
|
|
793
|
+
return (await goals.update(params.goalId, params.patch));
|
|
794
|
+
},
|
|
795
|
+
},
|
|
796
|
+
agentSessions: {
|
|
797
|
+
async create(params) {
|
|
798
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
799
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
800
|
+
const agent = await agents.getById(params.agentId);
|
|
801
|
+
requireInCompany("Agent", agent, companyId);
|
|
802
|
+
const taskKey = params.taskKey ?? `plugin:${pluginKey}:session:${randomUUID()}`;
|
|
803
|
+
const row = await db
|
|
804
|
+
.insert(agentTaskSessionsTable)
|
|
805
|
+
.values({
|
|
806
|
+
companyId,
|
|
807
|
+
agentId: params.agentId,
|
|
808
|
+
adapterType: agent.adapterType,
|
|
809
|
+
taskKey,
|
|
810
|
+
sessionParamsJson: null,
|
|
811
|
+
sessionDisplayId: null,
|
|
812
|
+
lastRunId: null,
|
|
813
|
+
lastError: null,
|
|
814
|
+
})
|
|
815
|
+
.returning()
|
|
816
|
+
.then((rows) => rows[0]);
|
|
817
|
+
return {
|
|
818
|
+
sessionId: row.id,
|
|
819
|
+
agentId: params.agentId,
|
|
820
|
+
companyId,
|
|
821
|
+
status: "active",
|
|
822
|
+
createdAt: row.createdAt.toISOString(),
|
|
823
|
+
};
|
|
824
|
+
},
|
|
825
|
+
async list(params) {
|
|
826
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
827
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
828
|
+
const rows = await db
|
|
829
|
+
.select()
|
|
830
|
+
.from(agentTaskSessionsTable)
|
|
831
|
+
.where(and(eq(agentTaskSessionsTable.agentId, params.agentId), eq(agentTaskSessionsTable.companyId, companyId), like(agentTaskSessionsTable.taskKey, `plugin:${pluginKey}:session:%`)))
|
|
832
|
+
.orderBy(desc(agentTaskSessionsTable.createdAt));
|
|
833
|
+
return rows.map((row) => ({
|
|
834
|
+
sessionId: row.id,
|
|
835
|
+
agentId: row.agentId,
|
|
836
|
+
companyId: row.companyId,
|
|
837
|
+
status: "active",
|
|
838
|
+
createdAt: row.createdAt.toISOString(),
|
|
839
|
+
}));
|
|
840
|
+
},
|
|
841
|
+
async sendMessage(params) {
|
|
842
|
+
if (disposed) {
|
|
843
|
+
throw new Error("Host services have been disposed");
|
|
844
|
+
}
|
|
845
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
846
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
847
|
+
// Verify session exists and belongs to this plugin
|
|
848
|
+
const session = await db
|
|
849
|
+
.select()
|
|
850
|
+
.from(agentTaskSessionsTable)
|
|
851
|
+
.where(and(eq(agentTaskSessionsTable.id, params.sessionId), eq(agentTaskSessionsTable.companyId, companyId), like(agentTaskSessionsTable.taskKey, `plugin:${pluginKey}:session:%`)))
|
|
852
|
+
.then((rows) => rows[0] ?? null);
|
|
853
|
+
if (!session)
|
|
854
|
+
throw new Error(`Session not found: ${params.sessionId}`);
|
|
855
|
+
const run = await heartbeat.wakeup(session.agentId, {
|
|
856
|
+
source: "automation",
|
|
857
|
+
triggerDetail: "system",
|
|
858
|
+
reason: params.reason ?? null,
|
|
859
|
+
payload: { prompt: params.prompt },
|
|
860
|
+
contextSnapshot: {
|
|
861
|
+
taskKey: session.taskKey,
|
|
862
|
+
wakeSource: "automation",
|
|
863
|
+
wakeTriggerDetail: "system",
|
|
864
|
+
},
|
|
865
|
+
requestedByActorType: "system",
|
|
866
|
+
requestedByActorId: pluginId,
|
|
867
|
+
});
|
|
868
|
+
if (!run)
|
|
869
|
+
throw new Error("Agent wakeup was skipped by heartbeat policy");
|
|
870
|
+
// Subscribe to live events and forward to the plugin worker as notifications.
|
|
871
|
+
// Track the subscription so it can be cleaned up on dispose() if the run
|
|
872
|
+
// never reaches a terminal status (hang, crash, network partition).
|
|
873
|
+
if (notifyWorker) {
|
|
874
|
+
const TERMINAL_STATUSES = new Set(["succeeded", "failed", "cancelled", "timed_out"]);
|
|
875
|
+
const cleanup = () => {
|
|
876
|
+
unsubscribe();
|
|
877
|
+
clearTimeout(timeoutTimer);
|
|
878
|
+
activeSubscriptions.delete(entry);
|
|
879
|
+
};
|
|
880
|
+
const unsubscribe = subscribeCompanyLiveEvents(companyId, (event) => {
|
|
881
|
+
const payload = event.payload;
|
|
882
|
+
if (!payload || payload.runId !== run.id)
|
|
883
|
+
return;
|
|
884
|
+
if (event.type === "heartbeat.run.log" || event.type === "heartbeat.run.event") {
|
|
885
|
+
notifyWorker("agents.sessions.event", {
|
|
886
|
+
sessionId: params.sessionId,
|
|
887
|
+
runId: run.id,
|
|
888
|
+
seq: payload.seq ?? 0,
|
|
889
|
+
eventType: "chunk",
|
|
890
|
+
stream: payload.stream ?? null,
|
|
891
|
+
message: payload.chunk ?? payload.message ?? null,
|
|
892
|
+
payload: payload,
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
else if (event.type === "heartbeat.run.status") {
|
|
896
|
+
const status = payload.status;
|
|
897
|
+
if (TERMINAL_STATUSES.has(status)) {
|
|
898
|
+
notifyWorker("agents.sessions.event", {
|
|
899
|
+
sessionId: params.sessionId,
|
|
900
|
+
runId: run.id,
|
|
901
|
+
seq: 0,
|
|
902
|
+
eventType: status === "succeeded" ? "done" : "error",
|
|
903
|
+
stream: "system",
|
|
904
|
+
message: status === "succeeded" ? "Run completed" : `Run ${status}`,
|
|
905
|
+
payload: payload,
|
|
906
|
+
});
|
|
907
|
+
cleanup();
|
|
908
|
+
}
|
|
909
|
+
else {
|
|
910
|
+
notifyWorker("agents.sessions.event", {
|
|
911
|
+
sessionId: params.sessionId,
|
|
912
|
+
runId: run.id,
|
|
913
|
+
seq: 0,
|
|
914
|
+
eventType: "status",
|
|
915
|
+
stream: "system",
|
|
916
|
+
message: `Run status: ${status}`,
|
|
917
|
+
payload: payload,
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
// Safety-net timeout: if the run never reaches a terminal status,
|
|
923
|
+
// force-cleanup the subscription to prevent unbounded leaks.
|
|
924
|
+
const timeoutTimer = setTimeout(() => {
|
|
925
|
+
logger.warn({ pluginId, pluginKey, runId: run.id }, "session event subscription timed out — forcing cleanup");
|
|
926
|
+
cleanup();
|
|
927
|
+
}, SESSION_EVENT_SUBSCRIPTION_TIMEOUT_MS);
|
|
928
|
+
const entry = { unsubscribe, timer: timeoutTimer };
|
|
929
|
+
activeSubscriptions.add(entry);
|
|
930
|
+
}
|
|
931
|
+
return { runId: run.id };
|
|
932
|
+
},
|
|
933
|
+
async close(params) {
|
|
934
|
+
const companyId = ensureCompanyId(params.companyId);
|
|
935
|
+
await ensurePluginAvailableForCompany(companyId);
|
|
936
|
+
const deleted = await db
|
|
937
|
+
.delete(agentTaskSessionsTable)
|
|
938
|
+
.where(and(eq(agentTaskSessionsTable.id, params.sessionId), eq(agentTaskSessionsTable.companyId, companyId), like(agentTaskSessionsTable.taskKey, `plugin:${pluginKey}:session:%`)))
|
|
939
|
+
.returning()
|
|
940
|
+
.then((rows) => rows.length);
|
|
941
|
+
if (deleted === 0)
|
|
942
|
+
throw new Error(`Session not found: ${params.sessionId}`);
|
|
943
|
+
},
|
|
944
|
+
},
|
|
945
|
+
/**
|
|
946
|
+
* Clean up all active session event subscriptions and flush any buffered
|
|
947
|
+
* log entries. Must be called when the plugin worker is stopped, crashed,
|
|
948
|
+
* or unloaded to prevent leaked listeners and lost log entries.
|
|
949
|
+
*/
|
|
950
|
+
dispose() {
|
|
951
|
+
disposed = true;
|
|
952
|
+
// Clear event bus subscriptions to prevent accumulation on worker restart.
|
|
953
|
+
// Without this, each crash/restart cycle adds duplicate subscriptions.
|
|
954
|
+
scopedBus.clear();
|
|
955
|
+
// Snapshot to avoid iterator invalidation from concurrent sendMessage() calls
|
|
956
|
+
const snapshot = Array.from(activeSubscriptions);
|
|
957
|
+
activeSubscriptions.clear();
|
|
958
|
+
for (const entry of snapshot) {
|
|
959
|
+
clearTimeout(entry.timer);
|
|
960
|
+
entry.unsubscribe();
|
|
961
|
+
}
|
|
962
|
+
// Flush any buffered log entries synchronously-as-possible on dispose.
|
|
963
|
+
flushPluginLogBuffer().catch((err) => {
|
|
964
|
+
console.error("[plugin-host-services] dispose() log flush failed:", err);
|
|
965
|
+
});
|
|
966
|
+
},
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
//# sourceMappingURL=plugin-host-services.js.map
|