botmux 3.11.0 → 3.12.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/.runtime-build-id +1 -1
- package/dist/adapters/backend/riff-backend.d.ts +18 -0
- package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
- package/dist/adapters/backend/riff-backend.js +154 -2
- package/dist/adapters/backend/riff-backend.js.map +1 -1
- package/dist/adapters/cli/coco.js +3 -3
- package/dist/adapters/cli/coco.js.map +1 -1
- package/dist/adapters/cli/codex.js +2 -2
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/kimi.d.ts.map +1 -1
- package/dist/adapters/cli/kimi.js +22 -8
- package/dist/adapters/cli/kimi.js.map +1 -1
- package/dist/adapters/cli/pi.d.ts.map +1 -1
- package/dist/adapters/cli/pi.js +3 -1
- package/dist/adapters/cli/pi.js.map +1 -1
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +4 -1
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/dashboard-command.d.ts +23 -0
- package/dist/cli/dashboard-command.d.ts.map +1 -0
- package/dist/cli/dashboard-command.js +61 -0
- package/dist/cli/dashboard-command.js.map +1 -0
- package/dist/cli/dashboard-endpoint.d.ts +3 -3
- package/dist/cli/dashboard-endpoint.d.ts.map +1 -1
- package/dist/cli/dashboard-endpoint.js +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +101 -49
- package/dist/cli.js.map +1 -1
- package/dist/codex-rpc-engine.d.ts +33 -3
- package/dist/codex-rpc-engine.d.ts.map +1 -1
- package/dist/codex-rpc-engine.js +182 -20
- package/dist/codex-rpc-engine.js.map +1 -1
- package/dist/codex-rpc-lifecycle.d.ts +42 -7
- package/dist/codex-rpc-lifecycle.d.ts.map +1 -1
- package/dist/codex-rpc-lifecycle.js +73 -7
- package/dist/codex-rpc-lifecycle.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/core/command-handler.d.ts +3 -2
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +19 -4
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +16 -11
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +17 -1
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +13 -1
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/dispatch.d.ts +9 -10
- package/dist/core/dispatch.d.ts.map +1 -1
- package/dist/core/dispatch.js +17 -10
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/maintenance.d.ts.map +1 -1
- package/dist/core/maintenance.js +5 -0
- package/dist/core/maintenance.js.map +1 -1
- package/dist/core/role-resolver.d.ts +5 -2
- package/dist/core/role-resolver.d.ts.map +1 -1
- package/dist/core/role-resolver.js +55 -23
- package/dist/core/role-resolver.js.map +1 -1
- package/dist/core/session-manager.d.ts +2 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +20 -18
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/skills/cli-admin-command.d.ts.map +1 -1
- package/dist/core/skills/cli-admin-command.js +142 -3
- package/dist/core/skills/cli-admin-command.js.map +1 -1
- package/dist/core/skills/frontmatter.d.ts.map +1 -1
- package/dist/core/skills/frontmatter.js +44 -7
- package/dist/core/skills/frontmatter.js.map +1 -1
- package/dist/core/skills/im-command.d.ts +6 -0
- package/dist/core/skills/im-command.d.ts.map +1 -1
- package/dist/core/skills/im-command.js +34 -7
- package/dist/core/skills/im-command.js.map +1 -1
- package/dist/core/skills/install-command.d.ts +4 -0
- package/dist/core/skills/install-command.d.ts.map +1 -0
- package/dist/core/skills/install-command.js +89 -0
- package/dist/core/skills/install-command.js.map +1 -0
- package/dist/core/skills/package.d.ts.map +1 -1
- package/dist/core/skills/package.js +10 -3
- package/dist/core/skills/package.js.map +1 -1
- package/dist/core/skills/policy.d.ts +5 -1
- package/dist/core/skills/policy.d.ts.map +1 -1
- package/dist/core/skills/policy.js +66 -3
- package/dist/core/skills/policy.js.map +1 -1
- package/dist/core/skills/references.d.ts +9 -1
- package/dist/core/skills/references.d.ts.map +1 -1
- package/dist/core/skills/references.js +35 -2
- package/dist/core/skills/references.js.map +1 -1
- package/dist/core/skills/registry-paths.d.ts +1 -0
- package/dist/core/skills/registry-paths.d.ts.map +1 -1
- package/dist/core/skills/registry-paths.js +3 -0
- package/dist/core/skills/registry-paths.js.map +1 -1
- package/dist/core/skills/session-resolver.d.ts +2 -1
- package/dist/core/skills/session-resolver.d.ts.map +1 -1
- package/dist/core/skills/session-resolver.js +1 -0
- package/dist/core/skills/session-resolver.js.map +1 -1
- package/dist/core/skills/session-runtime.d.ts.map +1 -1
- package/dist/core/skills/session-runtime.js +2 -0
- package/dist/core/skills/session-runtime.js.map +1 -1
- package/dist/core/skills/sources.d.ts +23 -0
- package/dist/core/skills/sources.d.ts.map +1 -1
- package/dist/core/skills/sources.js +128 -12
- package/dist/core/skills/sources.js.map +1 -1
- package/dist/core/skills/types.d.ts +22 -1
- package/dist/core/skills/types.d.ts.map +1 -1
- package/dist/core/terminal-write-auth.d.ts +4 -4
- package/dist/core/terminal-write-auth.d.ts.map +1 -1
- package/dist/core/terminal-write-auth.js +18 -6
- package/dist/core/terminal-write-auth.js.map +1 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +52 -1
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +1 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +101 -12
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/auth.d.ts +21 -11
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +39 -25
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/bot-onboarding.js +2 -114
- package/dist/dashboard/bot-onboarding.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +0 -1
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +0 -1
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/connector-api.d.ts.map +1 -1
- package/dist/dashboard/connector-api.js +66 -6
- package/dist/dashboard/connector-api.js.map +1 -1
- package/dist/dashboard/dashboard-summary-endpoint.d.ts +39 -0
- package/dist/dashboard/dashboard-summary-endpoint.d.ts.map +1 -0
- package/dist/dashboard/dashboard-summary-endpoint.js +50 -0
- package/dist/dashboard/dashboard-summary-endpoint.js.map +1 -0
- package/dist/dashboard/dashboard-summary.d.ts +62 -0
- package/dist/dashboard/dashboard-summary.d.ts.map +1 -0
- package/dist/dashboard/dashboard-summary.js +106 -0
- package/dist/dashboard/dashboard-summary.js.map +1 -0
- package/dist/dashboard/public-redact.d.ts.map +1 -1
- package/dist/dashboard/public-redact.js +3 -0
- package/dist/dashboard/public-redact.js.map +1 -1
- package/dist/dashboard/skill-install-request.js +10 -11
- package/dist/dashboard/skill-install-request.js.map +1 -1
- package/dist/dashboard/skill-pack-response.d.ts +15 -0
- package/dist/dashboard/skill-pack-response.d.ts.map +1 -0
- package/dist/dashboard/skill-pack-response.js +32 -0
- package/dist/dashboard/skill-pack-response.js.map +1 -0
- package/dist/dashboard/web/connectors-page.d.ts +69 -0
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
- package/dist/dashboard/web/connectors-page.js +47 -7
- package/dist/dashboard/web/connectors-page.js.map +1 -1
- package/dist/dashboard/web/feed-group-picker.d.ts +13 -0
- package/dist/dashboard/web/feed-group-picker.d.ts.map +1 -0
- package/dist/dashboard/web/feed-group-picker.js +45 -0
- package/dist/dashboard/web/feed-group-picker.js.map +1 -0
- package/dist/dashboard/web/groups-page.d.ts.map +1 -1
- package/dist/dashboard/web/groups-page.js +2 -5
- package/dist/dashboard/web/groups-page.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +309 -40
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/preferences.d.ts +4 -2
- package/dist/dashboard/web/preferences.d.ts.map +1 -1
- package/dist/dashboard/web/preferences.js +14 -6
- package/dist/dashboard/web/preferences.js.map +1 -1
- package/dist/dashboard/web/roles-page.d.ts.map +1 -1
- package/dist/dashboard/web/roles-page.js +36 -4
- package/dist/dashboard/web/roles-page.js.map +1 -1
- package/dist/dashboard/web/roles.d.ts +3 -1
- package/dist/dashboard/web/roles.d.ts.map +1 -1
- package/dist/dashboard/web/roles.js +10 -2
- package/dist/dashboard/web/roles.js.map +1 -1
- package/dist/dashboard/web/schedules-page.d.ts.map +1 -1
- package/dist/dashboard/web/schedules-page.js +8 -2
- package/dist/dashboard/web/schedules-page.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +101 -5
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts +3 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +13 -6
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/skills/bot-assignments-tab.d.ts +27 -0
- package/dist/dashboard/web/skills/bot-assignments-tab.d.ts.map +1 -0
- package/dist/dashboard/web/skills/bot-assignments-tab.js +257 -0
- package/dist/dashboard/web/skills/bot-assignments-tab.js.map +1 -0
- package/dist/dashboard/web/skills/delivery-settings-tab.d.ts +25 -0
- package/dist/dashboard/web/skills/delivery-settings-tab.d.ts.map +1 -0
- package/dist/dashboard/web/skills/delivery-settings-tab.js +20 -0
- package/dist/dashboard/web/skills/delivery-settings-tab.js.map +1 -0
- package/dist/dashboard/web/skills/shared.d.ts +86 -0
- package/dist/dashboard/web/skills/shared.d.ts.map +1 -0
- package/dist/dashboard/web/skills/shared.js +178 -0
- package/dist/dashboard/web/skills/shared.js.map +1 -0
- package/dist/dashboard/web/skills/skill-library-tab.d.ts +75 -0
- package/dist/dashboard/web/skills/skill-library-tab.d.ts.map +1 -0
- package/dist/dashboard/web/skills/skill-library-tab.js +108 -0
- package/dist/dashboard/web/skills/skill-library-tab.js.map +1 -0
- package/dist/dashboard/web/skills/skill-packs-tab.d.ts +21 -0
- package/dist/dashboard/web/skills/skill-packs-tab.d.ts.map +1 -0
- package/dist/dashboard/web/skills/skill-packs-tab.js +185 -0
- package/dist/dashboard/web/skills/skill-packs-tab.js.map +1 -0
- package/dist/dashboard/web/skills/types.d.ts +95 -0
- package/dist/dashboard/web/skills/types.d.ts.map +1 -0
- package/dist/dashboard/web/skills/types.js +2 -0
- package/dist/dashboard/web/skills/types.js.map +1 -0
- package/dist/dashboard/web/skills/use-skills-data.d.ts +31 -0
- package/dist/dashboard/web/skills/use-skills-data.d.ts.map +1 -0
- package/dist/dashboard/web/skills/use-skills-data.js +86 -0
- package/dist/dashboard/web/skills/use-skills-data.js.map +1 -0
- package/dist/dashboard/web/skills-page.d.ts +34 -31
- package/dist/dashboard/web/skills-page.d.ts.map +1 -1
- package/dist/dashboard/web/skills-page.js +321 -176
- package/dist/dashboard/web/skills-page.js.map +1 -1
- package/dist/dashboard/webhook-routes.d.ts +18 -0
- package/dist/dashboard/webhook-routes.d.ts.map +1 -1
- package/dist/dashboard/webhook-routes.js +35 -1
- package/dist/dashboard/webhook-routes.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/{bot-defaults-page-GED4FEMS.js → bot-defaults-page-HL655CNR.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-HK7NIBJG.js → chunk-5PAYQ3KT.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-KRHWZEXU.js → chunk-5ZL7NLR5.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-6ALR252E.js +1 -0
- package/dist/dashboard-web/chunks/{chunk-VBXJOJFH.js → chunk-BFUTTYVK.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-ELL53D62.js +55 -0
- package/dist/dashboard-web/chunks/connectors-page-3QQACF23.js +1 -0
- package/dist/dashboard-web/chunks/groups-page-SDZMJ7UV.js +8 -0
- package/dist/dashboard-web/chunks/{insights-page-54UBPPOC.js → insights-page-ZZ3JEJ6L.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-PORHVKRH.js → monitor-room-ROJ5GZ4N.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-XGA7AXNL.js → monitoring-page-IATV7KJF.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-AO3AFG45.js → office-page-TYO5OIIT.js} +1 -1
- package/dist/dashboard-web/chunks/{overview-page-F5BUTYR6.js → overview-page-VJUULZF2.js} +1 -1
- package/dist/dashboard-web/chunks/roles-page-7RJJKZGK.js +1 -0
- package/dist/dashboard-web/chunks/schedules-page-JTEJ5IXW.js +1 -0
- package/dist/dashboard-web/chunks/sessions-page-KD7HDT3U.js +8 -0
- package/dist/dashboard-web/chunks/{settings-page-OJAZLZQT.js → settings-page-7CTTFBRS.js} +1 -1
- package/dist/dashboard-web/chunks/skills-page-57NZECJ3.js +4 -0
- package/dist/dashboard-web/chunks/{team-federation-page-ZJVAP7HW.js → team-federation-page-6YYIMJG3.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-GYWTRGO2.js → v3-page-ZGKBSBK3.js} +1 -1
- package/dist/dashboard-web/chunks/{whiteboards-page-MSDAG6P7.js → whiteboards-page-AACJF6DB.js} +1 -1
- package/dist/dashboard-web/style.css +1952 -377
- package/dist/dashboard.js +316 -47
- package/dist/dashboard.js.map +1 -1
- package/dist/desktop/main/ipc.js +1 -1
- package/dist/desktop/main/runtime-service.js +2 -2
- package/dist/desktop/main/runtime-service.js.map +1 -1
- package/dist/desktop/shared/types.d.ts +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +5 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +5 -1
- package/dist/i18n/zh.js.map +1 -1
- package/dist/index-daemon.js +6 -1
- package/dist/index-daemon.js.map +1 -1
- package/dist/services/adopt-input-sequence.d.ts +52 -0
- package/dist/services/adopt-input-sequence.d.ts.map +1 -0
- package/dist/services/adopt-input-sequence.js +50 -0
- package/dist/services/adopt-input-sequence.js.map +1 -0
- package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
- package/dist/services/bridge-fallback-gate.js +34 -11
- package/dist/services/bridge-fallback-gate.js.map +1 -1
- package/dist/services/codex-bridge-queue.d.ts +103 -7
- package/dist/services/codex-bridge-queue.d.ts.map +1 -1
- package/dist/services/codex-bridge-queue.js +291 -17
- package/dist/services/codex-bridge-queue.js.map +1 -1
- package/dist/services/codex-transcript.d.ts +4 -3
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/connector-store.d.ts +14 -1
- package/dist/services/connector-store.d.ts.map +1 -1
- package/dist/services/connector-store.js.map +1 -1
- package/dist/services/connector-topic-template.d.ts +7 -0
- package/dist/services/connector-topic-template.d.ts.map +1 -0
- package/dist/services/connector-topic-template.js +210 -0
- package/dist/services/connector-topic-template.js.map +1 -0
- package/dist/services/project-scanner.d.ts +33 -0
- package/dist/services/project-scanner.d.ts.map +1 -1
- package/dist/services/project-scanner.js +40 -1
- package/dist/services/project-scanner.js.map +1 -1
- package/dist/services/skill-pack-store.d.ts +50 -0
- package/dist/services/skill-pack-store.d.ts.map +1 -0
- package/dist/services/skill-pack-store.js +270 -0
- package/dist/services/skill-pack-store.js.map +1 -0
- package/dist/services/skill-registry-store.d.ts +8 -0
- package/dist/services/skill-registry-store.d.ts.map +1 -1
- package/dist/services/skill-registry-store.js +100 -68
- package/dist/services/skill-registry-store.js.map +1 -1
- package/dist/services/structured-bridge-clis.d.ts +8 -1
- package/dist/services/structured-bridge-clis.d.ts.map +1 -1
- package/dist/services/structured-bridge-clis.js +13 -0
- package/dist/services/structured-bridge-clis.js.map +1 -1
- package/dist/services/submit-confirmation.d.ts +50 -0
- package/dist/services/submit-confirmation.d.ts.map +1 -1
- package/dist/services/submit-confirmation.js +82 -0
- package/dist/services/submit-confirmation.js.map +1 -1
- package/dist/services/todo-state.d.ts +74 -0
- package/dist/services/todo-state.d.ts.map +1 -0
- package/dist/services/todo-state.js +351 -0
- package/dist/services/todo-state.js.map +1 -0
- package/dist/setup/agent-preset.d.ts.map +1 -1
- package/dist/setup/agent-preset.js +2 -0
- package/dist/setup/agent-preset.js.map +1 -1
- package/dist/setup/owner-identity.d.ts +47 -0
- package/dist/setup/owner-identity.d.ts.map +1 -0
- package/dist/setup/owner-identity.js +196 -0
- package/dist/setup/owner-identity.js.map +1 -0
- package/dist/setup/register-app.d.ts +4 -3
- package/dist/setup/register-app.d.ts.map +1 -1
- package/dist/setup/register-app.js.map +1 -1
- package/dist/setup/setup-args.d.ts +1 -1
- package/dist/setup/setup-args.d.ts.map +1 -1
- package/dist/setup/setup-args.js +7 -3
- package/dist/setup/setup-args.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/async-serial-queue.d.ts +9 -0
- package/dist/utils/async-serial-queue.d.ts.map +1 -0
- package/dist/utils/async-serial-queue.js +13 -0
- package/dist/utils/async-serial-queue.js.map +1 -0
- package/dist/utils/child-env.d.ts +25 -0
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +47 -0
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/runtime-screen-status.d.ts +52 -0
- package/dist/utils/runtime-screen-status.d.ts.map +1 -0
- package/dist/utils/runtime-screen-status.js +60 -0
- package/dist/utils/runtime-screen-status.js.map +1 -0
- package/dist/worker.js +1697 -468
- package/dist/worker.js.map +1 -1
- package/dist/workflows/definition.d.ts +44 -44
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/chunk-6J5LS5AU.js +0 -51
- package/dist/dashboard-web/chunks/connectors-page-EELM66G3.js +0 -1
- package/dist/dashboard-web/chunks/groups-page-WKUV6E42.js +0 -8
- package/dist/dashboard-web/chunks/roles-page-M5GIASJU.js +0 -1
- package/dist/dashboard-web/chunks/schedules-page-O232WQRR.js +0 -1
- package/dist/dashboard-web/chunks/sessions-page-YFRPSTIL.js +0 -6
- package/dist/dashboard-web/chunks/skills-page-EFZQPWV4.js +0 -4
package/dist/dashboard.js
CHANGED
|
@@ -11,7 +11,7 @@ import { logger } from './utils/logger.js';
|
|
|
11
11
|
import { gracefulProcessExitCode } from './pm2-graceful-exit.js';
|
|
12
12
|
import { config, isWildcardBindHost } from './config.js';
|
|
13
13
|
import { listenWithProbe } from './utils/listen-with-probe.js';
|
|
14
|
-
import {
|
|
14
|
+
import { parseCookie, buildSetCookie, verifyHmac, cliAuthBind, decideDashboardAuth, loadPersistedToken, loadOrCreatePersistedToken, rotatePersistedToken, loadDashboardSecret, loadOrCreateDashboardSecret, } from './dashboard/auth.js';
|
|
15
15
|
import { DaemonRegistry, botsRosterSignature } from './dashboard/registry.js';
|
|
16
16
|
import { Aggregator, subscribeDaemon } from './dashboard/aggregator.js';
|
|
17
17
|
import { createSessionPresentationCoordinator } from './dashboard/session-presentation.js';
|
|
@@ -62,14 +62,17 @@ import { listTeamReports, readTeamBoard, setTeamBoardEntry } from './services/te
|
|
|
62
62
|
import { createCliAdapterSync } from './adapters/cli/registry.js';
|
|
63
63
|
import { hd2dAssetPath, hd2dStatus, startHd2dDownload } from './dashboard/hd2d-assets.js';
|
|
64
64
|
import { buildSkillInstallAuditSummary, installLocalSkillLinks, readSkillRegistry, removeInstalledSkill, removeInstalledSkills, updateInstalledSkillAsync, } from './services/skill-registry-store.js';
|
|
65
|
+
import { readSkillPackRegistry } from './services/skill-pack-store.js';
|
|
66
|
+
import { cloneSkillPack, createSkillPack, deleteSkillPack, getSkillPack, listSkillPacks, updateSkillPack, SkillPackStoreError, } from './services/skill-pack-store.js';
|
|
65
67
|
import { redactGitUrlCredentials } from './core/skills/sources.js';
|
|
68
|
+
import { enrichPackForDashboard, enrichPacksForDashboard, sanitizeSkillForDashboard, } from './dashboard/skill-pack-response.js';
|
|
66
69
|
import { effectiveDefaultWorkingDir, getBot, loadBotConfigs, parseBotConfigsFromText } from './bot-registry.js';
|
|
67
70
|
import { addChatToFeedGroup, createFeedGroup, FEED_GROUP_SCOPES, FeedGroupApiError, listFeedGroups } from './dashboard/feed-groups.js';
|
|
68
71
|
import { generateAuthUrl, handleCallbackUrl, isCallbackUrl } from './utils/user-token.js';
|
|
69
72
|
import { findEntryIndex, readRawConfig, requireConfigPath, writeRawConfigAtomic } from './services/config-store.js';
|
|
70
73
|
import { emitCodexNotifierOutboxItem, installCodexNotifierHook, isCodexNotifierWorkerStateFresh, isCodexNotifierHookInstalled, listCodexNotifierOutbox, readCodexNotifierWorkerState, resolveCodexNotifierConfig, runCodexSideConversationMonitor, runCodexNotifierWorkerSupervisor, } from './features/codex-notifier/index.js';
|
|
71
74
|
import { discoverNativeCliSkillGroups } from './core/skills/discovery.js';
|
|
72
|
-
import { analyzeSkillReferences } from './core/skills/references.js';
|
|
75
|
+
import { analyzeSkillReferences, packsContainingSkill } from './core/skills/references.js';
|
|
73
76
|
import { discoverDashboardSkills, installDashboardSkill, parseDashboardSkillInstallRequest, parseInstallLocalLinksSources, MAX_LOCAL_LINK_SOURCES } from './dashboard/skill-install-request.js';
|
|
74
77
|
import { botDefaultsPayload, botSummaryPayload, brandMapByAppId } from './dashboard/bot-payload.js';
|
|
75
78
|
import { handleVcMeetingConsumerProfilesGet, handleVcMeetingConsumerProfilesPut, } from './dashboard/vc-consumer-profiles-api.js';
|
|
@@ -104,6 +107,15 @@ import { resolveEffectivePluginIds, updateBotPluginOverride } from './core/plugi
|
|
|
104
107
|
import { assertPluginBindingTransition, describePluginDependencyError } from './core/plugins/dependencies.js';
|
|
105
108
|
import { inspectGatewayEntry } from './core/plugins/mcp/gateway-installer.js';
|
|
106
109
|
import { fetchDaemonIpc } from './core/daemon-ipc-auth.js';
|
|
110
|
+
import { buildDashboardSummary, parseDashboardSummaryRows, } from './dashboard/dashboard-summary.js';
|
|
111
|
+
import { createDashboardSummaryEndpoint } from './dashboard/dashboard-summary-endpoint.js';
|
|
112
|
+
import { scrubWorkflowWorkerEnv } from './utils/child-env.js';
|
|
113
|
+
// The dashboard is an independent long-lived PM2 app and can be resurrected
|
|
114
|
+
// from a stale dump.pm2 without passing through cli.ts pm2Env(). Its start/stop
|
|
115
|
+
// and detached-restart children inherit process.env, so a leaked workflow
|
|
116
|
+
// marker would make those CLI commands fail at the workflow safety gate before
|
|
117
|
+
// they can reach their own cleanup boundary.
|
|
118
|
+
scrubWorkflowWorkerEnv(process.env);
|
|
107
119
|
const SECRET_PATH = dashboardSecretPath();
|
|
108
120
|
const TOKEN_PATH = join(homedir(), '.botmux', '.dashboard-token');
|
|
109
121
|
/** Per-daemon budget for the cross-daemon insight overview fan-out — bounds
|
|
@@ -113,7 +125,8 @@ const BOTS_JSON_PATH = join(homedir(), '.botmux', 'bots.json');
|
|
|
113
125
|
const REGISTRY_DIR = join(resolveBotmuxDataDir(), 'dashboard-daemons');
|
|
114
126
|
// The dashboard probes upward if its configured port is busy (e.g. a second
|
|
115
127
|
// botmux instance on this host). The actually-bound port is persisted here so
|
|
116
|
-
// the `botmux dashboard` CLI can reach /__cli/
|
|
128
|
+
// the `botmux dashboard` CLI can reach /__cli/current, /__cli/ensure, and
|
|
129
|
+
// /__cli/rotate without guessing.
|
|
117
130
|
const PORT_PATH = join(homedir(), '.botmux', '.dashboard-port');
|
|
118
131
|
function loadOrCreateSecret() {
|
|
119
132
|
let existing;
|
|
@@ -137,15 +150,21 @@ function loadOrCreateSecret() {
|
|
|
137
150
|
process.exit(1);
|
|
138
151
|
}
|
|
139
152
|
}
|
|
140
|
-
// The
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
153
|
+
// The persisted file is the active-token authority. Reading it at each use
|
|
154
|
+
// keeps multiple dashboard processes coherent: first creation converges under
|
|
155
|
+
// a file lock, and an explicit rotation is observed by every process without a
|
|
156
|
+
// restart. `/__cli/current` remains a strictly read-only probe.
|
|
157
|
+
function currentDashboardToken() {
|
|
158
|
+
try {
|
|
159
|
+
return loadPersistedToken(TOKEN_PATH);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
logger.warn(`[dashboard] Failed to read token from ${TOKEN_PATH}: ${error.message}`);
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
147
166
|
// The port we actually bound (may differ from config.dashboard.port after an
|
|
148
|
-
// EADDRINUSE probe). Used for
|
|
167
|
+
// EADDRINUSE probe). Used for token-bearing URLs and persisted for the CLI.
|
|
149
168
|
let boundDashboardPort = config.dashboard.port;
|
|
150
169
|
const SECRET = loadOrCreateSecret();
|
|
151
170
|
function tcpPortAvailable(host, port) {
|
|
@@ -220,7 +239,7 @@ aggregator.on(sessionPresentation.onEvent);
|
|
|
220
239
|
// 调试终端(owner-only 裸 bash)。默认工作目录取当前所有 session 的工作目录去重,
|
|
221
240
|
// 让 owner 从熟悉的目录起终端复现问题;都没有时模块内退回 homedir。
|
|
222
241
|
const debugTerminalManager = createDebugTerminalManager({
|
|
223
|
-
getActiveToken:
|
|
242
|
+
getActiveToken: currentDashboardToken,
|
|
224
243
|
defaultWorkingDirs: () => {
|
|
225
244
|
const dirs = new Set();
|
|
226
245
|
for (const s of aggregator.getSessions()) {
|
|
@@ -1032,9 +1051,9 @@ const groupsActionDeps = {
|
|
|
1032
1051
|
// ─── PR2 C8: Route B internal API (`/__daemon/*`) ───────────────────────────
|
|
1033
1052
|
// HMAC + loopback + ts ±60s + nonce TTL, signed-request envelope = full
|
|
1034
1053
|
// (ts, nonce, method, pathWithQuery, sha256(body)). Reuses `.dashboard-secret`
|
|
1035
|
-
// for the HMAC key — the same secret `/__cli
|
|
1036
|
-
// signing material is wider so a
|
|
1037
|
-
//
|
|
1054
|
+
// for the HMAC key — the same secret the `/__cli/*` protocol uses — but the
|
|
1055
|
+
// signing material is wider so a CLI signature cannot be replayed here and
|
|
1056
|
+
// vice versa (different protocols, same secret, no cross-replay).
|
|
1038
1057
|
//
|
|
1039
1058
|
// SECRET fail-closed: `loadOrCreateSecret()` returns a 32-byte base64url
|
|
1040
1059
|
// string and never empty; we still guard below at server-startup time.
|
|
@@ -1751,7 +1770,7 @@ async function handlePluginManagementApi(req, res, url) {
|
|
|
1751
1770
|
return false;
|
|
1752
1771
|
}
|
|
1753
1772
|
// ─── HTTP routing ────────────────────────────────────────────────────────────
|
|
1754
|
-
function authedToken(req, url) {
|
|
1773
|
+
function authedToken(req, url, activeToken) {
|
|
1755
1774
|
const q = url.searchParams.get('t');
|
|
1756
1775
|
if (q && q === activeToken)
|
|
1757
1776
|
return q;
|
|
@@ -2294,16 +2313,13 @@ function startSkillJob(type, run) {
|
|
|
2294
2313
|
})());
|
|
2295
2314
|
return job;
|
|
2296
2315
|
}
|
|
2297
|
-
function sanitizeSkillForDashboard(skill) {
|
|
2298
|
-
if (skill.source.type !== 'git')
|
|
2299
|
-
return skill;
|
|
2300
|
-
return {
|
|
2301
|
-
...skill,
|
|
2302
|
-
source: { ...skill.source, url: redactGitUrlCredentials(skill.source.url) },
|
|
2303
|
-
};
|
|
2304
|
-
}
|
|
2305
2316
|
function dashboardSkillCliIds() {
|
|
2306
2317
|
const ids = new Set();
|
|
2318
|
+
// Always scan all known CLI skill dirs, not just configured bots — users may
|
|
2319
|
+
// want to discover codex/trae/... skills even before creating a bot for them.
|
|
2320
|
+
const allCliIds = ['claude-code', 'seed', 'relay', 'aiden', 'coco', 'codex', 'codex-app', 'cursor', 'gemini', 'genius', 'opencode', 'antigravity', 'mtr', 'hermes', 'mira', 'mir', 'traex', 'pi', 'copilot', 'oh-my-pi', 'kimi', 'grok', 'kiro-cli', 'riff'];
|
|
2321
|
+
for (const cliId of allCliIds)
|
|
2322
|
+
ids.add(cliId);
|
|
2307
2323
|
try {
|
|
2308
2324
|
for (const cliId of configuredCliIds().values())
|
|
2309
2325
|
ids.add(cliId);
|
|
@@ -2333,6 +2349,76 @@ function dashboardSkillsPayload() {
|
|
|
2333
2349
|
delivery: globalSkills.delivery ?? 'auto',
|
|
2334
2350
|
};
|
|
2335
2351
|
}
|
|
2352
|
+
// --- Skill pack dashboard helpers ------------------------------------------
|
|
2353
|
+
function loadBotConfigsSafe() {
|
|
2354
|
+
try {
|
|
2355
|
+
return loadBotConfigs();
|
|
2356
|
+
}
|
|
2357
|
+
catch {
|
|
2358
|
+
return [];
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
function botsReferencingPack(packId, bots) {
|
|
2362
|
+
const selector = `pack:${packId}`;
|
|
2363
|
+
return bots
|
|
2364
|
+
.filter((bot) => Array.isArray(bot.skills?.include) && bot.skills.include.includes(selector))
|
|
2365
|
+
.map((bot) => ({ larkAppId: bot.larkAppId, botName: bot.name ?? bot.larkAppId }))
|
|
2366
|
+
.sort((a, b) => a.botName.localeCompare(b.botName));
|
|
2367
|
+
}
|
|
2368
|
+
function parsePackInput(body) {
|
|
2369
|
+
if (!body || typeof body !== 'object' || Array.isArray(body))
|
|
2370
|
+
throw new SkillPackStoreError({ code: 'SKILL_PACK_INVALID', reason: 'body must be an object' });
|
|
2371
|
+
const b = body;
|
|
2372
|
+
return {
|
|
2373
|
+
id: typeof b.id === 'string' ? b.id : '',
|
|
2374
|
+
name: typeof b.name === 'string' ? b.name : '',
|
|
2375
|
+
description: typeof b.description === 'string' ? b.description : undefined,
|
|
2376
|
+
tags: Array.isArray(b.tags) ? b.tags : undefined,
|
|
2377
|
+
include: Array.isArray(b.include) ? b.include : [],
|
|
2378
|
+
};
|
|
2379
|
+
}
|
|
2380
|
+
function parsePackUpdate(body) {
|
|
2381
|
+
if (!body || typeof body !== 'object' || Array.isArray(body))
|
|
2382
|
+
throw new SkillPackStoreError({ code: 'SKILL_PACK_INVALID', reason: 'body must be an object' });
|
|
2383
|
+
const b = body;
|
|
2384
|
+
return {
|
|
2385
|
+
name: typeof b.name === 'string' ? b.name : undefined,
|
|
2386
|
+
description: b.description === null ? null : typeof b.description === 'string' ? b.description : undefined,
|
|
2387
|
+
tags: b.tags === null ? null : Array.isArray(b.tags) ? b.tags : undefined,
|
|
2388
|
+
include: Array.isArray(b.include) ? b.include : undefined,
|
|
2389
|
+
expectedRevision: typeof b.expectedRevision === 'number' ? b.expectedRevision : undefined,
|
|
2390
|
+
};
|
|
2391
|
+
}
|
|
2392
|
+
function packErrorStatus(err) {
|
|
2393
|
+
if (err instanceof SkillPackStoreError) {
|
|
2394
|
+
switch (err.detail.code) {
|
|
2395
|
+
case 'SKILL_PACK_NOT_FOUND': return 404;
|
|
2396
|
+
case 'SKILL_PACK_ID_CONFLICT': return 409;
|
|
2397
|
+
case 'SKILL_PACK_REVISION_CONFLICT': return 409;
|
|
2398
|
+
case 'SKILL_PACK_IN_USE': return 409;
|
|
2399
|
+
default: return 400;
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
return 400;
|
|
2403
|
+
}
|
|
2404
|
+
function packErrorBody(err) {
|
|
2405
|
+
if (err instanceof SkillPackStoreError) {
|
|
2406
|
+
const d = err.detail;
|
|
2407
|
+
const body = { ok: false, error: d.code };
|
|
2408
|
+
if (d.code === 'SKILL_PACK_REVISION_CONFLICT')
|
|
2409
|
+
body.current = d.current;
|
|
2410
|
+
if (d.code === 'SKILL_PACK_INVALID')
|
|
2411
|
+
body.reason = d.reason;
|
|
2412
|
+
if (d.code === 'SKILL_PACK_INVALID_SELECTOR')
|
|
2413
|
+
body.selector = d.selector;
|
|
2414
|
+
return body;
|
|
2415
|
+
}
|
|
2416
|
+
return {
|
|
2417
|
+
ok: false,
|
|
2418
|
+
error: 'internal_error',
|
|
2419
|
+
detail: redactGitUrlCredentials(err instanceof Error ? err.message : String(err)),
|
|
2420
|
+
};
|
|
2421
|
+
}
|
|
2336
2422
|
function mergeSkillReferenceBot(refs, ref) {
|
|
2337
2423
|
const current = refs.get(ref.larkAppId);
|
|
2338
2424
|
if (!current) {
|
|
@@ -2344,11 +2430,18 @@ function mergeSkillReferenceBot(refs, ref) {
|
|
|
2344
2430
|
async function dashboardSkillReferencesMany(skillNames) {
|
|
2345
2431
|
const uniqueNames = [...new Set(skillNames)];
|
|
2346
2432
|
const refsBySkill = new Map(uniqueNames.map(name => [name, new Map()]));
|
|
2433
|
+
let packs;
|
|
2434
|
+
try {
|
|
2435
|
+
packs = readSkillPackRegistry().packs;
|
|
2436
|
+
}
|
|
2437
|
+
catch {
|
|
2438
|
+
// packs.json may be absent; fall back to direct-only analysis.
|
|
2439
|
+
}
|
|
2347
2440
|
try {
|
|
2348
2441
|
const configuredBots = loadBotConfigs();
|
|
2349
2442
|
for (const name of uniqueNames) {
|
|
2350
2443
|
const refs = refsBySkill.get(name);
|
|
2351
|
-
for (const ref of analyzeSkillReferences(name, { bots: configuredBots }).bots)
|
|
2444
|
+
for (const ref of analyzeSkillReferences(name, { bots: configuredBots, packs }).bots)
|
|
2352
2445
|
mergeSkillReferenceBot(refs, ref);
|
|
2353
2446
|
}
|
|
2354
2447
|
}
|
|
@@ -2374,15 +2467,16 @@ async function dashboardSkillReferencesMany(skillNames) {
|
|
|
2374
2467
|
const availableOnlineConfigs = onlineConfigs.filter(config => config !== null);
|
|
2375
2468
|
for (const name of uniqueNames) {
|
|
2376
2469
|
const refs = refsBySkill.get(name);
|
|
2377
|
-
for (const ref of analyzeSkillReferences(name, { bots: availableOnlineConfigs }).bots)
|
|
2470
|
+
for (const ref of analyzeSkillReferences(name, { bots: availableOnlineConfigs, packs }).bots)
|
|
2378
2471
|
mergeSkillReferenceBot(refs, ref);
|
|
2379
2472
|
}
|
|
2380
2473
|
return new Map([...refsBySkill].map(([name, refs]) => [name, {
|
|
2381
2474
|
bots: [...refs.values()].sort((a, b) => a.botName.localeCompare(b.botName)),
|
|
2475
|
+
packs: packsContainingSkill(name, packs),
|
|
2382
2476
|
}]));
|
|
2383
2477
|
}
|
|
2384
2478
|
async function dashboardSkillReferences(skillName) {
|
|
2385
|
-
return (await dashboardSkillReferencesMany([skillName])).get(skillName) ?? { bots: [] };
|
|
2479
|
+
return (await dashboardSkillReferencesMany([skillName])).get(skillName) ?? { bots: [], packs: [] };
|
|
2386
2480
|
}
|
|
2387
2481
|
/** Extract the sessionId from a terminal path `/s/<sessionId>[/...]`. Returns
|
|
2388
2482
|
* the first path segment after `/s/` (stops at the next `/`; query/hash are
|
|
@@ -2393,6 +2487,52 @@ function parseTerminalSessionId(pathname) {
|
|
|
2393
2487
|
const seg = pathname.slice(3).split('/')[0];
|
|
2394
2488
|
return seg || undefined;
|
|
2395
2489
|
}
|
|
2490
|
+
/**
|
|
2491
|
+
* Read every currently-online daemon directly for the public dashboard
|
|
2492
|
+
* summary. The regular aggregator intentionally retains offline
|
|
2493
|
+
* rows for operator history, so using it here would make an offline bot's old
|
|
2494
|
+
* sessions or schedules look live. A failed or malformed daemon snapshot
|
|
2495
|
+
* rejects the whole projection instead of silently turning missing data into
|
|
2496
|
+
* zeroes.
|
|
2497
|
+
*/
|
|
2498
|
+
async function liveDashboardSummary() {
|
|
2499
|
+
const daemons = registry.list();
|
|
2500
|
+
const configuredBots = loadBotConfigs();
|
|
2501
|
+
const snapshots = await Promise.all(daemons.map(async (daemon) => {
|
|
2502
|
+
const [sessionsResponse, schedulesResponse] = await Promise.all([
|
|
2503
|
+
fetchDaemonIpc(daemon.ipcPort, '/api/sessions', {
|
|
2504
|
+
signal: AbortSignal.timeout(2_000),
|
|
2505
|
+
}),
|
|
2506
|
+
fetchDaemonIpc(daemon.ipcPort, '/api/schedules', {
|
|
2507
|
+
signal: AbortSignal.timeout(2_000),
|
|
2508
|
+
}),
|
|
2509
|
+
]);
|
|
2510
|
+
if (!sessionsResponse.ok || !schedulesResponse.ok) {
|
|
2511
|
+
throw new Error('daemon_snapshot_http_error');
|
|
2512
|
+
}
|
|
2513
|
+
const [sessionsBody, schedulesBody] = await Promise.all([
|
|
2514
|
+
sessionsResponse.json(),
|
|
2515
|
+
schedulesResponse.json(),
|
|
2516
|
+
]);
|
|
2517
|
+
return parseDashboardSummaryRows({
|
|
2518
|
+
sessions: sessionsBody.sessions,
|
|
2519
|
+
schedules: schedulesBody.schedules,
|
|
2520
|
+
});
|
|
2521
|
+
}));
|
|
2522
|
+
return buildDashboardSummary({
|
|
2523
|
+
generatedAt: new Date(),
|
|
2524
|
+
configuredBotAppIds: configuredBots.map(bot => bot.larkAppId),
|
|
2525
|
+
onlineBotAppIds: daemons.map(daemon => daemon.larkAppId),
|
|
2526
|
+
sessions: snapshots.flatMap(snapshot => snapshot.sessions),
|
|
2527
|
+
schedules: snapshots.flatMap(snapshot => snapshot.schedules),
|
|
2528
|
+
});
|
|
2529
|
+
}
|
|
2530
|
+
const dashboardSummaryEndpoint = createDashboardSummaryEndpoint({
|
|
2531
|
+
load: liveDashboardSummary,
|
|
2532
|
+
onError: error => {
|
|
2533
|
+
logger.warn(`[dashboard-summary] live snapshot unavailable: ${error instanceof Error ? error.message : String(error)}`);
|
|
2534
|
+
},
|
|
2535
|
+
});
|
|
2396
2536
|
const server = createServer(async (req, res) => {
|
|
2397
2537
|
try {
|
|
2398
2538
|
const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
|
|
@@ -2411,7 +2551,8 @@ const server = createServer(async (req, res) => {
|
|
|
2411
2551
|
// outside the browser auth gate so packaged desktop apps can decide whether
|
|
2412
2552
|
// this runtime speaks their dashboard protocol before loading the SPA.
|
|
2413
2553
|
if (req.method === 'GET' && url.pathname === '/__desktop/compat') {
|
|
2414
|
-
const
|
|
2554
|
+
const activeToken = currentDashboardToken();
|
|
2555
|
+
const presentedToken = authedToken(req, url, activeToken);
|
|
2415
2556
|
const boundMachineId = activeToken && presentedToken === activeToken
|
|
2416
2557
|
? readPlatformBinding()?.machineId
|
|
2417
2558
|
: null;
|
|
@@ -2473,32 +2614,53 @@ const server = createServer(async (req, res) => {
|
|
|
2473
2614
|
if (await daemonInternalApi.handle(req, res, url)) {
|
|
2474
2615
|
return;
|
|
2475
2616
|
}
|
|
2476
|
-
// CLI rotate (HMAC + loopback only) — for `botmux dashboard`.
|
|
2477
|
-
// token
|
|
2617
|
+
// CLI rotate (HMAC + loopback only) — for `botmux dashboard rotate`.
|
|
2618
|
+
// Publish the new token only after a durable write succeeds.
|
|
2478
2619
|
if (req.method === 'POST' && url.pathname === '/__cli/rotate') {
|
|
2479
2620
|
const gate = verifyCliRequest(req, url.pathname);
|
|
2480
2621
|
if (!gate.ok)
|
|
2481
2622
|
return jsonRes(res, gate.status, gate.body);
|
|
2482
|
-
activeToken = generateToken();
|
|
2483
2623
|
try {
|
|
2484
|
-
|
|
2624
|
+
const token = rotatePersistedToken(TOKEN_PATH);
|
|
2625
|
+
return jsonRes(res, 200, dashboardUrlsFor(token));
|
|
2485
2626
|
}
|
|
2486
2627
|
catch (e) {
|
|
2487
2628
|
logger.warn(`[dashboard] Failed to persist token to ${TOKEN_PATH}: ${e.message}`);
|
|
2629
|
+
return jsonRes(res, 500, { error: 'token_persist_failed' });
|
|
2488
2630
|
}
|
|
2489
|
-
return jsonRes(res, 200, dashboardUrlsFor(activeToken));
|
|
2490
2631
|
}
|
|
2491
|
-
// CLI
|
|
2492
|
-
//
|
|
2493
|
-
|
|
2494
|
-
|
|
2632
|
+
// CLI get-or-create URL (HMAC + loopback only). Existing links survive
|
|
2633
|
+
// untouched; the first caller atomically creates and persists a token.
|
|
2634
|
+
if (req.method === 'POST' && url.pathname === '/__cli/ensure') {
|
|
2635
|
+
const gate = verifyCliRequest(req, url.pathname);
|
|
2636
|
+
if (!gate.ok)
|
|
2637
|
+
return jsonRes(res, gate.status, gate.body);
|
|
2638
|
+
try {
|
|
2639
|
+
const token = loadOrCreatePersistedToken(TOKEN_PATH);
|
|
2640
|
+
return jsonRes(res, 200, dashboardUrlsFor(token));
|
|
2641
|
+
}
|
|
2642
|
+
catch (e) {
|
|
2643
|
+
logger.warn(`[dashboard] Failed to ensure token at ${TOKEN_PATH}: ${e.message}`);
|
|
2644
|
+
return jsonRes(res, 500, { error: 'token_persist_failed' });
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
// CLI read current URL (HMAC + loopback only) — for start/restart hints and
|
|
2648
|
+
// safe port discovery. This never mints a token.
|
|
2495
2649
|
if (req.method === 'POST' && url.pathname === '/__cli/current') {
|
|
2496
2650
|
const gate = verifyCliRequest(req, url.pathname);
|
|
2497
2651
|
if (!gate.ok)
|
|
2498
2652
|
return jsonRes(res, gate.status, gate.body);
|
|
2499
|
-
|
|
2653
|
+
let token;
|
|
2654
|
+
try {
|
|
2655
|
+
token = loadPersistedToken(TOKEN_PATH);
|
|
2656
|
+
}
|
|
2657
|
+
catch (e) {
|
|
2658
|
+
logger.warn(`[dashboard] Failed to read token from ${TOKEN_PATH}: ${e.message}`);
|
|
2659
|
+
return jsonRes(res, 500, { error: 'token_unavailable' });
|
|
2660
|
+
}
|
|
2661
|
+
if (!token)
|
|
2500
2662
|
return jsonRes(res, 404, { error: 'no_active_token' });
|
|
2501
|
-
return jsonRes(res, 200, dashboardUrlsFor(
|
|
2663
|
+
return jsonRes(res, 200, dashboardUrlsFor(token));
|
|
2502
2664
|
}
|
|
2503
2665
|
// CLI 通知绑定变化(HMAC + loopback)——`botmux bind` 写完绑定后捅一下,立即重连平台,
|
|
2504
2666
|
// 无需重启 daemon,也不依赖 fs.watch。
|
|
@@ -2521,7 +2683,8 @@ const server = createServer(async (req, res) => {
|
|
|
2521
2683
|
startPlatformTunnelIfBound();
|
|
2522
2684
|
return jsonRes(res, 200, { ok: true });
|
|
2523
2685
|
}
|
|
2524
|
-
const
|
|
2686
|
+
const activeToken = currentDashboardToken();
|
|
2687
|
+
const presentedToken = authedToken(req, url, activeToken);
|
|
2525
2688
|
const globalDashboardConfig = readGlobalConfig().dashboard;
|
|
2526
2689
|
const decision = decideDashboardAuth({
|
|
2527
2690
|
method: req.method ?? 'GET',
|
|
@@ -2659,6 +2822,12 @@ const server = createServer(async (req, res) => {
|
|
|
2659
2822
|
return jsonRes(res, 200, startHd2dDownload());
|
|
2660
2823
|
}
|
|
2661
2824
|
// ─── Public API (cookie/token already validated above) ──────────────────
|
|
2825
|
+
if (req.method === 'GET' && url.pathname === '/api/dashboard/v1/summary') {
|
|
2826
|
+
const result = await dashboardSummaryEndpoint.get({ authenticated: authed });
|
|
2827
|
+
for (const [name, value] of Object.entries(result.headers))
|
|
2828
|
+
res.setHeader(name, value);
|
|
2829
|
+
return jsonRes(res, result.status, result.body);
|
|
2830
|
+
}
|
|
2662
2831
|
if (await handleResourceMonitorApi(req, res, url, resourceMonitor)) {
|
|
2663
2832
|
return;
|
|
2664
2833
|
}
|
|
@@ -3256,10 +3425,14 @@ const server = createServer(async (req, res) => {
|
|
|
3256
3425
|
if (missing.length > 0)
|
|
3257
3426
|
return jsonRes(res, 400, { ok: false, error: 'skill_not_installed', missing });
|
|
3258
3427
|
const referencesBySkill = await dashboardSkillReferencesMany(names);
|
|
3259
|
-
const references = names.map(name => ({ name, refs: referencesBySkill.get(name) ?? { bots: [] } }));
|
|
3428
|
+
const references = names.map(name => ({ name, refs: referencesBySkill.get(name) ?? { bots: [], packs: [] } }));
|
|
3260
3429
|
const affectedSkills = references
|
|
3261
|
-
.filter(item => item.refs.bots.length > 0)
|
|
3262
|
-
.map(item => ({
|
|
3430
|
+
.filter(item => item.refs.bots.length > 0 || item.refs.packs.length > 0)
|
|
3431
|
+
.map(item => ({
|
|
3432
|
+
name: item.name,
|
|
3433
|
+
affectedBots: item.refs.bots,
|
|
3434
|
+
affectedPacks: item.refs.packs,
|
|
3435
|
+
}));
|
|
3263
3436
|
if (body.force !== true && affectedSkills.length > 0) {
|
|
3264
3437
|
return jsonRes(res, 409, {
|
|
3265
3438
|
ok: false,
|
|
@@ -3390,11 +3563,12 @@ const server = createServer(async (req, res) => {
|
|
|
3390
3563
|
if (!readSkillRegistry().skills[name])
|
|
3391
3564
|
return jsonRes(res, 400, { ok: false, error: 'skill_not_installed' });
|
|
3392
3565
|
const refs = await dashboardSkillReferences(name);
|
|
3393
|
-
if (!force && refs.bots.length > 0) {
|
|
3566
|
+
if (!force && (refs.bots.length > 0 || refs.packs.length > 0)) {
|
|
3394
3567
|
return jsonRes(res, 409, {
|
|
3395
3568
|
ok: false,
|
|
3396
3569
|
error: 'skill_in_use',
|
|
3397
3570
|
affectedBots: refs.bots,
|
|
3571
|
+
affectedPacks: refs.packs,
|
|
3398
3572
|
});
|
|
3399
3573
|
}
|
|
3400
3574
|
const r = removeInstalledSkill(name);
|
|
@@ -3403,9 +3577,103 @@ const server = createServer(async (req, res) => {
|
|
|
3403
3577
|
return jsonRes(res, 200, {
|
|
3404
3578
|
ok: true,
|
|
3405
3579
|
affectedBots: refs.bots,
|
|
3580
|
+
affectedPacks: refs.packs,
|
|
3406
3581
|
...dashboardSkillsPayload(),
|
|
3407
3582
|
});
|
|
3408
3583
|
}
|
|
3584
|
+
// --- Skill pack CRUD ---------------------------------------------------
|
|
3585
|
+
if (req.method === 'GET' && url.pathname === '/api/skill-packs') {
|
|
3586
|
+
const registrySkills = readSkillRegistry().skills;
|
|
3587
|
+
const bots = loadBotConfigsSafe();
|
|
3588
|
+
const packs = enrichPacksForDashboard(listSkillPacks(), registrySkills, (packId) => botsReferencingPack(packId, bots));
|
|
3589
|
+
return jsonRes(res, 200, { ok: true, packs });
|
|
3590
|
+
}
|
|
3591
|
+
if (req.method === 'POST' && url.pathname === '/api/skill-packs') {
|
|
3592
|
+
let body;
|
|
3593
|
+
try {
|
|
3594
|
+
body = await readJsonBody(req);
|
|
3595
|
+
}
|
|
3596
|
+
catch {
|
|
3597
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
3598
|
+
}
|
|
3599
|
+
try {
|
|
3600
|
+
const input = parsePackInput(body);
|
|
3601
|
+
const pack = createSkillPack(input);
|
|
3602
|
+
return jsonRes(res, 201, { ok: true, pack });
|
|
3603
|
+
}
|
|
3604
|
+
catch (err) {
|
|
3605
|
+
return jsonRes(res, packErrorStatus(err), packErrorBody(err));
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
let mPack;
|
|
3609
|
+
if (req.method === 'GET' && (mPack = url.pathname.match(/^\/api\/skill-packs\/([^/]+)$/))) {
|
|
3610
|
+
const id = decodeURIComponent(mPack[1]);
|
|
3611
|
+
const pack = getSkillPack(id);
|
|
3612
|
+
if (!pack)
|
|
3613
|
+
return jsonRes(res, 404, { ok: false, error: 'SKILL_PACK_NOT_FOUND' });
|
|
3614
|
+
const registrySkills = readSkillRegistry().skills;
|
|
3615
|
+
const bots = loadBotConfigsSafe();
|
|
3616
|
+
return jsonRes(res, 200, {
|
|
3617
|
+
ok: true,
|
|
3618
|
+
pack: enrichPackForDashboard(pack, registrySkills, botsReferencingPack(pack.id, bots)),
|
|
3619
|
+
});
|
|
3620
|
+
}
|
|
3621
|
+
if (req.method === 'PUT' && (mPack = url.pathname.match(/^\/api\/skill-packs\/([^/]+)$/))) {
|
|
3622
|
+
const id = decodeURIComponent(mPack[1]);
|
|
3623
|
+
let body;
|
|
3624
|
+
try {
|
|
3625
|
+
body = await readJsonBody(req);
|
|
3626
|
+
}
|
|
3627
|
+
catch {
|
|
3628
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
3629
|
+
}
|
|
3630
|
+
try {
|
|
3631
|
+
const input = parsePackUpdate(body);
|
|
3632
|
+
const pack = updateSkillPack(id, input);
|
|
3633
|
+
return jsonRes(res, 200, { ok: true, pack });
|
|
3634
|
+
}
|
|
3635
|
+
catch (err) {
|
|
3636
|
+
return jsonRes(res, packErrorStatus(err), packErrorBody(err));
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
if (req.method === 'DELETE' && (mPack = url.pathname.match(/^\/api\/skill-packs\/([^/]+)$/))) {
|
|
3640
|
+
const id = decodeURIComponent(mPack[1]);
|
|
3641
|
+
const force = url.searchParams.get('force') === '1';
|
|
3642
|
+
const pack = getSkillPack(id);
|
|
3643
|
+
if (!pack)
|
|
3644
|
+
return jsonRes(res, 404, { ok: false, error: 'SKILL_PACK_NOT_FOUND' });
|
|
3645
|
+
const refs = botsReferencingPack(id, loadBotConfigsSafe());
|
|
3646
|
+
if (!force && refs.length > 0) {
|
|
3647
|
+
return jsonRes(res, 409, { ok: false, error: 'SKILL_PACK_IN_USE', references: refs });
|
|
3648
|
+
}
|
|
3649
|
+
try {
|
|
3650
|
+
deleteSkillPack(id);
|
|
3651
|
+
return jsonRes(res, 200, { ok: true, references: refs });
|
|
3652
|
+
}
|
|
3653
|
+
catch (err) {
|
|
3654
|
+
return jsonRes(res, packErrorStatus(err), packErrorBody(err));
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
if (req.method === 'POST' && (mPack = url.pathname.match(/^\/api\/skill-packs\/([^/]+)\/clone$/))) {
|
|
3658
|
+
const id = decodeURIComponent(mPack[1]);
|
|
3659
|
+
let body;
|
|
3660
|
+
try {
|
|
3661
|
+
body = await readJsonBody(req);
|
|
3662
|
+
}
|
|
3663
|
+
catch {
|
|
3664
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
3665
|
+
}
|
|
3666
|
+
const newId = typeof body?.id === 'string' ? body.id.trim() : '';
|
|
3667
|
+
if (!newId)
|
|
3668
|
+
return jsonRes(res, 400, { ok: false, error: 'id_required' });
|
|
3669
|
+
try {
|
|
3670
|
+
const pack = cloneSkillPack(id, newId);
|
|
3671
|
+
return jsonRes(res, 201, { ok: true, pack });
|
|
3672
|
+
}
|
|
3673
|
+
catch (err) {
|
|
3674
|
+
return jsonRes(res, packErrorStatus(err), packErrorBody(err));
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3409
3677
|
if (req.method === 'GET' && url.pathname === '/api/whiteboards') {
|
|
3410
3678
|
return jsonRes(res, 200, { enabled: whiteboardEnabled(), whiteboards: listWhiteboards() });
|
|
3411
3679
|
}
|
|
@@ -5482,15 +5750,16 @@ function startPlatformTunnelIfBound() {
|
|
|
5482
5750
|
const binding = readPlatformBinding();
|
|
5483
5751
|
if (!binding)
|
|
5484
5752
|
return;
|
|
5485
|
-
|
|
5486
|
-
|
|
5753
|
+
const existingToken = currentDashboardToken();
|
|
5754
|
+
loadOrCreatePersistedToken(TOKEN_PATH);
|
|
5755
|
+
if (!existingToken) {
|
|
5487
5756
|
logger.info('[platform-tunnel] 已初始化 dashboard token');
|
|
5488
5757
|
}
|
|
5489
5758
|
const version = readBotmuxVersion();
|
|
5490
5759
|
platformTunnel = startPlatformTunnelClient({
|
|
5491
5760
|
binding,
|
|
5492
5761
|
getDashboardPort: () => boundDashboardPort,
|
|
5493
|
-
getDashboardToken:
|
|
5762
|
+
getDashboardToken: currentDashboardToken,
|
|
5494
5763
|
getVersion: () => version,
|
|
5495
5764
|
getBots: () => readPlatformBotsInfo(),
|
|
5496
5765
|
getTeamSyncRev: () => getPlatformTeamSyncRev(config.session.dataDir),
|