@geminixiang/mikan 1.0.0-beta.76 → 1.0.0-beta.78
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/CHANGELOG.md +39 -0
- package/dist/adapters/commands/login.d.ts.map +1 -1
- package/dist/adapters/commands/login.js +0 -9
- package/dist/adapters/commands/login.js.map +1 -1
- package/dist/adapters/commands/manifest.d.ts +0 -19
- package/dist/adapters/commands/manifest.d.ts.map +1 -1
- package/dist/adapters/commands/manifest.js +0 -34
- package/dist/adapters/commands/manifest.js.map +1 -1
- package/dist/adapters/commands/model.d.ts +0 -5
- package/dist/adapters/commands/model.d.ts.map +1 -1
- package/dist/adapters/commands/model.js +0 -5
- package/dist/adapters/commands/model.js.map +1 -1
- package/dist/adapters/commands/new.d.ts.map +1 -1
- package/dist/adapters/commands/new.js +0 -2
- package/dist/adapters/commands/new.js.map +1 -1
- package/dist/adapters/commands/registry.d.ts +0 -1
- package/dist/adapters/commands/registry.d.ts.map +1 -1
- package/dist/adapters/commands/registry.js +0 -8
- package/dist/adapters/commands/registry.js.map +1 -1
- package/dist/adapters/commands/session-view.d.ts.map +1 -1
- package/dist/adapters/commands/session-view.js +0 -2
- package/dist/adapters/commands/session-view.js.map +1 -1
- package/dist/adapters/commands/types.d.ts +0 -29
- package/dist/adapters/commands/types.d.ts.map +1 -1
- package/dist/adapters/commands/types.js.map +1 -1
- package/dist/adapters/commands/utils.d.ts +0 -3
- package/dist/adapters/commands/utils.d.ts.map +1 -1
- package/dist/adapters/commands/utils.js +0 -3
- package/dist/adapters/commands/utils.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +0 -4
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +5 -41
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/components.d.ts +0 -23
- package/dist/adapters/discord/components.d.ts.map +1 -1
- package/dist/adapters/discord/components.js +0 -23
- package/dist/adapters/discord/components.js.map +1 -1
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +1 -11
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/discord/format.d.ts +0 -1
- package/dist/adapters/discord/format.d.ts.map +1 -1
- package/dist/adapters/discord/format.js +0 -37
- package/dist/adapters/discord/format.js.map +1 -1
- package/dist/adapters/github/bot.d.ts +0 -44
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +1 -120
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/client.d.ts +0 -57
- package/dist/adapters/github/client.d.ts.map +1 -1
- package/dist/adapters/github/client.js +0 -59
- package/dist/adapters/github/client.js.map +1 -1
- package/dist/adapters/github/context.d.ts.map +1 -1
- package/dist/adapters/github/context.js +1 -8
- package/dist/adapters/github/context.js.map +1 -1
- package/dist/adapters/github/github-ops.d.ts +0 -55
- package/dist/adapters/github/github-ops.d.ts.map +1 -1
- package/dist/adapters/github/github-ops.js +0 -59
- package/dist/adapters/github/github-ops.js.map +1 -1
- package/dist/adapters/github/ids.d.ts +0 -27
- package/dist/adapters/github/ids.d.ts.map +1 -1
- package/dist/adapters/github/ids.js +0 -29
- package/dist/adapters/github/ids.js.map +1 -1
- package/dist/adapters/github/repo.d.ts +0 -25
- package/dist/adapters/github/repo.d.ts.map +1 -1
- package/dist/adapters/github/repo.js +0 -49
- package/dist/adapters/github/repo.js.map +1 -1
- package/dist/adapters/github/tool-pack.d.ts +0 -10
- package/dist/adapters/github/tool-pack.d.ts.map +1 -1
- package/dist/adapters/github/tool-pack.js +0 -10
- package/dist/adapters/github/tool-pack.js.map +1 -1
- package/dist/adapters/github/tools/checks.d.ts +0 -6
- package/dist/adapters/github/tools/checks.d.ts.map +1 -1
- package/dist/adapters/github/tools/checks.js +0 -7
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/tools/issue.d.ts +0 -5
- package/dist/adapters/github/tools/issue.d.ts.map +1 -1
- package/dist/adapters/github/tools/issue.js +0 -5
- package/dist/adapters/github/tools/issue.js.map +1 -1
- package/dist/adapters/github/tools/pr.d.ts +0 -7
- package/dist/adapters/github/tools/pr.d.ts.map +1 -1
- package/dist/adapters/github/tools/pr.js +0 -7
- package/dist/adapters/github/tools/pr.js.map +1 -1
- package/dist/adapters/github/tools/read.d.ts +0 -6
- package/dist/adapters/github/tools/read.d.ts.map +1 -1
- package/dist/adapters/github/tools/read.js +0 -8
- package/dist/adapters/github/tools/read.js.map +1 -1
- package/dist/adapters/github/tools/review-reply.d.ts +0 -5
- package/dist/adapters/github/tools/review-reply.d.ts.map +1 -1
- package/dist/adapters/github/tools/review-reply.js +0 -5
- package/dist/adapters/github/tools/review-reply.js.map +1 -1
- package/dist/adapters/github/tools/sync.d.ts +0 -6
- package/dist/adapters/github/tools/sync.d.ts.map +1 -1
- package/dist/adapters/github/tools/sync.js +0 -6
- package/dist/adapters/github/tools/sync.js.map +1 -1
- package/dist/adapters/github/types.d.ts +0 -88
- package/dist/adapters/github/types.d.ts.map +1 -1
- package/dist/adapters/github/types.js.map +1 -1
- package/dist/adapters/github/webhook.d.ts +0 -13
- package/dist/adapters/github/webhook.d.ts.map +1 -1
- package/dist/adapters/github/webhook.js +0 -16
- package/dist/adapters/github/webhook.js.map +1 -1
- package/dist/adapters/index.d.ts +3 -4
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/intake.d.ts +0 -17
- package/dist/adapters/intake.d.ts.map +1 -1
- package/dist/adapters/intake.js +6 -32
- package/dist/adapters/intake.js.map +1 -1
- package/dist/adapters/markdown-tables.d.ts +0 -10
- package/dist/adapters/markdown-tables.d.ts.map +1 -1
- package/dist/adapters/markdown-tables.js +1 -42
- package/dist/adapters/markdown-tables.js.map +1 -1
- package/dist/adapters/progressive-renderer.d.ts.map +1 -1
- package/dist/adapters/progressive-renderer.js +3 -25
- package/dist/adapters/progressive-renderer.js.map +1 -1
- package/dist/adapters/shared.d.ts +0 -57
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/shared.js +0 -71
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/assistant.d.ts +0 -49
- package/dist/adapters/slack/assistant.d.ts.map +1 -1
- package/dist/adapters/slack/assistant.js +0 -97
- package/dist/adapters/slack/assistant.js.map +1 -1
- package/dist/adapters/slack/auto-reply-context.d.ts +0 -7
- package/dist/adapters/slack/auto-reply-context.d.ts.map +1 -1
- package/dist/adapters/slack/auto-reply-context.js +0 -7
- package/dist/adapters/slack/auto-reply-context.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts +0 -9
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +0 -20
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +0 -116
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +7 -231
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +1 -3
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/slack/jev-context.d.ts +0 -13
- package/dist/adapters/slack/jev-context.d.ts.map +1 -1
- package/dist/adapters/slack/jev-context.js +0 -12
- package/dist/adapters/slack/jev-context.js.map +1 -1
- package/dist/adapters/slack/markdown.d.ts +0 -1
- package/dist/adapters/slack/markdown.d.ts.map +1 -1
- package/dist/adapters/slack/markdown.js +0 -5
- package/dist/adapters/slack/markdown.js.map +1 -1
- package/dist/adapters/slack/persona.d.ts +0 -9
- package/dist/adapters/slack/persona.d.ts.map +1 -1
- package/dist/adapters/slack/persona.js +0 -9
- package/dist/adapters/slack/persona.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +1 -45
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/session.d.ts +2 -1
- package/dist/adapters/slack/session.d.ts.map +1 -1
- package/dist/adapters/slack/session.js +2 -2
- package/dist/adapters/slack/session.js.map +1 -1
- package/dist/adapters/slack/stream-limits.d.ts +0 -25
- package/dist/adapters/slack/stream-limits.d.ts.map +1 -1
- package/dist/adapters/slack/stream-limits.js +0 -34
- package/dist/adapters/slack/stream-limits.js.map +1 -1
- package/dist/adapters/slack/task-intent.d.ts +0 -13
- package/dist/adapters/slack/task-intent.d.ts.map +1 -1
- package/dist/adapters/slack/task-intent.js +0 -7
- package/dist/adapters/slack/task-intent.js.map +1 -1
- package/dist/adapters/slack/task-status.d.ts +0 -1
- package/dist/adapters/slack/task-status.d.ts.map +1 -1
- package/dist/adapters/slack/task-status.js +1 -9
- package/dist/adapters/slack/task-status.js.map +1 -1
- package/dist/adapters/slack/tool-pack.d.ts +0 -6
- package/dist/adapters/slack/tool-pack.d.ts.map +1 -1
- package/dist/adapters/slack/tool-pack.js +0 -6
- package/dist/adapters/slack/tool-pack.js.map +1 -1
- package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -1
- package/dist/adapters/slack/tools/blockkit.js +0 -11
- package/dist/adapters/slack/tools/blockkit.js.map +1 -1
- package/dist/adapters/slack/types.d.ts +0 -19
- package/dist/adapters/slack/types.d.ts.map +1 -1
- package/dist/adapters/slack/types.js.map +1 -1
- package/dist/adapters/slack/update-diagnostics.d.ts +0 -1
- package/dist/adapters/slack/update-diagnostics.d.ts.map +1 -1
- package/dist/adapters/slack/update-diagnostics.js +1 -7
- package/dist/adapters/slack/update-diagnostics.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts +0 -6
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +1 -50
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +1 -8
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/adapters/types.d.ts +0 -57
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/adapters/web/admin/client-assets.d.ts +4 -0
- package/dist/adapters/web/admin/client-assets.d.ts.map +1 -0
- package/dist/adapters/web/admin/client-assets.js +1765 -0
- package/dist/adapters/web/admin/client-assets.js.map +1 -0
- package/dist/adapters/web/admin/portal.d.ts +0 -10
- package/dist/adapters/web/admin/portal.d.ts.map +1 -1
- package/dist/adapters/web/admin/portal.js +6 -1909
- package/dist/adapters/web/admin/portal.js.map +1 -1
- package/dist/adapters/web/admin/types.d.ts +0 -3
- package/dist/adapters/web/admin/types.d.ts.map +1 -1
- package/dist/adapters/web/admin/types.js.map +1 -1
- package/dist/adapters/web/login/oauth.d.ts.map +1 -1
- package/dist/adapters/web/login/oauth.js +3 -7
- package/dist/adapters/web/login/oauth.js.map +1 -1
- package/dist/adapters/web/login/portal.d.ts +0 -10
- package/dist/adapters/web/login/portal.d.ts.map +1 -1
- package/dist/adapters/web/login/portal.js +4 -37
- package/dist/adapters/web/login/portal.js.map +1 -1
- package/dist/adapters/web/login/types.d.ts +0 -5
- package/dist/adapters/web/login/types.d.ts.map +1 -1
- package/dist/adapters/web/login/types.js.map +1 -1
- package/dist/adapters/web/portal-shell.d.ts +0 -12
- package/dist/adapters/web/portal-shell.d.ts.map +1 -1
- package/dist/adapters/web/portal-shell.js +8 -25
- package/dist/adapters/web/portal-shell.js.map +1 -1
- package/dist/adapters/web/server.d.ts +0 -1
- package/dist/adapters/web/server.d.ts.map +1 -1
- package/dist/adapters/web/server.js +0 -2
- package/dist/adapters/web/server.js.map +1 -1
- package/dist/adapters/web/session-view/portal.d.ts.map +1 -1
- package/dist/adapters/web/session-view/portal.js +13 -24
- package/dist/adapters/web/session-view/portal.js.map +1 -1
- package/dist/adapters/web/session-view/types.d.ts.map +1 -1
- package/dist/adapters/web/session-view/types.js.map +1 -1
- package/dist/adapters/web/token-store.d.ts +0 -2
- package/dist/adapters/web/token-store.d.ts.map +1 -1
- package/dist/adapters/web/token-store.js +0 -2
- package/dist/adapters/web/token-store.js.map +1 -1
- package/dist/cli/arg-grammar.d.ts +0 -3
- package/dist/cli/arg-grammar.d.ts.map +1 -1
- package/dist/cli/arg-grammar.js +0 -3
- package/dist/cli/arg-grammar.js.map +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +3 -12
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/download.d.ts.map +1 -1
- package/dist/cli/download.js +2 -6
- package/dist/cli/download.js.map +1 -1
- package/dist/cli/office.d.ts.map +1 -1
- package/dist/cli/office.js +0 -31
- package/dist/cli/office.js.map +1 -1
- package/dist/cli/onboard.d.ts +0 -2
- package/dist/cli/onboard.d.ts.map +1 -1
- package/dist/cli/onboard.js +0 -30
- package/dist/cli/onboard.js.map +1 -1
- package/dist/cli/process-lifecycle.d.ts +0 -5
- package/dist/cli/process-lifecycle.d.ts.map +1 -1
- package/dist/cli/process-lifecycle.js +0 -6
- package/dist/cli/process-lifecycle.js.map +1 -1
- package/dist/cli/sandbox.d.ts +3 -0
- package/dist/cli/sandbox.d.ts.map +1 -0
- package/dist/cli/sandbox.js +79 -0
- package/dist/cli/sandbox.js.map +1 -0
- package/dist/cli/sessions.d.ts.map +1 -1
- package/dist/cli/sessions.js +0 -11
- package/dist/cli/sessions.js.map +1 -1
- package/dist/cli/types.d.ts +2 -6
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/env-manifest.d.ts +0 -21
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +0 -11
- package/dist/env-manifest.js.map +1 -1
- package/dist/events/index.d.ts +0 -51
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +0 -42
- package/dist/events/index.js.map +1 -1
- package/dist/events/scheduler.d.ts +0 -8
- package/dist/events/scheduler.d.ts.map +1 -1
- package/dist/events/scheduler.js +0 -8
- package/dist/events/scheduler.js.map +1 -1
- package/dist/file-guards.d.ts +0 -15
- package/dist/file-guards.d.ts.map +1 -1
- package/dist/file-guards.js +2 -26
- package/dist/file-guards.js.map +1 -1
- package/dist/harness/execution-env.d.ts +0 -15
- package/dist/harness/execution-env.d.ts.map +1 -1
- package/dist/harness/execution-env.js +4 -55
- package/dist/harness/execution-env.js.map +1 -1
- package/dist/harness/http.d.ts +0 -12
- package/dist/harness/http.d.ts.map +1 -1
- package/dist/harness/http.js +0 -34
- package/dist/harness/http.js.map +1 -1
- package/dist/harness/index.d.ts +4 -7
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +4 -7
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/jev.d.ts +0 -28
- package/dist/harness/jev.d.ts.map +1 -1
- package/dist/harness/jev.js +0 -45
- package/dist/harness/jev.js.map +1 -1
- package/dist/harness/mcp-result.d.ts +20 -0
- package/dist/harness/mcp-result.d.ts.map +1 -0
- package/dist/harness/mcp-result.js +171 -0
- package/dist/harness/mcp-result.js.map +1 -0
- package/dist/harness/mcp.d.ts +0 -19
- package/dist/harness/mcp.d.ts.map +1 -1
- package/dist/harness/mcp.js +7 -66
- package/dist/harness/mcp.js.map +1 -1
- package/dist/harness/models.d.ts +0 -19
- package/dist/harness/models.d.ts.map +1 -1
- package/dist/harness/models.js +0 -52
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/open-connector.d.ts +0 -12
- package/dist/harness/open-connector.d.ts.map +1 -1
- package/dist/harness/open-connector.js +0 -22
- package/dist/harness/open-connector.js.map +1 -1
- package/dist/harness/presenter.d.ts +1 -0
- package/dist/harness/presenter.d.ts.map +1 -1
- package/dist/harness/presenter.js +16 -66
- package/dist/harness/presenter.js.map +1 -1
- package/dist/harness/prompt.d.ts +0 -11
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +1 -18
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +8 -28
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session.d.ts +11 -28
- package/dist/harness/session.d.ts.map +1 -1
- package/dist/harness/session.js +100 -38
- package/dist/harness/session.js.map +1 -1
- package/dist/harness/skills.d.ts +0 -22
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +0 -20
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/subagent-profiles.d.ts +0 -4
- package/dist/harness/subagent-profiles.d.ts.map +1 -1
- package/dist/harness/subagent-profiles.js +0 -29
- package/dist/harness/subagent-profiles.js.map +1 -1
- package/dist/harness/subagent.d.ts +0 -25
- package/dist/harness/subagent.d.ts.map +1 -1
- package/dist/harness/subagent.js +1 -70
- package/dist/harness/subagent.js.map +1 -1
- package/dist/harness/tools/event.d.ts.map +1 -1
- package/dist/harness/tools/event.js +0 -9
- package/dist/harness/tools/event.js.map +1 -1
- package/dist/harness/tools/generate-image.d.ts +0 -6
- package/dist/harness/tools/generate-image.d.ts.map +1 -1
- package/dist/harness/tools/generate-image.js.map +1 -1
- package/dist/harness/tools/host-fn-tool.d.ts +0 -17
- package/dist/harness/tools/host-fn-tool.d.ts.map +1 -1
- package/dist/harness/tools/host-fn-tool.js +0 -16
- package/dist/harness/tools/host-fn-tool.js.map +1 -1
- package/dist/harness/tools/index.d.ts +1 -7
- package/dist/harness/tools/index.d.ts.map +1 -1
- package/dist/harness/tools/index.js +3 -14
- package/dist/harness/tools/index.js.map +1 -1
- package/dist/harness/tools/jev-browser.d.ts +4 -94
- package/dist/harness/tools/jev-browser.d.ts.map +1 -1
- package/dist/harness/tools/jev-browser.js +203 -92
- package/dist/harness/tools/jev-browser.js.map +1 -1
- package/dist/harness/tools/jev.d.ts +0 -8
- package/dist/harness/tools/jev.d.ts.map +1 -1
- package/dist/harness/tools/jev.js +0 -11
- package/dist/harness/tools/jev.js.map +1 -1
- package/dist/harness/tools/pi-tools.d.ts +1 -11
- package/dist/harness/tools/pi-tools.d.ts.map +1 -1
- package/dist/harness/tools/pi-tools.js +1 -30
- package/dist/harness/tools/pi-tools.js.map +1 -1
- package/dist/harness/tools/react.d.ts +0 -5
- package/dist/harness/tools/react.d.ts.map +1 -1
- package/dist/harness/tools/react.js +0 -5
- package/dist/harness/tools/react.js.map +1 -1
- package/dist/harness/tools/secret-redaction.d.ts +0 -25
- package/dist/harness/tools/secret-redaction.d.ts.map +1 -1
- package/dist/harness/tools/secret-redaction.js +3 -36
- package/dist/harness/tools/secret-redaction.js.map +1 -1
- package/dist/harness/tools/subagent.d.ts +0 -34
- package/dist/harness/tools/subagent.d.ts.map +1 -1
- package/dist/harness/tools/subagent.js +0 -92
- package/dist/harness/tools/subagent.js.map +1 -1
- package/dist/harness/tools/task.d.ts +0 -1
- package/dist/harness/tools/task.d.ts.map +1 -1
- package/dist/harness/tools/task.js +0 -1
- package/dist/harness/tools/task.js.map +1 -1
- package/dist/harness/tools/types.d.ts +0 -16
- package/dist/harness/tools/types.d.ts.map +1 -1
- package/dist/harness/tools/types.js.map +1 -1
- package/dist/harness/types.d.ts +1 -77
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +0 -13
- package/dist/log.js.map +1 -1
- package/dist/main.js +7 -52
- package/dist/main.js.map +1 -1
- package/dist/memory-capture/index.d.ts +16 -0
- package/dist/memory-capture/index.d.ts.map +1 -0
- package/dist/memory-capture/index.js +194 -0
- package/dist/memory-capture/index.js.map +1 -0
- package/dist/memory-capture/types.d.ts +27 -0
- package/dist/memory-capture/types.d.ts.map +1 -0
- package/dist/memory-capture/types.js.map +1 -0
- package/dist/observability/index.d.ts +0 -9
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +0 -9
- package/dist/observability/index.js.map +1 -1
- package/dist/observability/instrument.js +0 -5
- package/dist/observability/instrument.js.map +1 -1
- package/dist/observability/otel.js +0 -1
- package/dist/observability/otel.js.map +1 -1
- package/dist/observability/sentry.d.ts +0 -18
- package/dist/observability/sentry.d.ts.map +1 -1
- package/dist/observability/sentry.js +0 -36
- package/dist/observability/sentry.js.map +1 -1
- package/dist/observability/types.d.ts +1 -10
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/observability/types.js.map +1 -1
- package/dist/office/index.d.ts +0 -76
- package/dist/office/index.d.ts.map +1 -1
- package/dist/office/index.js +4 -154
- package/dist/office/index.js.map +1 -1
- package/dist/office/projection.d.ts +0 -29
- package/dist/office/projection.d.ts.map +1 -1
- package/dist/office/projection.js +5 -41
- package/dist/office/projection.js.map +1 -1
- package/dist/office/types.d.ts +0 -66
- package/dist/office/types.d.ts.map +1 -1
- package/dist/office/types.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +22 -83
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/session-lifecycle.d.ts +0 -10
- package/dist/runtime/session-lifecycle.d.ts.map +1 -1
- package/dist/runtime/session-lifecycle.js +0 -12
- package/dist/runtime/session-lifecycle.js.map +1 -1
- package/dist/runtime/types.d.ts +2 -29
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +2 -1
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +21 -15
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +0 -2
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/identity.d.ts +0 -28
- package/dist/sandbox/identity.d.ts.map +1 -1
- package/dist/sandbox/identity.js +0 -28
- package/dist/sandbox/identity.js.map +1 -1
- package/dist/sandbox/index.d.ts +0 -18
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +2 -19
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/layout.d.ts +7 -0
- package/dist/sandbox/layout.d.ts.map +1 -0
- package/dist/sandbox/layout.js +13 -0
- package/dist/sandbox/layout.js.map +1 -0
- package/dist/sandbox/provisioner.d.ts +24 -65
- package/dist/sandbox/provisioner.d.ts.map +1 -1
- package/dist/sandbox/provisioner.js +213 -125
- package/dist/sandbox/provisioner.js.map +1 -1
- package/dist/sandbox/types.d.ts +0 -39
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +2 -5
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +31 -31
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts +0 -6
- package/dist/sessions/chat-history-sync.d.ts.map +1 -1
- package/dist/sessions/chat-history-sync.js +1 -33
- package/dist/sessions/chat-history-sync.js.map +1 -1
- package/dist/sessions/history-line.d.ts +0 -20
- package/dist/sessions/history-line.d.ts.map +1 -1
- package/dist/sessions/history-line.js +0 -20
- package/dist/sessions/history-line.js.map +1 -1
- package/dist/sessions/migrate-common.d.ts +0 -15
- package/dist/sessions/migrate-common.d.ts.map +1 -1
- package/dist/sessions/migrate-common.js +0 -19
- package/dist/sessions/migrate-common.js.map +1 -1
- package/dist/sessions/migrate-pi-084.d.ts.map +1 -1
- package/dist/sessions/migrate-pi-084.js +0 -7
- package/dist/sessions/migrate-pi-084.js.map +1 -1
- package/dist/sessions/migrate-v3.d.ts +0 -7
- package/dist/sessions/migrate-v3.d.ts.map +1 -1
- package/dist/sessions/migrate-v3.js +1 -67
- package/dist/sessions/migrate-v3.js.map +1 -1
- package/dist/sessions/session-key.d.ts +3 -17
- package/dist/sessions/session-key.d.ts.map +1 -1
- package/dist/sessions/session-key.js +8 -35
- package/dist/sessions/session-key.js.map +1 -1
- package/dist/sessions/session-store.d.ts +1 -7
- package/dist/sessions/session-store.d.ts.map +1 -1
- package/dist/sessions/session-store.js +8 -50
- package/dist/sessions/session-store.js.map +1 -1
- package/dist/sessions/store.d.ts +0 -60
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +0 -113
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +0 -17
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/settings/apply.d.ts +0 -6
- package/dist/settings/apply.d.ts.map +1 -1
- package/dist/settings/apply.js +0 -29
- package/dist/settings/apply.js.map +1 -1
- package/dist/settings/index.d.ts +0 -53
- package/dist/settings/index.d.ts.map +1 -1
- package/dist/settings/index.js +0 -77
- package/dist/settings/index.js.map +1 -1
- package/dist/settings/migrate.d.ts +0 -5
- package/dist/settings/migrate.d.ts.map +1 -1
- package/dist/settings/migrate.js +0 -17
- package/dist/settings/migrate.js.map +1 -1
- package/dist/types.d.ts +9 -159
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.d.ts +2 -36
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +135 -65
- package/dist/vault/index.js.map +1 -1
- package/dist/vault/types.d.ts +0 -15
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/types.js.map +1 -1
- package/package.json +1 -1
- package/dist/dream/index.d.ts +0 -20
- package/dist/dream/index.d.ts.map +0 -1
- package/dist/dream/index.js +0 -264
- package/dist/dream/index.js.map +0 -1
- package/dist/dream/types.d.ts +0 -30
- package/dist/dream/types.d.ts.map +0 -1
- package/dist/dream/types.js.map +0 -1
- /package/dist/{dream → memory-capture}/types.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../../../src/adapters/web/admin/portal.ts"],"names":[],"mappings":"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","sourcesContent":["import { validateEventFilename } from \"../../../events/index.js\";\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { basename, join, resolve as pathResolve, sep as pathSep } from \"node:path\";\nimport { atomicWritePrivateFile } from \"../../../file-guards.js\";\nimport { MikanModels, parseFrontmatter, validateSkill } from \"../../../harness/index.js\";\nimport { SessionStore } from \"../../../sessions/session-store.js\";\nimport type { EventStore } from \"../../../events/index.js\";\nimport type { PlatformName } from \"../../index.js\";\nimport { InMemoryTokenStore } from \"../token-store.js\";\nimport type { AdminToken } from \"./types.js\";\nexport type { AdminToken } from \"./types.js\";\n\nconst ADMIN_TOKEN_TTL_MS = 30 * 60 * 1000;\n\nexport class InMemoryAdminTokenStore extends InMemoryTokenStore<AdminToken> {\n create(args: {\n platform: PlatformName;\n platformUserId: string;\n conversationId: string;\n platformUserName?: string;\n }): AdminToken {\n this.deleteWhere(\n (token) => token.platform === args.platform && token.platformUserId === args.platformUserId,\n );\n return this.createRecord(ADMIN_TOKEN_TTL_MS, {\n platform: args.platform,\n platformUserId: args.platformUserId,\n ...(args.platformUserName ? { platformUserName: args.platformUserName } : {}),\n conversationId: args.conversationId,\n });\n }\n}\n\nimport {\n loadOfficeVisibilityOverride,\n loadGlobalSettings,\n loadScopeMcpServers,\n resolveConversationSettings,\n type AgentConfig,\n type SandboxSettings,\n} from \"../../../settings/index.js\";\nimport { findMcpPreset, listMcpPresets, materializeMcpPreset } from \"../../../harness/mcp.js\";\nimport { loadMcpTools } from \"../../../harness/mcp.js\";\nimport {\n isValidMcpServerName,\n parseStandardMcpServers,\n redactMcpUrl,\n} from \"../../../harness/mcp.js\";\nimport type { McpServerConfig } from \"../../../harness/types.js\";\nimport {\n applyConversationSettings,\n applyOfficeVisibility,\n applyGlobalSettings,\n} from \"../../../settings/apply.js\";\nimport {\n escapeHtml,\n jsonResponse as jsonRes,\n readJsonBody,\n renderPortalShell,\n} from \"../portal-shell.js\";\nimport { resolveExistingSessionFile } from \"../session-view/portal.js\";\nimport { PRODUCT_NAME } from \"../../messages.js\";\nimport { credentialAuthorizationKey } from \"../../../sandbox/identity.js\";\nimport { resolveWorkspaceProjection } from \"../../../office/projection.js\";\nimport { sharedVaultKey } from \"../../../vault/index.js\";\nimport { modelKey, resolveAdminModelAccessStatuses } from \"./provider-models.js\";\n\nexport type { AdminRuntimeBridge, AdminServices, EventSummary } from \"./types.js\";\nimport type { AdminServices, EventSummary } from \"./types.js\";\nimport type { OfficeAddress } from \"../../index.js\";\nimport {\n assertPlatformName,\n createOfficeAddress,\n listRegisteredOffices,\n sameOffice,\n type Office,\n type Workspace,\n} from \"../../../office/index.js\";\n\n// ── Handler ────────────────────────────────────────────────────────────────────\n\nexport async function handleAdminRequest(\n req: IncomingMessage,\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<boolean> {\n if (!url.pathname.startsWith(\"/admin\")) return false;\n\n if (req.method === \"GET\" && url.pathname === \"/admin\") {\n const provided = url.searchParams.get(\"token\") ?? \"\";\n const token = services.adminTokenStore.peek(provided);\n if (!token) {\n res.writeHead(403, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderAdminErrorPage(\n \"Admin link is missing, invalid, or expired. Send `/admin` to the bot to get a fresh link.\",\n ),\n );\n return true;\n }\n res.writeHead(200, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n });\n res.end(renderAdminPage(token));\n return true;\n }\n\n if (url.pathname.startsWith(\"/admin/api/\")) {\n await routeApiRequest(req, res, url, services);\n return true;\n }\n\n return false;\n}\n\n// ── API routing ────────────────────────────────────────────────────────────────\n\nasync function routeApiRequest(\n req: IncomingMessage,\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<void> {\n if (req.method === \"GET\") {\n await routeGetApiRequest(res, url, services);\n return;\n }\n if (req.method !== \"POST\") {\n jsonRes(res, 405, { error: \"Method not allowed\" });\n return;\n }\n await routePostApiRequest(req, res, url, services);\n}\n\nasync function routeGetApiRequest(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<void> {\n const token = services.adminTokenStore.peek(url.searchParams.get(\"token\") ?? \"\");\n if (!token) {\n jsonRes(res, 403, { error: \"Unauthorized\" });\n return;\n }\n switch (url.pathname) {\n case \"/admin/api/conversations\":\n return serveConversationsList(res, services);\n case \"/admin/api/session-usage\":\n return serveSessionUsage(res, services);\n case \"/admin/api/conversation-usage\":\n return serveConversationUsage(res, url, services);\n case \"/admin/api/conversation-state\":\n return serveConversationState(res, url, services, token);\n case \"/admin/api/settings/global\":\n return serveGlobalSettings(res);\n case \"/admin/api/models\":\n return serveModelsList(res);\n case \"/admin/api/workspace/tree\":\n return serveWorkspaceTree(res, url, services, token);\n case \"/admin/api/workspace/file\":\n return serveWorkspaceFile(res, url, services, token);\n case \"/admin/api/skills\":\n return serveSkillsList(res, url, services, token);\n case \"/admin/api/skills/file\":\n return serveSkillFile(res, url, services, token);\n case \"/admin/api/mcp-servers\":\n return serveMcpServersList(res, url, services, token);\n case \"/admin/api/events\":\n return serveEventsList(res, services);\n case \"/admin/api/conversations/events\":\n return serveConversationEventsList(res, url, services, token);\n default:\n jsonRes(res, 404, { error: \"Not found\" });\n }\n}\n\nasync function routePostApiRequest(\n req: IncomingMessage,\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<void> {\n const bodyLimit = url.pathname === \"/admin/api/skills/mutate\" ? 256 * 1024 : 32 * 1024;\n const body = await readJsonBody(req, res, bodyLimit);\n if (!body) return;\n const token = services.adminTokenStore.peek(typeof body.token === \"string\" ? body.token : \"\");\n if (!token) {\n jsonRes(res, 403, { error: \"Unauthorized\" });\n return;\n }\n switch (url.pathname) {\n case \"/admin/api/conversations/model\":\n return serveConversationModelUpdate(res, body, services, token);\n case \"/admin/api/conversations/visibility\":\n return serveConversationVisibilityUpdate(res, body, services, token);\n case \"/admin/api/conversations/slack\":\n return serveConversationSlackUpdate(res, body, services, token);\n case \"/admin/api/conversations/session-link\":\n return serveConversationSessionLink(res, body, services, token);\n case \"/admin/api/conversations/login-link\":\n return serveConversationLoginLink(res, body, services, token);\n case \"/admin/api/conversations/events/delete\":\n return serveConversationEventDelete(res, body, services, token);\n case \"/admin/api/mcp-servers/mutate\":\n return serveMcpServerMutation(res, body, services, token);\n case \"/admin/api/skills/mutate\":\n return serveSkillMutation(res, body, services, token);\n case \"/admin/api/settings/model\":\n return serveGlobalModelUpdate(res, body, services);\n case \"/admin/api/settings/sandbox\":\n return serveGlobalSandboxUpdate(res, body, services);\n case \"/admin/api/settings/slack\":\n return serveGlobalSlackUpdate(res, body, services);\n default:\n jsonRes(res, 404, { error: \"Not found\" });\n }\n}\n\n// ── Scope helpers ──────────────────────────────────────────────────────────────\n\ninterface AdminConversationScope {\n address: OfficeAddress;\n conversationId: string;\n error?: string;\n}\n\n/**\n * Admin scope is a full office address. The platform defaults to the token's\n * (an admin invoked from Slack browses Slack offices); cross-platform targets\n * name theirs explicitly. Identity validation is the address factory's.\n */\nexport function resolveConversationScope(\n requestedId: string,\n requestedPlatform: string,\n token: AdminToken,\n): AdminConversationScope {\n const fallback = createOfficeAddress(token.platform, token.conversationId);\n try {\n const address = createOfficeAddress(\n requestedPlatform ? assertPlatformName(requestedPlatform) : token.platform,\n requestedId || token.conversationId,\n );\n return { address, conversationId: address.conversationId };\n } catch {\n return {\n address: fallback,\n conversationId: fallback.conversationId,\n error: \"Invalid conversation scope.\",\n };\n }\n}\n\nfunction resolveTargetConversation(\n body: Record<string, unknown>,\n token: AdminToken,\n): AdminConversationScope {\n const requested = typeof body.conversationId === \"string\" ? body.conversationId.trim() : \"\";\n const platform = typeof body.platform === \"string\" ? body.platform.trim() : \"\";\n return resolveConversationScope(requested, platform, token);\n}\n\nfunction requireAdminWorkspace(res: ServerResponse, services: AdminServices): Workspace | null {\n if (!services.workspace) {\n jsonRes(res, 503, { error: \"Working directory not available\" });\n return null;\n }\n return services.workspace;\n}\n\nfunction requireConversationWorkspace(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): { scope: AdminConversationScope; workspace: Workspace } | undefined {\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return undefined;\n }\n const workspace = requireAdminWorkspace(res, services);\n return workspace ? { scope, workspace } : undefined;\n}\n\n// ── API handlers ───────────────────────────────────────────────────────────────\n\n/**\n * Office directories are office-key named and not reversible to raw ids, so\n * enumeration reads the office registry — the durable raw-id ↔ office\n * mapping — instead of scanning the workspace. Offices whose directory\n * disappeared are filtered out.\n */\nfunction listAdminOffices(workspace: Workspace): OfficeAddress[] {\n return listRegisteredOffices(workspace.stateDir)\n .filter((office) => existsSync(workspace.office(office).dir))\n .map((office) => createOfficeAddress(office.platform, office.conversationId))\n .toSorted(\n (a, b) =>\n a.platform.localeCompare(b.platform) || a.conversationId.localeCompare(b.conversationId),\n );\n}\n\nfunction conversationLastActivity(workspace: Workspace, office: OfficeAddress): number | null {\n const dir = workspace.office(office).dir;\n if (!existsSync(dir)) return null;\n let latest = 0;\n const visit = (path: string, depth: number): void => {\n if (depth > 3) return;\n let entries;\n try {\n entries = readdirSync(path, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const full = join(path, entry.name);\n if (entry.isDirectory()) {\n visit(full, depth + 1);\n continue;\n }\n try {\n const stats = statSync(full);\n if (stats.mtimeMs > latest) latest = stats.mtimeMs;\n } catch {\n // ignore\n }\n }\n };\n visit(dir, 0);\n return latest > 0 ? latest : null;\n}\n\nfunction conversationDisplayLabel(services: AdminServices, office: OfficeAddress): string {\n const bot = services.botsByPlatform?.[office.platform];\n const channel = bot?.getMessagingInfo().channels.find((c) => c.id === office.conversationId);\n if (channel) return `${office.platform}:#${channel.name}:${office.conversationId}`;\n return `${office.platform}:${office.conversationId}`;\n}\n\nfunction serveConversationsList(res: ServerResponse, services: AdminServices): void {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const running = services.runtime?.getRunningSessions() ?? [];\n\n const conversations = listAdminOffices(workspace).map((office) => ({\n platform: office.platform,\n conversationId: office.conversationId,\n label: conversationDisplayLabel(services, office),\n running: running.some((session) => sameOffice(session.address, office)),\n lastActivityAt: conversationLastActivity(workspace, office),\n }));\n\n jsonRes(res, 200, { conversations });\n}\n\ninterface SessionUsageRow {\n conversationId: string;\n label: string;\n fileName: string;\n sessionId: string;\n updatedAt: string;\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n total: number;\n cost: number;\n}\n\nasync function serveSessionUsage(res: ServerResponse, services: AdminServices): Promise<void> {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const usageLists: SessionUsageRow[][] = [];\n for (const office of listAdminOffices(workspace)) {\n usageLists.push(\n await listConversationSessionUsage(\n workspace,\n office,\n conversationDisplayLabel(services, office),\n ),\n );\n }\n const rows = usageLists\n .flat()\n .toSorted((a, b) => b.total - a.total)\n .slice(0, 20);\n\n jsonRes(res, 200, { sessions: rows });\n}\n\nasync function listConversationSessionUsage(\n workspace: Workspace,\n office: OfficeAddress,\n label: string,\n): Promise<SessionUsageRow[]> {\n const sessionDir = workspace.office(office).sessionsDir;\n let files: string[];\n try {\n files = readdirSync(sessionDir, { withFileTypes: true })\n .filter((entry) => entry.isFile() && entry.name.endsWith(\".jsonl\"))\n .map((entry) => entry.name);\n } catch {\n return [];\n }\n const rows: SessionUsageRow[] = [];\n for (const name of files) {\n rows.push(...(await readSessionUsage(join(sessionDir, name), office.conversationId, label)));\n }\n return rows;\n}\n\nasync function readSessionUsage(\n sessionFile: string,\n conversationId: string,\n label: string,\n): Promise<SessionUsageRow[]> {\n try {\n const manager = await SessionStore.inspect(sessionFile);\n const header = manager.getHeader();\n\n const entries = await manager.getEntries();\n const usage = entries.reduce(\n (sum, entry) => {\n if (entry.type !== \"message\" || entry.message.role !== \"assistant\") return sum;\n const message = entry.message as unknown as AssistantUsageMessage;\n const item = message.usage;\n if (!item) return sum;\n sum.input += numberOrZero(item.input);\n sum.output += numberOrZero(item.output);\n sum.cacheRead += numberOrZero(item.cacheRead);\n sum.cacheWrite += numberOrZero(item.cacheWrite);\n sum.cost += numberOrZero(item.cost?.total);\n return sum;\n },\n { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 },\n );\n const total = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;\n if (total <= 0) return [];\n\n return [\n {\n conversationId,\n label,\n fileName: basename(sessionFile),\n sessionId: header.id,\n updatedAt:\n entries.length > 0 ? new Date(entries.at(-1)!.timestamp).toISOString() : header.timestamp,\n ...usage,\n total,\n },\n ];\n } catch {\n return [];\n }\n}\n\ninterface AssistantUsageMessage {\n usage?: {\n input?: unknown;\n output?: unknown;\n cacheRead?: unknown;\n cacheWrite?: unknown;\n cost?: { total?: unknown };\n };\n}\n\nfunction numberOrZero(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\ninterface UsageBucket {\n date: string;\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n total: number;\n cost: number;\n}\n\nfunction localDayKey(d: Date): string {\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\nfunction emptyBucket(date: string): UsageBucket {\n return { date, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0, cost: 0 };\n}\n\n/** Per-conversation daily token usage over the last N days (N clamped to 1..7). */\nasync function serveConversationUsage(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<void> {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const conversationId = (url.searchParams.get(\"conversationId\") ?? \"\").trim();\n const platformParam = (url.searchParams.get(\"platform\") ?? \"\").trim();\n const office = listAdminOffices(workspace).find(\n (candidate) =>\n candidate.conversationId === conversationId &&\n (!platformParam || candidate.platform === platformParam),\n );\n if (!office) {\n jsonRes(res, 400, { error: \"Unknown conversationId\" });\n return;\n }\n\n const days = 14;\n\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n const buckets = new Map<string, UsageBucket>();\n const order: string[] = [];\n for (let i = days - 1; i >= 0; i--) {\n const d = new Date(today);\n d.setDate(today.getDate() - i);\n const key = localDayKey(d);\n order.push(key);\n buckets.set(key, emptyBucket(key));\n }\n const cutoff = new Date(today);\n cutoff.setDate(today.getDate() - (days - 1));\n\n const flags = { hasOlder: false };\n const sessionDir = workspace.office(office).sessionsDir;\n try {\n for (const entry of readdirSync(sessionDir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) continue;\n await accumulateSessionUsageByDay(join(sessionDir, entry.name), cutoff, buckets, flags);\n }\n } catch {\n // No sessions directory yet — return empty buckets.\n }\n\n const series = order.map((key) => buckets.get(key) ?? emptyBucket(key));\n const totals = series.reduce((sum, b) => {\n sum.input += b.input;\n sum.output += b.output;\n sum.cacheRead += b.cacheRead;\n sum.cacheWrite += b.cacheWrite;\n sum.total += b.total;\n sum.cost += b.cost;\n return sum;\n }, emptyBucket(\"\"));\n\n jsonRes(res, 200, {\n platform: office.platform,\n conversationId,\n label: conversationDisplayLabel(services, office),\n days,\n hasOlder: flags.hasOlder,\n buckets: series,\n totals: {\n input: totals.input,\n output: totals.output,\n cacheRead: totals.cacheRead,\n cacheWrite: totals.cacheWrite,\n total: totals.total,\n cost: totals.cost,\n },\n });\n}\n\nasync function accumulateSessionUsageByDay(\n sessionFile: string,\n cutoff: Date,\n buckets: Map<string, UsageBucket>,\n flags: { hasOlder: boolean },\n): Promise<void> {\n try {\n const manager = await SessionStore.inspect(sessionFile);\n\n for (const entry of await manager.getEntries()) {\n if (entry.type !== \"message\" || entry.message.role !== \"assistant\") continue;\n const usage = (entry.message as unknown as AssistantUsageMessage).usage;\n if (!usage || !entry.timestamp) continue;\n\n const when = new Date(entry.timestamp);\n if (Number.isNaN(when.getTime())) continue;\n if (when < cutoff) {\n flags.hasOlder = true;\n continue;\n }\n\n const bucket = buckets.get(localDayKey(when));\n if (!bucket) continue;\n\n const input = numberOrZero(usage.input);\n const output = numberOrZero(usage.output);\n const cacheRead = numberOrZero(usage.cacheRead);\n const cacheWrite = numberOrZero(usage.cacheWrite);\n bucket.input += input;\n bucket.output += output;\n bucket.cacheRead += cacheRead;\n bucket.cacheWrite += cacheWrite;\n bucket.total += input + output + cacheRead + cacheWrite;\n bucket.cost += numberOrZero(usage.cost?.total);\n }\n } catch {\n // Skip unreadable session files.\n }\n}\n\nfunction serveConversationState(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 400, { error: scope.error });\n return;\n }\n const conversationId = scope.conversationId;\n\n const office = workspace.office(scope.address);\n const globalConfig = loadGlobalSettings();\n const conversationConfig = resolveConversationSettings(office);\n const conversationWorkspace = resolveWorkspaceProjection(office);\n\n jsonRes(res, 200, {\n conversationId,\n provider: conversationConfig.provider,\n model: conversationConfig.model,\n thinkingLevel: conversationConfig.thinkingLevel,\n globalProvider: globalConfig.provider,\n globalModel: globalConfig.model,\n globalThinkingLevel: globalConfig.thinkingLevel,\n officeVisibility: conversationWorkspace.visibility,\n officeVisibilitySource: conversationWorkspace.source,\n officeVisibilityOverride: loadOfficeVisibilityOverride(office),\n slack: {\n replyMode:\n conversationConfig.slack?.replyMode ?? globalConfig.slack?.replyMode ?? \"top-level\",\n globalReplyMode: globalConfig.slack?.replyMode ?? \"top-level\",\n },\n });\n}\n\nfunction serveGlobalSettings(res: ServerResponse): void {\n try {\n const config = loadGlobalSettings();\n jsonRes(res, 200, {\n provider: config.provider,\n model: config.model,\n thinkingLevel: config.thinkingLevel,\n sandboxCpus: config.sandbox?.cpus ?? null,\n sandboxMemory: config.sandbox?.memory ?? null,\n sandboxBoostCpus: config.sandbox?.boost?.cpus ?? null,\n sandboxBoostMemory: config.sandbox?.boost?.memory ?? null,\n defaultSharedVault: config.sandbox?.defaultSharedVault ?? null,\n slack: {\n replyMode: config.slack?.replyMode ?? \"top-level\",\n },\n });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nasync function serveModelsList(res: ServerResponse): Promise<void> {\n try {\n const registry = MikanModels.create();\n const availableModels = await registry.getAvailable();\n const statuses = await resolveAdminModelAccessStatuses(registry, availableModels);\n const models = availableModels.map((model) => ({\n provider: model.provider,\n id: model.id,\n name: model.name ?? model.id,\n reasoning: model.reasoning,\n input: model.input,\n contextWindow: model.contextWindow,\n maxTokens: model.maxTokens,\n status: statuses.get(modelKey(model.provider, model.id))?.status ?? \"available\",\n }));\n jsonRes(res, 200, { models });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nconst VALID_THINKING_LEVELS = new Set([\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"]);\n\nfunction serveConversationModelUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const provider = typeof body.provider === \"string\" ? body.provider.trim() : \"\";\n const model = typeof body.model === \"string\" ? body.model.trim() : \"\";\n const thinkingLevel =\n typeof body.thinkingLevel === \"string\" && VALID_THINKING_LEVELS.has(body.thinkingLevel)\n ? (body.thinkingLevel as AgentConfig[\"thinkingLevel\"])\n : undefined;\n\n if (!provider || !model) {\n jsonRes(res, 400, { error: \"Missing provider or model\" });\n return;\n }\n const target = requireConversationWorkspace(res, body, services, token);\n if (!target) return;\n const { scope, workspace } = target;\n\n try {\n const result = applyConversationSettings(services.runtime, workspace.office(scope.address), {\n provider,\n model,\n ...(thinkingLevel ? { thinkingLevel } : {}),\n });\n if (!result.ok) {\n jsonRes(res, 409, {\n error: \"Conversation has a running job; retry after it finishes (or /stop it).\",\n });\n return;\n }\n jsonRes(res, 200, { ok: true, runtimeSwitched: result.runtimeSwitched });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nfunction serveConversationVisibilityUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n if (body.visibility !== \"private\" && body.visibility !== \"default\") {\n jsonRes(res, 400, { error: \"visibility must be 'private' or 'default'\" });\n return;\n }\n const target = requireConversationWorkspace(res, body, services, token);\n if (!target) return;\n const { scope, workspace } = target;\n try {\n const result = applyOfficeVisibility(\n services.runtime,\n workspace.office(scope.address),\n body.visibility === \"private\" ? \"private\" : null,\n );\n if (!result.ok) {\n jsonRes(res, 409, { error: \"Conversation is busy; retry when the current run finishes\" });\n return;\n }\n jsonRes(res, 200, { ok: true });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nfunction serveConversationSlackUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const replyMode = body.replyMode;\n if (replyMode !== \"top-level\" && replyMode !== \"thread\") {\n jsonRes(res, 400, { error: \"replyMode must be 'top-level' or 'thread'\" });\n return;\n }\n const target = requireConversationWorkspace(res, body, services, token);\n if (!target) return;\n const { scope, workspace } = target;\n respondWithSettingsUpdate(res, () => {\n applyConversationSettings(services.runtime, workspace.office(scope.address), {\n slack: { replyMode },\n });\n return { ok: true };\n });\n}\n\nfunction serveConversationSessionLink(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const target = requireConversationWorkspace(res, body, services, token);\n if (!target) return;\n const { scope, workspace } = target;\n if (!services.sessionViewTokenStore) {\n jsonRes(res, 503, { error: \"Session view token store not available\" });\n return;\n }\n if (!services.portalBaseUrl) {\n jsonRes(res, 503, {\n error: \"Portal URL not configured. Set MIKAN_LINK_URL to enable link generation.\",\n });\n return;\n }\n\n const sessionFile = resolveExistingSessionFile(\n workspace.office(scope.address).dir,\n scope.conversationId,\n );\n if (!sessionFile) {\n jsonRes(res, 404, { error: \"No session file found for this conversation\" });\n return;\n }\n\n try {\n const { token: viewToken } = services.sessionViewTokenStore.create({\n platform: token.platform,\n platformUserId: token.platformUserId,\n conversationId: scope.conversationId,\n sessionKey: scope.conversationId,\n sessionFile,\n platformUserName: token.platformUserName,\n });\n const url = `${services.portalBaseUrl}/session?token=${encodeURIComponent(viewToken)}`;\n jsonRes(res, 200, { ok: true, url });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nfunction serveConversationLoginLink(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n if (!services.portalBaseUrl) {\n jsonRes(res, 503, { error: \"Portal URL not configured.\" });\n return;\n }\n if (!services.sandbox) {\n jsonRes(res, 503, { error: \"Sandbox config not available.\" });\n return;\n }\n const sharedName = typeof body.sharedVault === \"string\" ? body.sharedVault.trim() : \"\";\n let vaultId: string;\n if (sharedName) {\n const key = sharedVaultKey(sharedName);\n if (!key) {\n jsonRes(res, 400, { error: \"Invalid shared vault name\" });\n return;\n }\n vaultId = key;\n } else {\n try {\n vaultId = credentialAuthorizationKey(services.sandbox, {\n userId: token.platformUserId,\n address: scope.address,\n });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n return;\n }\n }\n try {\n const { token: linkToken } = services.linkTokenStore.create(\n token.platform,\n token.platformUserId,\n scope.conversationId,\n vaultId,\n \"\",\n );\n const url = `${services.portalBaseUrl}/link?token=${encodeURIComponent(linkToken)}`;\n jsonRes(res, 200, { ok: true, url, vaultId });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nfunction serveGlobalModelUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n): void {\n const provider = typeof body.provider === \"string\" ? body.provider.trim() : \"\";\n const model = typeof body.model === \"string\" ? body.model.trim() : \"\";\n const thinkingLevel =\n typeof body.thinkingLevel === \"string\" && VALID_THINKING_LEVELS.has(body.thinkingLevel)\n ? (body.thinkingLevel as AgentConfig[\"thinkingLevel\"])\n : undefined;\n\n if (!provider || !model) {\n jsonRes(res, 400, { error: \"Missing provider or model\" });\n return;\n }\n\n respondWithSettingsUpdate(res, () => {\n const result = applyGlobalSettings(services.runtime, {\n provider,\n model,\n ...(thinkingLevel ? { thinkingLevel } : {}),\n });\n return {\n ok: true,\n staleConversations: result.staleConversations.map(\n (office) => `${office.platform}:${office.conversationId}`,\n ),\n };\n });\n}\n\nfunction serveGlobalSlackUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n): void {\n const replyMode = body.replyMode;\n if (replyMode !== \"top-level\" && replyMode !== \"thread\") {\n jsonRes(res, 400, { error: \"replyMode must be 'top-level' or 'thread'\" });\n return;\n }\n\n respondWithSettingsUpdate(res, () => {\n applyGlobalSettings(services.runtime, { slack: { replyMode } });\n return { ok: true };\n });\n}\n\nfunction serveGlobalSandboxUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n): void {\n const cpus = typeof body.cpus === \"string\" ? body.cpus.trim() : \"\";\n const memory = typeof body.memory === \"string\" ? body.memory.trim() : \"\";\n const boostCpus = typeof body.boostCpus === \"string\" ? body.boostCpus.trim() : \"\";\n const boostMemory = typeof body.boostMemory === \"string\" ? body.boostMemory.trim() : \"\";\n const update: SandboxSettings = {\n ...(cpus ? { cpus } : {}),\n ...(memory ? { memory } : {}),\n ...(boostCpus || boostMemory\n ? {\n boost: {\n ...(boostCpus ? { cpus: boostCpus } : {}),\n ...(boostMemory ? { memory: boostMemory } : {}),\n },\n }\n : {}),\n };\n\n if (Object.keys(update).length === 0) {\n jsonRes(res, 400, { error: \"No valid sandbox fields provided\" });\n return;\n }\n\n respondWithSettingsUpdate(res, () => {\n applyGlobalSettings(services.runtime, { sandbox: update });\n return { ok: true };\n });\n}\n\nfunction respondWithSettingsUpdate(res: ServerResponse, update: () => object): void {\n try {\n jsonRes(res, 200, update());\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\n// ── Workspace ──────────────────────────────────────────────────────────────────\n\nconst WORKSPACE_TREE_MAX_DEPTH = 4;\nconst WORKSPACE_TREE_MAX_ENTRIES = 800;\nconst PREVIEW_FILE_MAX_BYTES = 256 * 1024;\n\nconst WORKSPACE_TOP_DIRS = new Set([\"scratch\"]);\n\n/**\n * Limit what the admin UI can browse under a conversation directory.\n * Allowed: top-level \"scratch/\" subtree.\n */\nfunction isWorkspacePathAllowed(rel: string): boolean {\n if (rel === \"\") return true;\n const first = rel.split(\"/\").find(Boolean);\n if (first === undefined) return true;\n return WORKSPACE_TOP_DIRS.has(first);\n}\n\nfunction resolveConversationFromQuery(url: URL, token: AdminToken): AdminConversationScope {\n const requested = (url.searchParams.get(\"conversationId\") ?? \"\").trim();\n const platform = (url.searchParams.get(\"platform\") ?? \"\").trim();\n return resolveConversationScope(requested, platform, token);\n}\n\ninterface SafePathResult {\n absolute: string;\n error?: string;\n}\n\nfunction safeJoinUnderRoot(rootDir: string, relative: string): SafePathResult {\n if (relative.startsWith(\"/\") || relative.includes(\"\\0\")) {\n return { absolute: \"\", error: \"Invalid path\" };\n }\n if (relative.split(/[\\\\/]+/).some((part) => part === \"..\" || part === \"\")) {\n if (relative !== \"\") return { absolute: \"\", error: \"Invalid path\" };\n }\n const target = pathResolve(rootDir, relative);\n const rootAbs = pathResolve(rootDir);\n if (target !== rootAbs && !target.startsWith(rootAbs + pathSep)) {\n return { absolute: \"\", error: \"Path escapes conversation directory\" };\n }\n return { absolute: target };\n}\n\ninterface TreeNode {\n name: string;\n path: string;\n type: \"dir\" | \"file\";\n size?: number;\n mtimeMs?: number;\n children?: TreeNode[];\n truncated?: boolean;\n}\n\nfunction buildTree(startDir: string, relPrefix: string): TreeNode | null {\n let counter = { value: 0 };\n const walk = (dir: string, rel: string, depth: number): TreeNode | null => {\n if (counter.value >= WORKSPACE_TREE_MAX_ENTRIES) return null;\n let stats;\n try {\n stats = statSync(dir);\n } catch {\n return null;\n }\n const name = rel === \"\" ? \".\" : basename(rel);\n if (!stats.isDirectory()) {\n counter.value += 1;\n return {\n name,\n path: rel,\n type: \"file\",\n size: stats.size,\n mtimeMs: stats.mtimeMs,\n };\n }\n counter.value += 1;\n if (depth >= WORKSPACE_TREE_MAX_DEPTH) {\n return { name, path: rel, type: \"dir\", truncated: true };\n }\n let entries;\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return { name, path: rel, type: \"dir\" };\n }\n const children: TreeNode[] = [];\n let truncated = false;\n for (const entry of entries.toSorted((a, b) => {\n if (a.isDirectory() !== b.isDirectory()) return a.isDirectory() ? -1 : 1;\n return a.name.localeCompare(b.name);\n })) {\n const childRel = rel === \"\" ? entry.name : `${rel}/${entry.name}`;\n if (!isWorkspacePathAllowed(childRel)) continue;\n if (counter.value >= WORKSPACE_TREE_MAX_ENTRIES) {\n truncated = true;\n break;\n }\n const node = walk(join(dir, entry.name), childRel, depth + 1);\n if (node) children.push(node);\n }\n return {\n name,\n path: rel,\n type: \"dir\",\n children,\n ...(truncated ? { truncated: true } : {}),\n };\n };\n const node = walk(startDir, relPrefix, 0);\n return node;\n}\n\nfunction serveWorkspaceTree(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const convDir = workspace.office(scope.address).dir;\n if (!existsSync(convDir)) {\n jsonRes(res, 200, { conversationId: scope.conversationId, tree: null });\n return;\n }\n const requestedSub = (url.searchParams.get(\"path\") ?? \"\").trim();\n if (!isWorkspacePathAllowed(requestedSub)) {\n jsonRes(res, 403, { error: \"Workspace path is not exposed\" });\n return;\n }\n const startSafe = safeJoinUnderRoot(convDir, requestedSub);\n if (startSafe.error) {\n jsonRes(res, 400, { error: startSafe.error });\n return;\n }\n const tree = buildTree(startSafe.absolute, requestedSub);\n jsonRes(res, 200, {\n conversationId: scope.conversationId,\n root: requestedSub || \".\",\n tree,\n });\n}\n\nconst BINARY_PROBE_BYTES = 4096;\n\nfunction looksTextual(buf: Buffer): boolean {\n const limit = Math.min(buf.length, BINARY_PROBE_BYTES);\n for (let i = 0; i < limit; i++) {\n const byte = buf[i];\n if (byte === undefined || byte === 0) return false;\n if (byte < 9) return false;\n if (byte === 11 || byte === 12) return false;\n if (byte > 13 && byte < 32) return false;\n }\n return true;\n}\n\nfunction servePreviewFile(\n res: ServerResponse,\n absolutePath: string,\n metadata: Record<string, unknown>,\n notFoundMessage: string,\n): void {\n let stats;\n try {\n stats = statSync(absolutePath);\n } catch {\n jsonRes(res, 404, { error: notFoundMessage });\n return;\n }\n if (!stats.isFile()) {\n jsonRes(res, 400, { error: \"Not a file\" });\n return;\n }\n if (stats.size > PREVIEW_FILE_MAX_BYTES) {\n jsonRes(res, 413, {\n error: \"File too large to preview\",\n size: stats.size,\n limit: PREVIEW_FILE_MAX_BYTES,\n });\n return;\n }\n let buf: Buffer;\n try {\n buf = readFileSync(absolutePath);\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n return;\n }\n if (!looksTextual(buf)) {\n jsonRes(res, 200, {\n ...metadata,\n size: stats.size,\n mtimeMs: stats.mtimeMs,\n binary: true,\n content: null,\n });\n return;\n }\n jsonRes(res, 200, {\n ...metadata,\n size: stats.size,\n mtimeMs: stats.mtimeMs,\n binary: false,\n content: buf.toString(\"utf-8\"),\n });\n}\n\nfunction serveWorkspaceFile(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const requestedPath = (url.searchParams.get(\"path\") ?? \"\").trim();\n if (!requestedPath) {\n jsonRes(res, 400, { error: \"Missing path\" });\n return;\n }\n if (!isWorkspacePathAllowed(requestedPath)) {\n jsonRes(res, 403, { error: \"Workspace path is not exposed\" });\n return;\n }\n const convDir = workspace.office(scope.address).dir;\n const safe = safeJoinUnderRoot(convDir, requestedPath);\n if (safe.error) {\n jsonRes(res, 400, { error: safe.error });\n return;\n }\n servePreviewFile(res, safe.absolute, { path: requestedPath }, \"File not found\");\n}\n\n// ── Skills ─────────────────────────────────────────────────────────────────────\n\ninterface SkillEntry {\n name: string;\n description: string;\n source: \"global\" | \"conversation\";\n path: string;\n directory: string;\n}\n\n/**\n * Read skill metadata via the harness frontmatter parser (the owning module).\n * The portal historically accepted frontmatter keys case-insensitively, so\n * the lookup — not the parser — preserves that leniency.\n */\nfunction readSkillMeta(filePath: string): { name?: string; description?: string } {\n let text: string;\n try {\n text = readFileSync(filePath, \"utf-8\");\n } catch {\n return {};\n }\n const { values } = parseFrontmatter(text);\n const out: { name?: string; description?: string } = {};\n for (const [key, value] of Object.entries(values)) {\n const normalized = key.toLowerCase();\n if (normalized === \"name\") out.name = value;\n if (normalized === \"description\") out.description = value;\n }\n return out;\n}\n\nexport function readSkillsFromDir(skillsDir: string, source: SkillEntry[\"source\"]): SkillEntry[] {\n if (!existsSync(skillsDir)) return [];\n const out: SkillEntry[] = [];\n let entries;\n try {\n entries = readdirSync(skillsDir, { withFileTypes: true });\n } catch {\n return [];\n }\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) continue;\n const skillMd = join(skillsDir, entry.name, \"SKILL.md\");\n if (!existsSync(skillMd)) continue;\n const meta = readSkillMeta(skillMd);\n out.push({\n name: meta.name ?? entry.name,\n description: meta.description ?? \"\",\n source,\n path: skillMd,\n directory: entry.name,\n });\n }\n return out.toSorted((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * List MCP servers for both scopes, with env/header VALUES redacted to key\n * names: they carry API keys, and this response renders in a browser. The\n * panel edits full entries but only ever needs to show which keys exist.\n */\nfunction serveMcpServersList(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const servers = loadScopeMcpServers(workspace.office(scope.address));\n jsonRes(res, 200, {\n conversationId: scope.conversationId,\n presets: listMcpPresets(),\n global: redactMcpServers(servers.global),\n conversation: redactMcpServers(servers.conversation),\n });\n}\n\nfunction redactMcpServers(map: Record<string, McpServerConfig>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(map).map(([name, config]) => [\n name,\n {\n ...(config.command !== undefined ? { command: config.command } : {}),\n ...(config.args !== undefined ? { args: config.args } : {}),\n ...(config.url !== undefined ? { url: redactMcpUrl(config.url) } : {}),\n ...(config.disabled !== undefined ? { disabled: config.disabled } : {}),\n envKeys: Object.keys(config.env ?? {}),\n headerKeys: Object.keys(config.headers ?? {}),\n },\n ]),\n );\n}\n\nfunction mcpStringMap(value: unknown): Record<string, string> | undefined {\n if (typeof value !== \"object\" || value === null) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(value)) {\n if (typeof v === \"string\" && k.trim()) out[k.trim()] = v;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nconst MCP_VERIFY_TIMEOUT_MS = 20_000;\n\ntype McpVerifyResult = { name: string; tools: number } | { name: string; error: string };\n\n/**\n * Connect to the given servers once, the way the runner will, and report per\n * server either the tool count or the server's own error text. This is the\n * difference between \"settings.json was written\" and \"it works\": the runner\n * only logs load failures host-side, so without this the portal is the only\n * place an operator can learn that a pasted token is wrong.\n *\n * For stdio entries this runs the configured command on the host now, at save\n * time, rather than at the next message.\n */\nasync function verifyMcpServers(\n servers: Record<string, McpServerConfig>,\n): Promise<McpVerifyResult[]> {\n const names = Object.keys(servers);\n if (names.length === 0) return [];\n const loaded = await loadMcpTools(servers, AbortSignal.timeout(MCP_VERIFY_TIMEOUT_MS));\n try {\n return names.map((name) => {\n const failure = loaded.errors.find((e) => e.server === name);\n if (failure) {\n const url = servers[name]?.url;\n const error = url ? failure.error.split(url).join(redactMcpUrl(url)) : failure.error;\n return { name, error };\n }\n const prefix = `mcp__${name}__`;\n return { name, tools: loaded.tools.filter((t) => t.name.startsWith(prefix)).length };\n });\n } finally {\n await loaded.dispose();\n }\n}\n\ntype McpMutationPlan =\n | { next: Record<string, McpServerConfig>; touched: Record<string, McpServerConfig> }\n | { status: number; error: string };\n\n/**\n * Compute the scope's next server map for one mutation. `import` takes the\n * cross-client `mcpServers` JSON verbatim (see `parseStandardMcpServers`) and\n * replaces every named entry outright — a pasted declaration is the whole\n * truth for that server, so no env/header carry-over from the previous entry.\n * `touched` lists the entries to connection-check after the write.\n */\nfunction planMcpMutation(\n action: \"import\" | \"install\" | \"remove\" | \"toggle\",\n body: Record<string, unknown>,\n current: Record<string, McpServerConfig>,\n): McpMutationPlan {\n const next: Record<string, McpServerConfig> = { ...current };\n if (action === \"import\") {\n const parsed = parseStandardMcpServers(typeof body.json === \"string\" ? body.json : \"\");\n if (!parsed.servers) return { status: 400, error: parsed.error };\n Object.assign(next, parsed.servers);\n return { next, touched: parsed.servers };\n }\n const preset =\n action === \"install\" && typeof body.presetId === \"string\"\n ? findMcpPreset(body.presetId)\n : undefined;\n if (action === \"install\" && !preset) return { status: 400, error: \"unknown MCP preset\" };\n const name = preset?.serverName ?? (typeof body.name === \"string\" ? body.name.trim() : \"\");\n if (!isValidMcpServerName(name)) {\n return {\n status: 400,\n error: \"invalid server name (letters, digits, '_' or '-', starting with a letter)\",\n };\n }\n if (action === \"install\") {\n try {\n next[name] = materializeMcpPreset(preset!, mcpStringMap(body.credentials) ?? {});\n } catch (err) {\n return { status: 400, error: err instanceof Error ? err.message : String(err) };\n }\n return { next, touched: { [name]: next[name] } };\n }\n if (!(name in next)) return { status: 404, error: \"Not declared here.\" };\n if (action === \"remove\") {\n delete next[name];\n return { next, touched: {} };\n }\n const entry = next[name]!;\n next[name] = entry.disabled ? { ...entry, disabled: undefined } : { ...entry, disabled: true };\n return { next, touched: {} };\n}\n\n/**\n * Import / install / remove / toggle / test MCP servers in one scope. Reads\n * the scope's raw map, applies the change, and writes the full map back\n * wholesale because merging would make removal impossible. Runner\n * caches refresh via applyGlobalSettings/applyConversationSettings.\n *\n * Writes persist even when the follow-up connection check fails: the\n * operator edits the entry, not retypes it. `test` re-checks an existing\n * entry without writing.\n */\nasync function serveMcpServerMutation(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): Promise<void> {\n const action = body.action;\n if (\n action !== \"import\" &&\n action !== \"install\" &&\n action !== \"remove\" &&\n action !== \"toggle\" &&\n action !== \"test\"\n ) {\n jsonRes(res, 400, {\n error: \"action must be 'import', 'install', 'remove', 'toggle', or 'test'\",\n });\n return;\n }\n const mutationScope = body.scope === \"global\" ? \"global\" : \"conversation\";\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const office = workspace.office(scope.address);\n const maps = loadScopeMcpServers(office);\n const current = mutationScope === \"global\" ? maps.global : maps.conversation;\n\n if (action === \"test\") {\n const name = typeof body.name === \"string\" ? body.name.trim() : \"\";\n const entry = current[name];\n if (!entry) {\n jsonRes(res, 404, { error: \"Not declared here.\" });\n return;\n }\n const results = await verifyMcpServers({ [name]: { ...entry, disabled: undefined } });\n jsonRes(res, 200, { ok: true, results });\n return;\n }\n\n const plan = planMcpMutation(action, body, current);\n if (\"error\" in plan) {\n jsonRes(res, plan.status, { error: plan.error });\n return;\n }\n const result =\n mutationScope === \"global\"\n ? applyGlobalSettings(services.runtime, { mcpServers: plan.next })\n : applyConversationSettings(services.runtime, office, { mcpServers: plan.next });\n if (!result.ok) {\n jsonRes(res, 409, { error: \"Conversation is busy; try again shortly.\" });\n return;\n }\n const results = await verifyMcpServers(plan.touched);\n jsonRes(res, 200, { ok: true, results });\n}\n\nfunction serveSkillsList(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const global = readSkillsFromDir(workspace.skillsDir, \"global\");\n const conversation = readSkillsFromDir(workspace.office(scope.address).skillsDir, \"conversation\");\n jsonRes(res, 200, {\n conversationId: scope.conversationId,\n skills: [...global, ...conversation],\n });\n}\n\nfunction serveSkillFile(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const source = (url.searchParams.get(\"source\") ?? \"\").trim();\n const directory = (url.searchParams.get(\"directory\") ?? \"\").trim();\n if (source !== \"global\" && source !== \"conversation\") {\n jsonRes(res, 400, { error: \"Invalid skill source\" });\n return;\n }\n if (\n !directory ||\n directory.includes(\"/\") ||\n directory.includes(\"\\\\\") ||\n directory.includes(\"..\")\n ) {\n jsonRes(res, 400, { error: \"Invalid skill directory\" });\n return;\n }\n\n const skillsRoot =\n source === \"global\" ? workspace.skillsDir : workspace.office(scope.address).skillsDir;\n const safe = safeJoinUnderRoot(skillsRoot, join(directory, \"SKILL.md\"));\n if (safe.error) {\n jsonRes(res, 400, { error: safe.error });\n return;\n }\n\n servePreviewFile(res, safe.absolute, { source, directory }, \"Skill file not found\");\n}\n\nconst SKILL_DIRECTORY_PATTERN = /^[a-z0-9-]+$/;\n\nfunction resolveSkillsRoot(\n workspace: Workspace,\n scope: AdminConversationScope,\n source: unknown,\n): { root: string; source: \"global\" | \"conversation\" } | { error: string } {\n if (source !== \"global\" && source !== \"conversation\") {\n return { error: \"Invalid skill source\" };\n }\n return {\n root: source === \"global\" ? workspace.skillsDir : workspace.office(scope.address).skillsDir,\n source,\n };\n}\n\n/**\n * Create, overwrite, or delete one skill directory. The directory name is\n * fixed at creation (renaming would leave the old directory as an orphan);\n * editing an existing skill always targets its current directory. Writes go\n * straight to the workspace skills tree — the same location the harness\n * loader reads — so a saved skill is available on the conversation's next\n * turn without a restart.\n */\nasync function serveSkillMutation(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): Promise<void> {\n const action = body.action;\n if (action !== \"save\" && action !== \"delete\") {\n jsonRes(res, 400, { error: \"action must be 'save' or 'delete'\" });\n return;\n }\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const resolved = resolveSkillsRoot(workspace, scope, body.source);\n if (\"error\" in resolved) {\n jsonRes(res, 400, { error: resolved.error });\n return;\n }\n\n const directory = typeof body.directory === \"string\" ? body.directory.trim() : \"\";\n if (!directory || !SKILL_DIRECTORY_PATTERN.test(directory)) {\n jsonRes(res, 400, {\n error: \"directory must be lowercase a-z, 0-9 and hyphens\",\n });\n return;\n }\n const safe = safeJoinUnderRoot(resolved.root, directory);\n if (safe.error) {\n jsonRes(res, 400, { error: safe.error });\n return;\n }\n\n if (action === \"delete\") {\n if (!existsSync(join(safe.absolute, \"SKILL.md\"))) {\n jsonRes(res, 404, { error: \"Skill not found\" });\n return;\n }\n try {\n rmSync(safe.absolute, { recursive: true, force: true });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n return;\n }\n jsonRes(res, 200, { ok: true });\n return;\n }\n\n const name = typeof body.name === \"string\" ? body.name.trim() : directory;\n const description = typeof body.description === \"string\" ? body.description.trim() : \"\";\n const content = typeof body.content === \"string\" ? body.content : \"\";\n if (!description) {\n jsonRes(res, 400, { error: \"description is required\" });\n return;\n }\n const errors = validateSkill(name, description);\n if (errors.length > 0) {\n jsonRes(res, 400, { error: errors.join(\"; \") });\n return;\n }\n\n try {\n if (existsSync(safe.absolute) && lstatSync(safe.absolute).isSymbolicLink()) {\n throw new Error(\"Refusing to write through a symlinked skill directory\");\n }\n mkdirSync(safe.absolute, { recursive: true });\n const frontmatter = [\"---\", `name: ${name}`, `description: ${description}`, \"---\", \"\"].join(\n \"\\n\",\n );\n atomicWritePrivateFile(join(safe.absolute, \"SKILL.md\"), frontmatter + content.trim() + \"\\n\");\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n return;\n }\n jsonRes(res, 200, { ok: true, name, directory, source: resolved.source });\n}\n\n// ── Events ─────────────────────────────────────────────────────────────────────\n\n/**\n * List events through the owning store, whose payloads are validated by the\n * event-format module (files that fail validation stay visible with a null\n * payload so operators can delete them).\n */\nexport async function listOfficeEvents(store: EventStore): Promise<EventSummary[]> {\n const entries = await store.list();\n return entries.map((entry) => {\n const payload = entry.payload;\n return {\n name: entry.filename,\n officePlatform: store.address.platform,\n officeConversationId: store.address.conversationId,\n size: entry.size,\n mtimeMs: entry.mtimeMs,\n type: payload?.type ?? null,\n platform: payload?.platform ?? null,\n conversationId: payload?.conversationId ?? null,\n text: payload?.text ?? null,\n at: payload?.type === \"one-shot\" ? payload.at : null,\n schedule: payload?.type === \"periodic\" ? payload.schedule : null,\n timezone: payload?.type === \"periodic\" ? payload.timezone : null,\n };\n });\n}\n\nfunction requireAdminEventStore(\n res: ServerResponse,\n services: AdminServices,\n office: Office,\n): EventStore | null {\n if (!services.eventStore) {\n jsonRes(res, 503, { error: \"Working directory not available\" });\n return null;\n }\n return services.eventStore(office);\n}\n\n/** Every registered office's events, each read through its own store. */\nasync function serveEventsList(res: ServerResponse, services: AdminServices): Promise<void> {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n if (!services.eventStore) {\n jsonRes(res, 503, { error: \"Working directory not available\" });\n return;\n }\n const events: EventSummary[] = [];\n for (const record of listRegisteredOffices(workspace.stateDir)) {\n events.push(...(await listOfficeEvents(services.eventStore(workspace.office(record)))));\n }\n jsonRes(res, 200, { events });\n}\n\n/** Per-conversation listing through that office's confined store. */\nasync function serveConversationEventsList(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): Promise<void> {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const store = requireAdminEventStore(res, services, workspace.office(scope.address));\n if (!store) return;\n jsonRes(res, 200, {\n conversationId: scope.conversationId,\n events: await listOfficeEvents(store),\n });\n}\n\n/** Delete a single event file scoped to the caller's conversation. */\nasync function serveConversationEventDelete(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): Promise<void> {\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n let name: string;\n try {\n name = validateEventFilename(typeof body.name === \"string\" ? body.name : \"\");\n } catch {\n jsonRes(res, 400, { error: \"Invalid name\" });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const store = requireAdminEventStore(res, services, workspace.office(scope.address));\n if (!store) return;\n // The store is confined to this office: another office's filename is \"not found\".\n try {\n await store.delete(name);\n jsonRes(res, 200, { ok: true });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n jsonRes(res, /not found/.test(message) ? 404 : 500, { error: message });\n }\n}\n\n// ── Utilities ──────────────────────────────────────────────────────────────────\n\nconst esc = escapeHtml;\n\n// ── HTML ───────────────────────────────────────────────────────────────────────\n\n/**\n * Settings-app rail icons: a fixed inline-SVG set instead of an icon font, so\n * the admin page has no extra network request and every icon shares one\n * visual language (1.6px stroke, 18x18, currentColor). Keys match the\n * `railLink`/`settingsPane` id namespace, not the API endpoints they load.\n */\ntype RailIconKey =\n | \"settings\"\n | \"workspace\"\n | \"skills\"\n | \"mcp\"\n | \"vault\"\n | \"events\"\n | \"session\"\n | \"overview\"\n | \"usage\";\n\nconst ICONS: Record<RailIconKey, string> = {\n settings: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h.01a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v.01a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z\"/></svg>`,\n workspace: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z\"/></svg>`,\n skills: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 19.5V5a2 2 0 0 1 2-2h11a1 1 0 0 1 1 1v14\"/><path d=\"M6 17h13v4H6.5A2.5 2.5 0 0 1 4 18.5v0A2.5 2.5 0 0 1 6.5 16H20\"/></svg>`,\n mcp: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"7\" rx=\"1.5\"/><rect x=\"3\" y=\"13\" width=\"18\" height=\"7\" rx=\"1.5\"/><circle cx=\"7\" cy=\"7.5\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"7\" cy=\"16.5\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/></svg>`,\n vault: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"10\" rx=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/></svg>`,\n events: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\"/><path d=\"M3 10h18M8 3v4M16 3v4\"/></svg>`,\n session: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z\"/></svg>`,\n overview: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1.5\"/><rect x=\"13\" y=\"3\" width=\"8\" height=\"5\" rx=\"1.5\"/><rect x=\"13\" y=\"11\" width=\"8\" height=\"10\" rx=\"1.5\"/><rect x=\"3\" y=\"14\" width=\"8\" height=\"7\" rx=\"1.5\"/></svg>`,\n usage: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 21V3\"/><path d=\"M3 21h18\"/><path d=\"M7 17V11M12 17V7M17 17v-4\"/></svg>`,\n};\n\n/** One entry in the settings rail: an icon, a label, and the pane id it activates. */\nfunction railLink(id: string, label: string, icon: RailIconKey, active = false): string {\n const svg = ICONS[icon];\n // The label span is hidden below 860px, so mirror it into aria-label/title to\n // keep an accessible name and a hover hint once the text disappears.\n return `<button class=\"rail-link${active ? \" active\" : \"\"}\" type=\"button\" data-pane=\"${id}\" aria-current=\"${active ? \"page\" : \"false\"}\" aria-label=\"${esc(label)}\" title=\"${esc(label)}\">${svg}<span>${esc(label)}</span></button>`;\n}\n\n/**\n * One settings pane: an eyebrow-free header (icon lives in the rail, not\n * repeated here) with a title, a one-line description, and header actions,\n * followed by body content. Every pane shares this shape so scanning the\n * page feels like one continuous settings surface instead of assembled\n * cards — the visual language `frontend-design` calls for here is a\n * quiet, editorial settings app, not a dashboard of boxes.\n */\nfunction settingsPane(\n id: string,\n title: string,\n description: string,\n actions: string,\n body: string,\n): string {\n return `<section class=\"pane\" id=\"pane-${id}\" data-pane=\"${id}\">\n <header class=\"pane-head\">\n <div><h2 class=\"pane-title\">${esc(title)}</h2><p class=\"pane-desc\">${esc(description)}</p></div>\n <div class=\"pane-actions\">${actions}</div>\n </header>\n <div class=\"pane-body\">${body}</div>\n </section>`;\n}\n\nconst adminViewBody = `<div class=\"settings-shell\">\n <aside class=\"settings-rail\" aria-label=\"Admin sections\">\n <div class=\"rail-scope\" role=\"tablist\" aria-label=\"Scope\">\n <button class=\"rail-scope-btn active\" role=\"tab\" aria-selected=\"true\" aria-controls=\"panel-conversation\" data-tab=\"conversation\">This conversation</button>\n <button class=\"rail-scope-btn\" role=\"tab\" aria-selected=\"false\" aria-controls=\"panel-global\" data-tab=\"global\">Workspace</button>\n </div>\n <nav class=\"rail-nav\" id=\"rail-nav-conversation\" data-scope=\"conversation\">\n ${railLink(\"settings\", \"Settings\", \"settings\", true)}\n ${railLink(\"workspace\", \"Workspace\", \"workspace\")}\n ${railLink(\"skills\", \"Skills\", \"skills\")}\n ${railLink(\"mcp\", \"MCP servers\", \"mcp\")}\n ${railLink(\"vault\", \"Vault\", \"vault\")}\n ${railLink(\"events\", \"Events\", \"events\")}\n ${railLink(\"session\", \"Session view\", \"session\")}\n </nav>\n <nav class=\"rail-nav\" id=\"rail-nav-global\" data-scope=\"global\" hidden>\n ${railLink(\"g-overview\", \"All conversations\", \"overview\", true)}\n ${railLink(\"g-usage\", \"Token usage\", \"usage\")}\n ${railLink(\"g-settings\", \"Defaults\", \"settings\")}\n ${railLink(\"g-mcp\", \"MCP servers\", \"mcp\")}\n ${railLink(\"g-skills\", \"Skills\", \"skills\")}\n ${railLink(\"g-events\", \"Events\", \"events\")}\n </nav>\n </aside>\n\n <div class=\"settings-panels\">\n <div class=\"tab-panel active\" id=\"panel-conversation\">\n ${settingsPane(\"settings\", \"Settings\", \"Model, thinking level, auto-reply, and workspace visibility for this conversation.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadSettings()\">↻</button>', '<div id=\"settings-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"workspace\", \"Workspace\", \"Read-only browser for this conversation's files on disk.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadWorkspace()\">↻</button>', '<div class=\"workspace-split\"><div id=\"workspace-tree\" class=\"workspace-tree\"><div class=\"loading-msg\">Loading…</div></div><div id=\"workspace-preview\" class=\"workspace-preview\"><div class=\"placeholder-msg\">Click a file to preview</div></div></div>')}\n\n ${settingsPane(\"skills\", \"Skills\", \"Instructions the agent can load for specific tasks in this conversation.\", '<button class=\"primary-action-btn\" onclick=\"openSkillDialog(\\'conversation\\')\">+ New skill</button><button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadSkills()\">↻</button>', '<div class=\"workspace-split\"><div id=\"skills-content\" class=\"workspace-tree\"><div class=\"loading-msg\">Loading…</div></div><div id=\"skills-preview\" class=\"workspace-preview\"><div class=\"placeholder-msg\">Click a skill to preview SKILL.md</div></div></div>')}\n\n ${settingsPane(\"mcp\", \"MCP servers\", \"External tools this conversation can call during a run.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadMcpServers()\">↻</button>', '<div id=\"mcp-conv-msg\" class=\"status-msg\" style=\"display:none\"></div><div id=\"mcp-conv-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"vault\", \"Vault\", \"Credentials scoped to this conversation.\", '<button class=\"primary-action-btn\" onclick=\"openLogin()\">Open in new tab ↗</button>', '<div id=\"vault-link-result\" class=\"link-result\" style=\"display:none\"></div><p class=\"card-desc\">Opens the one-time credential form for this conversation\\'s vault in a new tab.</p>')}\n\n ${settingsPane(\"events\", \"Events\", \"Scheduled and one-shot events tied to this conversation.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadConversationEvents()\">↻</button>', '<div id=\"events-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"session\", \"Session view\", \"The full message and tool-call timeline for this conversation.\", '<button class=\"primary-action-btn\" onclick=\"openSessionView()\">Open in new tab ↗</button>', '<div id=\"session-link-result\" class=\"link-result\" style=\"display:none\"></div><p class=\"card-desc\">Opens the session timeline for this conversation in a new tab.</p>')}\n </div>\n\n <div class=\"tab-panel\" id=\"panel-global\">\n ${settingsPane(\"g-overview\", \"All conversations\", \"Every registered conversation across every platform.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadAllConversations()\">↻</button>', '<div id=\"all-conv-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"g-usage\", \"Token usage\", \"Spend and volume across every conversation.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadTokenUsage()\">↻</button>', '<h3 class=\"card-subtitle\">Top 20 sessions</h3><div id=\"session-usage-content\"><div class=\"loading-msg\">Loading…</div></div><h3 class=\"card-subtitle\" style=\"margin-top:24px\">Usage timeline</h3><div class=\"timeline-controls\"><label>Conversation<select id=\"timeline-conv\" onchange=\"loadUsageTimeline()\"></select></label></div><div id=\"usage-timeline-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"g-settings\", \"Workspace defaults\", \"The fallback model, sandbox limits, and Slack behavior every conversation inherits.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadGlobalSettings()\">↻</button>', '<div id=\"global-settings-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"g-mcp\", \"MCP servers\", \"External tools available to every conversation in this workspace.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadMcpServers()\">↻</button>', '<div id=\"mcp-global-msg\" class=\"status-msg\" style=\"display:none\"></div><div id=\"mcp-global-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"g-skills\", \"Skills\", \"Shared instructions available to every conversation in this workspace.\", '<button class=\"primary-action-btn\" onclick=\"openSkillDialog(\\'global\\')\">+ New global skill</button><button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadGlobalSkills()\">↻</button>', '<div class=\"workspace-split\"><div id=\"global-skills-content\" class=\"workspace-tree\"><div class=\"loading-msg\">Loading…</div></div><div id=\"global-skills-preview\" class=\"workspace-preview\"><div class=\"placeholder-msg\">Click a skill to preview SKILL.md</div></div></div>')}\n\n ${settingsPane(\"g-events\", \"Global events\", \"Every scheduled event across the whole workspace.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadEvents()\">↻</button>', '<div id=\"global-events-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n </div>\n </div>\n </div>\n\n <dialog id=\"mcp-install-dialog\" class=\"mcp-dialog\" aria-labelledby=\"mcp-dialog-title\">\n <div class=\"mcp-dialog-head\">\n <div>\n <p class=\"eyebrow\">Install MCP preset</p>\n <h2 id=\"mcp-dialog-title\" class=\"card-title\"></h2>\n </div>\n <button class=\"mcp-dialog-close\" type=\"button\" aria-label=\"Close\" onclick=\"closeMcpInstall()\">×</button>\n </div>\n <div id=\"mcp-dialog-content\"></div>\n <div id=\"mcp-dialog-error\" class=\"inline-result err\" style=\"display:none\"></div>\n <div class=\"mcp-dialog-actions\">\n <button class=\"mcp-btn\" type=\"button\" onclick=\"closeMcpInstall()\">Cancel</button>\n <button id=\"mcp-dialog-install\" class=\"primary-action-btn\" type=\"button\" onclick=\"installMcpPreset(this)\">Install preset</button>\n </div>\n </dialog>\n\n <dialog id=\"mcp-custom-dialog\" class=\"mcp-dialog\" aria-labelledby=\"mcp-custom-dialog-title\">\n <div class=\"mcp-dialog-head\">\n <div>\n <p class=\"eyebrow\">Add MCP server</p>\n <h2 id=\"mcp-custom-dialog-title\" class=\"card-title\">新增自訂 server</h2>\n </div>\n <button class=\"mcp-dialog-close\" type=\"button\" aria-label=\"Close\" onclick=\"closeMcpCustomDialog()\">×</button>\n </div>\n <div id=\"mcp-custom-dialog-content\"></div>\n <div id=\"mcp-custom-dialog-error\" class=\"inline-result err\" style=\"display:none\"></div>\n <div class=\"mcp-dialog-actions\">\n <button class=\"mcp-btn\" type=\"button\" onclick=\"closeMcpCustomDialog()\">Cancel</button>\n <button id=\"mcp-custom-dialog-submit\" class=\"primary-action-btn\" type=\"button\" onclick=\"submitMcpCustomDialog(this)\">新增並測試連線</button>\n </div>\n </dialog>\n\n <dialog id=\"skill-dialog\" class=\"mcp-dialog\" aria-labelledby=\"skill-dialog-title\">\n <div class=\"mcp-dialog-head\">\n <div>\n <p class=\"eyebrow\" id=\"skill-dialog-eyebrow\">Skill</p>\n <h2 id=\"skill-dialog-title\" class=\"card-title\">New skill</h2>\n </div>\n <button class=\"mcp-dialog-close\" type=\"button\" aria-label=\"Close\" onclick=\"closeSkillDialog()\">×</button>\n </div>\n <div class=\"mcp-field\">\n <span>Directory</span>\n <input id=\"skill-dialog-directory\" class=\"form-input mcp-json\" placeholder=\"my-skill\" autocomplete=\"off\" />\n <small class=\"mcp-secret-note\">Lowercase letters, digits, hyphens. Cannot be changed after creation.</small>\n </div>\n <div class=\"mcp-field\">\n <span>Name</span>\n <input id=\"skill-dialog-name\" class=\"form-input mcp-json\" placeholder=\"my-skill\" autocomplete=\"off\" />\n </div>\n <div class=\"mcp-field\">\n <span>Description</span>\n <input id=\"skill-dialog-description\" class=\"form-input mcp-json\" placeholder=\"Use when …\" autocomplete=\"off\" />\n </div>\n <div class=\"mcp-field\">\n <span>Instructions (SKILL.md body)</span>\n <textarea id=\"skill-dialog-content\" class=\"form-input mcp-json\" spellcheck=\"false\" rows=\"12\" placeholder=\"# My skill Instructions here.\"></textarea>\n </div>\n <div id=\"skill-dialog-error\" class=\"inline-result err\" style=\"display:none\"></div>\n <div class=\"mcp-dialog-actions\">\n <button class=\"mcp-btn\" type=\"button\" onclick=\"closeSkillDialog()\">Cancel</button>\n <button id=\"skill-dialog-submit\" class=\"primary-action-btn\" type=\"button\" onclick=\"submitSkillDialog(this)\">Save</button>\n </div>\n </dialog>`;\n\nconst adminViewScript = ` let activeConversationKey = defaultConversationKey;\n function scopeOf(key) {\n const sep = key.indexOf(':');\n return { platform: key.slice(0, sep), conversationId: key.slice(sep + 1) };\n }\n function scopeQuery() {\n const scope = scopeOf(activeConversationKey);\n return 'conversationId=' + encodeURIComponent(scope.conversationId) +\n '&platform=' + encodeURIComponent(scope.platform);\n }\n function scopeBody() {\n const scope = scopeOf(activeConversationKey);\n return { conversationId: scope.conversationId, platform: scope.platform };\n }\n let availableModels = [];\n let modelsLoaded = false;\n let mcpPresets = [];\n let mcpServersByScope = { conversation: {}, global: {} };\n let pendingMcpInstall = null;\n\n // ── Helpers ──────────────────────────────────────────────────────────────────\n\n function escHtml(str) {\n return String(str).replace(/[&<>\"']/g, (c) => (\n {'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]\n ));\n }\n const escAttr = escHtml;\n async function copyToClipboard(text) {\n try { await navigator.clipboard.writeText(text); } catch { prompt('Copy this link:', text); }\n }\n document.addEventListener('click', (event) => {\n const target = event.target instanceof Element\n ? event.target.closest('[data-admin-action]')\n : null;\n if (!target) return;\n switch (target.dataset.adminAction) {\n case 'preview-file':\n void previewFile(target.dataset.filePath || '');\n break;\n case 'copy-link':\n void copyToClipboard(target.dataset.copyText || '');\n break;\n case 'delete-event':\n void deleteEvent(target.dataset.eventName || '', target);\n break;\n case 'select-conversation':\n setActiveConversation(target.dataset.conversationId || '');\n switchTab('conversation');\n break;\n case 'toggle-timeline-filter':\n toggleTimelineFilter(target.dataset.filterKey || '');\n break;\n }\n });\n async function apiGet(path) {\n const url = path + (path.includes('?') ? '&' : '?') + 'token=' + encodeURIComponent(adminToken);\n const r = await fetch(url);\n const data = await r.json();\n if (!r.ok) throw new Error(data.error || ('HTTP ' + r.status));\n return data;\n }\n async function apiPost(path, body) {\n const r = await fetch(path, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: adminToken, ...body }),\n });\n const data = await r.json();\n if (!r.ok) throw new Error(data.error || ('HTTP ' + r.status));\n return data;\n }\n async function loadModels() {\n try {\n const data = await apiGet('/admin/api/models');\n availableModels = Array.isArray(data.models) ? data.models : [];\n } catch (err) {\n availableModels = [];\n } finally {\n modelsLoaded = true;\n }\n }\n function modelRef(provider, model) {\n return provider && model ? provider + '/' + model : '';\n }\n function parseModelRef(value) {\n const slash = value.indexOf('/');\n if (slash <= 0 || slash === value.length - 1) return { provider: '', model: '' };\n return { provider: value.slice(0, slash), model: value.slice(slash + 1) };\n }\n function renderModelOptions(currentProvider, currentModel) {\n const current = modelRef(currentProvider, currentModel);\n const seen = new Set();\n const groups = {\n available: [],\n unverified: [],\n };\n if (current) {\n seen.add(current);\n groups.available.push('<option value=\"' + escAttr(current) + '\">' + escHtml(current + ' (current)') + '</option>');\n }\n for (const model of availableModels) {\n const ref = modelRef(model.provider, model.id);\n if (!ref || seen.has(ref)) continue;\n seen.add(ref);\n const details = [model.name && model.name !== model.id ? model.name : '', model.reasoning ? 'thinking' : '', Array.isArray(model.input) && model.input.includes('image') ? 'image' : '']\n .filter(Boolean)\n .join(' · ');\n const option = '<option value=\"' + escAttr(ref) + '\">' + escHtml(details ? ref + ' — ' + details : ref) + '</option>';\n if (model.status === 'unverified') groups.unverified.push(option);\n else groups.available.push(option);\n }\n const sections = [];\n if (groups.available.length > 0) sections.push('<optgroup label=\"Available\">' + groups.available.join('') + '</optgroup>');\n if (groups.unverified.length > 0) sections.push('<optgroup label=\"Configured but unverified\">' + groups.unverified.join('') + '</optgroup>');\n if (sections.length === 0) {\n return '<option value=\"\">No available models</option>';\n }\n return sections.join('');\n }\n\n // ── Scope tabs (rail top switch) ────────────────────────────────────────────\n\n const scopeBtns = document.querySelectorAll('.rail-scope-btn');\n const tabPanels = document.querySelectorAll('.tab-panel');\n const railNavConversation = document.getElementById('rail-nav-conversation');\n const railNavGlobal = document.getElementById('rail-nav-global');\n\n function switchTab(tabId) {\n scopeBtns.forEach((btn) => {\n const active = btn.dataset.tab === tabId;\n btn.classList.toggle('active', active);\n btn.setAttribute('aria-selected', active ? 'true' : 'false');\n });\n tabPanels.forEach((panel) => panel.classList.toggle('active', panel.id === 'panel-' + tabId));\n railNavConversation.hidden = tabId !== 'conversation';\n railNavGlobal.hidden = tabId !== 'global';\n if (tabId === 'global') initGlobal();\n const firstPane = (tabId === 'global' ? railNavGlobal : railNavConversation).querySelector('.rail-link');\n if (firstPane) selectPane(tabId, firstPane.dataset.pane);\n }\n scopeBtns.forEach((btn) => btn.addEventListener('click', () => switchTab(btn.dataset.tab)));\n\n // ── Rail navigation (single active pane per scope) ──────────────────────────\n\n // Looked up by name (not collected into an object up front) because the\n // loaders below are const declarations further down this same script;\n // referencing them before their own line runs would hit the temporal\n // dead zone. By the time this function is actually called (after a rail\n // click, always after the whole script has executed), they're all\n // initialized.\n function paneLoader(key) {\n switch (key) {\n case 'settings': return loadSettings;\n case 'workspace': return loadWorkspace;\n case 'skills': return loadSkills;\n case 'mcp': return loadMcpServers;\n case 'events': return loadConversationEvents;\n case 'g-overview': return loadAllConversations;\n case 'g-usage': return loadTokenUsage;\n case 'g-settings': return loadGlobalSettings;\n case 'g-mcp': return loadMcpServers;\n case 'g-skills': return loadGlobalSkills;\n case 'g-events': return loadEvents;\n default: return undefined;\n }\n }\n const paneLoaded = new Set();\n\n function ensurePaneLoaded(key) {\n if (paneLoaded.has(key)) return;\n const loader = paneLoader(key);\n if (!loader) return;\n paneLoaded.add(key);\n loader();\n }\n\n function selectPane(scope, key) {\n const nav = scope === 'global' ? railNavGlobal : railNavConversation;\n const panel = document.getElementById(scope === 'global' ? 'panel-global' : 'panel-conversation');\n nav.querySelectorAll('.rail-link').forEach((btn) => {\n const active = btn.dataset.pane === key;\n btn.classList.toggle('active', active);\n btn.setAttribute('aria-current', active ? 'page' : 'false');\n });\n panel.querySelectorAll('.pane').forEach((pane) => {\n pane.classList.toggle('active', pane.dataset.pane === key);\n });\n ensurePaneLoaded(key);\n }\n\n function initRailNav() {\n document.querySelectorAll('.rail-link').forEach((btn) => {\n btn.addEventListener('click', () => {\n const nav = btn.closest('.rail-nav');\n const scope = nav.dataset.scope;\n selectPane(scope, btn.dataset.pane);\n });\n });\n // The first rail link in each scope starts active in the markup, so its\n // pane needs the matching 'active' class and its data loaded up front.\n selectPane('conversation', 'settings');\n }\n\n // ── Conversation switcher ───────────────────────────────────────────────────\n\n async function initConvSwitcher() {\n const sel = document.getElementById('conv-switcher');\n try {\n const data = await apiGet('/admin/api/conversations');\n sel.innerHTML = data.conversations.map((c) => {\n const key = c.platform + ':' + c.conversationId;\n const label = (c.label || c.conversationId) + (c.running ? ' (running)' : '');\n const selected = key === defaultConversationKey ? ' selected' : '';\n return '<option value=\"' + escAttr(key) + '\"' + selected + '>' + escHtml(label) + '</option>';\n }).join('');\n sel.addEventListener('change', () => setActiveConversation(sel.value));\n } catch (err) {\n // ignore; conversation selector stays empty\n }\n }\n\n function setActiveConversation(key) {\n activeConversationKey = key;\n const sel = document.getElementById('conv-switcher');\n if (sel && sel.value !== key) sel.value = key;\n // Data is scoped to the previous conversation; drop the conversation\n // panes (not the global ones — those aren't conversation-scoped) so\n // the active pane refetches for the new scope.\n const activeLink = railNavConversation.querySelector('.rail-link.active');\n ['settings', 'workspace', 'skills', 'mcp', 'events'].forEach((key) => paneLoaded.delete(key));\n if (activeLink) ensurePaneLoaded(activeLink.dataset.pane);\n openLogin(true);\n openSessionView(true);\n }\n\n // ── Settings ─────────────────────────────────────────────────────────────────\n\n const loadSettings = () => loadSettingsPanel('settings-content', () => '/admin/api/conversation-state?' + scopeQuery(), renderSettings);\n const loadGlobalSettings = () => loadSettingsPanel('global-settings-content', () => '/admin/api/settings/global', renderGlobalSettings);\n\n async function loadSettingsPanel(id, path, render) {\n const container = document.getElementById(id);\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n if (!modelsLoaded) await loadModels();\n try {\n const data = await apiGet(path());\n container.innerHTML = render(data);\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n function renderConfigCard(title, content, action, buttonLabel, resultId) {\n return '<div class=\"config-block\"><h3 class=\"card-subtitle\">' + title + '</h3>' + content +\n '<button class=\"primary-action-btn\" onclick=\"' + action + '(this)\">' + buttonLabel + '</button>' +\n '<div id=\"' + resultId + '\" class=\"inline-result\" style=\"display:none\"></div></div>';\n }\n\n function renderOptions(choices, selected) {\n return choices.map(([value, label]) =>\n '<option value=\"' + escAttr(value) + '\"' + (selected === value ? ' selected' : '') + '>' + escHtml(label) + '</option>'\n ).join('');\n }\n function renderThinkingOptions(value) {\n return renderOptions(['off','minimal','low','medium','high','xhigh','max'].map((t) => [t, t]), value);\n }\n function renderReplyOptions(slack) {\n return renderOptions(['top-level','thread'].map((m) => [m, m]), (slack && slack.replyMode) || 'top-level');\n }\n function renderSettings(data) {\n const thinkingOpts = renderThinkingOptions(data.thinkingLevel);\n const replyModeOpts = renderReplyOptions(data.slack);\n const globalReplyMode = (data.slack && data.slack.globalReplyMode) || 'top-level';\n const globalModel = [data.globalProvider, data.globalModel].filter(Boolean).join('/');\n const globalModelLabel = globalModel + (data.globalThinkingLevel ? ':' + data.globalThinkingLevel : '');\n return [\n '<div class=\"config-grid\">',\n renderConfigCard('Model', [\n '<div class=\"config-row config-row-stack\"><label>Model</label><select id=\"m-model-ref\">' + renderModelOptions(data.provider, data.model) + '</select></div>',\n '<div class=\"config-row\"><label>Thinking</label><select id=\"m-thinking\">' + thinkingOpts + '</select></div>',\n '<p class=\"muted-note\">Global default: ' + escHtml(globalModelLabel) + '</p>',\n ].join(''), 'saveModel', 'Save model', 'model-save-result'),\n\n renderVisibilityCard(data),\n renderConfigCard('Slack', [\n '<div class=\"config-row\"><label>Reply mode</label><select id=\"m-slack-reply-mode\">' + replyModeOpts + '</select></div>',\n '<p class=\"muted-note\">Global default: ' + escHtml(globalReplyMode) + '</p>',\n ].join(''), 'saveSlack', 'Save Slack', 'slack-save-result'),\n '</div>',\n ].join('');\n }\n\n async function saveModel(btn) {\n const selectedModel = parseModelRef(document.getElementById('m-model-ref').value.trim());\n const provider = selectedModel.provider;\n const model = selectedModel.model;\n const thinkingLevel = document.getElementById('m-thinking').value;\n const result = document.getElementById('model-save-result');\n if (!provider || !model) {\n result.style.display = 'block'; result.className = 'inline-result err';\n result.textContent = 'Provider and model are required';\n return;\n }\n await saveConversationSetting(btn, result, 'model', { provider, model, thinkingLevel }, 'Save model');\n }\n\n async function saveSlack(btn) {\n const replyMode = document.getElementById('m-slack-reply-mode').value;\n const result = document.getElementById('slack-save-result');\n await saveConversationSetting(btn, result, 'slack', { replyMode }, 'Save Slack');\n }\n\n // Only a public Slack channel has a choice to make; private channels and\n // DMs are always hidden, so the card just states that without a control.\n function renderVisibilityCard(data) {\n const hidden = data.officeVisibilityOverride === 'private';\n const canChoose = data.officeVisibilitySource === 'platform' ? data.officeVisibility === 'public' : hidden;\n if (!canChoose) {\n const why = data.officeVisibilitySource === 'platform'\n ? 'This is a DM, a private channel, or a conversation on a platform other than Slack, so its files are hidden from every other office. The platform decides this; it cannot be opened up here.'\n : 'Slack has not reported what kind of conversation this is yet, so it is treated as hidden until it does.';\n return '<div class=\"config-block\"><h3 class=\"card-subtitle\">Who can see the files in this office</h3>' +\n '<p><strong>Hidden</strong> — only this office.</p><p class=\"muted-note\">' + why + '</p></div>';\n }\n return renderConfigCard('Who can see the files in this office', [\n '<div class=\"config-row\"><label><input type=\"checkbox\" id=\"m-visibility\"' + (hidden ? ' checked' : '') + '> Hide the files in this channel from other offices</label></div>',\n '<p>' + (hidden\n ? '<strong>Hidden</strong> — other offices cannot read the files in this channel, and it can read shared MEMORY.md and skills but not change them.'\n : '<strong>Shared</strong> — every other office can read the files in this channel (read-only), and this channel may update shared MEMORY.md and skills.') + '</p>',\n '<p class=\"muted-note\">Slack says this is a public channel, which is why sharing is the default. Hiding is the only change allowed; nothing can be made more visible than Slack allows.</p>',\n ].join(''), 'saveVisibility', 'Save', 'mount-save-result');\n }\n\n async function saveVisibility(btn) {\n const visibility = document.getElementById('m-visibility').checked ? 'private' : 'default';\n const result = document.getElementById('mount-save-result');\n await saveConversationSetting(btn, result, 'visibility', { visibility }, 'Save visibility', loadSettings);\n }\n\n function saveConversationSetting(btn, result, setting, values, label, onSaved) {\n return saveSetting(btn, result, 'conversations/' + setting, { ...scopeBody(), ...values }, label, onSaved);\n }\n\n async function saveSetting(btn, result, path, values, label, onSaved) {\n btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';\n try {\n await apiPost('/admin/api/' + path, values);\n result.style.display = 'block'; result.className = 'inline-result ok'; result.textContent = 'Saved ✓';\n if (onSaved) onSaved();\n } catch (err) {\n result.style.display = 'block'; result.className = 'inline-result err'; result.textContent = err.message;\n } finally {\n btn.disabled = false; btn.textContent = label;\n }\n }\n\n // ── Workspace ────────────────────────────────────────────────────────────────\n\n async function loadWorkspace() {\n const treeEl = document.getElementById('workspace-tree');\n const previewEl = document.getElementById('workspace-preview');\n treeEl.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n previewEl.innerHTML = '<div class=\"placeholder-msg\">Click a file to preview</div>';\n try {\n const data = await apiGet('/admin/api/workspace/tree?' + scopeQuery());\n if (!data.tree) {\n treeEl.innerHTML = '<div class=\"empty-state\">No files</div>';\n return;\n }\n treeEl.innerHTML = '<ul class=\"tree-root\">' + renderTreeChildren(data.tree) + '</ul>';\n } catch (err) {\n treeEl.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n function renderTreeChildren(node) {\n if (node.type === 'file') {\n return '<li><button class=\"tree-file\" data-admin-action=\"preview-file\" data-file-path=\"' + escAttr(node.path) + '\">' + escHtml(node.name) + '</button></li>';\n }\n if (!node.children || node.children.length === 0) {\n return '<li><span class=\"tree-dir empty\">' + escHtml(node.name || '.') + '/</span></li>';\n }\n const inner = node.children.map((c) =>\n c.type === 'file'\n ? '<li><button class=\"tree-file\" data-admin-action=\"preview-file\" data-file-path=\"' + escAttr(c.path) + '\">' + escHtml(c.name) + '</button></li>'\n : '<li><details open><summary class=\"tree-dir\">' + escHtml(c.name) + '/</summary><ul>' + renderTreeChildren(c) + '</ul></details></li>'\n ).join('');\n return inner;\n }\n\n function renderPreviewFileResult(previewEl, label, data) {\n if (data.binary) {\n previewEl.innerHTML = '<div class=\"preview-meta\">' + escHtml(label) + ' · ' + data.size + ' bytes · binary</div><div class=\"placeholder-msg\">Binary file — preview not available</div>';\n return;\n }\n previewEl.innerHTML =\n '<div class=\"preview-meta\">' + escHtml(label) + ' · ' + data.size + ' bytes</div>' +\n '<pre class=\"preview-body\">' + escHtml(data.content || '') + '</pre>';\n }\n\n async function previewFile(path) {\n const previewEl = document.getElementById('workspace-preview');\n previewEl.innerHTML = '<div class=\"loading-msg\">Loading ' + escHtml(path) + '…</div>';\n try {\n const data = await apiGet('/admin/api/workspace/file?' + scopeQuery() + '&path=' + encodeURIComponent(path));\n renderPreviewFileResult(previewEl, path, data);\n } catch (err) {\n previewEl.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n // ── Skills ───────────────────────────────────────────────────────────────────\n\n async function loadScopePanels(prefix, endpoint, render) {\n const convEl = document.getElementById(prefix + '-conv-content');\n const globalEl = document.getElementById(prefix + '-global-content');\n if (convEl) convEl.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n if (globalEl) globalEl.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n try {\n const data = await apiGet('/admin/api/' + endpoint + '?' + scopeQuery());\n render(data, convEl, globalEl);\n } catch (err) {\n if (convEl) convEl.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n if (globalEl) globalEl.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n // ── MCP servers ───────────────────────────────────────────────────────────────────────\n\n function mcpMessage(scope, text, kind) {\n const el = document.getElementById(scope === 'global' ? 'mcp-global-msg' : 'mcp-conv-msg');\n if (!el) return;\n el.style.display = 'block';\n el.className = 'status-msg status-msg-' + kind;\n el.textContent = text;\n }\n\n function mcpTransport(server) {\n return server.command\n ? server.command + (server.args && server.args.length ? ' ' + server.args.join(' ') : '')\n : (server.url || '');\n }\n\n function renderMcpServer(scope, name, server) {\n const transport = (server.command ? 'stdio: ' : 'http: ') + mcpTransport(server);\n const keys = [];\n if (server.envKeys && server.envKeys.length) keys.push('env: ' + server.envKeys.join(', '));\n if (server.headerKeys && server.headerKeys.length) keys.push('headers: ' + server.headerKeys.join(', '));\n return '<article class=\"mcp-preset mcp-installed-card\">' +\n '<div class=\"mcp-preset-top\">' +\n '<span class=\"mcp-preset-category\">' + (server.command ? 'STDIO' : 'HTTP') + '</span>' +\n (server.disabled ? '<span class=\"mcp-badge mcp-badge-warn\">disabled</span>' : '<span class=\"mcp-badge mcp-badge-ok\">enabled</span>') +\n '</div>' +\n '<h3>' + escHtml(name) + '</h3>' +\n '<p class=\"mcp-preset-meta mcp-installed-transport\">' + escHtml(transport) + '</p>' +\n (keys.length ? '<div class=\"mcp-preset-meta\">' + escHtml(keys.join(' · ')) + '</div>' : '') +\n '<div class=\"mcp-preset-actions\">' +\n '<button class=\"mcp-btn\" data-mcp-action=\"test\" data-mcp-scope=\"' + scope + '\" data-mcp-name=\"' + escAttr(name) + '\">Test</button>' +\n '<button class=\"mcp-btn\" data-mcp-action=\"toggle\" data-mcp-scope=\"' + scope + '\" data-mcp-name=\"' + escAttr(name) + '\">' + (server.disabled ? 'Enable' : 'Disable') + '</button>' +\n '<button class=\"mcp-btn mcp-btn-danger\" data-mcp-action=\"remove\" data-mcp-scope=\"' + scope + '\" data-mcp-name=\"' + escAttr(name) + '\">Remove</button>' +\n '</div>' +\n '</article>';\n }\n\n function renderMcpPreset(scope, preset, servers) {\n const installed = Boolean(servers[preset.serverName]);\n const transport = preset.server.command ? 'Runs on host' : 'Remote service';\n return '<article class=\"mcp-preset\">' +\n '<div class=\"mcp-preset-top\">' +\n '<span class=\"mcp-preset-category\">' + escHtml(preset.category) + '</span>' +\n (installed ? '<span class=\"mcp-badge mcp-badge-ok\">Installed here</span>' : '') +\n '</div>' +\n '<h3>' + escHtml(preset.name) + '</h3>' +\n '<p>' + escHtml(preset.description) + '</p>' +\n '<div class=\"mcp-preset-meta\">' + escHtml(transport) + ' · <code>' + escHtml(preset.serverName) + '</code></div>' +\n '<div class=\"mcp-preset-actions\">' +\n '<a href=\"' + escAttr(preset.sourceUrl) + '\" target=\"_blank\" rel=\"noopener\">Source ↗</a>' +\n '<button class=\"primary-action-btn\" data-mcp-action=\"preset\" data-mcp-scope=\"' + scope + '\" data-mcp-preset=\"' + escAttr(preset.id) + '\">' + (installed ? 'Review' : 'Install') + '</button>' +\n '</div>' +\n '</article>';\n }\n\n function renderMcpScope(el, scope, servers) {\n const presets = mcpPresets.map((preset) => renderMcpPreset(scope, preset, servers)).join('');\n const rows = Object.entries(servers).map(([name, server]) => renderMcpServer(scope, name, server)).join('');\n el.innerHTML =\n '<div class=\"mcp-market-head\"><div><h3>Explore presets</h3><p>Reviewed recipes that install into this scope.</p></div><span>' + mcpPresets.length + ' available</span></div>' +\n '<div class=\"mcp-preset-grid\">' + presets + '</div>' +\n '<details class=\"mcp-installed\" open><summary>Installed in this scope</summary>' +\n '<div class=\"mcp-preset-grid\">' +\n rows +\n '<button type=\"button\" class=\"mcp-add-card\" data-mcp-action=\"open-custom\" data-mcp-scope=\"' + scope + '\">' +\n '<span class=\"mcp-add-card-plus\">+</span><span>新增 server</span>' +\n '</button>' +\n '</div>' +\n '</details>';\n }\n\n function renderMcpGuidedForm(scope) {\n return '<div class=\"mcp-guided-grid\">' +\n '<label class=\"mcp-field\"><span>Server 名稱</span><input id=\"mcp-' + scope + '-g-name\" class=\"form-input mcp-json\" placeholder=\"例如 github\" autocomplete=\"off\" /></label>' +\n '<div class=\"mcp-transport-toggle\">' +\n '<label><input type=\"radio\" name=\"mcp-' + scope + '-g-transport\" value=\"stdio\" checked /> 本機指令 (stdio)</label>' +\n '<label><input type=\"radio\" name=\"mcp-' + scope + '-g-transport\" value=\"http\" /> 遠端服務 (HTTP)</label>' +\n '</div>' +\n '<div id=\"mcp-' + scope + '-g-stdio\" class=\"mcp-transport-fields\">' +\n '<label class=\"mcp-field\"><span>指令</span><input id=\"mcp-' + scope + '-g-command\" class=\"form-input mcp-json\" placeholder=\"npx\" autocomplete=\"off\" /></label>' +\n '<label class=\"mcp-field\"><span>參數(以逗號分隔)</span><input id=\"mcp-' + scope + '-g-args\" class=\"form-input mcp-json\" placeholder=\"-y, @modelcontextprotocol/server-github\" autocomplete=\"off\" /></label>' +\n '</div>' +\n '<div id=\"mcp-' + scope + '-g-http\" class=\"mcp-transport-fields\" style=\"display:none\">' +\n '<label class=\"mcp-field\"><span>URL</span><input id=\"mcp-' + scope + '-g-url\" class=\"form-input mcp-json\" placeholder=\"https://mcp.example.com/mcp\" autocomplete=\"off\" /></label>' +\n '</div>' +\n '<div class=\"mcp-kv-block\">' +\n '<div class=\"mcp-kv-head\"><span id=\"mcp-' + scope + '-g-kv-label\">環境變數 (env)</span><button type=\"button\" class=\"mcp-btn\" data-mcp-kv-add=\"' + scope + '\">+ 新增一列</button></div>' +\n '<div id=\"mcp-' + scope + '-g-kv\" class=\"mcp-kv-rows\"></div>' +\n '</div>' +\n '</div>';\n }\n\n function renderMcpKvRow() {\n return '<div class=\"mcp-kv-row\">' +\n '<input class=\"form-input mcp-json\" placeholder=\"KEY\" data-kv-key autocomplete=\"off\" />' +\n '<input class=\"form-input mcp-json\" type=\"password\" placeholder=\"value\" data-kv-value autocomplete=\"off\" />' +\n '<button type=\"button\" class=\"mcp-btn mcp-btn-danger\" data-mcp-kv-remove>移除</button>' +\n '</div>';\n }\n\n function addMcpGuidedRow(scope) {\n const container = document.getElementById('mcp-' + scope + '-g-kv');\n if (container) container.insertAdjacentHTML('beforeend', renderMcpKvRow());\n }\n\n function updateMcpGuidedTransport(scope) {\n const checked = document.querySelector('input[name=\"mcp-' + scope + '-g-transport\"]:checked');\n const transport = checked ? checked.value : 'stdio';\n const stdioEl = document.getElementById('mcp-' + scope + '-g-stdio');\n const httpEl = document.getElementById('mcp-' + scope + '-g-http');\n const kvLabel = document.getElementById('mcp-' + scope + '-g-kv-label');\n if (stdioEl) stdioEl.style.display = transport === 'stdio' ? '' : 'none';\n if (httpEl) httpEl.style.display = transport === 'http' ? '' : 'none';\n if (kvLabel) kvLabel.textContent = transport === 'stdio' ? '環境變數 (env)' : 'HTTP Headers';\n }\n\n let pendingMcpCustomScope = null;\n\n function openMcpCustomDialog(scope) {\n pendingMcpCustomScope = scope;\n const content = document.getElementById('mcp-custom-dialog-content');\n content.innerHTML =\n '<div class=\"mcp-add-mode\">' +\n '<button type=\"button\" class=\"mcp-mode-btn active\" data-mcp-mode=\"guided\">引導式表單</button>' +\n '<button type=\"button\" class=\"mcp-mode-btn\" data-mcp-mode=\"json\">貼上 JSON</button>' +\n '</div>' +\n '<div id=\"mcp-custom-guided-panel\" class=\"mcp-panel\">' + renderMcpGuidedForm('custom') + '</div>' +\n '<div id=\"mcp-custom-json-panel\" class=\"mcp-panel\" style=\"display:none\">' +\n '<p class=\"mcp-manual-hint\">貼上 MCP server 文件給的 <code>mcpServers</code> JSON,原樣保存到這個 scope。remote 走 Streamable HTTP,local 走 stdio。</p>' +\n '<textarea id=\"mcp-custom-json\" class=\"form-input mcp-json\" spellcheck=\"false\" rows=\"9\" placeholder=\"' + escAttr(MCP_JSON_PLACEHOLDER) + '\"></textarea>' +\n '</div>';\n const dialogError = document.getElementById('mcp-custom-dialog-error');\n dialogError.style.display = 'none';\n dialogError.textContent = '';\n addMcpGuidedRow('custom');\n document.getElementById('mcp-custom-dialog').showModal();\n }\n\n function closeMcpCustomDialog() {\n pendingMcpCustomScope = null;\n document.getElementById('mcp-custom-dialog').close();\n }\n\n function switchMcpCustomMode(mode) {\n const guidedEl = document.getElementById('mcp-custom-guided-panel');\n const jsonEl = document.getElementById('mcp-custom-json-panel');\n if (guidedEl) guidedEl.style.display = mode === 'guided' ? '' : 'none';\n if (jsonEl) jsonEl.style.display = mode === 'json' ? '' : 'none';\n document.querySelectorAll('#mcp-custom-dialog-content [data-mcp-mode]').forEach((b) => {\n b.classList.toggle('active', b.dataset.mcpMode === mode);\n });\n }\n\n async function submitMcpCustomDialog(btn) {\n const scope = pendingMcpCustomScope;\n if (!scope) return;\n const dialogError = document.getElementById('mcp-custom-dialog-error');\n dialogError.style.display = 'none';\n dialogError.textContent = '';\n const jsonMode = document.getElementById('mcp-custom-json-panel').style.display !== 'none';\n let json;\n if (jsonMode) {\n const raw = document.getElementById('mcp-custom-json').value.trim();\n if (!raw) { dialogError.textContent = '請貼上 mcpServers JSON'; dialogError.style.display = 'block'; return; }\n json = raw;\n } else {\n const nameEl = document.getElementById('mcp-custom-g-name');\n const name = nameEl ? nameEl.value.trim() : '';\n if (!name) { dialogError.textContent = '請輸入 server 名稱'; dialogError.style.display = 'block'; return; }\n const checked = document.querySelector('input[name=\"mcp-custom-g-transport\"]:checked');\n const transport = checked ? checked.value : 'stdio';\n const kv = {};\n document.querySelectorAll('#mcp-custom-g-kv .mcp-kv-row').forEach((row) => {\n const keyInput = row.querySelector('[data-kv-key]');\n const valueInput = row.querySelector('[data-kv-value]');\n const key = keyInput ? keyInput.value.trim() : '';\n if (key) kv[key] = valueInput ? valueInput.value : '';\n });\n let entry;\n if (transport === 'stdio') {\n const commandEl = document.getElementById('mcp-custom-g-command');\n const command = commandEl ? commandEl.value.trim() : '';\n if (!command) { dialogError.textContent = '請輸入指令'; dialogError.style.display = 'block'; return; }\n const argsEl = document.getElementById('mcp-custom-g-args');\n const argsRaw = argsEl ? argsEl.value.trim() : '';\n const args = argsRaw ? argsRaw.split(',').map((s) => s.trim()).filter(Boolean) : [];\n entry = Object.assign({ command: command }, args.length ? { args: args } : {}, Object.keys(kv).length ? { env: kv } : {});\n } else {\n const urlEl = document.getElementById('mcp-custom-g-url');\n const url = urlEl ? urlEl.value.trim() : '';\n if (!url) { dialogError.textContent = '請輸入 URL'; dialogError.style.display = 'block'; return; }\n entry = Object.assign({ url: url }, Object.keys(kv).length ? { headers: kv } : {});\n }\n json = JSON.stringify({ mcpServers: { [name]: entry } });\n }\n btn.disabled = true;\n btn.textContent = '儲存中…';\n try {\n const data = await apiPost('/admin/api/mcp-servers/mutate', {\n action: 'import', scope: scope, json: json, ...scopeBody(),\n });\n const results = Array.isArray(data.results) ? data.results : [];\n const failed = results.filter((r) => r.error).length;\n closeMcpCustomDialog();\n mcpMessage(scope, failed ? '已儲存,但 ' + failed + ' 個 server 連線失敗,見上方選項維護。' : '已儲存並連線成功。', failed ? 'err' : 'ok');\n await loadMcpServers();\n } catch (err) {\n dialogError.textContent = err.message;\n dialogError.style.display = 'block';\n } finally {\n btn.disabled = false;\n btn.textContent = '新增並測試連線';\n }\n }\n\n const MCP_JSON_PLACEHOLDER = JSON.stringify({\n mcpServers: {\n browserless: {\n type: 'http',\n url: 'https://mcp.browserless.io/mcp',\n headers: { Authorization: 'Bearer YOUR_API_TOKEN' },\n },\n },\n }, null, 2);\n\n const loadMcpServers = () => loadScopePanels('mcp', 'mcp-servers', (data, convEl, globalEl) => {\n mcpPresets = Array.isArray(data.presets) ? data.presets : [];\n mcpServersByScope = { conversation: data.conversation || {}, global: data.global || {} };\n if (convEl) renderMcpScope(convEl, 'conversation', mcpServersByScope.conversation);\n if (globalEl) renderMcpScope(globalEl, 'global', mcpServersByScope.global);\n });\n\n async function mutateMcpServer(scope, action, name, extra) {\n mcpMessage(scope, action === 'test' ? '連線測試中…' : '儲存並測試連線中…', 'busy');\n try {\n const data = await apiPost('/admin/api/mcp-servers/mutate', {\n action: action,\n scope: scope,\n ...(name ? { name: name } : {}),\n ...(extra || {}),\n ...scopeBody(),\n });\n const results = Array.isArray(data.results) ? data.results : [];\n const failed = results.filter((r) => r.error).length;\n if (action === 'test') {\n mcpMessage(scope, failed ? '✗ ' + name + ': ' + results[0].error : '✓ ' + name + ': ' + results[0].tools + ' tool(s)', failed ? 'err' : 'ok');\n return;\n }\n if (action === 'remove' || action === 'toggle') {\n mcpMessage(scope, '完成。新設定在下一次回應生效。', 'ok');\n } else {\n mcpMessage(scope, failed ? '已儲存,但 ' + failed + ' 個 server 連線失敗,見下方錯誤。' : '已儲存並連線成功。', failed ? 'err' : 'ok');\n }\n await loadMcpServers();\n } catch (err) {\n mcpMessage(scope, err.message, 'err');\n }\n }\n\n function openMcpPreset(scope, presetId) {\n const preset = mcpPresets.find((item) => item.id === presetId);\n if (!preset) return;\n pendingMcpInstall = { scope: scope, preset: preset };\n const local = Boolean(preset.server.command);\n const installed = Boolean(mcpServersByScope[scope][preset.serverName]);\n const credentials = preset.credentials.map((credential, index) =>\n '<label class=\"mcp-credential\"><span>' + escHtml(credential.label) + (credential.required ? ' *' : '') + '</span>' +\n '<input data-mcp-credential=\"' + index + '\" type=\"' + (credential.secret ? 'password' : 'text') + '\" autocomplete=\"off\" />' +\n '<small>' + escHtml(credential.description) + '</small></label>'\n ).join('');\n document.getElementById('mcp-dialog-title').textContent = preset.name;\n const dialogError = document.getElementById('mcp-dialog-error');\n dialogError.style.display = 'none';\n dialogError.textContent = '';\n document.getElementById('mcp-dialog-content').innerHTML =\n '<p class=\"mcp-dialog-desc\">' + escHtml(preset.description) + '</p>' +\n '<div class=\"mcp-install-preview\"><span>' + (local ? 'Host command' : 'Remote endpoint') + '</span><code>' + escHtml(mcpTransport(preset.server)) + '</code></div>' +\n '<div class=\"mcp-security-note ' + (local ? 'local' : 'remote') + '\">' +\n (local\n ? '<strong>Host code execution.</strong> This command runs outside the conversation sandbox with the mikan process user permissions.'\n : '<strong>External service.</strong> Tool calls and selected data will be sent to this remote origin.') +\n '</div>' +\n (installed ? '<div class=\"mcp-replace-note\">Installing again replaces the existing <code>' + escHtml(preset.serverName) + '</code> entry in this scope.</div>' : '') +\n (credentials || '<p class=\"mcp-no-credentials\">No credentials required.</p>') +\n '<p class=\"mcp-secret-note\">These values are stored in host-private settings and are not shown to the model or sandbox.</p>' +\n '<a class=\"mcp-setup-link\" href=\"' + escAttr(preset.setupUrl) + '\" target=\"_blank\" rel=\"noopener\">Setup documentation ↗</a>';\n document.getElementById('mcp-install-dialog').showModal();\n }\n\n function closeMcpInstall() {\n pendingMcpInstall = null;\n document.getElementById('mcp-install-dialog').close();\n }\n\n async function installMcpPreset(btn) {\n if (!pendingMcpInstall) return;\n const { scope, preset } = pendingMcpInstall;\n const credentials = {};\n document.querySelectorAll('[data-mcp-credential]').forEach((input) => {\n const descriptor = preset.credentials[Number(input.dataset.mcpCredential)];\n if (descriptor) credentials[descriptor.key] = input.value;\n });\n btn.disabled = true;\n btn.textContent = 'Installing…';\n try {\n const data = await apiPost('/admin/api/mcp-servers/mutate', {\n action: 'install', scope: scope, presetId: preset.id, credentials: credentials, ...scopeBody(),\n });\n closeMcpInstall();\n const result = (Array.isArray(data.results) ? data.results : [])[0];\n if (result && result.error) mcpMessage(scope, '✗ ' + preset.name + ' saved but failed to connect: ' + result.error, 'err');\n else mcpMessage(scope, '✓ ' + preset.name + ' installed, ' + (result ? result.tools : 0) + ' tool(s).', 'ok');\n await loadMcpServers();\n } catch (err) {\n const dialogError = document.getElementById('mcp-dialog-error');\n dialogError.textContent = err.message;\n dialogError.style.display = 'block';\n } finally {\n btn.disabled = false;\n btn.textContent = 'Install preset';\n }\n }\n\n document.addEventListener('click', (event) => {\n const modeBtn = event.target.closest('#mcp-custom-dialog-content [data-mcp-mode]');\n if (modeBtn) { switchMcpCustomMode(modeBtn.dataset.mcpMode); return; }\n const kvAddBtn = event.target.closest('[data-mcp-kv-add]');\n if (kvAddBtn) { addMcpGuidedRow(kvAddBtn.dataset.mcpKvAdd); return; }\n const kvRemoveBtn = event.target.closest('[data-mcp-kv-remove]');\n if (kvRemoveBtn) { kvRemoveBtn.closest('.mcp-kv-row').remove(); return; }\n const transportRadio = event.target.closest('input[name^=\"mcp-\"][name$=\"-g-transport\"]');\n if (transportRadio) {\n const match = /^mcp-(.+)-g-transport$/.exec(transportRadio.name);\n if (match) updateMcpGuidedTransport(match[1]);\n return;\n }\n const btn = event.target.closest('[data-mcp-action]');\n if (!btn) return;\n if (btn.dataset.mcpAction === 'open-custom') { openMcpCustomDialog(btn.dataset.mcpScope); return; }\n if (btn.dataset.mcpAction === 'preset') { openMcpPreset(btn.dataset.mcpScope, btn.dataset.mcpPreset); return; }\n void mutateMcpServer(btn.dataset.mcpScope, btn.dataset.mcpAction, btn.dataset.mcpName);\n });\n\n let skillsCache = [];\n\n function renderSkillsInto(containerId, skills, allowedSource) {\n const container = document.getElementById(containerId);\n if (!container) return;\n const filtered = allowedSource ? skills.filter((s) => s.source === allowedSource) : skills;\n if (filtered.length === 0) {\n container.innerHTML = '<div class=\"empty-state\">No skills available</div>';\n return;\n }\n container.innerHTML = '<div class=\"skills-list\">' +\n filtered.map((s) =>\n '<div class=\"skill-row\">' +\n '<button class=\"skill-row-btn\" data-skill-source=\"' + escAttr(s.source) + '\" data-skill-directory=\"' + escAttr(s.directory) + '\" data-skill-name=\"' + escAttr(s.name) + '\">' +\n '<div class=\"skill-name\">' + escHtml(s.name) + '<span class=\"skill-source skill-source-' + s.source + '\">' + s.source + '</span></div>' +\n (s.description ? '<div class=\"skill-desc\">' + escHtml(s.description) + '</div>' : '') +\n '</button>' +\n '<div class=\"skill-row-actions\">' +\n '<button class=\"mcp-btn\" data-skill-edit-source=\"' + escAttr(s.source) + '\" data-skill-edit-directory=\"' + escAttr(s.directory) + '\">Edit</button>' +\n '<button class=\"mcp-btn mcp-btn-danger\" data-skill-delete-source=\"' + escAttr(s.source) + '\" data-skill-delete-directory=\"' + escAttr(s.directory) + '\" data-skill-delete-name=\"' + escAttr(s.name) + '\">Delete</button>' +\n '</div>' +\n '</div>'\n ).join('') + '</div>';\n }\n\n async function loadSkills() {\n const container = document.getElementById('skills-content');\n const previewEl = document.getElementById('skills-preview');\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n if (previewEl) previewEl.innerHTML = '<div class=\"placeholder-msg\">Click a skill to preview SKILL.md</div>';\n try {\n const data = await apiGet('/admin/api/skills?' + scopeQuery());\n skillsCache = Array.isArray(data.skills) ? data.skills : [];\n renderSkillsInto('skills-content', skillsCache);\n renderSkillsInto('global-skills-content', skillsCache, 'global');\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n const loadGlobalSkills = loadSkills;\n\n async function previewSkillInto(previewId, source, directory, name) {\n const previewEl = document.getElementById(previewId);\n if (!previewEl) return;\n if (!source || !directory) {\n previewEl.innerHTML = '<div class=\"err-msg\">Missing skill source or directory</div>';\n return;\n }\n previewEl.innerHTML = '<div class=\"loading-msg\">Loading ' + escHtml(name || directory) + '…</div>';\n try {\n const data = await apiGet('/admin/api/skills/file?' + scopeQuery() + '&source=' + encodeURIComponent(source) + '&directory=' + encodeURIComponent(directory));\n renderPreviewFileResult(previewEl, source + '/' + directory + '/SKILL.md', data);\n } catch (err) {\n previewEl.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n async function deleteSkill(source, directory, name) {\n if (!confirm('Delete skill \"' + (name || directory) + '\" (' + source + ')?')) return;\n try {\n await apiPost('/admin/api/skills/mutate', { action: 'delete', source: source, directory: directory, ...scopeBody() });\n await loadSkills();\n } catch (err) {\n alert(err.message);\n }\n }\n\n function bindSkillListEvents(containerId, previewId) {\n const el = document.getElementById(containerId);\n if (!el) return;\n el.addEventListener('click', (event) => {\n const previewBtn = event.target.closest('[data-skill-source]');\n if (previewBtn) {\n previewSkillInto(previewId, previewBtn.dataset.skillSource, previewBtn.dataset.skillDirectory, previewBtn.dataset.skillName);\n return;\n }\n const editBtn = event.target.closest('[data-skill-edit-source]');\n if (editBtn) {\n const skill = skillsCache.find((s) => s.source === editBtn.dataset.skillEditSource && s.directory === editBtn.dataset.skillEditDirectory);\n if (skill) void openSkillDialog(skill.source, skill);\n return;\n }\n const deleteBtn = event.target.closest('[data-skill-delete-source]');\n if (deleteBtn) {\n void deleteSkill(deleteBtn.dataset.skillDeleteSource, deleteBtn.dataset.skillDeleteDirectory, deleteBtn.dataset.skillDeleteName);\n }\n });\n }\n bindSkillListEvents('skills-content', 'skills-preview');\n bindSkillListEvents('global-skills-content', 'global-skills-preview');\n\n let editingSkill = null;\n let pendingSkillScope = null;\n\n async function openSkillDialog(scope, existing) {\n editingSkill = existing ? { source: existing.source, directory: existing.directory } : null;\n document.getElementById('skill-dialog-eyebrow').textContent = scope === 'global' ? 'Global skill' : 'Conversation skill';\n document.getElementById('skill-dialog-title').textContent = existing ? 'Edit skill' : 'New skill';\n const dirInput = document.getElementById('skill-dialog-directory');\n dirInput.value = existing ? existing.directory : '';\n dirInput.disabled = Boolean(existing);\n document.getElementById('skill-dialog-name').value = existing ? existing.name : '';\n document.getElementById('skill-dialog-description').value = existing ? existing.description : '';\n const contentEl = document.getElementById('skill-dialog-content');\n contentEl.value = '';\n const dialogError = document.getElementById('skill-dialog-error');\n dialogError.style.display = 'none';\n dialogError.textContent = '';\n pendingSkillScope = scope;\n if (existing) {\n contentEl.value = 'Loading…';\n try {\n const data = await apiGet('/admin/api/skills/file?' + scopeQuery() + '&source=' + encodeURIComponent(existing.source) + '&directory=' + encodeURIComponent(existing.directory));\n contentEl.value = data.binary ? '' : (data.content || '').replace(/^---[\\\\s\\\\S]*?---\\\\n?/, '').trim();\n } catch (err) {\n contentEl.value = '';\n dialogError.textContent = 'Failed to load current content: ' + err.message;\n dialogError.style.display = 'block';\n }\n }\n document.getElementById('skill-dialog').showModal();\n }\n\n function closeSkillDialog() {\n editingSkill = null;\n pendingSkillScope = null;\n document.getElementById('skill-dialog').close();\n }\n\n async function submitSkillDialog(btn) {\n const dialogError = document.getElementById('skill-dialog-error');\n dialogError.style.display = 'none';\n dialogError.textContent = '';\n const directory = document.getElementById('skill-dialog-directory').value.trim();\n const name = document.getElementById('skill-dialog-name').value.trim() || directory;\n const description = document.getElementById('skill-dialog-description').value.trim();\n const content = document.getElementById('skill-dialog-content').value;\n if (!directory) { dialogError.textContent = 'Directory is required'; dialogError.style.display = 'block'; return; }\n if (!description) { dialogError.textContent = 'Description is required'; dialogError.style.display = 'block'; return; }\n const source = editingSkill ? editingSkill.source : pendingSkillScope;\n btn.disabled = true;\n btn.textContent = 'Saving…';\n try {\n await apiPost('/admin/api/skills/mutate', {\n action: 'save', source: source, directory: directory, name: name, description: description, content: content, ...scopeBody(),\n });\n closeSkillDialog();\n await loadSkills();\n } catch (err) {\n dialogError.textContent = err.message;\n dialogError.style.display = 'block';\n } finally {\n btn.disabled = false;\n btn.textContent = 'Save';\n }\n }\n\n // ── Vault (Login link) ───────────────────────────────────────────────────────\n\n const openLogin = (silent) => openPortalLink('vault', 'login', silent);\n const openSessionView = (silent) => openPortalLink('session', 'session', silent);\n\n // Generates a fresh one-time/short-lived link for the other portal and\n // opens it in a new tab — the login and session-view tokens are separate\n // capabilities from the admin token (see docs/portal-auth-model.md), so\n // this always mints a new link rather than reusing anything cached here.\n async function openPortalLink(resultId, kind, silent) {\n const result = document.getElementById(resultId + '-link-result');\n if (silent) { result.style.display = 'none'; return; }\n result.style.display = 'block'; result.className = 'link-result loading'; result.textContent = 'Generating link…';\n try {\n const data = await apiPost('/admin/api/conversations/' + kind + '-link', scopeBody());\n result.className = 'link-result ok';\n result.innerHTML =\n (kind === 'login' ? '<span class=\"link-vault\">vault: <code>' + escHtml(data.vaultId) + '</code></span>' : '') +\n '<a href=\"' + escAttr(data.url) + '\" target=\"_blank\" rel=\"noopener\">' + escHtml(data.url) + '</a>' +\n '<button class=\"copy-link-btn\" data-admin-action=\"copy-link\" data-copy-text=\"' + escAttr(data.url) + '\">Copy</button>';\n window.open(data.url, '_blank', 'noopener');\n } catch (err) {\n result.className = 'link-result err'; result.textContent = err.message;\n }\n }\n\n // ── Events ───────────────────────────────────────────────────────────────────\n\n const loadConversationEvents = () => loadEventList(true);\n const loadEvents = () => loadEventList(false);\n\n async function loadEventList(conversation) {\n const container = document.getElementById(conversation ? 'events-content' : 'global-events-content');\n if (!container) return;\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n try {\n const data = await apiGet(conversation ? '/admin/api/conversations/events?' + scopeQuery() : '/admin/api/events');\n if (data.events.length === 0) {\n container.innerHTML = '<div class=\"empty-state\">' + (conversation ? '沒有關聯此對話的 event' : 'No events scheduled') + '</div>';\n return;\n }\n container.innerHTML = '<div class=\"events-list\">' +\n data.events.map((e) => renderEventRow(e, conversation)).join('') + '</div>';\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n function renderEventRow(e, allowDelete) {\n const meta = [e.type, e.platform, e.conversationId, e.schedule || e.at]\n .filter(Boolean).map(escHtml).join(' · ');\n const preview = e.text ? '<div class=\"event-text\">' + escHtml(e.text.length > 240 ? e.text.slice(0, 237) + '…' : e.text) + '</div>' : '';\n const deleteBtn = allowDelete\n ? '<button class=\"event-delete-btn\" data-admin-action=\"delete-event\" data-event-name=\"' + escAttr(e.name) + '\">Delete</button>'\n : '';\n return '<div class=\"event-row\">' +\n '<div class=\"event-row-top\">' +\n '<div class=\"event-name\"><code>' + escHtml(e.name) + '</code></div>' +\n deleteBtn +\n '</div>' +\n '<div class=\"event-meta\">' + meta + '</div>' +\n preview +\n '</div>';\n }\n\n async function deleteEvent(name, btn) {\n if (!confirm('Delete event \"' + name + '\"?')) return;\n btn.disabled = true; btn.textContent = 'Deleting…';\n try {\n await apiPost('/admin/api/conversations/events/delete', {\n ...scopeBody(), name,\n });\n await loadConversationEvents();\n } catch (err) {\n btn.disabled = false; btn.textContent = 'Delete';\n alert(err.message);\n }\n }\n\n // ── Global section ──────────────────────────────────────────────────────────\n\n // Switching to the Workspace scope only needs to (re)select its first\n // pane; every pane still loads lazily through paneLoader/ensurePaneLoaded\n // the first time it becomes active, same as the conversation scope.\n function initGlobal() {}\n\n async function loadAllConversations() {\n const container = document.getElementById('all-conv-content');\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n try {\n const data = await apiGet('/admin/api/conversations');\n if (data.conversations.length === 0) {\n container.innerHTML = '<div class=\"empty-state\">No conversations found</div>';\n return;\n }\n container.innerHTML = '<div class=\"conv-list\">' + data.conversations.map((c) => {\n const last = c.lastActivityAt ? new Date(c.lastActivityAt).toLocaleString() : '—';\n return '<button class=\"conv-row-btn\" data-admin-action=\"select-conversation\" data-conversation-id=\"' + escAttr(c.conversationId) + '\">' +\n '<span class=\"conv-id\">' + escHtml(c.label || c.conversationId) + '</span>' +\n (c.running ? '<span class=\"status-pill running\">running</span>' : '') +\n '<span class=\"conv-last\">' + escHtml(last) + '</span>' +\n '</button>';\n }).join('') + '</div>';\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n async function loadSessionUsage() {\n const container = document.getElementById('session-usage-content');\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n try {\n const data = await apiGet('/admin/api/session-usage');\n if (data.sessions.length === 0) {\n container.innerHTML = '<div class=\"empty-state\">No token usage found</div>';\n return;\n }\n container.innerHTML = '<div class=\"usage-table-wrap\"><table class=\"usage-table\"><thead><tr><th>#</th><th>Channel</th><th>Session</th><th>Updated</th><th>Input</th><th>Output</th><th>Cache Read</th><th>Cache Write</th><th>Total</th><th>Cost</th></tr></thead><tbody>' +\n data.sessions.map((s, i) => '<tr>' +\n '<td>' + (i + 1) + '</td>' +\n '<td>' + escHtml(s.label || s.conversationId) + '</td>' +\n '<td><code>' + escHtml(s.fileName) + '</code></td>' +\n '<td>' + escHtml(new Date(s.updatedAt).toLocaleString()) + '</td>' +\n '<td>' + fmtNum(s.input) + '</td>' +\n '<td>' + fmtNum(s.output) + '</td>' +\n '<td>' + fmtNum(s.cacheRead) + '</td>' +\n '<td>' + fmtNum(s.cacheWrite) + '</td>' +\n '<td><strong>' + fmtNum(s.total) + '</strong></td>' +\n '<td>' + (s.cost > 0 ? '$' + Number(s.cost).toFixed(4) : '—') + '</td>' +\n '</tr>').join('') + '</tbody></table></div>';\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n function fmtNum(value) {\n return Number(value || 0).toLocaleString('en-US');\n }\n\n let timelineConvLoaded = false;\n let timelineData = null;\n let timelineFilter = null;\n async function ensureTimelineConvOptions() {\n if (timelineConvLoaded) return;\n const sel = document.getElementById('timeline-conv');\n const prev = sel.value;\n const data = await apiGet('/admin/api/conversations');\n if (!data.conversations.length) {\n sel.innerHTML = '<option value=\"\">No conversations</option>';\n timelineConvLoaded = true;\n return;\n }\n const want = prev || defaultConversationKey;\n sel.innerHTML = data.conversations.map((c) => {\n const key = c.platform + ':' + c.conversationId;\n return '<option value=\"' + escAttr(key) + '\"' +\n (key === want ? ' selected' : '') + '>' +\n escHtml(c.label || c.conversationId) + '</option>';\n }).join('');\n timelineConvLoaded = true;\n }\n\n // Shared refresh for the merged Token Usage section: reloads the session\n // ranking and re-fetches the conversation list (so new sessions appear),\n // preserving the currently selected conversation.\n async function loadTokenUsage() {\n loadSessionUsage();\n timelineConvLoaded = false;\n await loadUsageTimeline();\n }\n\n async function loadUsageTimeline() {\n const container = document.getElementById('usage-timeline-content');\n try {\n await ensureTimelineConvOptions();\n const conv = document.getElementById('timeline-conv').value;\n if (!conv) {\n container.innerHTML = '<div class=\"empty-state\">No conversations found</div>';\n return;\n }\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n const convScope = scopeOf(conv);\n const data = await apiGet('/admin/api/conversation-usage?conversationId=' +\n encodeURIComponent(convScope.conversationId) +\n '&platform=' + encodeURIComponent(convScope.platform));\n timelineData = data;\n container.innerHTML = renderUsageTimeline(data);\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n function tlCard(label, value) {\n return '<div class=\"tl-card\"><div class=\"tl-card-label\">' + label +\n '</div><div class=\"tl-card-value\">' + value + '</div></div>';\n }\n\n const TL_SERIES = [\n { key: 'cacheRead', seg: 'tl-cache-read', sw: 'sw-cache-read', label: 'Cache read' },\n { key: 'cacheWrite', seg: 'tl-cache-write', sw: 'sw-cache-write', label: 'Cache write' },\n { key: 'input', seg: 'tl-input', sw: 'sw-input', label: 'Input' },\n { key: 'output', seg: 'tl-output', sw: 'sw-output', label: 'Output' },\n ];\n\n // Click a legend item to show only that series; click it again for all.\n function toggleTimelineFilter(key) {\n timelineFilter = timelineFilter === key ? null : key;\n if (timelineData) {\n document.getElementById('usage-timeline-content').innerHTML = renderUsageTimeline(timelineData);\n }\n }\n\n function renderUsageTimeline(data) {\n const buckets = data.buckets || [];\n const totals = data.totals || { total: 0, cost: 0, cacheRead: 0 };\n const cacheHit = totals.total > 0 ? Math.round((totals.cacheRead / totals.total) * 100) : 0;\n const cards = '<div class=\"tl-cards\">' +\n tlCard('Total cost', totals.cost > 0 ? '$' + Number(totals.cost).toFixed(4) : '—') +\n tlCard('Total tokens', fmtNum(totals.total)) +\n tlCard('Cache hit', cacheHit + '%') +\n '</div>';\n\n if (totals.total === 0) {\n const emptyNote = data.hasOlder\n ? '<div class=\"tl-note\">No usage in the last 14 days · earlier activity exists</div>'\n : '<div class=\"empty-state\">No token usage in the last 14 days</div>';\n return cards + emptyNote;\n }\n\n const active = TL_SERIES.find((s) => s.key === timelineFilter) || null;\n const valueOf = (b) => active ? (b[active.key] || 0) : b.total;\n const max = Math.max(1, ...buckets.map(valueOf));\n const px = (v) => Math.round((v / max) * 180);\n\n const legend = '<div class=\"tl-legend\">' + TL_SERIES.map((s) => {\n const cls = 'tl-legend-item' +\n (active && active.key === s.key ? ' active' : (active ? ' dim' : ''));\n return '<span class=\"' + cls + '\" data-admin-action=\"toggle-timeline-filter\" data-filter-key=\"' + escAttr(s.key) + '\">' +\n '<i class=\"sw ' + s.sw + '\"></i>' + s.label + '</span>';\n }).join('') + '</div>';\n\n const bars = buckets.map((b) => {\n const val = valueOf(b);\n const tip = active\n ? b.date + ' · ' + active.label + ': ' + fmtNum(b[active.key] || 0) + ' tokens'\n : b.date + ' · ' + fmtNum(b.total) + ' tokens' +\n (b.cost > 0 ? ' · $' + Number(b.cost).toFixed(4) : '');\n let inner;\n if (val <= 0) {\n inner = '<span class=\"tl-empty\"></span>';\n } else if (active) {\n inner = '<span class=\"tl-seg ' + active.seg + '\" style=\"height:' + px(val) + 'px\"></span>';\n } else {\n inner = '<span class=\"tl-seg tl-output\" style=\"height:' + px(b.output) + 'px\"></span>' +\n '<span class=\"tl-seg tl-input\" style=\"height:' + px(b.input) + 'px\"></span>' +\n '<span class=\"tl-seg tl-cache-write\" style=\"height:' + px(b.cacheWrite) + 'px\"></span>' +\n '<span class=\"tl-seg tl-cache-read\" style=\"height:' + px(b.cacheRead) + 'px\"></span>';\n }\n return '<div class=\"tl-bar\">' +\n '<span class=\"tl-tip\">' + escHtml(tip) + '</span>' +\n '<div class=\"tl-fill\">' + inner + '</div>' +\n '</div>';\n }).join('');\n\n const axis = buckets.length\n ? '<div class=\"tl-axis\"><span>' + escHtml(buckets[0].date.slice(5)) +\n '</span><span>' + escHtml(buckets[buckets.length - 1].date.slice(5)) + '</span></div>'\n : '';\n const note = data.hasOlder\n ? '<div class=\"tl-note\">Showing last 14 days · earlier activity not shown</div>'\n : '<div class=\"tl-note\">Showing last 14 days</div>';\n const peak = '<div class=\"tl-peak\" style=\"bottom:180px\"><span class=\"tl-peak-label\">' +\n fmtNum(max) + ' tokens</span></div>';\n return cards + legend + '<div class=\"tl-chart\">' + peak + bars + '</div>' + axis + note;\n }\n\n function renderGlobalSettings(data) {\n const thinkingOpts = renderThinkingOptions(data.thinkingLevel);\n const replyModeOpts = renderReplyOptions(data.slack);\n return [\n '<div class=\"config-grid\">',\n renderConfigCard('Default model', [\n '<div class=\"config-row config-row-stack\"><label>Model</label><select id=\"g-model-ref\">' + renderModelOptions(data.provider, data.model) + '</select></div>',\n '<div class=\"config-row\"><label>Thinking</label><select id=\"g-thinking\">' + thinkingOpts + '</select></div>',\n ].join(''), 'saveGlobalModel', 'Save model', 'g-model-result'),\n renderConfigCard('Sandbox limits', [\n '<div class=\"config-row\"><label>CPUs</label><input id=\"g-cpus\" placeholder=\"0.5\" value=\"' + escAttr(data.sandboxCpus || '') + '\"></div>',\n '<div class=\"config-row\"><label>Memory</label><input id=\"g-mem\" placeholder=\"1g\" value=\"' + escAttr(data.sandboxMemory || '') + '\"></div>',\n '<div class=\"config-row\"><label>Boost CPUs</label><input id=\"g-bcpus\" placeholder=\"2\" value=\"' + escAttr(data.sandboxBoostCpus || '') + '\"></div>',\n '<div class=\"config-row\"><label>Boost Mem</label><input id=\"g-bmem\" placeholder=\"4g\" value=\"' + escAttr(data.sandboxBoostMemory || '') + '\"></div>',\n ].join(''), 'saveGlobalSandbox', 'Save sandbox', 'g-sandbox-result'),\n renderConfigCard('Slack', [\n '<div class=\"config-row\"><label>Reply mode</label><select id=\"g-slack-reply-mode\">' + replyModeOpts + '</select></div>',\n ].join(''), 'saveGlobalSlack', 'Save Slack', 'g-slack-result'),\n '</div>',\n ].join('');\n }\n\n async function saveGlobalModel(btn) {\n const selectedModel = parseModelRef(document.getElementById('g-model-ref').value.trim());\n const provider = selectedModel.provider;\n const model = selectedModel.model;\n const thinkingLevel = document.getElementById('g-thinking').value;\n const result = document.getElementById('g-model-result');\n if (!provider || !model) {\n result.style.display = 'block'; result.className = 'inline-result err';\n result.textContent = 'Provider and model are required'; return;\n }\n btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';\n try {\n await apiPost('/admin/api/settings/model', { provider, model, thinkingLevel });\n result.style.display = 'block'; result.className = 'inline-result ok'; result.textContent = 'Saved ✓';\n } catch (err) {\n result.style.display = 'block'; result.className = 'inline-result err'; result.textContent = err.message;\n } finally {\n btn.disabled = false; btn.textContent = 'Save model';\n }\n }\n\n async function saveGlobalSandbox(btn) {\n const cpus = document.getElementById('g-cpus').value.trim();\n const memory = document.getElementById('g-mem').value.trim();\n const boostCpus = document.getElementById('g-bcpus').value.trim();\n const boostMemory = document.getElementById('g-bmem').value.trim();\n const result = document.getElementById('g-sandbox-result');\n await saveSetting(btn, result, 'settings/sandbox', { cpus, memory, boostCpus, boostMemory }, 'Save sandbox');\n }\n\n async function saveGlobalSlack(btn) {\n const replyMode = document.getElementById('g-slack-reply-mode').value;\n const result = document.getElementById('g-slack-result');\n await saveSetting(btn, result, 'settings/slack', { replyMode }, 'Save Slack');\n }\n\n // ── Init ─────────────────────────────────────────────────────────────────────\n\n // Panes load on demand (see ensurePaneLoaded); loadSettingsPanel already\n // calls loadModels() itself the first time it's needed.\n initConvSwitcher();\n initRailNav();\n `;\n\nfunction renderAdminPage(token: AdminToken): string {\n const userLabel = token.platformUserName ?? token.platformUserId;\n const script = `\n const adminToken = ${JSON.stringify(token.token)};\n // Conversation ids never contain \":\" (session-key grammar), so\n // \"platform:id\" is a safe composite scope key for the UI.\n const defaultConversationKey = ${JSON.stringify(`${token.platform}:${token.conversationId}`)};\n${adminViewScript}`;\n\n return renderPortalShell({\n activeView: \"admin\",\n pageTitle: \"Admin\",\n identity: { primary: token.platform, secondary: userLabel },\n conversationSwitcher: { currentId: token.conversationId },\n body: adminViewBody,\n extraStyles: adminViewStyles,\n inlineScript: script,\n });\n}\n\nfunction renderAdminErrorPage(message: string): string {\n return renderPortalShell({\n activeView: \"admin\",\n pageTitle: \"Admin\",\n body: `<section class=\"card\" style=\"text-align:center;padding:40px 32px\">\n <p class=\"eyebrow\">${PRODUCT_NAME} admin</p>\n <h1 class=\"page-title\" style=\"margin:12px 0 16px\">Access Denied</h1>\n <div class=\"err-msg\">${esc(message)}</div>\n </section>`,\n });\n}\n\n// ── Styles ─────────────────────────────────────────────────────────────────────\n\nconst adminViewStyles = `\n /* The shared shell caps at 960px for the narrower session/login portals;\n the sidebar + single-pane layout here reads cramped at that width, so\n admin alone widens it. */\n .shell { max-width: 1180px; }\n\n /* ── Settings shell: persistent rail + single active pane ───────────── */\n\n .settings-shell {\n display: grid;\n grid-template-columns: 216px 1fr;\n align-items: start;\n gap: 22px;\n }\n\n .settings-rail {\n position: sticky;\n top: 28px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .rail-scope {\n display: flex;\n padding: 3px;\n border: 1px solid var(--border);\n border-radius: 11px;\n background: rgba(0,0,0,0.03);\n gap: 2px;\n }\n .rail-scope-btn {\n flex: 1;\n padding: 7px 8px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--muted);\n font: 600 0.72rem/1.2 'DM Sans', sans-serif;\n letter-spacing: 0.01em;\n cursor: pointer;\n transition: background 140ms, color 140ms;\n }\n .rail-scope-btn:hover { color: var(--text); }\n .rail-scope-btn.active { background: var(--surface); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,0.1); }\n .rail-scope-btn:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }\n\n .rail-nav { display: flex; flex-direction: column; gap: 1px; }\n .rail-nav[hidden] { display: none; }\n .rail-link {\n display: flex; align-items: center; gap: 10px;\n padding: 8px 10px; border: none; border-radius: 9px;\n background: transparent; color: var(--muted); text-align: left;\n font: 500 0.86rem/1.2 'DM Sans', sans-serif; cursor: pointer;\n transition: background 120ms, color 120ms;\n }\n .rail-link svg { flex-shrink: 0; opacity: 0.75; }\n .rail-link:hover { background: rgba(0,0,0,0.045); color: var(--text); }\n .rail-link:hover svg { opacity: 1; }\n .rail-link.active {\n background: var(--text); color: #fafafa; font-weight: 600;\n }\n .rail-link.active svg { opacity: 1; }\n .rail-link:focus-visible { outline: 2px solid var(--text); outline-offset: 1px; }\n\n .settings-panels { min-width: 0; }\n .tab-panel { display: none; flex-direction: column; gap: 0; }\n .tab-panel.active { display: flex; }\n\n /* ── Panes: one continuous surface, not stacked cards ────────────────── */\n\n .pane { display: none; padding: 30px 0; border-bottom: 1px solid var(--border); }\n .pane:last-child { border-bottom: none; }\n .pane.active { display: block; animation: pane-in 180ms ease; }\n @keyframes pane-in { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }\n\n .pane-head {\n display: flex; align-items: flex-start; justify-content: space-between;\n gap: 16px; margin-bottom: 22px; flex-wrap: wrap;\n }\n .pane-title {\n font-family: 'Lora', Georgia, serif; font-size: 1.32rem; font-weight: 600;\n letter-spacing: -0.01em; line-height: 1.25; margin-bottom: 5px;\n }\n .pane-desc { color: var(--muted); font-size: 0.88rem; line-height: 1.55; max-width: 52ch; }\n .pane-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }\n .pane-body { display: flex; flex-direction: column; gap: 14px; }\n\n .card-desc { color: var(--muted); font-size: 0.9rem; line-height: 1.55; margin-bottom: 12px; }\n\n .link-result {\n margin-top: 12px; padding: 10px 14px; border-radius: 10px;\n display: flex; gap: 10px; align-items: center; flex-wrap: wrap;\n font-size: 0.84rem;\n }\n .link-result.ok { background: var(--ok-bg); border: 1px solid var(--ok-border); }\n .link-result.err { background: var(--err-bg); border: 1px solid var(--err-border); color: var(--err-text); }\n .link-result.loading { background: rgba(0,0,0,0.025); border: 1px solid var(--border); color: var(--muted); }\n .link-result a {\n color: var(--ok-text);\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n font-size: 0.78rem; word-break: break-all; flex: 1; min-width: 0;\n }\n .link-vault { color: var(--muted); font-size: 0.78rem; flex-shrink: 0; }\n .copy-link-btn {\n padding: 5px 12px; border: 1px solid var(--ok-border); border-radius: 7px;\n background: rgba(255,255,255,0.7); color: var(--ok-text);\n font: 500 0.78rem/1.2 'DM Sans', sans-serif;\n cursor: pointer; flex-shrink: 0;\n }\n\n .config-grid {\n display: grid; grid-template-columns: 1fr 1fr; gap: 18px;\n }\n .config-block { display: flex; flex-direction: column; gap: 10px; }\n /* Config blocks are flex columns, so a plain child button stretches to the\n full column width. Keep the save action a normal-sized button instead. */\n .config-block .primary-action-btn { align-self: flex-start; min-width: 132px; justify-content: center; }\n .config-row { display: grid; grid-template-columns: 110px 1fr; gap: 10px; align-items: center; }\n .config-row.config-row-stack { grid-template-columns: 1fr; }\n .config-row label { font-size: 0.82rem; color: var(--muted); }\n .config-row input, .config-row select, .config-row textarea {\n padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px;\n font-family: inherit; font-size: 0.84rem; width: 100%;\n }\n .config-row textarea {\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n resize: vertical;\n }\n .toggle { display: inline-flex; align-items: center; gap: 8px; font-size: 0.84rem; }\n\n .inline-result {\n padding: 8px 12px; border-radius: 8px; font-size: 0.82rem; margin-top: 4px;\n }\n .inline-result.ok { background: var(--ok-bg); color: var(--ok-text); border: 1px solid var(--ok-border); }\n .inline-result.err { background: var(--err-bg); color: var(--err-text); border: 1px solid var(--err-border); }\n\n .refresh-btn {\n flex-shrink: 0; padding: 6px 12px;\n border: 1px solid var(--border); border-radius: 10px;\n background: rgba(0,0,0,0.025); color: var(--muted);\n font: 500 0.8rem/1.2 'DM Sans', sans-serif; cursor: pointer;\n transition: background 120ms, color 120ms;\n }\n .refresh-btn:hover { background: rgba(0,0,0,0.06); color: var(--text); }\n\n /* ── Workspace ──────────────────────────────────────────────────────── */\n\n .workspace-split {\n display: grid; grid-template-columns: 260px 1fr; gap: 14px;\n min-height: 360px;\n }\n .workspace-tree {\n border: 1px solid var(--border); border-radius: 12px; padding: 10px;\n background: rgba(0,0,0,0.02); overflow: auto; max-height: 480px;\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n font-size: 0.78rem;\n }\n .workspace-tree ul { list-style: none; padding-left: 12px; margin: 0; }\n .workspace-tree .tree-root { padding-left: 0; }\n .workspace-tree details { margin: 1px 0; }\n .workspace-tree summary { cursor: pointer; padding: 2px 4px; border-radius: 4px; }\n .workspace-tree summary:hover { background: rgba(0,0,0,0.05); }\n .tree-dir { color: var(--text); font-weight: 600; }\n .tree-dir.empty { color: var(--subtle); font-weight: 400; }\n .tree-file {\n display: block; width: 100%; text-align: left;\n background: transparent; border: none; cursor: pointer;\n padding: 2px 4px; border-radius: 4px;\n font-family: inherit; font-size: inherit; color: var(--muted);\n }\n .tree-file:hover { background: rgba(0,0,0,0.05); color: var(--text); }\n\n .workspace-preview {\n border: 1px solid var(--border); border-radius: 12px;\n background: #fff; padding: 12px; overflow: auto; max-height: 480px;\n }\n .preview-meta {\n font-size: 0.74rem; color: var(--subtle);\n margin-bottom: 8px; padding-bottom: 8px; border-bottom: 1px solid var(--border);\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n }\n .preview-body {\n margin: 0; white-space: pre-wrap; word-break: break-word;\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n font-size: 0.78rem; color: var(--text);\n }\n .placeholder-msg { color: var(--subtle); font-size: 0.86rem; padding: 24px 8px; text-align: center; }\n\n /* ── Skills ─────────────────────────────────────────────────────────── */\n\n .skills-list { display: flex; flex-direction: column; gap: 8px; }\n .skill-row {\n padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;\n background: rgba(0,0,0,0.02);\n display: flex; flex-direction: column; align-items: stretch; gap: 6px;\n }\n .skill-row-btn {\n flex: 1 1 auto; min-width: 0; text-align: left; cursor: pointer; font-family: inherit;\n background: transparent; border: none; padding: 0;\n }\n .skill-row-btn:hover .skill-name { color: var(--accent); }\n .skill-row-actions { display: flex; gap: 6px; flex-shrink: 0; justify-content: flex-end; }\n .skill-name {\n font-weight: 650; font-size: 0.9rem; color: var(--text);\n display: flex; align-items: center; gap: 8px; flex-wrap: wrap;\n }\n .skill-source {\n padding: 1px 8px; border-radius: 999px; font-size: 0.7rem;\n font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;\n }\n .skill-source-global { background: rgba(59,130,246,0.1); color: #1d4ed8; }\n .skill-source-conversation { background: rgba(217,119,6,0.1); color: var(--accent); }\n .skill-desc { color: var(--muted); font-size: 0.82rem; margin-top: 4px; line-height: 1.5; }\n\n /* ── MCP marketplace ───────────────────────────────────────────────── */\n\n .form-input {\n flex: 1 1 240px; min-width: 0; padding: 8px 10px;\n border: 1px solid var(--border); border-radius: 8px; background: var(--card);\n font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 0.8rem; color: var(--text);\n }\n .status-msg {\n padding: 8px 12px; border-radius: 8px; margin-bottom: 12px;\n font-size: 0.82rem; line-height: 1.5; word-break: break-word;\n }\n .status-msg-ok { background: rgba(22,163,74,0.1); color: #15803d; }\n .status-msg-err { background: rgba(220,38,38,0.1); color: #b91c1c; }\n .status-msg-busy { background: rgba(0,0,0,0.05); color: var(--muted); }\n .mcp-btn {\n padding: 4px 10px; border: 1px solid var(--border); border-radius: 7px;\n background: var(--card); color: var(--text); font-size: 0.76rem; cursor: pointer;\n }\n .mcp-btn:hover { background: rgba(0,0,0,0.05); }\n .mcp-btn-danger { color: #b91c1c; }\n .mcp-badge {\n padding: 1px 8px; border-radius: 999px; font-size: 0.7rem;\n font-weight: 600; letter-spacing: 0.03em;\n }\n .mcp-badge-ok { background: rgba(22,163,74,0.1); color: #15803d; }\n .mcp-badge-warn { background: rgba(217,119,6,0.12); color: var(--accent); }\n\n .mcp-market-head {\n display: flex; align-items: end; justify-content: space-between; gap: 16px;\n margin-bottom: 12px;\n }\n .mcp-market-head h3 { margin: 0; font-size: 1rem; }\n .mcp-market-head p { margin: 3px 0 0; color: var(--muted); font-size: 0.8rem; }\n .mcp-market-head > span {\n color: var(--subtle); font: 500 0.72rem/1.2 'JetBrains Mono', ui-monospace, monospace;\n }\n .mcp-preset-grid {\n display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px;\n }\n .mcp-preset {\n min-width: 0; padding: 14px; border: 1px solid var(--border); border-radius: 12px;\n background:\n linear-gradient(145deg, rgba(255,255,255,0.85), rgba(247,245,238,0.72)),\n var(--card);\n display: flex; flex-direction: column; min-height: 190px;\n }\n .mcp-preset-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\n .mcp-preset-category {\n color: var(--accent); font-size: 0.66rem; font-weight: 700;\n letter-spacing: 0.09em; text-transform: uppercase;\n }\n .mcp-preset h3 { margin: 14px 0 5px; font-size: 1.06rem; letter-spacing: -0.02em; }\n .mcp-preset p { margin: 0; color: var(--muted); font-size: 0.8rem; line-height: 1.5; }\n .mcp-preset-meta {\n margin-top: 12px; color: var(--subtle); font-size: 0.72rem;\n }\n .mcp-preset-meta code { color: var(--text); background: transparent; }\n .mcp-preset-actions {\n margin-top: auto; padding-top: 16px; display: flex; align-items: center;\n justify-content: space-between; gap: 10px;\n }\n .mcp-preset-actions a, .mcp-setup-link {\n color: var(--muted); font-size: 0.76rem; text-decoration: none;\n }\n .mcp-preset-actions a:hover, .mcp-setup-link:hover { color: var(--text); text-decoration: underline; }\n .mcp-preset-actions .primary-action-btn { padding: 6px 12px; }\n .mcp-installed {\n margin-top: 14px; border-top: 1px solid var(--border); padding-top: 12px;\n }\n .mcp-installed > summary {\n cursor: pointer; color: var(--muted); font-size: 0.8rem; font-weight: 600;\n margin-bottom: 10px;\n }\n .mcp-installed-card { min-height: 150px; }\n .mcp-installed-transport {\n font-family: 'JetBrains Mono', ui-monospace, monospace; word-break: break-all;\n }\n .mcp-add-card {\n min-width: 0; min-height: 190px; border: 1.5px dashed var(--border); border-radius: 12px;\n background: transparent; color: var(--muted); font-size: 0.86rem; font-weight: 600;\n display: flex; flex-direction: column; align-items: center; justify-content: center;\n gap: 8px; cursor: pointer;\n }\n .mcp-add-card:hover { background: rgba(0,0,0,0.03); color: var(--text); border-color: var(--text); }\n .mcp-add-card-plus { font-size: 1.8rem; line-height: 1; font-weight: 400; }\n .mcp-manual-hint { color: var(--muted); font-size: 0.8rem; margin: 0 0 10px; line-height: 1.5; }\n .mcp-add-mode { display: flex; gap: 8px; margin: 0 0 12px; }\n .mcp-mode-btn {\n padding: 6px 12px; border: 1px solid var(--border); border-radius: 999px;\n background: var(--card); font-size: 0.8rem; cursor: pointer; color: var(--muted);\n }\n .mcp-mode-btn.active { background: var(--text); color: #fafafa; border-color: var(--text); }\n .mcp-guided-grid { display: grid; gap: 12px; }\n .mcp-field { display: grid; gap: 5px; }\n .mcp-field span { font-size: 0.78rem; font-weight: 650; color: var(--muted); }\n .mcp-transport-toggle { display: flex; gap: 16px; font-size: 0.85rem; align-items: center; }\n .mcp-transport-toggle label { display: flex; align-items: center; gap: 6px; cursor: pointer; }\n .mcp-transport-fields { display: grid; gap: 12px; }\n .mcp-kv-block { display: grid; gap: 8px; }\n .mcp-kv-head { display: flex; align-items: center; justify-content: space-between; }\n .mcp-kv-head span { font-size: 0.78rem; font-weight: 650; color: var(--muted); }\n .mcp-kv-rows { display: grid; gap: 6px; }\n .mcp-kv-row { display: flex; gap: 8px; }\n .mcp-kv-row .form-input { flex: 1 1 auto; }\n .mcp-json {\n width: 100%; box-sizing: border-box; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.8rem; line-height: 1.45; resize: vertical;\n }\n .mcp-verify { margin-top: 10px; display: grid; gap: 6px; }\n .mcp-verify .inline-result { word-break: break-word; }\n\n .mcp-dialog {\n width: min(620px, calc(100vw - 28px)); max-height: calc(100vh - 40px);\n border: 1px solid var(--border); border-radius: 18px; padding: 22px;\n color: var(--text); background: #fbfaf6; box-shadow: 0 28px 90px rgba(18,18,16,0.24);\n /* The shell's global \"* { margin: 0 }\" reset overrides the UA stylesheet's\n dialog[open] { margin: auto } centering rule, so pin it back explicitly. */\n position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); margin: 0;\n }\n .mcp-dialog::backdrop { background: rgba(20,20,18,0.5); backdrop-filter: blur(3px); }\n .mcp-dialog-head {\n display: flex; align-items: flex-start; justify-content: space-between; gap: 18px;\n padding-bottom: 14px; border-bottom: 1px solid var(--border);\n }\n .mcp-dialog-head .card-title { margin: 4px 0 0; }\n .mcp-dialog-close {\n border: 0; background: transparent; color: var(--muted); cursor: pointer;\n font-size: 1.6rem; line-height: 1; padding: 2px 5px;\n }\n .mcp-dialog-desc { color: var(--muted); line-height: 1.55; font-size: 0.88rem; }\n .mcp-install-preview {\n display: grid; gap: 6px; padding: 12px; border-radius: 10px;\n background: #1d211f; color: #f5f2e9;\n }\n .mcp-install-preview span {\n color: #aeb8b1; font-size: 0.66rem; font-weight: 700;\n letter-spacing: 0.08em; text-transform: uppercase;\n }\n .mcp-install-preview code {\n color: #f5f2e9; background: transparent; word-break: break-all; font-size: 0.78rem;\n }\n .mcp-security-note, .mcp-replace-note {\n margin-top: 12px; padding: 10px 12px; border-radius: 9px;\n font-size: 0.78rem; line-height: 1.5;\n }\n .mcp-security-note.local {\n background: rgba(220,38,38,0.08); border: 1px solid rgba(185,28,28,0.18); color: #991b1b;\n }\n .mcp-security-note.remote {\n background: rgba(59,130,246,0.08); border: 1px solid rgba(29,78,216,0.16); color: #1e40af;\n }\n .mcp-replace-note { background: rgba(217,119,6,0.1); color: #92400e; }\n .mcp-credential { display: grid; gap: 5px; margin-top: 14px; }\n .mcp-credential span { font-size: 0.78rem; font-weight: 650; }\n .mcp-credential input {\n width: 100%; padding: 9px 10px; border: 1px solid var(--border); border-radius: 8px;\n background: #fff; color: var(--text); font: 0.8rem/1.3 'JetBrains Mono', ui-monospace, monospace;\n }\n .mcp-credential small, .mcp-secret-note, .mcp-no-credentials {\n color: var(--subtle); font-size: 0.72rem; line-height: 1.45;\n }\n .mcp-secret-note { margin: 14px 0 8px; }\n .mcp-no-credentials { margin: 14px 0 0; }\n #mcp-dialog-error, #mcp-custom-dialog-error { margin-top: 14px; }\n .mcp-dialog-actions {\n display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px;\n padding-top: 14px; border-top: 1px solid var(--border);\n }\n\n /* ── Events ─────────────────────────────────────────────────────────── */\n\n .events-list { display: flex; flex-direction: column; gap: 8px; }\n .event-row {\n padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;\n background: rgba(0,0,0,0.02);\n }\n .event-row-top {\n display: flex; align-items: center; justify-content: space-between;\n gap: 10px;\n }\n .event-name { min-width: 0; flex: 1; word-break: break-all; }\n .event-name code { font-size: 0.82rem; background: transparent; padding: 0; }\n .event-meta { font-size: 0.74rem; color: var(--muted); margin-top: 3px; }\n .event-text {\n font-size: 0.82rem; color: var(--text); margin-top: 6px;\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n white-space: pre-wrap; word-break: break-word;\n }\n .event-delete-btn {\n flex-shrink: 0; padding: 4px 10px;\n border-radius: 7px; border: 1px solid rgba(185, 28, 28, 0.18);\n background: rgba(0,0,0,0.03); color: var(--err-text);\n font: 500 0.76rem/1.2 'DM Sans', sans-serif; cursor: pointer;\n }\n .event-delete-btn:hover:not(:disabled) {\n background: var(--err-bg); border-color: rgba(185, 28, 28, 0.28);\n }\n .event-delete-btn:disabled { opacity: 0.5; cursor: wait; }\n\n /* ── All Conversations list ─────────────────────────────────────────── */\n\n .conv-list { display: flex; flex-direction: column; gap: 6px; }\n .conv-row-btn {\n display: flex; align-items: center; gap: 12px;\n padding: 10px 14px; border: 1px solid var(--border); border-radius: 10px;\n background: rgba(0,0,0,0.02); cursor: pointer; text-align: left;\n transition: background 120ms, border-color 120ms;\n }\n .conv-row-btn:hover { background: rgba(0,0,0,0.05); border-color: rgba(0,0,0,0.14); }\n .conv-id { flex: 1; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 0.84rem; }\n .conv-last { color: var(--subtle); font-size: 0.78rem; }\n\n .usage-table-wrap { overflow-x: auto; }\n .usage-table { width: 100%; border-collapse: collapse; font-size: 0.78rem; }\n .usage-table th, .usage-table td {\n padding: 8px 10px; border-bottom: 1px solid var(--border);\n text-align: left; white-space: nowrap;\n }\n .usage-table th {\n color: var(--subtle); font-size: 0.68rem;\n text-transform: uppercase; letter-spacing: 0.08em;\n }\n .usage-table code { font-size: 0.72rem; }\n\n .timeline-controls {\n display: flex; flex-wrap: wrap; gap: 18px; align-items: center; margin-bottom: 16px;\n }\n .timeline-controls label {\n display: flex; align-items: center; gap: 8px;\n font-size: 0.76rem; color: var(--muted);\n }\n .timeline-controls select {\n padding: 6px 10px; border: 1px solid var(--border); border-radius: 8px;\n background: #fff; color: var(--text); font-size: 0.8rem; max-width: 240px;\n }\n .tl-note { margin-top: 8px; font-size: 0.72rem; color: var(--subtle); }\n .tl-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; }\n .tl-card { background: rgba(0,0,0,0.025); border-radius: 10px; padding: 10px 12px; }\n .tl-card-label { font-size: 0.73rem; color: var(--muted); margin-bottom: 4px; }\n .tl-card-value { font-size: 1.35rem; font-weight: 600; color: var(--text); }\n .tl-legend { display: flex; gap: 16px; font-size: 0.73rem; color: var(--muted); margin-bottom: 10px; }\n .tl-legend span { display: inline-flex; align-items: center; gap: 6px; }\n .tl-legend-item { cursor: pointer; transition: opacity 100ms; }\n .tl-legend-item:hover { text-decoration: underline; }\n .tl-legend-item.active { color: var(--text); font-weight: 600; text-decoration: underline; }\n .tl-legend-item.dim { opacity: 0.4; }\n .sw { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }\n .sw-cache-read { background: rgba(0,0,0,0.18); }\n .sw-cache-write { background: #3b6fb0; }\n .sw-input { background: var(--accent); }\n .sw-output { background: var(--ok-text); }\n .tl-chart {\n position: relative;\n display: flex; align-items: flex-end; gap: 6px;\n height: 216px; border-bottom: 1px solid var(--border);\n }\n .tl-peak {\n position: absolute; left: 0; right: 0; height: 0;\n border-top: 1px dashed var(--accent); pointer-events: none;\n }\n .tl-peak-label {\n position: absolute; left: 0; top: -15px;\n font-size: 0.7rem; color: var(--accent); white-space: nowrap;\n }\n .tl-bar {\n position: relative; flex: 1; min-width: 0; height: 180px;\n display: flex; flex-direction: column; justify-content: flex-end;\n border-radius: 6px 6px 0 0; transition: background 80ms ease;\n }\n .tl-bar:hover { background: rgba(0,0,0,0.06); }\n .tl-bar:hover .tl-seg { opacity: 0.55; }\n .tl-fill {\n display: flex; flex-direction: column; justify-content: flex-end;\n border-radius: 3px 3px 0 0; overflow: hidden;\n }\n .tl-tip {\n position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);\n margin-bottom: 6px; padding: 5px 9px; border-radius: 6px;\n background: var(--text); color: #fafafa; font-size: 0.7rem; line-height: 1.35;\n white-space: nowrap; opacity: 0; pointer-events: none; z-index: 5;\n }\n .tl-bar:hover .tl-tip { opacity: 1; }\n .tl-seg { display: block; width: 100%; }\n .tl-seg.tl-output { background: var(--ok-text); }\n .tl-seg.tl-input { background: var(--accent); }\n .tl-seg.tl-cache-write { background: #3b6fb0; }\n .tl-seg.tl-cache-read { background: rgba(0,0,0,0.18); }\n .tl-empty { display: block; width: 100%; height: 3px; background: var(--border); }\n .tl-axis { display: flex; justify-content: space-between; margin-top: 6px; font-size: 0.7rem; color: var(--subtle); }\n\n .status-pill {\n display: inline-flex; padding: 2px 9px; border-radius: 999px;\n font-size: 0.7rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;\n }\n .status-pill.running { background: var(--ok-bg); color: var(--ok-text); border: 1px solid var(--ok-border); }\n\n @media (max-width: 860px) {\n .settings-shell { grid-template-columns: 1fr; }\n .settings-rail { position: static; }\n /* Keep labels on narrow screens: a scrollable chip row is far easier to\n scan than a row of bare icons with no text. */\n .rail-nav {\n flex-direction: row; flex-wrap: nowrap; gap: 6px;\n overflow-x: auto; padding-bottom: 6px;\n /* Without min-width:0 a nowrap flex row refuses to shrink and blows the\n page width out instead of scrolling. */\n min-width: 0; max-width: 100%;\n scrollbar-width: thin; -webkit-overflow-scrolling: touch;\n }\n .settings-rail { min-width: 0; }\n .rail-nav[hidden] { display: none; }\n .rail-link { flex: 0 0 auto; padding: 7px 11px; }\n .rail-link span { white-space: nowrap; }\n }\n\n @media (max-width: 640px) {\n .config-grid { grid-template-columns: 1fr; }\n .config-row { grid-template-columns: 1fr; gap: 4px; }\n .workspace-split { grid-template-columns: 1fr; }\n .workspace-tree, .workspace-preview { max-height: 260px; }\n .mcp-preset-grid { grid-template-columns: 1fr; }\n .mcp-dialog { padding: 18px; }\n }\n`;\n"]}
|
|
1
|
+
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../../../src/adapters/web/admin/portal.ts"],"names":[],"mappings":"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","sourcesContent":["import { validateEventFilename } from \"../../../events/index.js\";\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { basename, join, resolve as pathResolve, sep as pathSep } from \"node:path\";\nimport { atomicWritePrivateFile } from \"../../../file-guards.js\";\nimport { MikanModels, parseFrontmatter, validateSkill } from \"../../../harness/index.js\";\nimport { SessionStore } from \"../../../sessions/session-store.js\";\nimport type { EventStore } from \"../../../events/index.js\";\nimport type { PlatformName } from \"../../index.js\";\nimport { InMemoryTokenStore } from \"../token-store.js\";\nimport type { AdminToken } from \"./types.js\";\nimport {\n adminViewFunctionsScript,\n adminViewStartupScript,\n adminViewStyles,\n} from \"./client-assets.js\";\nexport type { AdminToken } from \"./types.js\";\n\nconst ADMIN_TOKEN_TTL_MS = 30 * 60 * 1000;\n\nexport class InMemoryAdminTokenStore extends InMemoryTokenStore<AdminToken> {\n create(args: {\n platform: PlatformName;\n platformUserId: string;\n conversationId: string;\n platformUserName?: string;\n }): AdminToken {\n this.deleteWhere(\n (token) => token.platform === args.platform && token.platformUserId === args.platformUserId,\n );\n return this.createRecord(ADMIN_TOKEN_TTL_MS, {\n platform: args.platform,\n platformUserId: args.platformUserId,\n ...(args.platformUserName ? { platformUserName: args.platformUserName } : {}),\n conversationId: args.conversationId,\n });\n }\n}\n\nimport {\n loadOfficeVisibilityOverride,\n loadGlobalSettings,\n loadScopeMcpServers,\n resolveConversationSettings,\n type AgentConfig,\n type SandboxSettings,\n} from \"../../../settings/index.js\";\nimport { findMcpPreset, listMcpPresets, materializeMcpPreset } from \"../../../harness/mcp.js\";\nimport { loadMcpTools } from \"../../../harness/mcp.js\";\nimport {\n isValidMcpServerName,\n parseStandardMcpServers,\n redactMcpUrl,\n} from \"../../../harness/mcp.js\";\nimport type { McpServerConfig } from \"../../../harness/types.js\";\nimport {\n applyConversationSettings,\n applyOfficeVisibility,\n applyGlobalSettings,\n} from \"../../../settings/apply.js\";\nimport {\n escapeHtml,\n jsonResponse as jsonRes,\n readJsonBody,\n renderPortalShell,\n} from \"../portal-shell.js\";\nimport { resolveExistingSessionFile } from \"../session-view/portal.js\";\nimport { PRODUCT_NAME } from \"../../messages.js\";\nimport { credentialAuthorizationKey } from \"../../../sandbox/identity.js\";\nimport { resolveWorkspaceProjection } from \"../../../office/projection.js\";\nimport { sharedVaultKey } from \"../../../vault/index.js\";\nimport { modelKey, resolveAdminModelAccessStatuses } from \"./provider-models.js\";\n\nexport type { AdminRuntimeBridge, AdminServices, EventSummary } from \"./types.js\";\nimport type { AdminServices, EventSummary } from \"./types.js\";\nimport type { OfficeAddress } from \"../../index.js\";\nimport {\n assertPlatformName,\n createOfficeAddress,\n listRegisteredOffices,\n sameOffice,\n type Office,\n type Workspace,\n} from \"../../../office/index.js\";\n\nexport async function handleAdminRequest(\n req: IncomingMessage,\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<boolean> {\n if (!url.pathname.startsWith(\"/admin\")) return false;\n\n if (req.method === \"GET\" && url.pathname === \"/admin\") {\n const provided = url.searchParams.get(\"token\") ?? \"\";\n const token = services.adminTokenStore.peek(provided);\n if (!token) {\n res.writeHead(403, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderAdminErrorPage(\n \"Admin link is missing, invalid, or expired. Send `/admin` to the bot to get a fresh link.\",\n ),\n );\n return true;\n }\n res.writeHead(200, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n });\n res.end(renderAdminPage(token));\n return true;\n }\n\n if (url.pathname.startsWith(\"/admin/api/\")) {\n await routeApiRequest(req, res, url, services);\n return true;\n }\n\n return false;\n}\n\nasync function routeApiRequest(\n req: IncomingMessage,\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<void> {\n if (req.method === \"GET\") {\n await routeGetApiRequest(res, url, services);\n return;\n }\n if (req.method !== \"POST\") {\n jsonRes(res, 405, { error: \"Method not allowed\" });\n return;\n }\n await routePostApiRequest(req, res, url, services);\n}\n\nasync function routeGetApiRequest(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<void> {\n const token = services.adminTokenStore.peek(url.searchParams.get(\"token\") ?? \"\");\n if (!token) {\n jsonRes(res, 403, { error: \"Unauthorized\" });\n return;\n }\n switch (url.pathname) {\n case \"/admin/api/conversations\":\n return serveConversationsList(res, services);\n case \"/admin/api/session-usage\":\n return serveSessionUsage(res, services);\n case \"/admin/api/conversation-usage\":\n return serveConversationUsage(res, url, services);\n case \"/admin/api/conversation-state\":\n return serveConversationState(res, url, services, token);\n case \"/admin/api/settings/global\":\n return serveGlobalSettings(res);\n case \"/admin/api/models\":\n return serveModelsList(res);\n case \"/admin/api/workspace/tree\":\n return serveWorkspaceTree(res, url, services, token);\n case \"/admin/api/workspace/file\":\n return serveWorkspaceFile(res, url, services, token);\n case \"/admin/api/skills\":\n return serveSkillsList(res, url, services, token);\n case \"/admin/api/skills/file\":\n return serveSkillFile(res, url, services, token);\n case \"/admin/api/mcp-servers\":\n return serveMcpServersList(res, url, services, token);\n case \"/admin/api/events\":\n return serveEventsList(res, services);\n case \"/admin/api/conversations/events\":\n return serveConversationEventsList(res, url, services, token);\n default:\n jsonRes(res, 404, { error: \"Not found\" });\n }\n}\n\nasync function routePostApiRequest(\n req: IncomingMessage,\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<void> {\n const bodyLimit = url.pathname === \"/admin/api/skills/mutate\" ? 256 * 1024 : 32 * 1024;\n const body = await readJsonBody(req, res, bodyLimit);\n if (!body) return;\n const token = services.adminTokenStore.peek(typeof body.token === \"string\" ? body.token : \"\");\n if (!token) {\n jsonRes(res, 403, { error: \"Unauthorized\" });\n return;\n }\n switch (url.pathname) {\n case \"/admin/api/conversations/model\":\n return serveConversationModelUpdate(res, body, services, token);\n case \"/admin/api/conversations/visibility\":\n return serveConversationVisibilityUpdate(res, body, services, token);\n case \"/admin/api/conversations/slack\":\n return serveConversationSlackUpdate(res, body, services, token);\n case \"/admin/api/conversations/session-link\":\n return serveConversationSessionLink(res, body, services, token);\n case \"/admin/api/conversations/login-link\":\n return serveConversationLoginLink(res, body, services, token);\n case \"/admin/api/conversations/events/delete\":\n return serveConversationEventDelete(res, body, services, token);\n case \"/admin/api/mcp-servers/mutate\":\n return serveMcpServerMutation(res, body, services, token);\n case \"/admin/api/skills/mutate\":\n return serveSkillMutation(res, body, services, token);\n case \"/admin/api/settings/model\":\n return serveGlobalModelUpdate(res, body, services);\n case \"/admin/api/settings/sandbox\":\n return serveGlobalSandboxUpdate(res, body, services);\n case \"/admin/api/settings/slack\":\n return serveGlobalSlackUpdate(res, body, services);\n default:\n jsonRes(res, 404, { error: \"Not found\" });\n }\n}\n\ninterface AdminConversationScope {\n address: OfficeAddress;\n conversationId: string;\n error?: string;\n}\n\nexport function resolveConversationScope(\n requestedId: string,\n requestedPlatform: string,\n token: AdminToken,\n): AdminConversationScope {\n const fallback = createOfficeAddress(token.platform, token.conversationId);\n try {\n const address = createOfficeAddress(\n requestedPlatform ? assertPlatformName(requestedPlatform) : token.platform,\n requestedId || token.conversationId,\n );\n return { address, conversationId: address.conversationId };\n } catch {\n return {\n address: fallback,\n conversationId: fallback.conversationId,\n error: \"Invalid conversation scope.\",\n };\n }\n}\n\nfunction resolveTargetConversation(\n body: Record<string, unknown>,\n token: AdminToken,\n): AdminConversationScope {\n const requested = typeof body.conversationId === \"string\" ? body.conversationId.trim() : \"\";\n const platform = typeof body.platform === \"string\" ? body.platform.trim() : \"\";\n return resolveConversationScope(requested, platform, token);\n}\n\nfunction requireAdminWorkspace(res: ServerResponse, services: AdminServices): Workspace | null {\n if (!services.workspace) {\n jsonRes(res, 503, { error: \"Working directory not available\" });\n return null;\n }\n return services.workspace;\n}\n\nfunction requireConversationWorkspace(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): { scope: AdminConversationScope; workspace: Workspace } | undefined {\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return undefined;\n }\n const workspace = requireAdminWorkspace(res, services);\n return workspace ? { scope, workspace } : undefined;\n}\n\nfunction listAdminOffices(workspace: Workspace): OfficeAddress[] {\n return listRegisteredOffices(workspace.stateDir)\n .filter((office) => existsSync(workspace.office(office).dir))\n .map((office) => createOfficeAddress(office.platform, office.conversationId))\n .toSorted(\n (a, b) =>\n a.platform.localeCompare(b.platform) || a.conversationId.localeCompare(b.conversationId),\n );\n}\n\nfunction conversationLastActivity(workspace: Workspace, office: OfficeAddress): number | null {\n const dir = workspace.office(office).dir;\n if (!existsSync(dir)) return null;\n let latest = 0;\n const visit = (path: string, depth: number): void => {\n if (depth > 3) return;\n let entries;\n try {\n entries = readdirSync(path, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const full = join(path, entry.name);\n if (entry.isDirectory()) {\n visit(full, depth + 1);\n continue;\n }\n try {\n const stats = statSync(full);\n if (stats.mtimeMs > latest) latest = stats.mtimeMs;\n } catch {}\n }\n };\n visit(dir, 0);\n return latest > 0 ? latest : null;\n}\n\nfunction conversationDisplayLabel(services: AdminServices, office: OfficeAddress): string {\n const bot = services.botsByPlatform?.[office.platform];\n const channel = bot?.getMessagingInfo().channels.find((c) => c.id === office.conversationId);\n if (channel) return `${office.platform}:#${channel.name}:${office.conversationId}`;\n return `${office.platform}:${office.conversationId}`;\n}\n\nfunction serveConversationsList(res: ServerResponse, services: AdminServices): void {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const running = services.runtime?.getRunningSessions() ?? [];\n\n const conversations = listAdminOffices(workspace).map((office) => ({\n platform: office.platform,\n conversationId: office.conversationId,\n label: conversationDisplayLabel(services, office),\n running: running.some((session) => sameOffice(session.address, office)),\n lastActivityAt: conversationLastActivity(workspace, office),\n }));\n\n jsonRes(res, 200, { conversations });\n}\n\ninterface SessionUsageRow {\n conversationId: string;\n label: string;\n fileName: string;\n sessionId: string;\n updatedAt: string;\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n total: number;\n cost: number;\n}\n\nasync function serveSessionUsage(res: ServerResponse, services: AdminServices): Promise<void> {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const usageLists: SessionUsageRow[][] = [];\n for (const office of listAdminOffices(workspace)) {\n usageLists.push(\n await listConversationSessionUsage(\n workspace,\n office,\n conversationDisplayLabel(services, office),\n ),\n );\n }\n const rows = usageLists\n .flat()\n .toSorted((a, b) => b.total - a.total)\n .slice(0, 20);\n\n jsonRes(res, 200, { sessions: rows });\n}\n\nasync function listConversationSessionUsage(\n workspace: Workspace,\n office: OfficeAddress,\n label: string,\n): Promise<SessionUsageRow[]> {\n const sessionDir = workspace.office(office).sessionsDir;\n let files: string[];\n try {\n files = readdirSync(sessionDir, { withFileTypes: true })\n .filter((entry) => entry.isFile() && entry.name.endsWith(\".jsonl\"))\n .map((entry) => entry.name);\n } catch {\n return [];\n }\n const rows: SessionUsageRow[] = [];\n for (const name of files) {\n rows.push(...(await readSessionUsage(join(sessionDir, name), office.conversationId, label)));\n }\n return rows;\n}\n\nasync function readSessionUsage(\n sessionFile: string,\n conversationId: string,\n label: string,\n): Promise<SessionUsageRow[]> {\n try {\n const manager = await SessionStore.inspect(sessionFile);\n const header = manager.getHeader();\n\n const entries = await manager.getEntries();\n const usage = entries.reduce(\n (sum, entry) => {\n if (entry.type !== \"message\" || entry.message.role !== \"assistant\") return sum;\n const message = entry.message as unknown as AssistantUsageMessage;\n const item = message.usage;\n if (!item) return sum;\n sum.input += numberOrZero(item.input);\n sum.output += numberOrZero(item.output);\n sum.cacheRead += numberOrZero(item.cacheRead);\n sum.cacheWrite += numberOrZero(item.cacheWrite);\n sum.cost += numberOrZero(item.cost?.total);\n return sum;\n },\n { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 },\n );\n const total = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;\n if (total <= 0) return [];\n\n return [\n {\n conversationId,\n label,\n fileName: basename(sessionFile),\n sessionId: header.id,\n updatedAt:\n entries.length > 0 ? new Date(entries.at(-1)!.timestamp).toISOString() : header.timestamp,\n ...usage,\n total,\n },\n ];\n } catch {\n return [];\n }\n}\n\ninterface AssistantUsageMessage {\n usage?: {\n input?: unknown;\n output?: unknown;\n cacheRead?: unknown;\n cacheWrite?: unknown;\n cost?: { total?: unknown };\n };\n}\n\nfunction numberOrZero(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\ninterface UsageBucket {\n date: string;\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n total: number;\n cost: number;\n}\n\nfunction localDayKey(d: Date): string {\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\nfunction emptyBucket(date: string): UsageBucket {\n return { date, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0, cost: 0 };\n}\n\nasync function serveConversationUsage(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n): Promise<void> {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const conversationId = (url.searchParams.get(\"conversationId\") ?? \"\").trim();\n const platformParam = (url.searchParams.get(\"platform\") ?? \"\").trim();\n const office = listAdminOffices(workspace).find(\n (candidate) =>\n candidate.conversationId === conversationId &&\n (!platformParam || candidate.platform === platformParam),\n );\n if (!office) {\n jsonRes(res, 400, { error: \"Unknown conversationId\" });\n return;\n }\n\n const days = 14;\n\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n const buckets = new Map<string, UsageBucket>();\n const order: string[] = [];\n for (let i = days - 1; i >= 0; i--) {\n const d = new Date(today);\n d.setDate(today.getDate() - i);\n const key = localDayKey(d);\n order.push(key);\n buckets.set(key, emptyBucket(key));\n }\n const cutoff = new Date(today);\n cutoff.setDate(today.getDate() - (days - 1));\n\n const flags = { hasOlder: false };\n const sessionDir = workspace.office(office).sessionsDir;\n try {\n for (const entry of readdirSync(sessionDir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) continue;\n await accumulateSessionUsageByDay(join(sessionDir, entry.name), cutoff, buckets, flags);\n }\n } catch {}\n\n const series = order.map((key) => buckets.get(key) ?? emptyBucket(key));\n const totals = series.reduce((sum, b) => {\n sum.input += b.input;\n sum.output += b.output;\n sum.cacheRead += b.cacheRead;\n sum.cacheWrite += b.cacheWrite;\n sum.total += b.total;\n sum.cost += b.cost;\n return sum;\n }, emptyBucket(\"\"));\n\n jsonRes(res, 200, {\n platform: office.platform,\n conversationId,\n label: conversationDisplayLabel(services, office),\n days,\n hasOlder: flags.hasOlder,\n buckets: series,\n totals: {\n input: totals.input,\n output: totals.output,\n cacheRead: totals.cacheRead,\n cacheWrite: totals.cacheWrite,\n total: totals.total,\n cost: totals.cost,\n },\n });\n}\n\nasync function accumulateSessionUsageByDay(\n sessionFile: string,\n cutoff: Date,\n buckets: Map<string, UsageBucket>,\n flags: { hasOlder: boolean },\n): Promise<void> {\n try {\n const manager = await SessionStore.inspect(sessionFile);\n\n for (const entry of await manager.getEntries()) {\n if (entry.type !== \"message\" || entry.message.role !== \"assistant\") continue;\n const usage = (entry.message as unknown as AssistantUsageMessage).usage;\n if (!usage || !entry.timestamp) continue;\n\n const when = new Date(entry.timestamp);\n if (Number.isNaN(when.getTime())) continue;\n if (when < cutoff) {\n flags.hasOlder = true;\n continue;\n }\n\n const bucket = buckets.get(localDayKey(when));\n if (!bucket) continue;\n\n const input = numberOrZero(usage.input);\n const output = numberOrZero(usage.output);\n const cacheRead = numberOrZero(usage.cacheRead);\n const cacheWrite = numberOrZero(usage.cacheWrite);\n bucket.input += input;\n bucket.output += output;\n bucket.cacheRead += cacheRead;\n bucket.cacheWrite += cacheWrite;\n bucket.total += input + output + cacheRead + cacheWrite;\n bucket.cost += numberOrZero(usage.cost?.total);\n }\n } catch {}\n}\n\nfunction serveConversationState(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 400, { error: scope.error });\n return;\n }\n const conversationId = scope.conversationId;\n\n const office = workspace.office(scope.address);\n const globalConfig = loadGlobalSettings();\n const conversationConfig = resolveConversationSettings(office);\n const conversationWorkspace = resolveWorkspaceProjection(office);\n\n jsonRes(res, 200, {\n conversationId,\n provider: conversationConfig.provider,\n model: conversationConfig.model,\n thinkingLevel: conversationConfig.thinkingLevel,\n globalProvider: globalConfig.provider,\n globalModel: globalConfig.model,\n globalThinkingLevel: globalConfig.thinkingLevel,\n officeVisibility: conversationWorkspace.visibility,\n officeVisibilitySource: conversationWorkspace.source,\n officeVisibilityOverride: loadOfficeVisibilityOverride(office),\n slack: {\n replyMode:\n conversationConfig.slack?.replyMode ?? globalConfig.slack?.replyMode ?? \"top-level\",\n globalReplyMode: globalConfig.slack?.replyMode ?? \"top-level\",\n },\n });\n}\n\nfunction serveGlobalSettings(res: ServerResponse): void {\n try {\n const config = loadGlobalSettings();\n jsonRes(res, 200, {\n provider: config.provider,\n model: config.model,\n thinkingLevel: config.thinkingLevel,\n sandboxCpus: config.sandbox?.cpus ?? null,\n sandboxMemory: config.sandbox?.memory ?? null,\n sandboxBoostCpus: config.sandbox?.boost?.cpus ?? null,\n sandboxBoostMemory: config.sandbox?.boost?.memory ?? null,\n defaultSharedVault: config.sandbox?.defaultSharedVault ?? null,\n slack: {\n replyMode: config.slack?.replyMode ?? \"top-level\",\n },\n });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nasync function serveModelsList(res: ServerResponse): Promise<void> {\n try {\n const registry = MikanModels.create();\n const availableModels = await registry.getAvailable();\n const statuses = await resolveAdminModelAccessStatuses(registry, availableModels);\n const models = availableModels.map((model) => ({\n provider: model.provider,\n id: model.id,\n name: model.name ?? model.id,\n reasoning: model.reasoning,\n input: model.input,\n contextWindow: model.contextWindow,\n maxTokens: model.maxTokens,\n status: statuses.get(modelKey(model.provider, model.id))?.status ?? \"available\",\n }));\n jsonRes(res, 200, { models });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nconst VALID_THINKING_LEVELS = new Set([\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"]);\n\nfunction serveConversationModelUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const provider = typeof body.provider === \"string\" ? body.provider.trim() : \"\";\n const model = typeof body.model === \"string\" ? body.model.trim() : \"\";\n const thinkingLevel =\n typeof body.thinkingLevel === \"string\" && VALID_THINKING_LEVELS.has(body.thinkingLevel)\n ? (body.thinkingLevel as AgentConfig[\"thinkingLevel\"])\n : undefined;\n\n if (!provider || !model) {\n jsonRes(res, 400, { error: \"Missing provider or model\" });\n return;\n }\n const target = requireConversationWorkspace(res, body, services, token);\n if (!target) return;\n const { scope, workspace } = target;\n\n try {\n const result = applyConversationSettings(services.runtime, workspace.office(scope.address), {\n provider,\n model,\n ...(thinkingLevel ? { thinkingLevel } : {}),\n });\n if (!result.ok) {\n jsonRes(res, 409, {\n error: \"Conversation has a running job; retry after it finishes (or /stop it).\",\n });\n return;\n }\n jsonRes(res, 200, { ok: true, runtimeSwitched: result.runtimeSwitched });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nfunction serveConversationVisibilityUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n if (body.visibility !== \"private\" && body.visibility !== \"default\") {\n jsonRes(res, 400, { error: \"visibility must be 'private' or 'default'\" });\n return;\n }\n const target = requireConversationWorkspace(res, body, services, token);\n if (!target) return;\n const { scope, workspace } = target;\n try {\n const result = applyOfficeVisibility(\n services.runtime,\n workspace.office(scope.address),\n body.visibility === \"private\" ? \"private\" : null,\n );\n if (!result.ok) {\n jsonRes(res, 409, { error: \"Conversation is busy; retry when the current run finishes\" });\n return;\n }\n jsonRes(res, 200, { ok: true });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nfunction serveConversationSlackUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const replyMode = body.replyMode;\n if (replyMode !== \"top-level\" && replyMode !== \"thread\") {\n jsonRes(res, 400, { error: \"replyMode must be 'top-level' or 'thread'\" });\n return;\n }\n const target = requireConversationWorkspace(res, body, services, token);\n if (!target) return;\n const { scope, workspace } = target;\n respondWithSettingsUpdate(res, () => {\n applyConversationSettings(services.runtime, workspace.office(scope.address), {\n slack: { replyMode },\n });\n return { ok: true };\n });\n}\n\nfunction serveConversationSessionLink(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const target = requireConversationWorkspace(res, body, services, token);\n if (!target) return;\n const { scope, workspace } = target;\n if (!services.sessionViewTokenStore) {\n jsonRes(res, 503, { error: \"Session view token store not available\" });\n return;\n }\n if (!services.portalBaseUrl) {\n jsonRes(res, 503, {\n error: \"Portal URL not configured. Set MIKAN_LINK_URL to enable link generation.\",\n });\n return;\n }\n\n const sessionFile = resolveExistingSessionFile(\n workspace.office(scope.address).dir,\n scope.conversationId,\n );\n if (!sessionFile) {\n jsonRes(res, 404, { error: \"No session file found for this conversation\" });\n return;\n }\n\n try {\n const { token: viewToken } = services.sessionViewTokenStore.create({\n platform: token.platform,\n platformUserId: token.platformUserId,\n conversationId: scope.conversationId,\n sessionKey: scope.conversationId,\n sessionFile,\n platformUserName: token.platformUserName,\n });\n const url = `${services.portalBaseUrl}/session?token=${encodeURIComponent(viewToken)}`;\n jsonRes(res, 200, { ok: true, url });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nfunction serveConversationLoginLink(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n if (!services.portalBaseUrl) {\n jsonRes(res, 503, { error: \"Portal URL not configured.\" });\n return;\n }\n if (!services.sandbox) {\n jsonRes(res, 503, { error: \"Sandbox config not available.\" });\n return;\n }\n const sharedName = typeof body.sharedVault === \"string\" ? body.sharedVault.trim() : \"\";\n let vaultId: string;\n if (sharedName) {\n const key = sharedVaultKey(sharedName);\n if (!key) {\n jsonRes(res, 400, { error: \"Invalid shared vault name\" });\n return;\n }\n vaultId = key;\n } else {\n try {\n vaultId = credentialAuthorizationKey(services.sandbox, {\n userId: token.platformUserId,\n address: scope.address,\n });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n return;\n }\n }\n try {\n const { token: linkToken } = services.linkTokenStore.create(\n token.platform,\n token.platformUserId,\n scope.conversationId,\n vaultId,\n \"\",\n );\n const url = `${services.portalBaseUrl}/link?token=${encodeURIComponent(linkToken)}`;\n jsonRes(res, 200, { ok: true, url, vaultId });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nfunction serveGlobalModelUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n): void {\n const provider = typeof body.provider === \"string\" ? body.provider.trim() : \"\";\n const model = typeof body.model === \"string\" ? body.model.trim() : \"\";\n const thinkingLevel =\n typeof body.thinkingLevel === \"string\" && VALID_THINKING_LEVELS.has(body.thinkingLevel)\n ? (body.thinkingLevel as AgentConfig[\"thinkingLevel\"])\n : undefined;\n\n if (!provider || !model) {\n jsonRes(res, 400, { error: \"Missing provider or model\" });\n return;\n }\n\n respondWithSettingsUpdate(res, () => {\n const result = applyGlobalSettings(services.runtime, {\n provider,\n model,\n ...(thinkingLevel ? { thinkingLevel } : {}),\n });\n return {\n ok: true,\n staleConversations: result.staleConversations.map(\n (office) => `${office.platform}:${office.conversationId}`,\n ),\n };\n });\n}\n\nfunction serveGlobalSlackUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n): void {\n const replyMode = body.replyMode;\n if (replyMode !== \"top-level\" && replyMode !== \"thread\") {\n jsonRes(res, 400, { error: \"replyMode must be 'top-level' or 'thread'\" });\n return;\n }\n\n respondWithSettingsUpdate(res, () => {\n applyGlobalSettings(services.runtime, { slack: { replyMode } });\n return { ok: true };\n });\n}\n\nfunction serveGlobalSandboxUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n): void {\n const cpus = typeof body.cpus === \"string\" ? body.cpus.trim() : \"\";\n const memory = typeof body.memory === \"string\" ? body.memory.trim() : \"\";\n const boostCpus = typeof body.boostCpus === \"string\" ? body.boostCpus.trim() : \"\";\n const boostMemory = typeof body.boostMemory === \"string\" ? body.boostMemory.trim() : \"\";\n const update: SandboxSettings = {\n ...(cpus ? { cpus } : {}),\n ...(memory ? { memory } : {}),\n ...(boostCpus || boostMemory\n ? {\n boost: {\n ...(boostCpus ? { cpus: boostCpus } : {}),\n ...(boostMemory ? { memory: boostMemory } : {}),\n },\n }\n : {}),\n };\n\n if (Object.keys(update).length === 0) {\n jsonRes(res, 400, { error: \"No valid sandbox fields provided\" });\n return;\n }\n\n respondWithSettingsUpdate(res, () => {\n applyGlobalSettings(services.runtime, { sandbox: update });\n return { ok: true };\n });\n}\n\nfunction respondWithSettingsUpdate(res: ServerResponse, update: () => object): void {\n try {\n jsonRes(res, 200, update());\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\nconst WORKSPACE_TREE_MAX_DEPTH = 4;\nconst WORKSPACE_TREE_MAX_ENTRIES = 800;\nconst PREVIEW_FILE_MAX_BYTES = 256 * 1024;\n\nconst WORKSPACE_TOP_DIRS = new Set([\"scratch\"]);\n\nfunction isWorkspacePathAllowed(rel: string): boolean {\n if (rel === \"\") return true;\n const first = rel.split(\"/\").find(Boolean);\n if (first === undefined) return true;\n return WORKSPACE_TOP_DIRS.has(first);\n}\n\nfunction resolveConversationFromQuery(url: URL, token: AdminToken): AdminConversationScope {\n const requested = (url.searchParams.get(\"conversationId\") ?? \"\").trim();\n const platform = (url.searchParams.get(\"platform\") ?? \"\").trim();\n return resolveConversationScope(requested, platform, token);\n}\n\ninterface SafePathResult {\n absolute: string;\n error?: string;\n}\n\nfunction safeJoinUnderRoot(rootDir: string, relative: string): SafePathResult {\n if (relative.startsWith(\"/\") || relative.includes(\"\\0\")) {\n return { absolute: \"\", error: \"Invalid path\" };\n }\n if (relative.split(/[\\\\/]+/).some((part) => part === \"..\" || part === \"\")) {\n if (relative !== \"\") return { absolute: \"\", error: \"Invalid path\" };\n }\n const target = pathResolve(rootDir, relative);\n const rootAbs = pathResolve(rootDir);\n if (target !== rootAbs && !target.startsWith(rootAbs + pathSep)) {\n return { absolute: \"\", error: \"Path escapes conversation directory\" };\n }\n return { absolute: target };\n}\n\ninterface TreeNode {\n name: string;\n path: string;\n type: \"dir\" | \"file\";\n size?: number;\n mtimeMs?: number;\n children?: TreeNode[];\n truncated?: boolean;\n}\n\nfunction buildTree(startDir: string, relPrefix: string): TreeNode | null {\n let counter = { value: 0 };\n const walk = (dir: string, rel: string, depth: number): TreeNode | null => {\n if (counter.value >= WORKSPACE_TREE_MAX_ENTRIES) return null;\n let stats;\n try {\n stats = statSync(dir);\n } catch {\n return null;\n }\n const name = rel === \"\" ? \".\" : basename(rel);\n if (!stats.isDirectory()) {\n counter.value += 1;\n return {\n name,\n path: rel,\n type: \"file\",\n size: stats.size,\n mtimeMs: stats.mtimeMs,\n };\n }\n counter.value += 1;\n if (depth >= WORKSPACE_TREE_MAX_DEPTH) {\n return { name, path: rel, type: \"dir\", truncated: true };\n }\n let entries;\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return { name, path: rel, type: \"dir\" };\n }\n const children: TreeNode[] = [];\n let truncated = false;\n for (const entry of entries.toSorted((a, b) => {\n if (a.isDirectory() !== b.isDirectory()) return a.isDirectory() ? -1 : 1;\n return a.name.localeCompare(b.name);\n })) {\n const childRel = rel === \"\" ? entry.name : `${rel}/${entry.name}`;\n if (!isWorkspacePathAllowed(childRel)) continue;\n if (counter.value >= WORKSPACE_TREE_MAX_ENTRIES) {\n truncated = true;\n break;\n }\n const node = walk(join(dir, entry.name), childRel, depth + 1);\n if (node) children.push(node);\n }\n return {\n name,\n path: rel,\n type: \"dir\",\n children,\n ...(truncated ? { truncated: true } : {}),\n };\n };\n const node = walk(startDir, relPrefix, 0);\n return node;\n}\n\nfunction serveWorkspaceTree(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const convDir = workspace.office(scope.address).dir;\n if (!existsSync(convDir)) {\n jsonRes(res, 200, { conversationId: scope.conversationId, tree: null });\n return;\n }\n const requestedSub = (url.searchParams.get(\"path\") ?? \"\").trim();\n if (!isWorkspacePathAllowed(requestedSub)) {\n jsonRes(res, 403, { error: \"Workspace path is not exposed\" });\n return;\n }\n const startSafe = safeJoinUnderRoot(convDir, requestedSub);\n if (startSafe.error) {\n jsonRes(res, 400, { error: startSafe.error });\n return;\n }\n const tree = buildTree(startSafe.absolute, requestedSub);\n jsonRes(res, 200, {\n conversationId: scope.conversationId,\n root: requestedSub || \".\",\n tree,\n });\n}\n\nconst BINARY_PROBE_BYTES = 4096;\n\nfunction looksTextual(buf: Buffer): boolean {\n const limit = Math.min(buf.length, BINARY_PROBE_BYTES);\n for (let i = 0; i < limit; i++) {\n const byte = buf[i];\n if (byte === undefined || byte === 0) return false;\n if (byte < 9) return false;\n if (byte === 11 || byte === 12) return false;\n if (byte > 13 && byte < 32) return false;\n }\n return true;\n}\n\nfunction servePreviewFile(\n res: ServerResponse,\n absolutePath: string,\n metadata: Record<string, unknown>,\n notFoundMessage: string,\n): void {\n let stats;\n try {\n stats = statSync(absolutePath);\n } catch {\n jsonRes(res, 404, { error: notFoundMessage });\n return;\n }\n if (!stats.isFile()) {\n jsonRes(res, 400, { error: \"Not a file\" });\n return;\n }\n if (stats.size > PREVIEW_FILE_MAX_BYTES) {\n jsonRes(res, 413, {\n error: \"File too large to preview\",\n size: stats.size,\n limit: PREVIEW_FILE_MAX_BYTES,\n });\n return;\n }\n let buf: Buffer;\n try {\n buf = readFileSync(absolutePath);\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n return;\n }\n if (!looksTextual(buf)) {\n jsonRes(res, 200, {\n ...metadata,\n size: stats.size,\n mtimeMs: stats.mtimeMs,\n binary: true,\n content: null,\n });\n return;\n }\n jsonRes(res, 200, {\n ...metadata,\n size: stats.size,\n mtimeMs: stats.mtimeMs,\n binary: false,\n content: buf.toString(\"utf-8\"),\n });\n}\n\nfunction serveWorkspaceFile(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const requestedPath = (url.searchParams.get(\"path\") ?? \"\").trim();\n if (!requestedPath) {\n jsonRes(res, 400, { error: \"Missing path\" });\n return;\n }\n if (!isWorkspacePathAllowed(requestedPath)) {\n jsonRes(res, 403, { error: \"Workspace path is not exposed\" });\n return;\n }\n const convDir = workspace.office(scope.address).dir;\n const safe = safeJoinUnderRoot(convDir, requestedPath);\n if (safe.error) {\n jsonRes(res, 400, { error: safe.error });\n return;\n }\n servePreviewFile(res, safe.absolute, { path: requestedPath }, \"File not found\");\n}\n\ninterface SkillEntry {\n name: string;\n description: string;\n source: \"global\" | \"conversation\";\n path: string;\n directory: string;\n}\n\nfunction readSkillMeta(filePath: string): { name?: string; description?: string } {\n let text: string;\n try {\n text = readFileSync(filePath, \"utf-8\");\n } catch {\n return {};\n }\n const { values } = parseFrontmatter(text);\n const out: { name?: string; description?: string } = {};\n for (const [key, value] of Object.entries(values)) {\n const normalized = key.toLowerCase();\n if (normalized === \"name\") out.name = value;\n if (normalized === \"description\") out.description = value;\n }\n return out;\n}\n\nexport function readSkillsFromDir(skillsDir: string, source: SkillEntry[\"source\"]): SkillEntry[] {\n if (!existsSync(skillsDir)) return [];\n const out: SkillEntry[] = [];\n let entries;\n try {\n entries = readdirSync(skillsDir, { withFileTypes: true });\n } catch {\n return [];\n }\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) continue;\n const skillMd = join(skillsDir, entry.name, \"SKILL.md\");\n if (!existsSync(skillMd)) continue;\n const meta = readSkillMeta(skillMd);\n out.push({\n name: meta.name ?? entry.name,\n description: meta.description ?? \"\",\n source,\n path: skillMd,\n directory: entry.name,\n });\n }\n return out.toSorted((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction serveMcpServersList(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const servers = loadScopeMcpServers(workspace.office(scope.address));\n jsonRes(res, 200, {\n conversationId: scope.conversationId,\n presets: listMcpPresets(),\n global: redactMcpServers(servers.global),\n conversation: redactMcpServers(servers.conversation),\n });\n}\n\nfunction redactMcpServers(map: Record<string, McpServerConfig>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(map).map(([name, config]) => [\n name,\n {\n ...(config.command !== undefined ? { command: config.command } : {}),\n ...(config.args !== undefined ? { args: config.args } : {}),\n ...(config.url !== undefined ? { url: redactMcpUrl(config.url) } : {}),\n ...(config.disabled !== undefined ? { disabled: config.disabled } : {}),\n envKeys: Object.keys(config.env ?? {}),\n headerKeys: Object.keys(config.headers ?? {}),\n },\n ]),\n );\n}\n\nfunction mcpStringMap(value: unknown): Record<string, string> | undefined {\n if (typeof value !== \"object\" || value === null) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(value)) {\n if (typeof v === \"string\" && k.trim()) out[k.trim()] = v;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nconst MCP_VERIFY_TIMEOUT_MS = 20_000;\n\ntype McpVerifyResult = { name: string; tools: number } | { name: string; error: string };\n\nasync function verifyMcpServers(\n servers: Record<string, McpServerConfig>,\n): Promise<McpVerifyResult[]> {\n const names = Object.keys(servers);\n if (names.length === 0) return [];\n const loaded = await loadMcpTools(servers, AbortSignal.timeout(MCP_VERIFY_TIMEOUT_MS));\n try {\n return names.map((name) => {\n const failure = loaded.errors.find((e) => e.server === name);\n if (failure) {\n const url = servers[name]?.url;\n const error = url ? failure.error.split(url).join(redactMcpUrl(url)) : failure.error;\n return { name, error };\n }\n const prefix = `mcp__${name}__`;\n return { name, tools: loaded.tools.filter((t) => t.name.startsWith(prefix)).length };\n });\n } finally {\n await loaded.dispose();\n }\n}\n\ntype McpMutationPlan =\n | { next: Record<string, McpServerConfig>; touched: Record<string, McpServerConfig> }\n | { status: number; error: string };\n\nfunction planMcpMutation(\n action: \"import\" | \"install\" | \"remove\" | \"toggle\",\n body: Record<string, unknown>,\n current: Record<string, McpServerConfig>,\n): McpMutationPlan {\n const next: Record<string, McpServerConfig> = { ...current };\n if (action === \"import\") {\n const parsed = parseStandardMcpServers(typeof body.json === \"string\" ? body.json : \"\");\n if (!parsed.servers) return { status: 400, error: parsed.error };\n Object.assign(next, parsed.servers);\n return { next, touched: parsed.servers };\n }\n const preset =\n action === \"install\" && typeof body.presetId === \"string\"\n ? findMcpPreset(body.presetId)\n : undefined;\n if (action === \"install\" && !preset) return { status: 400, error: \"unknown MCP preset\" };\n const name = preset?.serverName ?? (typeof body.name === \"string\" ? body.name.trim() : \"\");\n if (!isValidMcpServerName(name)) {\n return {\n status: 400,\n error: \"invalid server name (letters, digits, '_' or '-', starting with a letter)\",\n };\n }\n if (action === \"install\") {\n try {\n next[name] = materializeMcpPreset(preset!, mcpStringMap(body.credentials) ?? {});\n } catch (err) {\n return { status: 400, error: err instanceof Error ? err.message : String(err) };\n }\n return { next, touched: { [name]: next[name] } };\n }\n if (!(name in next)) return { status: 404, error: \"Not declared here.\" };\n if (action === \"remove\") {\n delete next[name];\n return { next, touched: {} };\n }\n const entry = next[name]!;\n next[name] = entry.disabled ? { ...entry, disabled: undefined } : { ...entry, disabled: true };\n return { next, touched: {} };\n}\n\nasync function serveMcpServerMutation(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): Promise<void> {\n const action = body.action;\n if (\n action !== \"import\" &&\n action !== \"install\" &&\n action !== \"remove\" &&\n action !== \"toggle\" &&\n action !== \"test\"\n ) {\n jsonRes(res, 400, {\n error: \"action must be 'import', 'install', 'remove', 'toggle', or 'test'\",\n });\n return;\n }\n const mutationScope = body.scope === \"global\" ? \"global\" : \"conversation\";\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const office = workspace.office(scope.address);\n const maps = loadScopeMcpServers(office);\n const current = mutationScope === \"global\" ? maps.global : maps.conversation;\n\n if (action === \"test\") {\n const name = typeof body.name === \"string\" ? body.name.trim() : \"\";\n const entry = current[name];\n if (!entry) {\n jsonRes(res, 404, { error: \"Not declared here.\" });\n return;\n }\n const results = await verifyMcpServers({ [name]: { ...entry, disabled: undefined } });\n jsonRes(res, 200, { ok: true, results });\n return;\n }\n\n const plan = planMcpMutation(action, body, current);\n if (\"error\" in plan) {\n jsonRes(res, plan.status, { error: plan.error });\n return;\n }\n const result =\n mutationScope === \"global\"\n ? applyGlobalSettings(services.runtime, { mcpServers: plan.next })\n : applyConversationSettings(services.runtime, office, { mcpServers: plan.next });\n if (!result.ok) {\n jsonRes(res, 409, { error: \"Conversation is busy; try again shortly.\" });\n return;\n }\n const results = await verifyMcpServers(plan.touched);\n jsonRes(res, 200, { ok: true, results });\n}\n\nfunction serveSkillsList(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const global = readSkillsFromDir(workspace.skillsDir, \"global\");\n const conversation = readSkillsFromDir(workspace.office(scope.address).skillsDir, \"conversation\");\n jsonRes(res, 200, {\n conversationId: scope.conversationId,\n skills: [...global, ...conversation],\n });\n}\n\nfunction serveSkillFile(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): void {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n\n const source = (url.searchParams.get(\"source\") ?? \"\").trim();\n const directory = (url.searchParams.get(\"directory\") ?? \"\").trim();\n if (source !== \"global\" && source !== \"conversation\") {\n jsonRes(res, 400, { error: \"Invalid skill source\" });\n return;\n }\n if (\n !directory ||\n directory.includes(\"/\") ||\n directory.includes(\"\\\\\") ||\n directory.includes(\"..\")\n ) {\n jsonRes(res, 400, { error: \"Invalid skill directory\" });\n return;\n }\n\n const skillsRoot =\n source === \"global\" ? workspace.skillsDir : workspace.office(scope.address).skillsDir;\n const safe = safeJoinUnderRoot(skillsRoot, join(directory, \"SKILL.md\"));\n if (safe.error) {\n jsonRes(res, 400, { error: safe.error });\n return;\n }\n\n servePreviewFile(res, safe.absolute, { source, directory }, \"Skill file not found\");\n}\n\nconst SKILL_DIRECTORY_PATTERN = /^[a-z0-9-]+$/;\n\nfunction resolveSkillsRoot(\n workspace: Workspace,\n scope: AdminConversationScope,\n source: unknown,\n): { root: string; source: \"global\" | \"conversation\" } | { error: string } {\n if (source !== \"global\" && source !== \"conversation\") {\n return { error: \"Invalid skill source\" };\n }\n return {\n root: source === \"global\" ? workspace.skillsDir : workspace.office(scope.address).skillsDir,\n source,\n };\n}\n\nasync function serveSkillMutation(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): Promise<void> {\n const action = body.action;\n if (action !== \"save\" && action !== \"delete\") {\n jsonRes(res, 400, { error: \"action must be 'save' or 'delete'\" });\n return;\n }\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const resolved = resolveSkillsRoot(workspace, scope, body.source);\n if (\"error\" in resolved) {\n jsonRes(res, 400, { error: resolved.error });\n return;\n }\n\n const directory = typeof body.directory === \"string\" ? body.directory.trim() : \"\";\n if (!directory || !SKILL_DIRECTORY_PATTERN.test(directory)) {\n jsonRes(res, 400, {\n error: \"directory must be lowercase a-z, 0-9 and hyphens\",\n });\n return;\n }\n const safe = safeJoinUnderRoot(resolved.root, directory);\n if (safe.error) {\n jsonRes(res, 400, { error: safe.error });\n return;\n }\n\n if (action === \"delete\") {\n if (!existsSync(join(safe.absolute, \"SKILL.md\"))) {\n jsonRes(res, 404, { error: \"Skill not found\" });\n return;\n }\n try {\n rmSync(safe.absolute, { recursive: true, force: true });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n return;\n }\n jsonRes(res, 200, { ok: true });\n return;\n }\n\n const name = typeof body.name === \"string\" ? body.name.trim() : directory;\n const description = typeof body.description === \"string\" ? body.description.trim() : \"\";\n const content = typeof body.content === \"string\" ? body.content : \"\";\n if (!description) {\n jsonRes(res, 400, { error: \"description is required\" });\n return;\n }\n const errors = validateSkill(name, description);\n if (errors.length > 0) {\n jsonRes(res, 400, { error: errors.join(\"; \") });\n return;\n }\n\n try {\n if (existsSync(safe.absolute) && lstatSync(safe.absolute).isSymbolicLink()) {\n throw new Error(\"Refusing to write through a symlinked skill directory\");\n }\n mkdirSync(safe.absolute, { recursive: true });\n const frontmatter = [\"---\", `name: ${name}`, `description: ${description}`, \"---\", \"\"].join(\n \"\\n\",\n );\n atomicWritePrivateFile(join(safe.absolute, \"SKILL.md\"), frontmatter + content.trim() + \"\\n\");\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n return;\n }\n jsonRes(res, 200, { ok: true, name, directory, source: resolved.source });\n}\n\nexport async function listOfficeEvents(store: EventStore): Promise<EventSummary[]> {\n const entries = await store.list();\n return entries.map((entry) => {\n const payload = entry.payload;\n return {\n name: entry.filename,\n officePlatform: store.address.platform,\n officeConversationId: store.address.conversationId,\n size: entry.size,\n mtimeMs: entry.mtimeMs,\n type: payload?.type ?? null,\n platform: payload?.platform ?? null,\n conversationId: payload?.conversationId ?? null,\n text: payload?.text ?? null,\n at: payload?.type === \"one-shot\" ? payload.at : null,\n schedule: payload?.type === \"periodic\" ? payload.schedule : null,\n timezone: payload?.type === \"periodic\" ? payload.timezone : null,\n };\n });\n}\n\nfunction requireAdminEventStore(\n res: ServerResponse,\n services: AdminServices,\n office: Office,\n): EventStore | null {\n if (!services.eventStore) {\n jsonRes(res, 503, { error: \"Working directory not available\" });\n return null;\n }\n return services.eventStore(office);\n}\n\nasync function serveEventsList(res: ServerResponse, services: AdminServices): Promise<void> {\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n if (!services.eventStore) {\n jsonRes(res, 503, { error: \"Working directory not available\" });\n return;\n }\n const events: EventSummary[] = [];\n for (const record of listRegisteredOffices(workspace.stateDir)) {\n events.push(...(await listOfficeEvents(services.eventStore(workspace.office(record)))));\n }\n jsonRes(res, 200, { events });\n}\n\nasync function serveConversationEventsList(\n res: ServerResponse,\n url: URL,\n services: AdminServices,\n token: AdminToken,\n): Promise<void> {\n const scope = resolveConversationFromQuery(url, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const store = requireAdminEventStore(res, services, workspace.office(scope.address));\n if (!store) return;\n jsonRes(res, 200, {\n conversationId: scope.conversationId,\n events: await listOfficeEvents(store),\n });\n}\n\nasync function serveConversationEventDelete(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): Promise<void> {\n const scope = resolveTargetConversation(body, token);\n if (scope.error) {\n jsonRes(res, 403, { error: scope.error });\n return;\n }\n let name: string;\n try {\n name = validateEventFilename(typeof body.name === \"string\" ? body.name : \"\");\n } catch {\n jsonRes(res, 400, { error: \"Invalid name\" });\n return;\n }\n const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\n const store = requireAdminEventStore(res, services, workspace.office(scope.address));\n if (!store) return;\n try {\n await store.delete(name);\n jsonRes(res, 200, { ok: true });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n jsonRes(res, /not found/.test(message) ? 404 : 500, { error: message });\n }\n}\n\nconst esc = escapeHtml;\n\ntype RailIconKey =\n | \"settings\"\n | \"workspace\"\n | \"skills\"\n | \"mcp\"\n | \"vault\"\n | \"events\"\n | \"session\"\n | \"overview\"\n | \"usage\";\n\nconst ICONS: Record<RailIconKey, string> = {\n settings: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h.01a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v.01a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z\"/></svg>`,\n workspace: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z\"/></svg>`,\n skills: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 19.5V5a2 2 0 0 1 2-2h11a1 1 0 0 1 1 1v14\"/><path d=\"M6 17h13v4H6.5A2.5 2.5 0 0 1 4 18.5v0A2.5 2.5 0 0 1 6.5 16H20\"/></svg>`,\n mcp: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"7\" rx=\"1.5\"/><rect x=\"3\" y=\"13\" width=\"18\" height=\"7\" rx=\"1.5\"/><circle cx=\"7\" cy=\"7.5\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"7\" cy=\"16.5\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/></svg>`,\n vault: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"10\" rx=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/></svg>`,\n events: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\"/><path d=\"M3 10h18M8 3v4M16 3v4\"/></svg>`,\n session: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z\"/></svg>`,\n overview: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1.5\"/><rect x=\"13\" y=\"3\" width=\"8\" height=\"5\" rx=\"1.5\"/><rect x=\"13\" y=\"11\" width=\"8\" height=\"10\" rx=\"1.5\"/><rect x=\"3\" y=\"14\" width=\"8\" height=\"7\" rx=\"1.5\"/></svg>`,\n usage: `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 21V3\"/><path d=\"M3 21h18\"/><path d=\"M7 17V11M12 17V7M17 17v-4\"/></svg>`,\n};\n\nfunction railLink(id: string, label: string, icon: RailIconKey, active = false): string {\n const svg = ICONS[icon];\n return `<button class=\"rail-link${active ? \" active\" : \"\"}\" type=\"button\" data-pane=\"${id}\" aria-current=\"${active ? \"page\" : \"false\"}\" aria-label=\"${esc(label)}\" title=\"${esc(label)}\">${svg}<span>${esc(label)}</span></button>`;\n}\n\nfunction settingsPane(\n id: string,\n title: string,\n description: string,\n actions: string,\n body: string,\n): string {\n return `<section class=\"pane\" id=\"pane-${id}\" data-pane=\"${id}\">\n <header class=\"pane-head\">\n <div><h2 class=\"pane-title\">${esc(title)}</h2><p class=\"pane-desc\">${esc(description)}</p></div>\n <div class=\"pane-actions\">${actions}</div>\n </header>\n <div class=\"pane-body\">${body}</div>\n </section>`;\n}\n\nconst adminViewBody = `<div class=\"settings-shell\">\n <aside class=\"settings-rail\" aria-label=\"Admin sections\">\n <div class=\"rail-scope\" role=\"tablist\" aria-label=\"Scope\">\n <button class=\"rail-scope-btn active\" role=\"tab\" aria-selected=\"true\" aria-controls=\"panel-conversation\" data-tab=\"conversation\">This conversation</button>\n <button class=\"rail-scope-btn\" role=\"tab\" aria-selected=\"false\" aria-controls=\"panel-global\" data-tab=\"global\">Workspace</button>\n </div>\n <nav class=\"rail-nav\" id=\"rail-nav-conversation\" data-scope=\"conversation\">\n ${railLink(\"settings\", \"Settings\", \"settings\", true)}\n ${railLink(\"workspace\", \"Workspace\", \"workspace\")}\n ${railLink(\"skills\", \"Skills\", \"skills\")}\n ${railLink(\"mcp\", \"MCP servers\", \"mcp\")}\n ${railLink(\"vault\", \"Vault\", \"vault\")}\n ${railLink(\"events\", \"Events\", \"events\")}\n ${railLink(\"session\", \"Session view\", \"session\")}\n </nav>\n <nav class=\"rail-nav\" id=\"rail-nav-global\" data-scope=\"global\" hidden>\n ${railLink(\"g-overview\", \"All conversations\", \"overview\", true)}\n ${railLink(\"g-usage\", \"Token usage\", \"usage\")}\n ${railLink(\"g-settings\", \"Defaults\", \"settings\")}\n ${railLink(\"g-mcp\", \"MCP servers\", \"mcp\")}\n ${railLink(\"g-skills\", \"Skills\", \"skills\")}\n ${railLink(\"g-events\", \"Events\", \"events\")}\n </nav>\n </aside>\n\n <div class=\"settings-panels\">\n <div class=\"tab-panel active\" id=\"panel-conversation\">\n ${settingsPane(\"settings\", \"Settings\", \"Model, thinking level, auto-reply, and workspace visibility for this conversation.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadSettings()\">↻</button>', '<div id=\"settings-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"workspace\", \"Workspace\", \"Read-only browser for this conversation's files on disk.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadWorkspace()\">↻</button>', '<div class=\"workspace-split\"><div id=\"workspace-tree\" class=\"workspace-tree\"><div class=\"loading-msg\">Loading…</div></div><div id=\"workspace-preview\" class=\"workspace-preview\"><div class=\"placeholder-msg\">Click a file to preview</div></div></div>')}\n\n ${settingsPane(\"skills\", \"Skills\", \"Instructions the agent can load for specific tasks in this conversation.\", '<button class=\"primary-action-btn\" onclick=\"openSkillDialog(\\'conversation\\')\">+ New skill</button><button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadSkills()\">↻</button>', '<div class=\"workspace-split\"><div id=\"skills-content\" class=\"workspace-tree\"><div class=\"loading-msg\">Loading…</div></div><div id=\"skills-preview\" class=\"workspace-preview\"><div class=\"placeholder-msg\">Click a skill to preview SKILL.md</div></div></div>')}\n\n ${settingsPane(\"mcp\", \"MCP servers\", \"External tools this conversation can call during a run.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadMcpServers()\">↻</button>', '<div id=\"mcp-conv-msg\" class=\"status-msg\" style=\"display:none\"></div><div id=\"mcp-conv-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"vault\", \"Vault\", \"Credentials scoped to this conversation.\", '<button class=\"primary-action-btn\" onclick=\"openLogin()\">Open in new tab ↗</button>', '<div id=\"vault-link-result\" class=\"link-result\" style=\"display:none\"></div><p class=\"card-desc\">Opens the one-time credential form for this conversation\\'s vault in a new tab.</p>')}\n\n ${settingsPane(\"events\", \"Events\", \"Scheduled and one-shot events tied to this conversation.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadConversationEvents()\">↻</button>', '<div id=\"events-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"session\", \"Session view\", \"The full message and tool-call timeline for this conversation.\", '<button class=\"primary-action-btn\" onclick=\"openSessionView()\">Open in new tab ↗</button>', '<div id=\"session-link-result\" class=\"link-result\" style=\"display:none\"></div><p class=\"card-desc\">Opens the session timeline for this conversation in a new tab.</p>')}\n </div>\n\n <div class=\"tab-panel\" id=\"panel-global\">\n ${settingsPane(\"g-overview\", \"All conversations\", \"Every registered conversation across every platform.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadAllConversations()\">↻</button>', '<div id=\"all-conv-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"g-usage\", \"Token usage\", \"Spend and volume across every conversation.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadTokenUsage()\">↻</button>', '<h3 class=\"card-subtitle\">Top 20 sessions</h3><div id=\"session-usage-content\"><div class=\"loading-msg\">Loading…</div></div><h3 class=\"card-subtitle\" style=\"margin-top:24px\">Usage timeline</h3><div class=\"timeline-controls\"><label>Conversation<select id=\"timeline-conv\" onchange=\"loadUsageTimeline()\"></select></label></div><div id=\"usage-timeline-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"g-settings\", \"Workspace defaults\", \"The fallback model, sandbox limits, and Slack behavior every conversation inherits.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadGlobalSettings()\">↻</button>', '<div id=\"global-settings-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"g-mcp\", \"MCP servers\", \"External tools available to every conversation in this workspace.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadMcpServers()\">↻</button>', '<div id=\"mcp-global-msg\" class=\"status-msg\" style=\"display:none\"></div><div id=\"mcp-global-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n\n ${settingsPane(\"g-skills\", \"Skills\", \"Shared instructions available to every conversation in this workspace.\", '<button class=\"primary-action-btn\" onclick=\"openSkillDialog(\\'global\\')\">+ New global skill</button><button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadGlobalSkills()\">↻</button>', '<div class=\"workspace-split\"><div id=\"global-skills-content\" class=\"workspace-tree\"><div class=\"loading-msg\">Loading…</div></div><div id=\"global-skills-preview\" class=\"workspace-preview\"><div class=\"placeholder-msg\">Click a skill to preview SKILL.md</div></div></div>')}\n\n ${settingsPane(\"g-events\", \"Global events\", \"Every scheduled event across the whole workspace.\", '<button class=\"refresh-btn\" type=\"button\" aria-label=\"Refresh\" title=\"Refresh\" onclick=\"loadEvents()\">↻</button>', '<div id=\"global-events-content\"><div class=\"loading-msg\">Loading…</div></div>')}\n </div>\n </div>\n </div>\n\n <dialog id=\"mcp-install-dialog\" class=\"mcp-dialog\" aria-labelledby=\"mcp-dialog-title\">\n <div class=\"mcp-dialog-head\">\n <div>\n <p class=\"eyebrow\">Install MCP preset</p>\n <h2 id=\"mcp-dialog-title\" class=\"card-title\"></h2>\n </div>\n <button class=\"mcp-dialog-close\" type=\"button\" aria-label=\"Close\" onclick=\"closeMcpInstall()\">×</button>\n </div>\n <div id=\"mcp-dialog-content\"></div>\n <div id=\"mcp-dialog-error\" class=\"inline-result err\" style=\"display:none\"></div>\n <div class=\"mcp-dialog-actions\">\n <button class=\"mcp-btn\" type=\"button\" onclick=\"closeMcpInstall()\">Cancel</button>\n <button id=\"mcp-dialog-install\" class=\"primary-action-btn\" type=\"button\" onclick=\"installMcpPreset(this)\">Install preset</button>\n </div>\n </dialog>\n\n <dialog id=\"mcp-custom-dialog\" class=\"mcp-dialog\" aria-labelledby=\"mcp-custom-dialog-title\">\n <div class=\"mcp-dialog-head\">\n <div>\n <p class=\"eyebrow\">Add MCP server</p>\n <h2 id=\"mcp-custom-dialog-title\" class=\"card-title\">新增自訂 server</h2>\n </div>\n <button class=\"mcp-dialog-close\" type=\"button\" aria-label=\"Close\" onclick=\"closeMcpCustomDialog()\">×</button>\n </div>\n <div id=\"mcp-custom-dialog-content\"></div>\n <div id=\"mcp-custom-dialog-error\" class=\"inline-result err\" style=\"display:none\"></div>\n <div class=\"mcp-dialog-actions\">\n <button class=\"mcp-btn\" type=\"button\" onclick=\"closeMcpCustomDialog()\">Cancel</button>\n <button id=\"mcp-custom-dialog-submit\" class=\"primary-action-btn\" type=\"button\" onclick=\"submitMcpCustomDialog(this)\">新增並測試連線</button>\n </div>\n </dialog>\n\n <dialog id=\"skill-dialog\" class=\"mcp-dialog\" aria-labelledby=\"skill-dialog-title\">\n <div class=\"mcp-dialog-head\">\n <div>\n <p class=\"eyebrow\" id=\"skill-dialog-eyebrow\">Skill</p>\n <h2 id=\"skill-dialog-title\" class=\"card-title\">New skill</h2>\n </div>\n <button class=\"mcp-dialog-close\" type=\"button\" aria-label=\"Close\" onclick=\"closeSkillDialog()\">×</button>\n </div>\n <div class=\"mcp-field\">\n <span>Directory</span>\n <input id=\"skill-dialog-directory\" class=\"form-input mcp-json\" placeholder=\"my-skill\" autocomplete=\"off\" />\n <small class=\"mcp-secret-note\">Lowercase letters, digits, hyphens. Cannot be changed after creation.</small>\n </div>\n <div class=\"mcp-field\">\n <span>Name</span>\n <input id=\"skill-dialog-name\" class=\"form-input mcp-json\" placeholder=\"my-skill\" autocomplete=\"off\" />\n </div>\n <div class=\"mcp-field\">\n <span>Description</span>\n <input id=\"skill-dialog-description\" class=\"form-input mcp-json\" placeholder=\"Use when …\" autocomplete=\"off\" />\n </div>\n <div class=\"mcp-field\">\n <span>Instructions (SKILL.md body)</span>\n <textarea id=\"skill-dialog-content\" class=\"form-input mcp-json\" spellcheck=\"false\" rows=\"12\" placeholder=\"# My skill Instructions here.\"></textarea>\n </div>\n <div id=\"skill-dialog-error\" class=\"inline-result err\" style=\"display:none\"></div>\n <div class=\"mcp-dialog-actions\">\n <button class=\"mcp-btn\" type=\"button\" onclick=\"closeSkillDialog()\">Cancel</button>\n <button id=\"skill-dialog-submit\" class=\"primary-action-btn\" type=\"button\" onclick=\"submitSkillDialog(this)\">Save</button>\n </div>\n </dialog>`;\n\nfunction renderAdminPage(token: AdminToken): string {\n const userLabel = token.platformUserName ?? token.platformUserId;\n const script = `\n const adminToken = ${JSON.stringify(token.token)};\n const defaultConversationKey = ${JSON.stringify(`${token.platform}:${token.conversationId}`)};\n${adminViewFunctionsScript}\n${adminViewStartupScript}`;\n\n return renderPortalShell({\n activeView: \"admin\",\n pageTitle: \"Admin\",\n identity: { primary: token.platform, secondary: userLabel },\n conversationSwitcher: { currentId: token.conversationId },\n body: adminViewBody,\n extraStyles: adminViewStyles,\n inlineScript: script,\n });\n}\n\nfunction renderAdminErrorPage(message: string): string {\n return renderPortalShell({\n activeView: \"admin\",\n pageTitle: \"Admin\",\n body: `<section class=\"card\" style=\"text-align:center;padding:40px 32px\">\n <p class=\"eyebrow\">${PRODUCT_NAME} admin</p>\n <h1 class=\"page-title\" style=\"margin:12px 0 16px\">Access Denied</h1>\n <div class=\"err-msg\">${esc(message)}</div>\n </section>`,\n });\n}\n"]}
|