@geminixiang/mikan 1.0.0-beta.53 → 1.0.0-beta.55
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 +29 -0
- package/README.md +3 -2
- package/dist/adapters/commands/admin.d.ts.map +1 -0
- package/dist/{commands → adapters/commands}/admin.js +4 -8
- package/dist/adapters/commands/admin.js.map +1 -0
- package/dist/adapters/commands/login.d.ts.map +1 -0
- package/dist/adapters/commands/login.js +166 -0
- package/dist/adapters/commands/login.js.map +1 -0
- package/dist/adapters/commands/manifest.d.ts.map +1 -0
- package/dist/{commands → adapters/commands}/manifest.js +0 -7
- package/dist/adapters/commands/manifest.js.map +1 -0
- package/dist/{commands → adapters/commands}/model.d.ts +6 -0
- package/dist/adapters/commands/model.d.ts.map +1 -0
- package/dist/{commands → adapters/commands}/model.js +56 -44
- package/dist/adapters/commands/model.js.map +1 -0
- package/dist/adapters/commands/new.d.ts.map +1 -0
- package/dist/{commands → adapters/commands}/new.js +7 -8
- package/dist/adapters/commands/new.js.map +1 -0
- package/dist/adapters/commands/registry.d.ts.map +1 -0
- package/dist/{commands → adapters/commands}/registry.js +1 -3
- package/dist/adapters/commands/registry.js.map +1 -0
- package/dist/adapters/commands/sandbox.d.ts.map +1 -0
- package/dist/{commands → adapters/commands}/sandbox.js +22 -21
- package/dist/adapters/commands/sandbox.js.map +1 -0
- package/dist/adapters/commands/session-view.d.ts.map +1 -0
- package/dist/{commands → adapters/commands}/session-view.js +8 -11
- package/dist/adapters/commands/session-view.js.map +1 -0
- package/dist/{commands → adapters/commands}/types.d.ts +6 -6
- package/dist/adapters/commands/types.d.ts.map +1 -0
- package/dist/adapters/commands/types.js.map +1 -0
- package/dist/adapters/commands/utils.d.ts +14 -0
- package/dist/adapters/commands/utils.d.ts.map +1 -0
- package/dist/{commands → adapters/commands}/utils.js +18 -1
- package/dist/adapters/commands/utils.js.map +1 -0
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +4 -5
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +3 -4
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/client.d.ts.map +1 -1
- package/dist/adapters/github/client.js +5 -18
- package/dist/adapters/github/client.js.map +1 -1
- package/dist/adapters/github/tool-pack.d.ts +1 -1
- package/dist/adapters/github/tool-pack.d.ts.map +1 -1
- package/dist/adapters/github/tool-pack.js.map +1 -1
- package/dist/adapters/github/tools/checks.js +1 -1
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/tools/issue.js +1 -1
- package/dist/adapters/github/tools/issue.js.map +1 -1
- package/dist/adapters/github/tools/pr.js +1 -1
- package/dist/adapters/github/tools/pr.js.map +1 -1
- package/dist/adapters/github/tools/read.d.ts.map +1 -1
- package/dist/adapters/github/tools/read.js +53 -53
- package/dist/adapters/github/tools/read.js.map +1 -1
- package/dist/adapters/github/tools/review-reply.js +1 -1
- package/dist/adapters/github/tools/review-reply.js.map +1 -1
- package/dist/adapters/github/tools/sync.js +1 -1
- package/dist/adapters/github/tools/sync.js.map +1 -1
- package/dist/adapters/intake.d.ts +1 -1
- package/dist/adapters/intake.d.ts.map +1 -1
- package/dist/adapters/intake.js +2 -6
- package/dist/adapters/intake.js.map +1 -1
- package/dist/adapters/markdown-tables.d.ts +0 -13
- package/dist/adapters/markdown-tables.d.ts.map +1 -1
- package/dist/adapters/markdown-tables.js +26 -38
- package/dist/adapters/markdown-tables.js.map +1 -1
- package/dist/adapters/shared.js +1 -1
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +7 -4
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +104 -122
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +33 -25
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/tool-pack.d.ts +1 -1
- package/dist/adapters/slack/tool-pack.d.ts.map +1 -1
- package/dist/adapters/slack/tool-pack.js.map +1 -1
- package/dist/adapters/slack/update-diagnostics.d.ts.map +1 -1
- package/dist/adapters/slack/update-diagnostics.js +8 -24
- package/dist/adapters/slack/update-diagnostics.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +3 -4
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/types.d.ts +2 -4
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/{web → adapters/web}/admin/portal.d.ts +3 -3
- package/dist/adapters/web/admin/portal.d.ts.map +1 -0
- package/dist/{web → adapters/web}/admin/portal.js +535 -709
- package/dist/adapters/web/admin/portal.js.map +1 -0
- package/dist/{web → adapters/web}/admin/provider-models.d.ts +1 -1
- package/dist/adapters/web/admin/provider-models.d.ts.map +1 -0
- package/dist/adapters/web/admin/provider-models.js.map +1 -0
- package/dist/{web → adapters/web}/admin/types.d.ts +5 -5
- package/dist/adapters/web/admin/types.d.ts.map +1 -0
- package/dist/adapters/web/admin/types.js.map +1 -0
- package/dist/adapters/web/login/oauth.d.ts.map +1 -0
- package/dist/{web → adapters/web}/login/oauth.js +50 -54
- package/dist/adapters/web/login/oauth.js.map +1 -0
- package/dist/{web → adapters/web}/login/portal.d.ts +2 -2
- package/dist/adapters/web/login/portal.d.ts.map +1 -0
- package/dist/{web → adapters/web}/login/portal.js +6 -6
- package/dist/adapters/web/login/portal.js.map +1 -0
- package/dist/{web → adapters/web}/login/types.d.ts +1 -1
- package/dist/adapters/web/login/types.d.ts.map +1 -0
- package/dist/adapters/web/login/types.js.map +1 -0
- package/dist/{web → adapters/web}/portal-shell.d.ts +2 -2
- package/dist/adapters/web/portal-shell.d.ts.map +1 -0
- package/dist/{web → adapters/web}/portal-shell.js +2 -2
- package/dist/adapters/web/portal-shell.js.map +1 -0
- package/dist/{web → adapters/web}/server.d.ts +5 -5
- package/dist/adapters/web/server.d.ts.map +1 -0
- package/dist/{web → adapters/web}/server.js +4 -7
- package/dist/adapters/web/server.js.map +1 -0
- package/dist/adapters/web/session-view/portal.d.ts.map +1 -0
- package/dist/{web → adapters/web}/session-view/portal.js +9 -9
- package/dist/adapters/web/session-view/portal.js.map +1 -0
- package/dist/{web → adapters/web}/session-view/types.d.ts +3 -3
- package/dist/adapters/web/session-view/types.d.ts.map +1 -0
- package/dist/adapters/web/session-view/types.js.map +1 -0
- package/dist/adapters/web/token-store.d.ts.map +1 -0
- package/dist/adapters/web/token-store.js.map +1 -0
- package/dist/adapters/web/types.d.ts.map +1 -0
- package/dist/adapters/web/types.js.map +1 -0
- package/dist/cli/arg-grammar.d.ts +24 -0
- package/dist/cli/arg-grammar.d.ts.map +1 -1
- package/dist/cli/arg-grammar.js +39 -8
- package/dist/cli/arg-grammar.js.map +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +48 -62
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/download.d.ts.map +1 -1
- package/dist/cli/download.js +51 -54
- package/dist/cli/download.js.map +1 -1
- package/dist/cli/office.d.ts.map +1 -1
- package/dist/cli/office.js +9 -26
- package/dist/cli/office.js.map +1 -1
- package/dist/cli/onboard.d.ts.map +1 -1
- package/dist/cli/onboard.js +15 -11
- package/dist/cli/onboard.js.map +1 -1
- package/dist/cli/sessions.d.ts.map +1 -1
- package/dist/cli/sessions.js +49 -52
- package/dist/cli/sessions.js.map +1 -1
- package/dist/config.d.ts +4 -28
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -112
- package/dist/config.js.map +1 -1
- package/dist/dream/index.d.ts.map +1 -1
- package/dist/dream/index.js +8 -2
- package/dist/dream/index.js.map +1 -1
- package/dist/dream/types.d.ts +1 -1
- package/dist/dream/types.d.ts.map +1 -1
- package/dist/dream/types.js.map +1 -1
- package/dist/env-manifest.d.ts +2 -0
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +29 -8
- package/dist/env-manifest.js.map +1 -1
- package/dist/events/index.d.ts +150 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/{harness/event-format.js → events/index.js} +80 -2
- package/dist/events/index.js.map +1 -0
- package/dist/{events.d.ts → events/watcher.d.ts} +4 -4
- package/dist/events/watcher.d.ts.map +1 -0
- package/dist/{events.js → events/watcher.js} +8 -8
- package/dist/events/watcher.js.map +1 -0
- package/dist/file-guards.d.ts.map +1 -0
- package/dist/file-guards.js.map +1 -0
- package/dist/harness/execution-env.d.ts +19 -0
- package/dist/harness/execution-env.d.ts.map +1 -0
- package/dist/harness/execution-env.js +262 -0
- package/dist/harness/execution-env.js.map +1 -0
- package/dist/harness/execution-resolver.d.ts +25 -0
- package/dist/harness/execution-resolver.d.ts.map +1 -0
- package/dist/{execution-resolver.js → harness/execution-resolver.js} +12 -21
- package/dist/harness/execution-resolver.js.map +1 -0
- package/dist/harness/index.d.ts +9 -9
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +8 -8
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/mcp.d.ts +38 -0
- package/dist/harness/mcp.d.ts.map +1 -0
- package/dist/{mcp/loader.js → harness/mcp.js} +155 -6
- package/dist/harness/mcp.js.map +1 -0
- package/dist/harness/models.js +1 -1
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/open-connector.d.ts.map +1 -0
- package/dist/{mcp → harness}/open-connector.js +1 -1
- package/dist/harness/open-connector.js.map +1 -0
- package/dist/{agent → harness}/presenter.d.ts +2 -9
- package/dist/harness/presenter.d.ts.map +1 -0
- package/dist/{agent → harness}/presenter.js +170 -146
- package/dist/harness/presenter.js.map +1 -0
- package/dist/{agent → harness}/prompt.d.ts +10 -3
- package/dist/harness/prompt.d.ts.map +1 -0
- package/dist/{agent → harness}/prompt.js +137 -41
- package/dist/harness/prompt.js.map +1 -0
- package/dist/harness/runner.d.ts +2 -109
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +499 -467
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session.d.ts +119 -0
- package/dist/harness/session.d.ts.map +1 -0
- package/dist/harness/session.js +561 -0
- package/dist/harness/session.js.map +1 -0
- package/dist/harness/skills.d.ts +10 -2
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +62 -39
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/{subagent-runner.d.ts → subagent.d.ts} +25 -6
- package/dist/harness/subagent.d.ts.map +1 -0
- package/dist/harness/{subagent-runner.js → subagent.js} +106 -54
- package/dist/harness/subagent.js.map +1 -0
- package/dist/harness/tools/attach.d.ts.map +1 -0
- package/dist/harness/tools/attach.js.map +1 -0
- package/dist/{tools → harness/tools}/event.d.ts +3 -32
- package/dist/harness/tools/event.d.ts.map +1 -0
- package/dist/harness/tools/event.js +178 -0
- package/dist/harness/tools/event.js.map +1 -0
- package/dist/harness/tools/generate-image.d.ts.map +1 -0
- package/dist/harness/tools/generate-image.js.map +1 -0
- package/dist/harness/tools/host-fn-tool.d.ts.map +1 -0
- package/dist/harness/tools/host-fn-tool.js.map +1 -0
- package/dist/{tools → harness/tools}/index.d.ts +5 -6
- package/dist/harness/tools/index.d.ts.map +1 -0
- package/dist/{tools → harness/tools}/index.js +12 -16
- package/dist/harness/tools/index.js.map +1 -0
- package/dist/harness/tools/pi-tools.d.ts +18 -0
- package/dist/harness/tools/pi-tools.d.ts.map +1 -0
- package/dist/harness/tools/pi-tools.js +84 -0
- package/dist/harness/tools/pi-tools.js.map +1 -0
- package/dist/harness/tools/react.d.ts.map +1 -0
- package/dist/harness/tools/react.js.map +1 -0
- package/dist/{tools → harness/tools}/sandbox.d.ts +2 -2
- package/dist/harness/tools/sandbox.d.ts.map +1 -0
- package/dist/{tools → harness/tools}/sandbox.js +1 -1
- package/dist/harness/tools/sandbox.js.map +1 -0
- package/dist/{tools → harness/tools}/subagent.d.ts +28 -1
- package/dist/harness/tools/subagent.d.ts.map +1 -0
- package/dist/{tools → harness/tools}/subagent.js +218 -2
- package/dist/harness/tools/subagent.js.map +1 -0
- package/dist/{tools → harness/tools}/types.d.ts +0 -33
- package/dist/harness/tools/types.d.ts.map +1 -0
- package/dist/harness/tools/types.js.map +1 -0
- package/dist/harness/types.d.ts +180 -97
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts +12 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/main.js +10 -12
- package/dist/main.js.map +1 -1
- package/dist/observability/index.d.ts +33 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +256 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/instrument.js +7 -1
- package/dist/observability/instrument.js.map +1 -1
- package/dist/observability/otel.d.ts +10 -0
- package/dist/observability/otel.d.ts.map +1 -0
- package/dist/observability/otel.js +183 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/observability/sentry.d.ts +22 -5
- package/dist/observability/sentry.d.ts.map +1 -1
- package/dist/observability/sentry.js +68 -23
- package/dist/observability/sentry.js.map +1 -1
- package/dist/observability/types.d.ts +6 -2
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/observability/types.js.map +1 -1
- package/dist/office/index.d.ts +2 -3
- package/dist/office/index.d.ts.map +1 -1
- package/dist/office/index.js +172 -140
- package/dist/office/index.js.map +1 -1
- package/dist/{workspace-projection/index.d.ts → office/projection.d.ts} +2 -2
- package/dist/office/projection.d.ts.map +1 -0
- package/dist/{workspace-projection/index.js → office/projection.js} +2 -2
- package/dist/office/projection.js.map +1 -0
- package/dist/office/types.d.ts +29 -2
- package/dist/office/types.d.ts.map +1 -1
- package/dist/office/types.js.map +1 -1
- package/dist/process-lifecycle.d.ts +1 -1
- package/dist/process-lifecycle.d.ts.map +1 -1
- package/dist/process-lifecycle.js +3 -3
- package/dist/process-lifecycle.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +106 -107
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/session-lifecycle.d.ts +10 -0
- package/dist/runtime/session-lifecycle.d.ts.map +1 -1
- package/dist/runtime/session-lifecycle.js +42 -24
- package/dist/runtime/session-lifecycle.js.map +1 -1
- package/dist/runtime/types.d.ts +3 -3
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts +1 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +41 -50
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +7 -4
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +27 -35
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +8 -15
- package/dist/sandbox/index.js.map +1 -1
- package/dist/{provisioner.d.ts → sandbox/provisioner.d.ts} +2 -2
- package/dist/sandbox/provisioner.d.ts.map +1 -0
- package/dist/{provisioner.js → sandbox/provisioner.js} +3 -3
- package/dist/sandbox/provisioner.js.map +1 -0
- package/dist/sandbox/types.d.ts +2 -0
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +5 -0
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +14 -0
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts.map +1 -1
- package/dist/sessions/chat-history-sync.js +72 -62
- package/dist/sessions/chat-history-sync.js.map +1 -1
- package/dist/sessions/migrate-common.d.ts +43 -0
- package/dist/sessions/migrate-common.d.ts.map +1 -0
- package/dist/sessions/migrate-common.js +99 -0
- package/dist/sessions/migrate-common.js.map +1 -0
- package/dist/sessions/migrate-pi-084.d.ts.map +1 -1
- package/dist/sessions/migrate-pi-084.js +152 -203
- package/dist/sessions/migrate-pi-084.js.map +1 -1
- package/dist/sessions/migrate-v3.d.ts +5 -0
- package/dist/sessions/migrate-v3.d.ts.map +1 -1
- package/dist/sessions/migrate-v3.js +161 -209
- package/dist/sessions/migrate-v3.js.map +1 -1
- package/dist/{harness → sessions}/session-store.d.ts +12 -1
- package/dist/sessions/session-store.d.ts.map +1 -0
- package/dist/{harness → sessions}/session-store.js +74 -35
- package/dist/sessions/session-store.js.map +1 -0
- package/dist/sessions/store.d.ts +1 -1
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +18 -17
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +40 -1
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/types.d.ts +7 -99
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +70 -53
- package/dist/vault/index.js.map +1 -1
- package/package.json +10 -4
- package/dist/adapters/slack/tools/attach.d.ts.map +0 -1
- package/dist/adapters/slack/tools/attach.js.map +0 -1
- package/dist/agent/catalog.d.ts +0 -22
- package/dist/agent/catalog.d.ts.map +0 -1
- package/dist/agent/catalog.js +0 -104
- package/dist/agent/catalog.js.map +0 -1
- package/dist/agent/execution.d.ts +0 -25
- package/dist/agent/execution.d.ts.map +0 -1
- package/dist/agent/execution.js +0 -171
- package/dist/agent/execution.js.map +0 -1
- package/dist/agent/presenter.d.ts.map +0 -1
- package/dist/agent/presenter.js.map +0 -1
- package/dist/agent/prompt.d.ts.map +0 -1
- package/dist/agent/prompt.js.map +0 -1
- package/dist/agent/runner.d.ts +0 -3
- package/dist/agent/runner.d.ts.map +0 -1
- package/dist/agent/runner.js +0 -452
- package/dist/agent/runner.js.map +0 -1
- package/dist/agent/types.d.ts +0 -101
- package/dist/agent/types.d.ts.map +0 -1
- package/dist/agent/types.js +0 -3
- package/dist/agent/types.js.map +0 -1
- package/dist/agent-events.d.ts +0 -6
- package/dist/agent-events.d.ts.map +0 -1
- package/dist/agent-events.js +0 -44
- package/dist/agent-events.js.map +0 -1
- package/dist/commands/admin.d.ts.map +0 -1
- package/dist/commands/admin.js.map +0 -1
- package/dist/commands/auto-reply.d.ts +0 -8
- package/dist/commands/auto-reply.d.ts.map +0 -1
- package/dist/commands/auto-reply.js +0 -65
- package/dist/commands/auto-reply.js.map +0 -1
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js +0 -158
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/manifest.d.ts.map +0 -1
- package/dist/commands/manifest.js.map +0 -1
- package/dist/commands/model.d.ts.map +0 -1
- package/dist/commands/model.js.map +0 -1
- package/dist/commands/new.d.ts.map +0 -1
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/registry.d.ts.map +0 -1
- package/dist/commands/registry.js.map +0 -1
- package/dist/commands/sandbox.d.ts.map +0 -1
- package/dist/commands/sandbox.js.map +0 -1
- package/dist/commands/session-view.d.ts.map +0 -1
- package/dist/commands/session-view.js.map +0 -1
- package/dist/commands/types.d.ts.map +0 -1
- package/dist/commands/types.js.map +0 -1
- package/dist/commands/utils.d.ts +0 -11
- package/dist/commands/utils.d.ts.map +0 -1
- package/dist/commands/utils.js.map +0 -1
- package/dist/events.d.ts.map +0 -1
- package/dist/events.js.map +0 -1
- package/dist/execution-resolver.d.ts +0 -27
- package/dist/execution-resolver.d.ts.map +0 -1
- package/dist/execution-resolver.js.map +0 -1
- package/dist/harness/event-format.d.ts +0 -33
- package/dist/harness/event-format.d.ts.map +0 -1
- package/dist/harness/event-format.js.map +0 -1
- package/dist/harness/session-store.d.ts.map +0 -1
- package/dist/harness/session-store.js.map +0 -1
- package/dist/harness/settings.d.ts +0 -29
- package/dist/harness/settings.d.ts.map +0 -1
- package/dist/harness/settings.js +0 -40
- package/dist/harness/settings.js.map +0 -1
- package/dist/harness/subagent-runner.d.ts.map +0 -1
- package/dist/harness/subagent-runner.js.map +0 -1
- package/dist/harness/subagent-slots.d.ts +0 -28
- package/dist/harness/subagent-slots.d.ts.map +0 -1
- package/dist/harness/subagent-slots.js +0 -72
- package/dist/harness/subagent-slots.js.map +0 -1
- package/dist/harness/usage.d.ts +0 -11
- package/dist/harness/usage.d.ts.map +0 -1
- package/dist/harness/usage.js +0 -38
- package/dist/harness/usage.js.map +0 -1
- package/dist/mcp/catalog.d.ts +0 -5
- package/dist/mcp/catalog.d.ts.map +0 -1
- package/dist/mcp/catalog.js +0 -68
- package/dist/mcp/catalog.js.map +0 -1
- package/dist/mcp/loader.d.ts +0 -12
- package/dist/mcp/loader.d.ts.map +0 -1
- package/dist/mcp/loader.js.map +0 -1
- package/dist/mcp/open-connector.d.ts.map +0 -1
- package/dist/mcp/open-connector.js.map +0 -1
- package/dist/mcp/types.d.ts +0 -66
- package/dist/mcp/types.d.ts.map +0 -1
- package/dist/mcp/types.js.map +0 -1
- package/dist/packages/index.d.ts +0 -169
- package/dist/packages/index.d.ts.map +0 -1
- package/dist/packages/index.js +0 -721
- package/dist/packages/index.js.map +0 -1
- package/dist/packages/types.d.ts +0 -100
- package/dist/packages/types.d.ts.map +0 -1
- package/dist/packages/types.js.map +0 -1
- package/dist/provisioner.d.ts.map +0 -1
- package/dist/provisioner.js.map +0 -1
- package/dist/subagent-progress.d.ts +0 -39
- package/dist/subagent-progress.d.ts.map +0 -1
- package/dist/subagent-progress.js +0 -225
- package/dist/subagent-progress.js.map +0 -1
- package/dist/tools/bash.d.ts +0 -12
- package/dist/tools/bash.d.ts.map +0 -1
- package/dist/tools/bash.js +0 -80
- package/dist/tools/bash.js.map +0 -1
- package/dist/tools/edit.d.ts +0 -11
- package/dist/tools/edit.d.ts.map +0 -1
- package/dist/tools/edit.js +0 -132
- package/dist/tools/edit.js.map +0 -1
- package/dist/tools/event.d.ts.map +0 -1
- package/dist/tools/event.js +0 -255
- package/dist/tools/event.js.map +0 -1
- package/dist/tools/generate-image.d.ts.map +0 -1
- package/dist/tools/generate-image.js.map +0 -1
- package/dist/tools/host-fn-tool.d.ts.map +0 -1
- package/dist/tools/host-fn-tool.js.map +0 -1
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/react.d.ts.map +0 -1
- package/dist/tools/react.js.map +0 -1
- package/dist/tools/read.d.ts +0 -12
- package/dist/tools/read.d.ts.map +0 -1
- package/dist/tools/read.js +0 -140
- package/dist/tools/read.js.map +0 -1
- package/dist/tools/sandbox.d.ts.map +0 -1
- package/dist/tools/sandbox.js.map +0 -1
- package/dist/tools/subagent.d.ts.map +0 -1
- package/dist/tools/subagent.js.map +0 -1
- package/dist/tools/types.d.ts.map +0 -1
- package/dist/tools/types.js.map +0 -1
- package/dist/tools/write.d.ts +0 -10
- package/dist/tools/write.d.ts.map +0 -1
- package/dist/tools/write.js +0 -23
- package/dist/tools/write.js.map +0 -1
- package/dist/trigger.d.ts +0 -23
- package/dist/trigger.d.ts.map +0 -1
- package/dist/trigger.js +0 -97
- package/dist/trigger.js.map +0 -1
- package/dist/utils/file-guards.d.ts.map +0 -1
- package/dist/utils/file-guards.js.map +0 -1
- package/dist/web/admin/portal.d.ts.map +0 -1
- package/dist/web/admin/portal.js.map +0 -1
- package/dist/web/admin/provider-models.d.ts.map +0 -1
- package/dist/web/admin/provider-models.js.map +0 -1
- package/dist/web/admin/types.d.ts.map +0 -1
- package/dist/web/admin/types.js.map +0 -1
- package/dist/web/login/oauth.d.ts.map +0 -1
- package/dist/web/login/oauth.js.map +0 -1
- package/dist/web/login/portal.d.ts.map +0 -1
- package/dist/web/login/portal.js.map +0 -1
- package/dist/web/login/types.d.ts.map +0 -1
- package/dist/web/login/types.js.map +0 -1
- package/dist/web/portal-shell.d.ts.map +0 -1
- package/dist/web/portal-shell.js.map +0 -1
- package/dist/web/server.d.ts.map +0 -1
- package/dist/web/server.js.map +0 -1
- package/dist/web/session-view/portal.d.ts.map +0 -1
- package/dist/web/session-view/portal.js.map +0 -1
- package/dist/web/session-view/types.d.ts.map +0 -1
- package/dist/web/session-view/types.js +0 -2
- package/dist/web/session-view/types.js.map +0 -1
- package/dist/web/token-store.d.ts.map +0 -1
- package/dist/web/token-store.js.map +0 -1
- package/dist/web/types.d.ts.map +0 -1
- package/dist/web/types.js +0 -2
- package/dist/web/types.js.map +0 -1
- package/dist/workspace-projection/index.d.ts.map +0 -1
- package/dist/workspace-projection/index.js.map +0 -1
- package/dist/workspace-projection/types.d.ts +0 -29
- package/dist/workspace-projection/types.d.ts.map +0 -1
- package/dist/workspace-projection/types.js +0 -2
- package/dist/workspace-projection/types.js.map +0 -1
- /package/dist/{commands → adapters/commands}/admin.d.ts +0 -0
- /package/dist/{commands → adapters/commands}/login.d.ts +0 -0
- /package/dist/{commands → adapters/commands}/manifest.d.ts +0 -0
- /package/dist/{commands → adapters/commands}/new.d.ts +0 -0
- /package/dist/{commands → adapters/commands}/registry.d.ts +0 -0
- /package/dist/{commands → adapters/commands}/sandbox.d.ts +0 -0
- /package/dist/{commands → adapters/commands}/session-view.d.ts +0 -0
- /package/dist/{commands → adapters/commands}/types.js +0 -0
- /package/dist/{web → adapters/web}/admin/provider-models.js +0 -0
- /package/dist/{mcp → adapters/web/admin}/types.js +0 -0
- /package/dist/{web → adapters/web}/login/oauth.d.ts +0 -0
- /package/dist/{packages → adapters/web/login}/types.js +0 -0
- /package/dist/{web → adapters/web}/session-view/portal.d.ts +0 -0
- /package/dist/{tools → adapters/web/session-view}/types.js +0 -0
- /package/dist/{web → adapters/web}/token-store.d.ts +0 -0
- /package/dist/{web → adapters/web}/token-store.js +0 -0
- /package/dist/{web → adapters/web}/types.d.ts +0 -0
- /package/dist/{web/admin → adapters/web}/types.js +0 -0
- /package/dist/{utils/file-guards.d.ts → file-guards.d.ts} +0 -0
- /package/dist/{utils/file-guards.js → file-guards.js} +0 -0
- /package/dist/{mcp → harness}/open-connector.d.ts +0 -0
- /package/dist/{adapters/slack → harness}/tools/attach.d.ts +0 -0
- /package/dist/{adapters/slack → harness}/tools/attach.js +0 -0
- /package/dist/{tools → harness/tools}/generate-image.d.ts +0 -0
- /package/dist/{tools → harness/tools}/generate-image.js +0 -0
- /package/dist/{tools → harness/tools}/host-fn-tool.d.ts +0 -0
- /package/dist/{tools → harness/tools}/host-fn-tool.js +0 -0
- /package/dist/{tools → harness/tools}/react.d.ts +0 -0
- /package/dist/{tools → harness/tools}/react.js +0 -0
- /package/dist/{web/login → harness/tools}/types.js +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../../src/web/admin/portal.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { basename, join, resolve as pathResolve, sep as pathSep } from \"node:path\";\nimport {\n MikanModels,\n parseFrontmatter,\n SessionStore,\n validateEventFilename,\n} from \"../../harness/index.js\";\nimport type { EventStore } from \"../../tools/types.js\";\nimport type { PlatformName } from \"../../adapter.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 loadConversationAutoReplyConfig,\n loadConversationWorkspaceOverride,\n loadGlobalSettings,\n loadScopeMcpServers,\n resolveConversationSettings,\n saveConversationAutoReplyConfig,\n type AgentConfig,\n type SandboxSettings,\n type WorkspacePolicyChoice,\n} from \"../../config.js\";\nimport { findMcpPreset, listMcpPresets, materializeMcpPreset } from \"../../mcp/catalog.js\";\nimport type { McpServerConfig } from \"../../mcp/types.js\";\nimport {\n applyConversationSettings,\n applyConversationWorkspacePolicy,\n applyGlobalSettings,\n applyGlobalWorkspacePolicy,\n} from \"../../settings-mutation.js\";\nimport {\n addPackage,\n inspectConversationPackages,\n refreshPackage,\n removePackage,\n} from \"../../packages/index.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 \"../../platform-messages.js\";\nimport { credentialAuthorizationKey } from \"../../sandbox/identity.js\";\nimport { resolveWorkspaceProjection } from \"../../workspace-projection/index.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 \"../../adapter.js\";\nimport {\n assertPlatformName,\n createOfficeAddress,\n listRegisteredOffices,\n sameOffice,\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/packages\":\n return servePackagesList(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 body = await readJsonBody(req, res, 32 * 1024);\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/sandbox\":\n return serveConversationSandboxUpdate(res, body, services, token);\n case \"/admin/api/conversations/auto-reply\":\n return serveConversationAutoReplyUpdate(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/packages/mutate\":\n return servePackageMutation(res, body, services, token);\n case \"/admin/api/settings/model\":\n return serveGlobalModelUpdate(res, body, services);\n case \"/admin/api/settings/workspace\":\n return serveGlobalWorkspaceUpdate(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\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 const globalWorkspaceSettings = globalConfig.sandbox?.workspace;\n const autoReply = loadConversationAutoReplyConfig(office.dir);\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 workspaceDoorPolicy: conversationWorkspace.doorPolicy,\n workspaceLayout: conversationWorkspace.layout,\n workspaceVisibility: conversationWorkspace.visibility,\n workspaceOverride: doorPolicyChoiceKey(loadConversationWorkspaceOverride(office)),\n globalWorkspaceDoorPolicy: globalWorkspaceSettings?.doorPolicy ?? \"isolated\",\n globalWorkspaceLayout: globalWorkspaceSettings?.layout ?? \"conversation\",\n globalWorkspaceVisibility: globalWorkspaceSettings?.visibility ?? \"public\",\n autoReplyEnabled: autoReply.enabled,\n autoReplyRules: autoReply.rules,\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 workspaceDoorPolicy: config.sandbox?.workspace?.doorPolicy ?? null,\n workspaceLayout: config.sandbox?.workspace?.layout ?? null,\n workspaceVisibility: config.sandbox?.workspace?.visibility ?? 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 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\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\n/**\n * Wire values for a door-policy selection; \"default\" clears the office's\n * override. `trusted-shared-support` keeps the historical read-write shared\n * MEMORY.md; `trusted-shared-support-private` is the same layout with the\n * shared MEMORY.md mounted read-only (modeled on Claude Tag's private-\n * channel memory: read the shared pool, never write into it).\n */\nfunction parseDoorPolicyChoice(\n value: unknown,\n): { choice: WorkspacePolicyChoice | null } | undefined {\n switch (value) {\n case \"default\":\n return { choice: null };\n case \"isolated\":\n return { choice: { doorPolicy: \"isolated\" } };\n case \"trusted-shared-support\":\n return { choice: { doorPolicy: \"trusted\", layout: \"shared-support\", visibility: \"public\" } };\n case \"trusted-shared-support-private\":\n return {\n choice: { doorPolicy: \"trusted\", layout: \"shared-support\", visibility: \"private\" },\n };\n case \"trusted-full\":\n return { choice: { doorPolicy: \"trusted\", layout: \"full\" } };\n default:\n return undefined;\n }\n}\n\nfunction doorPolicyChoiceKey(choice: WorkspacePolicyChoice | null): string {\n if (!choice) return \"default\";\n if (choice.doorPolicy === \"isolated\") return \"isolated\";\n if (choice.layout === \"full\") return \"trusted-full\";\n return choice.visibility === \"private\"\n ? \"trusted-shared-support-private\"\n : \"trusted-shared-support\";\n}\n\nfunction serveConversationSandboxUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const parsed = parseDoorPolicyChoice(body.doorPolicy);\n if (!parsed) {\n jsonRes(res, 400, {\n error:\n \"doorPolicy must be 'default', 'isolated', 'trusted-shared-support', 'trusted-shared-support-private', or 'trusted-full'\",\n });\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 try {\n const result = applyConversationWorkspacePolicy(\n services.runtime,\n workspace.office(scope.address),\n parsed.choice,\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 serveGlobalWorkspaceUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n): void {\n const parsed = parseDoorPolicyChoice(body.doorPolicy);\n if (!parsed) {\n jsonRes(res, 400, {\n error:\n \"doorPolicy must be 'default', 'isolated', 'trusted-shared-support', 'trusted-shared-support-private', or 'trusted-full'\",\n });\n return;\n }\n try {\n const result = applyGlobalWorkspacePolicy(services.runtime, parsed.choice);\n jsonRes(res, 200, { ok: true, staleConversations: result.staleConversations.length });\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 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 try {\n applyConversationSettings(services.runtime, workspace.office(scope.address), {\n slack: { replyMode },\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 serveConversationAutoReplyUpdate(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const enabled = body.enabled === true;\n const rules = body.rules;\n if (\n rules !== undefined &&\n (!Array.isArray(rules) || rules.some((rule) => typeof rule !== \"string\"))\n ) {\n jsonRes(res, 400, { error: \"rules must be an array of strings\" });\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 dir = workspace.office(scope.address).dir;\n try {\n const existing = loadConversationAutoReplyConfig(dir);\n saveConversationAutoReplyConfig(dir, {\n enabled,\n rules: rules ?? existing.rules,\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 serveConversationSessionLink(\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 const workspace = requireAdminWorkspace(res, services);\n if (!workspace) return;\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 try {\n const result = applyGlobalSettings(services.runtime, {\n provider,\n model,\n ...(thinkingLevel ? { thinkingLevel } : {}),\n });\n jsonRes(res, 200, {\n ok: true,\n staleConversations: result.staleConversations.map(\n (office) => `${office.platform}:${office.conversationId}`,\n ),\n });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\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 try {\n applyGlobalSettings(services.runtime, { slack: { replyMode } });\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 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 try {\n applyGlobalSettings(services.runtime, { sandbox: update });\n jsonRes(res, 200, { ok: true });\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_FILES = new Set([\"auto-reply\", \"auto-reply.disabled\"]);\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, and the two auto-reply marker files.\n */\nfunction isWorkspacePathAllowed(rel: string): boolean {\n if (rel === \"\") return true;\n const segments = rel.split(\"/\").filter(Boolean);\n const first = segments[0];\n if (first === undefined) return true;\n if (segments.length === 1) {\n return WORKSPACE_TOP_DIRS.has(first) || WORKSPACE_TOP_FILES.has(first);\n }\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/** Inventory of both scopes' declared packages for the selected conversation. */\nasync function servePackagesList(\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 try {\n const inventory = await inspectConversationPackages({\n office: workspace.office(scope.address),\n });\n jsonRes(res, 200, { conversationId: scope.conversationId, ...inventory });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\n/**\n * Add / remove / refresh, in one route because they share validation and all\n * three answer with the freshly re-read inventory: the panel never has to\n * guess what the write did.\n */\nfunction servePackageMutation(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const action = body.action;\n if (action !== \"add\" && action !== \"remove\" && action !== \"refresh\") {\n jsonRes(res, 400, { error: \"action must be 'add', 'remove', or 'refresh'\" });\n return;\n }\n const packageScope = body.scope === \"global\" ? \"global\" : \"conversation\";\n const source = typeof body.source === \"string\" ? body.source.trim() : \"\";\n if (!source) {\n jsonRes(res, 400, { error: \"source is required\" });\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\n const context = {\n office: workspace.office(scope.address),\n runtime: services.runtime,\n };\n\n try {\n if (action === \"add\") {\n const result = addPackage(packageScope, source, context);\n jsonRes(res, 200, { ok: true, source: result.source, dir: result.dir });\n return;\n }\n if (action === \"refresh\") {\n const result = refreshPackage(packageScope, source, context);\n jsonRes(res, 200, { ok: true, source: result.source, dir: result.dir });\n return;\n }\n const removed = removePackage(packageScope, source, context);\n jsonRes(res, removed ? 200 : 404, removed ? { ok: true } : { error: \"Not declared here.\" });\n } catch (err) {\n // Fetch/validation failures are the admin's problem to fix, not a server\n // fault: report them as a bad request with git's own message.\n jsonRes(res, 400, { error: err instanceof Error ? err.message : String(err) });\n }\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: 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\nconst MCP_SERVER_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;\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\nfunction parseMcpServerEntry(raw: unknown): { config?: McpServerConfig; error?: string } {\n if (typeof raw !== \"object\" || raw === null) return { error: \"server entry must be an object\" };\n const entry = raw as Record<string, unknown>;\n const command = typeof entry.command === \"string\" ? entry.command.trim() : \"\";\n const serverUrl = typeof entry.url === \"string\" ? entry.url.trim() : \"\";\n if (!command && !serverUrl) return { error: \"set either command (stdio) or url (HTTP)\" };\n if (command && serverUrl) return { error: \"set only one of command / url\" };\n if (serverUrl && !URL.canParse(serverUrl)) {\n return { error: \"url is not a valid URL\" };\n }\n const args = Array.isArray(entry.args)\n ? entry.args.filter((a): a is string => typeof a === \"string\")\n : undefined;\n const env = mcpStringMap(entry.env);\n const headers = mcpStringMap(entry.headers);\n return {\n config: {\n ...(command ? { command, ...(args && args.length > 0 ? { args } : {}) } : {}),\n ...(serverUrl ? { url: serverUrl } : {}),\n ...(env ? { env } : {}),\n ...(headers ? { headers } : {}),\n ...(entry.disabled === true ? { disabled: true } : {}),\n },\n };\n}\n\n/**\n * Set / remove / toggle one MCP server in one scope. Reads the scope's raw\n * map, applies the change, and writes the full map back (wholesale, like\n * packages — merge would make removal impossible). Runner caches refresh via\n * applyGlobalSettings/applyConversationSettings.\n */\nfunction serveMcpServerMutation(\n res: ServerResponse,\n body: Record<string, unknown>,\n services: AdminServices,\n token: AdminToken,\n): void {\n const action = body.action;\n if (action !== \"set\" && action !== \"install\" && action !== \"remove\" && action !== \"toggle\") {\n jsonRes(res, 400, { error: \"action must be 'set', 'install', 'remove', or 'toggle'\" });\n return;\n }\n const preset =\n action === \"install\" && typeof body.presetId === \"string\"\n ? findMcpPreset(body.presetId)\n : undefined;\n if (action === \"install\" && !preset) {\n jsonRes(res, 400, { error: \"unknown MCP preset\" });\n return;\n }\n const mutationScope = body.scope === \"global\" ? \"global\" : \"conversation\";\n const name = preset?.serverName ?? (typeof body.name === \"string\" ? body.name.trim() : \"\");\n if (!MCP_SERVER_NAME_PATTERN.test(name)) {\n jsonRes(res, 400, {\n error: \"invalid server name (letters, digits, '_' or '-', starting with a letter)\",\n });\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 office = workspace.office(scope.address);\n const maps = loadScopeMcpServers(office);\n const current = mutationScope === \"global\" ? maps.global : maps.conversation;\n\n const next: Record<string, McpServerConfig> = { ...current };\n if (action === \"set\") {\n const parsed = parseMcpServerEntry(body.server);\n if (!parsed.config) {\n jsonRes(res, 400, { error: parsed.error ?? \"invalid server entry\" });\n return;\n }\n // Env/headers omitted in the payload keep their existing values, so the\n // panel can edit command/args without re-entering credentials.\n const existing = current[name];\n next[name] = {\n ...parsed.config,\n ...(parsed.config.env === undefined && existing?.env ? { env: existing.env } : {}),\n ...(parsed.config.headers === undefined && existing?.headers\n ? { headers: existing.headers }\n : {}),\n };\n } else if (action === \"install\") {\n try {\n next[name] = materializeMcpPreset(preset!, mcpStringMap(body.credentials) ?? {});\n } catch (err) {\n jsonRes(res, 400, { error: err instanceof Error ? err.message : String(err) });\n return;\n }\n } else if (action === \"remove\") {\n if (!(name in next)) {\n jsonRes(res, 404, { error: \"Not declared here.\" });\n return;\n }\n delete next[name];\n } else {\n if (!(name in next)) {\n jsonRes(res, 404, { error: \"Not declared here.\" });\n return;\n }\n const entry = next[name]!;\n next[name] = entry.disabled ? { ...entry, disabled: undefined } : { ...entry, disabled: true };\n }\n\n const result =\n mutationScope === \"global\"\n ? applyGlobalSettings(services.runtime, { mcpServers: next })\n : applyConversationSettings(services.runtime, office, { mcpServers: next });\n if (!result.ok) {\n jsonRes(res, 409, { error: \"Conversation is busy; try again shortly.\" });\n return;\n }\n jsonRes(res, 200, { ok: true });\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\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 listAllEvents(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 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(res: ServerResponse, services: AdminServices): EventStore | null {\n if (!services.eventStore) {\n jsonRes(res, 503, { error: \"Working directory not available\" });\n return null;\n }\n return services.eventStore;\n}\n\nasync function serveEventsList(res: ServerResponse, services: AdminServices): Promise<void> {\n const store = requireAdminEventStore(res, services);\n if (!store) return;\n jsonRes(res, 200, { events: await listAllEvents(store) });\n}\n\n/** Per-conversation listing — filter all events by conversationId match. */\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 store = requireAdminEventStore(res, services);\n if (!store) return;\n const events = (await listAllEvents(store)).filter(\n (e) => e.conversationId === scope.conversationId,\n );\n jsonRes(res, 200, { conversationId: scope.conversationId, events });\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 store = requireAdminEventStore(res, services);\n if (!store) return;\n let payload: { conversationId?: string } | null;\n try {\n payload = (await store.read(name)).payload;\n } catch {\n jsonRes(res, 404, { error: \"Event not found\" });\n return;\n }\n // The store normalizes the legacy `channelId` alias into `conversationId`.\n if (payload?.conversationId !== scope.conversationId) {\n jsonRes(res, 403, { error: \"Event does not belong to this conversation.\" });\n return;\n }\n try {\n await store.delete(name);\n jsonRes(res, 200, { ok: true });\n } catch (err) {\n jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });\n }\n}\n\n// ── Utilities ──────────────────────────────────────────────────────────────────\n\nconst esc = escapeHtml;\n\n// ── HTML ───────────────────────────────────────────────────────────────────────\n\nconst adminViewBody = `<nav class=\"tab-nav\" role=\"tablist\" aria-label=\"Admin sections\">\n <button class=\"tab-btn active\" role=\"tab\" aria-selected=\"true\" aria-controls=\"panel-conversation\" data-tab=\"conversation\">Conversation</button>\n <button class=\"tab-btn\" role=\"tab\" aria-selected=\"false\" aria-controls=\"panel-global\" data-tab=\"global\">Global</button>\n </nav>\n\n <div class=\"tab-panel active\" id=\"panel-conversation\">\n <section class=\"card sect\" id=\"sect-settings\" data-section=\"settings\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Settings</p>\n <h2 class=\"card-title\">模型 / Thinking / Auto-reply / Workspace mount</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadSettings()\">↻</button>\n </header>\n <div id=\"settings-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\" id=\"sect-workspace\" data-section=\"workspace\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Workspace</p>\n <h2 class=\"card-title\">檔案瀏覽 (只讀)</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadWorkspace()\">↻</button>\n </header>\n <div class=\"workspace-split\">\n <div id=\"workspace-tree\" class=\"workspace-tree\"><div class=\"loading-msg\">Loading…</div></div>\n <div id=\"workspace-preview\" class=\"workspace-preview\"><div class=\"placeholder-msg\">Click a file to preview</div></div>\n </div>\n </section>\n\n <section class=\"card sect\" id=\"sect-skills\" data-section=\"skills\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Skills</p>\n <h2 class=\"card-title\">可用的 skills</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadSkills()\">↻</button>\n </header>\n <div class=\"workspace-split\">\n <div id=\"skills-content\" class=\"workspace-tree\"><div class=\"loading-msg\">Loading…</div></div>\n <div id=\"skills-preview\" class=\"workspace-preview\"><div class=\"placeholder-msg\">Click a skill to preview SKILL.md</div></div>\n </div>\n </section>\n\n <section class=\"card sect\" id=\"sect-packages\" data-section=\"packages\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Skill Packages</p>\n <h2 class=\"card-title\">此對話的 skill 套件</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadPackages()\">↻</button>\n </header>\n <div class=\"pkg-add\">\n <input id=\"pkg-conv-url\" class=\"pkg-input\" type=\"text\" spellcheck=\"false\"\n placeholder=\"github:owner/repo 或 https://github.com/owner/repo.git\" />\n <input id=\"pkg-conv-ref\" class=\"pkg-input pkg-input-ref\" type=\"text\" spellcheck=\"false\"\n placeholder=\"tag / branch / commit(可留空)\" />\n <button class=\"primary-action-btn\" onclick=\"addPackage('conversation')\">Add</button>\n </div>\n <div id=\"pkg-conv-msg\" class=\"pkg-msg\" style=\"display:none\"></div>\n <div id=\"pkg-conv-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\" id=\"sect-mcp\" data-section=\"mcp\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">MCP Servers</p>\n <h2 class=\"card-title\">此對話的 MCP servers</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadMcpServers()\">↻</button>\n </header>\n <div id=\"mcp-conv-msg\" class=\"pkg-msg\" style=\"display:none\"></div>\n <div id=\"mcp-conv-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\" id=\"sect-vault\" data-section=\"vault\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Vault</p>\n <h2 class=\"card-title\">該對話的憑證</h2>\n </div>\n <button class=\"primary-action-btn\" onclick=\"openLogin()\">Open login form</button>\n </header>\n <div id=\"vault-link-result\" class=\"link-result\" style=\"display:none\"></div>\n <iframe id=\"login-frame\" class=\"portal-frame\" title=\"Login\" style=\"display:none\"></iframe>\n </section>\n\n <section class=\"card sect\" id=\"sect-events\" data-section=\"events\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Events</p>\n <h2 class=\"card-title\">關聯此對話的 events</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadConversationEvents()\">↻</button>\n </header>\n <div id=\"events-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\" id=\"sect-session\" data-section=\"session\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Session View</p>\n <h2 class=\"card-title\">對話歷史檢視</h2>\n </div>\n <button class=\"primary-action-btn\" onclick=\"openSessionView()\">Open session view</button>\n </header>\n <div id=\"session-link-result\" class=\"link-result\" style=\"display:none\"></div>\n <iframe id=\"session-frame\" class=\"portal-frame\" title=\"Session View\" style=\"display:none\"></iframe>\n </section>\n </div>\n\n <div class=\"tab-panel\" id=\"panel-global\">\n <section class=\"card sect\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">All Conversations</p>\n <h2 class=\"card-title\">所有對話</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadAllConversations()\">↻</button>\n </header>\n <div id=\"all-conv-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Token Usage</p>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadTokenUsage()\">↻</button>\n </header>\n <h2 class=\"card-subtitle\" style=\"margin-bottom:10px\">Top 20 sessions</h3>\n <div id=\"session-usage-content\"><div class=\"loading-msg\">Loading…</div></div>\n <h2 class=\"card-subtitle\" style=\"margin:24px 0 10px\">Usage timeline</h3>\n <div class=\"timeline-controls\">\n <label>Conversation\n <select id=\"timeline-conv\" onchange=\"loadUsageTimeline()\"></select>\n </label>\n </div>\n <div id=\"usage-timeline-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Global Settings</p>\n <h2 class=\"card-title\">全域預設</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadGlobalSettings()\">↻</button>\n </header>\n <div id=\"global-settings-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Global Skill Packages</p>\n <h2 class=\"card-title\">所有對話都會載入的 skill 套件</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadPackages()\">↻</button>\n </header>\n <div class=\"pkg-add\">\n <input id=\"pkg-global-url\" class=\"pkg-input\" type=\"text\" spellcheck=\"false\"\n placeholder=\"github:owner/repo 或 https://github.com/owner/repo.git\" />\n <input id=\"pkg-global-ref\" class=\"pkg-input pkg-input-ref\" type=\"text\" spellcheck=\"false\"\n placeholder=\"tag / branch / commit(可留空)\" />\n <button class=\"primary-action-btn\" onclick=\"addPackage('global')\">Add</button>\n </div>\n <div id=\"pkg-global-msg\" class=\"pkg-msg\" style=\"display:none\"></div>\n <div id=\"pkg-global-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Global MCP Servers</p>\n <h2 class=\"card-title\">所有對話都可用的 MCP servers</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadMcpServers()\">↻</button>\n </header>\n <div id=\"mcp-global-msg\" class=\"pkg-msg\" style=\"display:none\"></div>\n <div id=\"mcp-global-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Global Skills</p>\n <h2 class=\"card-title\">全域 skills</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadGlobalSkills()\">↻</button>\n </header>\n <div id=\"global-skills-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\n\n <section class=\"card sect\">\n <header class=\"sect-head\">\n <div>\n <p class=\"eyebrow\">Global Events</p>\n <h2 class=\"card-title\">全域 events.json</h2>\n </div>\n <button class=\"refresh-btn\" onclick=\"loadEvents()\">↻</button>\n </header>\n <div id=\"global-events-content\"><div class=\"loading-msg\">Loading…</div></div>\n </section>\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=\"pkg-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\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 function escAttr(str) {\n return String(str).replace(/[\"'&<>]/g, (c) => (\n {'\"':'"',\"'\":''','&':'&','<':'<','>':'>'}[c]\n ));\n }\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 // ── Tab switching ────────────────────────────────────────────────────────────\n\n const tabBtns = document.querySelectorAll('.tab-btn');\n const tabPanels = document.querySelectorAll('.tab-panel');\n\n function switchTab(tabId) {\n tabBtns.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 if (tabId === 'global') initGlobal();\n }\n tabBtns.forEach((btn) => btn.addEventListener('click', () => switchTab(btn.dataset.tab)));\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 // Reset all conversation sections.\n loadSettings();\n loadWorkspace();\n loadSkills();\n loadPackages();\n loadMcpServers();\n loadConversationEvents();\n openLogin(true);\n openSessionView(true);\n }\n\n // ── Settings ─────────────────────────────────────────────────────────────────\n\n async function loadSettings() {\n const container = document.getElementById('settings-content');\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n if (!modelsLoaded) await loadModels();\n try {\n const data = await apiGet('/admin/api/conversation-state?' + scopeQuery());\n container.innerHTML = renderSettings(data);\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n function renderSettings(data) {\n const thinking = ['off','minimal','low','medium','high','xhigh','max'];\n const thinkingOpts = thinking.map((t) =>\n '<option value=\"' + t + '\"' + (data.thinkingLevel === t ? ' selected' : '') + '>' + t + '</option>'\n ).join('');\n const rulesText = (data.autoReplyRules || []).join('\\\\n');\n const replyModes = ['top-level','thread'];\n const replyModeOpts = replyModes.map((m) =>\n '<option value=\"' + m + '\"' + (((data.slack && data.slack.replyMode) || 'top-level') === m ? ' selected' : '') + '>' + m + '</option>'\n ).join('');\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 const doorPolicyChoices = [\n ['default', 'Automatic — follows the platform channel (public shares, private reads only, DMs isolated)'],\n ['isolated', 'isolated — own office only'],\n ['trusted-shared-support', 'trusted / shared-support (public) — office + shared memory, skills, events — read-write'],\n ['trusted-shared-support-private', 'trusted / shared-support (private) — same, but shared MEMORY.md is read-only'],\n ['trusted-full', 'trusted / full — entire workspace'],\n ];\n const doorPolicyOpts = doorPolicyChoices.map(([value, label]) =>\n '<option value=\"' + value + '\"' + ((data.workspaceOverride || 'default') === value ? ' selected' : '') + '>' + escHtml(label) + '</option>'\n ).join('');\n return [\n '<div class=\"config-grid\">',\n '<div class=\"config-block\">',\n '<h3 class=\"card-subtitle\">Model</h3>',\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 '<button class=\"primary-action-btn\" onclick=\"saveModel(this)\">Save model</button>',\n '<div id=\"model-save-result\" class=\"inline-result\" style=\"display:none\"></div>',\n '</div>',\n '<div class=\"config-block\">',\n '<h3 class=\"card-subtitle\">Auto-reply</h3>',\n '<div class=\"config-row\"><label>Enabled</label><label class=\"toggle\"><input type=\"checkbox\" id=\"a-enabled\"' + (data.autoReplyEnabled ? ' checked' : '') + '> on</label></div>',\n '<div class=\"config-row config-row-stack\"><label>Rules</label><textarea id=\"a-rules\" rows=\"5\" placeholder=\"一行一條規則\">' + escHtml(rulesText) + '</textarea></div>',\n '<button class=\"primary-action-btn\" onclick=\"saveAutoReply(this)\">Save auto-reply</button>',\n '<div id=\"auto-save-result\" class=\"inline-result\" style=\"display:none\"></div>',\n '</div>',\n '<div class=\"config-block\">',\n '<h3 class=\"card-subtitle\">Office data policy</h3>',\n '<div class=\"config-row\"><label>Door policy</label><select id=\"m-door-policy\">' + doorPolicyOpts + '</select></div>',\n '<p class=\"muted-note\">Effective: ' + escHtml(data.workspaceDoorPolicy + ' / ' + data.workspaceLayout + ' / ' + (data.workspaceVisibility || 'public')) + '</p>',\n '<p class=\"muted-note\">Changing the policy rebuilds the office sandbox container with the new mounts on its next message; the container contents are preserved.</p>',\n '<button class=\"primary-action-btn\" onclick=\"saveDoorPolicy(this)\">Save door policy</button>',\n '<div id=\"mount-save-result\" class=\"inline-result\" style=\"display:none\"></div>',\n '</div>',\n '<div class=\"config-block\">',\n '<h3 class=\"card-subtitle\">Slack</h3>',\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 '<button class=\"primary-action-btn\" onclick=\"saveSlack(this)\">Save Slack</button>',\n '<div id=\"slack-save-result\" class=\"inline-result\" style=\"display:none\"></div>',\n '</div>',\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 btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';\n try {\n const data = await apiPost('/admin/api/conversations/model', {\n ...scopeBody(), provider, model, thinkingLevel,\n });\n result.style.display = 'block'; result.className = 'inline-result ok';\n result.textContent = 'Saved ✓';\n } catch (err) {\n result.style.display = 'block'; result.className = 'inline-result err';\n result.textContent = err.message;\n } finally {\n btn.disabled = false; btn.textContent = 'Save model';\n }\n }\n\n async function saveAutoReply(btn) {\n const enabled = document.getElementById('a-enabled').checked;\n const rules = document.getElementById('a-rules').value.split('\\\\n').map((s) => s.trim()).filter(Boolean);\n const result = document.getElementById('auto-save-result');\n btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';\n try {\n await apiPost('/admin/api/conversations/auto-reply', {\n ...scopeBody(), enabled, rules,\n });\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 auto-reply';\n }\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 btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';\n try {\n await apiPost('/admin/api/conversations/slack', {\n ...scopeBody(), replyMode,\n });\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 Slack';\n }\n }\n\n async function saveDoorPolicy(btn) {\n const doorPolicy = document.getElementById('m-door-policy').value;\n const result = document.getElementById('mount-save-result');\n btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';\n try {\n await apiPost('/admin/api/conversations/sandbox', {\n ...scopeBody(), doorPolicy,\n });\n result.style.display = 'block'; result.className = 'inline-result ok'; result.textContent = 'Saved ✓';\n loadSettings();\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 door policy';\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 function packageMessage(scope, text, kind) {\n const el = document.getElementById(scope === 'global' ? 'pkg-global-msg' : 'pkg-conv-msg');\n if (!text) { el.style.display = 'none'; return; }\n el.className = 'pkg-msg pkg-msg-' + kind;\n el.textContent = text;\n el.style.display = 'block';\n }\n\n function renderPackageList(container, rows, scope) {\n if (rows.length === 0) {\n container.innerHTML = '<div class=\"empty-state\">尚未加入任何套件</div>';\n return;\n }\n container.innerHTML = '<div class=\"pkg-list\">' + rows.map((p) => {\n const provides = p.skills.map((s) => 'skill: ' + s);\n const status = p.error\n ? '<span class=\"pkg-badge pkg-badge-err\">' + escHtml(p.error) + '</span>'\n : p.shadowed\n ? '<span class=\"pkg-badge pkg-badge-warn\">被此對話的同名套件覆蓋,不會載入</span>'\n : '<span class=\"pkg-badge pkg-badge-ok\">已下載</span>'\n + '<span class=\"pkg-badge pkg-badge-warn\">需 /pi-new 才會載入</span>';\n return '<div class=\"pkg-row\">' +\n '<div class=\"pkg-row-main\">' +\n '<code class=\"pkg-source\">' + escHtml(p.source) + '</code>' + status +\n '</div>' +\n (provides.length > 0\n ? '<div class=\"pkg-provides\">' + provides.map((t) => '<span class=\"pkg-chip\">' + escHtml(t) + '</span>').join('') + '</div>'\n : '<div class=\"pkg-provides pkg-provides-empty\">此套件沒有提供 skill</div>') +\n '<div class=\"pkg-actions\">' +\n '<button class=\"pkg-btn\" data-pkg-action=\"refresh\" data-pkg-scope=\"' + scope + '\" data-pkg-source=\"' + escAttr(p.source) + '\">Update</button>' +\n '<button class=\"pkg-btn pkg-btn-danger\" data-pkg-action=\"remove\" data-pkg-scope=\"' + scope + '\" data-pkg-source=\"' + escAttr(p.source) + '\">Remove</button>' +\n '</div>' +\n '</div>';\n }).join('') + '</div>';\n }\n\n async function loadPackages() {\n const convEl = document.getElementById('pkg-conv-content');\n const globalEl = document.getElementById('pkg-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/packages?' + scopeQuery());\n if (convEl) renderPackageList(convEl, data.conversation, 'conversation');\n if (globalEl) renderPackageList(globalEl, data.global, 'global');\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 async function mutatePackage(scope, action, source) {\n packageMessage(scope, action === 'remove' ? '移除中…' : '取得中…', 'busy');\n try {\n const result = await apiPost('/admin/api/packages/mutate', {\n action: action,\n scope: scope,\n source: source,\n ...scopeBody(),\n });\n packageMessage(\n scope,\n action === 'remove'\n ? '已移除。對話輸入 /pi-new 生效。'\n : '完成:' + result.source + '(對話輸入 /pi-new 生效)',\n 'ok',\n );\n await loadPackages();\n } catch (err) {\n // Fetch and validation failures land here, next to the input that\n // caused them, rather than turning into a silently missing feature.\n packageMessage(scope, err.message, 'err');\n }\n }\n\n async function addPackage(scope) {\n const urlEl = document.getElementById(scope === 'global' ? 'pkg-global-url' : 'pkg-conv-url');\n const refEl = document.getElementById(scope === 'global' ? 'pkg-global-ref' : 'pkg-conv-ref');\n const url = urlEl.value.trim();\n const ref = refEl.value.trim();\n if (!url) { packageMessage(scope, '請填入 git URL', 'err'); return; }\n // Assembled here so nobody has to hand-write the @ref form, whose\n // ambiguity with git@host:owner/repo is the one sharp edge in the syntax.\n await mutatePackage(scope, 'add', ref ? url + '@' + ref : url);\n urlEl.value = '';\n refEl.value = '';\n }\n\n document.addEventListener('click', (event) => {\n const btn = event.target.closest('[data-pkg-action]');\n if (!btn) return;\n void mutatePackage(btn.dataset.pkgScope, btn.dataset.pkgAction, btn.dataset.pkgSource);\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 = 'pkg-msg pkg-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 '<div class=\"pkg-row\">' +\n '<div class=\"pkg-row-main\"><span class=\"pkg-source\">' + escHtml(name) + '</span>' +\n (server.disabled ? '<span class=\"pkg-badge pkg-badge-warn\">disabled</span>' : '<span class=\"pkg-badge pkg-badge-ok\">enabled</span>') +\n '</div>' +\n '<div class=\"skill-desc\">' + escHtml(transport) + (keys.length ? ' · ' + escHtml(keys.join(' · ')) : '') + '</div>' +\n '<div class=\"pkg-actions\">' +\n '<button class=\"pkg-btn\" data-mcp-action=\"toggle\" data-mcp-scope=\"' + scope + '\" data-mcp-name=\"' + escAttr(name) + '\">' + (server.disabled ? 'Enable' : 'Disable') + '</button>' +\n '<button class=\"pkg-btn pkg-btn-danger\" data-mcp-action=\"remove\" data-mcp-scope=\"' + scope + '\" data-mcp-name=\"' + escAttr(name) + '\">Remove</button>' +\n '</div>' +\n '</div>';\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=\"pkg-badge pkg-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=\"pkg-list\">' + (rows || '<div class=\"pkg-provides-empty\">No MCP servers installed here</div>') + '</div>' +\n '</details>' +\n '<details class=\"mcp-manual\"><summary>Advanced: add a custom server</summary>' +\n '<div class=\"pkg-add\">' +\n '<input id=\"mcp-' + scope + '-name\" class=\"pkg-input pkg-input-ref\" type=\"text\" spellcheck=\"false\" placeholder=\"name\" />' +\n '<input id=\"mcp-' + scope + '-target\" class=\"pkg-input\" type=\"text\" spellcheck=\"false\" placeholder=\"npx -y package@version 或 https://host/mcp\" />' +\n '<input id=\"mcp-' + scope + '-env\" class=\"pkg-input\" type=\"text\" spellcheck=\"false\" placeholder=\"KEY=value(HTTP 則為 header)\" />' +\n '<button class=\"primary-action-btn\" data-mcp-action=\"add\" data-mcp-scope=\"' + scope + '\">Add custom</button>' +\n '</div>' +\n '</details>';\n }\n\n async function loadMcpServers() {\n const convEl = document.getElementById('mcp-conv-content');\n const globalEl = document.getElementById('mcp-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/mcp-servers?' + scopeQuery());\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 } 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 async function mutateMcpServer(scope, action, name, server) {\n mcpMessage(scope, '儲存中…', 'busy');\n try {\n await apiPost('/admin/api/mcp-servers/mutate', {\n action: action,\n scope: scope,\n name: name,\n ...(server ? { server: server } : {}),\n ...scopeBody(),\n });\n mcpMessage(scope, '完成。新設定在下一次回應生效。', 'ok');\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 await apiPost('/admin/api/mcp-servers/mutate', {\n action: 'install', scope: scope, presetId: preset.id, credentials: credentials, ...scopeBody(),\n });\n closeMcpInstall();\n mcpMessage(scope, preset.name + ' installed. It will be available on the next response.', '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 function addMcpServer(scope) {\n const name = document.getElementById('mcp-' + scope + '-name').value.trim();\n const target = document.getElementById('mcp-' + scope + '-target').value.trim();\n const envRaw = document.getElementById('mcp-' + scope + '-env').value.trim();\n if (!name || !target) { mcpMessage(scope, '請填入 name 與 command/URL', 'err'); return; }\n const server = {};\n const pairs = {};\n for (const token of envRaw ? envRaw.split(/\\\\s+/) : []) {\n const eq = token.indexOf('=');\n if (eq > 0) pairs[token.slice(0, eq)] = token.slice(eq + 1);\n }\n if (/^https?:[/][/]/.test(target)) {\n server.url = target;\n if (Object.keys(pairs).length) server.headers = pairs;\n } else {\n const parts = target.split(/\\\\s+/);\n server.command = parts[0];\n if (parts.length > 1) server.args = parts.slice(1);\n if (Object.keys(pairs).length) server.env = pairs;\n }\n void mutateMcpServer(scope, 'set', name, server);\n }\n\n document.addEventListener('click', (event) => {\n const btn = event.target.closest('[data-mcp-action]');\n if (!btn) return;\n if (btn.dataset.mcpAction === 'add') { addMcpServer(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 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 if (data.skills.length === 0) {\n container.innerHTML = '<div class=\"empty-state\">No skills available</div>';\n return;\n }\n container.innerHTML = '<div class=\"skills-list\">' +\n data.skills.map((s) =>\n '<button class=\"skill-row 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 ).join('') + '</div>';\n\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n async function previewSkill(source, directory, name) {\n const previewEl = document.getElementById('skills-preview');\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 document.getElementById('skills-content').addEventListener('click', (event) => {\n const btn = event.target.closest('[data-skill-source]');\n if (!btn) return;\n previewSkill(btn.dataset.skillSource, btn.dataset.skillDirectory, btn.dataset.skillName);\n });\n\n // ── Vault (Login link) ───────────────────────────────────────────────────────\n\n async function openLogin(silent) {\n const result = document.getElementById('vault-link-result');\n const frame = document.getElementById('login-frame');\n if (silent) { frame.removeAttribute('src'); frame.style.display = 'none'; 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/login-link', scopeBody());\n result.className = 'link-result ok';\n result.innerHTML =\n '<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 frame.src = data.url; frame.style.display = 'block';\n } catch (err) {\n result.className = 'link-result err'; result.textContent = err.message;\n frame.removeAttribute('src'); frame.style.display = 'none';\n }\n }\n\n // ── Session View ─────────────────────────────────────────────────────────────\n\n async function openSessionView(silent) {\n const result = document.getElementById('session-link-result');\n const frame = document.getElementById('session-frame');\n if (silent) { frame.removeAttribute('src'); frame.style.display = 'none'; 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/session-link', scopeBody());\n result.className = 'link-result ok';\n result.innerHTML =\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 frame.src = data.url; frame.style.display = 'block';\n } catch (err) {\n result.className = 'link-result err'; result.textContent = err.message;\n frame.removeAttribute('src'); frame.style.display = 'none';\n }\n }\n\n // ── Events ───────────────────────────────────────────────────────────────────\n\n async function loadConversationEvents() {\n const container = document.getElementById('events-content');\n if (!container) return;\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n try {\n const data = await apiGet('/admin/api/conversations/events?' + scopeQuery());\n if (data.events.length === 0) {\n container.innerHTML = '<div class=\"empty-state\">沒有關聯此對話的 event</div>';\n return;\n }\n container.innerHTML = '<div class=\"events-list\">' +\n data.events.map((e) => renderEventRow(e, true)).join('') + '</div>';\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n async function loadEvents() {\n const container = document.getElementById('global-events-content');\n if (!container) return;\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n try {\n const data = await apiGet('/admin/api/events');\n if (data.events.length === 0) {\n container.innerHTML = '<div class=\"empty-state\">No events scheduled</div>';\n return;\n }\n container.innerHTML = '<div class=\"events-list\">' +\n data.events.map((e) => renderEventRow(e, false)).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 let globalLoaded = false;\n function initGlobal() {\n if (globalLoaded) return;\n globalLoaded = true;\n loadAllConversations();\n loadTokenUsage();\n loadGlobalSettings();\n loadGlobalSkills();\n loadEvents();\n loadMcpServers();\n }\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 async function loadGlobalSettings() {\n const container = document.getElementById('global-settings-content');\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n if (!modelsLoaded) await loadModels();\n try {\n const data = await apiGet('/admin/api/settings/global');\n container.innerHTML = renderGlobalSettings(data);\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n function renderGlobalSettings(data) {\n const thinking = ['off','minimal','low','medium','high','xhigh','max'];\n const thinkingOpts = thinking.map((t) =>\n '<option value=\"' + t + '\"' + (data.thinkingLevel === t ? ' selected' : '') + '>' + t + '</option>'\n ).join('');\n const replyModes = ['top-level','thread'];\n const replyModeOpts = replyModes.map((m) =>\n '<option value=\"' + m + '\"' + (((data.slack && data.slack.replyMode) || 'top-level') === m ? ' selected' : '') + '>' + m + '</option>'\n ).join('');\n const gDoorKey = !data.workspaceDoorPolicy\n ? 'default'\n : (data.workspaceDoorPolicy === 'isolated'\n ? 'isolated'\n : (data.workspaceLayout === 'full'\n ? 'trusted-full'\n : ((data.workspaceVisibility || 'public') === 'private' ? 'trusted-shared-support-private' : 'trusted-shared-support')));\n const gDoorPolicyChoices = [\n ['default', 'Automatic — follows each platform channel (public shares, private reads only, DMs isolated)'],\n ['isolated', 'isolated — own office only'],\n ['trusted-shared-support', 'trusted / shared-support (public) — office + shared memory, skills, events — read-write'],\n ['trusted-shared-support-private', 'trusted / shared-support (private) — same, but shared MEMORY.md is read-only'],\n ['trusted-full', 'trusted / full — entire workspace'],\n ];\n const gDoorPolicyOpts = gDoorPolicyChoices.map(([value, label]) =>\n '<option value=\"' + value + '\"' + (gDoorKey === value ? ' selected' : '') + '>' + escHtml(label) + '</option>'\n ).join('');\n return [\n '<div class=\"config-grid\">',\n '<div class=\"config-block\">',\n '<h3 class=\"card-subtitle\">Default model</h3>',\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 '<button class=\"primary-action-btn\" onclick=\"saveGlobalModel(this)\">Save model</button>',\n '<div id=\"g-model-result\" class=\"inline-result\" style=\"display:none\"></div>',\n '</div>',\n '<div class=\"config-block\">',\n '<h3 class=\"card-subtitle\">Sandbox limits</h3>',\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 '<button class=\"primary-action-btn\" onclick=\"saveGlobalSandbox(this)\">Save sandbox</button>',\n '<div id=\"g-sandbox-result\" class=\"inline-result\" style=\"display:none\"></div>',\n '</div>',\n '<div class=\"config-block\">',\n '<h3 class=\"card-subtitle\">Office door policy</h3>',\n '<div class=\"config-row\"><label>Default</label><select id=\"g-door-policy\">' + gDoorPolicyOpts + '</select></div>',\n '<p class=\"muted-note\">Applies to offices without their own policy. Affected offices rebuild their sandbox container with the new mounts on the next message; container contents are preserved.</p>',\n '<button class=\"primary-action-btn\" onclick=\"saveGlobalWorkspace(this)\">Save door policy</button>',\n '<div id=\"g-workspace-result\" class=\"inline-result\" style=\"display:none\"></div>',\n '</div>',\n '<div class=\"config-block\">',\n '<h3 class=\"card-subtitle\">Slack</h3>',\n '<div class=\"config-row\"><label>Reply mode</label><select id=\"g-slack-reply-mode\">' + replyModeOpts + '</select></div>',\n '<button class=\"primary-action-btn\" onclick=\"saveGlobalSlack(this)\">Save Slack</button>',\n '<div id=\"g-slack-result\" class=\"inline-result\" style=\"display:none\"></div>',\n '</div>',\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 btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';\n try {\n await apiPost('/admin/api/settings/sandbox', { cpus, memory, boostCpus, boostMemory });\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 sandbox';\n }\n }\n\n async function saveGlobalWorkspace(btn) {\n const doorPolicy = document.getElementById('g-door-policy').value;\n const result = document.getElementById('g-workspace-result');\n btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';\n try {\n const data = await apiPost('/admin/api/settings/workspace', { doorPolicy });\n result.style.display = 'block'; result.className = 'inline-result ok';\n result.textContent = data.staleConversations > 0\n ? 'Saved ✓ (' + data.staleConversations + ' busy conversation(s) refresh after their current run)'\n : '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 door policy';\n }\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 btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';\n try {\n await apiPost('/admin/api/settings/slack', { replyMode });\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 Slack';\n }\n }\n\n async function loadGlobalSkills() {\n const container = document.getElementById('global-skills-content');\n container.innerHTML = '<div class=\"loading-msg\">Loading…</div>';\n try {\n // Reuse skills endpoint scoped to a conversation that doesn't have any of its own; the global half is what we want.\n const data = await apiGet('/admin/api/skills?' + scopeQuery());\n const globals = data.skills.filter((s) => s.source === 'global');\n if (globals.length === 0) {\n container.innerHTML = '<div class=\"empty-state\">No global skills</div>';\n return;\n }\n container.innerHTML = '<div class=\"skills-list\">' + globals.map((s) =>\n '<div class=\"skill-row\"><div class=\"skill-name\">' + escHtml(s.name) + '</div>' +\n (s.description ? '<div class=\"skill-desc\">' + escHtml(s.description) + '</div>' : '') + '</div>'\n ).join('') + '</div>';\n } catch (err) {\n container.innerHTML = '<div class=\"err-msg\">' + escHtml(err.message) + '</div>';\n }\n }\n\n // ── Init ─────────────────────────────────────────────────────────────────────\n\n initConvSwitcher();\n loadModels().finally(() => {\n loadSettings();\n loadWorkspace();\n loadSkills();\n loadPackages();\n loadMcpServers();\n loadConversationEvents();\n });\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 .tab-nav {\n display: flex; gap: 6px; padding: 6px;\n border: 1px solid var(--border); border-radius: 16px;\n background: rgba(255,255,255,0.72); backdrop-filter: blur(8px);\n overflow-x: auto; scrollbar-width: none;\n }\n .tab-nav::-webkit-scrollbar { display: none; }\n .tab-btn {\n flex: 1; min-width: 80px; padding: 10px 16px;\n border: none; border-radius: 10px; background: transparent;\n color: var(--muted);\n font: 500 0.88rem/1.2 'DM Sans', sans-serif;\n cursor: pointer; white-space: nowrap;\n transition: background 140ms, color 140ms;\n }\n .tab-btn:hover { background: rgba(0,0,0,0.04); color: var(--text); }\n .tab-btn.active { background: var(--text); color: #fafafa; font-weight: 600; }\n .tab-btn:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }\n\n .tab-panel { display: none; flex-direction: column; gap: 14px; }\n .tab-panel.active { display: flex; }\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 .portal-frame {\n width: 100%; min-height: 720px;\n border: 1px solid var(--border); border-radius: 14px; background: #fff;\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-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 /* ── Sections (Conversation page stack) ─────────────────────────────── */\n\n .sect-head {\n display: flex; align-items: flex-start; justify-content: space-between;\n gap: 12px; margin-bottom: 14px; flex-wrap: wrap;\n }\n .sect-head .card-title { margin-bottom: 0; }\n .sect-disabled { opacity: 0.7; }\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.84rem/1.2 'DM Sans', sans-serif; cursor: pointer;\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 }\n .skill-row-btn {\n width: 100%; text-align: left; cursor: pointer; font-family: inherit;\n }\n .skill-row-btn:hover { background: rgba(0,0,0,0.05); }\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 /* ── Packages ───────────────────────────────────────────────────────── */\n\n .pkg-add { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }\n .pkg-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 .pkg-input-ref { flex: 0 1 200px; }\n .pkg-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 .pkg-msg-ok { background: rgba(22,163,74,0.1); color: #15803d; }\n .pkg-msg-err { background: rgba(220,38,38,0.1); color: #b91c1c; }\n .pkg-msg-busy { background: rgba(0,0,0,0.05); color: var(--muted); }\n .pkg-list { display: flex; flex-direction: column; gap: 8px; }\n .pkg-row {\n padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;\n background: rgba(0,0,0,0.02);\n }\n .pkg-row-main { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }\n .pkg-source {\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n font-size: 0.78rem; color: var(--text); word-break: break-all;\n }\n .pkg-badge {\n padding: 1px 8px; border-radius: 999px; font-size: 0.7rem;\n font-weight: 600; letter-spacing: 0.03em;\n }\n .pkg-badge-ok { background: rgba(22,163,74,0.1); color: #15803d; }\n .pkg-badge-warn { background: rgba(217,119,6,0.12); color: var(--accent); }\n .pkg-badge-err { background: rgba(220,38,38,0.1); color: #b91c1c; }\n .pkg-provides { margin-top: 6px; display: flex; gap: 6px; flex-wrap: wrap; }\n .pkg-provides-empty { color: var(--subtle); font-size: 0.78rem; }\n .pkg-chip {\n padding: 1px 8px; border-radius: 6px; background: rgba(59,130,246,0.1);\n color: #1d4ed8; font-size: 0.72rem;\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n }\n .pkg-actions { margin-top: 8px; display: flex; gap: 8px; }\n .pkg-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 .pkg-btn:hover { background: rgba(0,0,0,0.05); }\n .pkg-btn-danger { color: #b91c1c; }\n .pkg-group { margin-bottom: 16px; }\n .pkg-group-head {\n display: flex; align-items: center; gap: 8px; margin-bottom: 8px;\n font-size: 0.85rem;\n }\n .pkg-group-head .pkg-btn { margin-left: auto; }\n\n /* ── MCP marketplace ───────────────────────────────────────────────── */\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, .mcp-manual {\n margin-top: 14px; border-top: 1px solid var(--border); padding-top: 12px;\n }\n .mcp-installed > summary, .mcp-manual > summary {\n cursor: pointer; color: var(--muted); font-size: 0.8rem; font-weight: 600;\n margin-bottom: 10px;\n }\n .mcp-manual .pkg-add { margin: 12px 0 0; }\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 }\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 { 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: 640px) {\n .tab-btn { padding: 9px 12px; font-size: 0.82rem; min-width: 60px; }\n .config-grid { grid-template-columns: 1fr; }\n .config-row { grid-template-columns: 1fr; gap: 4px; }\n .portal-frame { min-height: 520px; }\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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"provider-models.d.ts","sourceRoot":"","sources":["../../../src/web/admin/provider-models.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,KAAK,gBAAgB,GAAG,WAAW,GAAG,YAAY,CAAC;AAEnD,UAAU,sBAAsB;IAC9B,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAYD,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GACnB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAgB9C;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE7D"}
|