@geminixiang/mikan 1.0.0-beta.76 → 1.0.0-beta.77
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 +20 -0
- package/dist/adapters/commands/login.d.ts.map +1 -1
- package/dist/adapters/commands/login.js +0 -9
- package/dist/adapters/commands/login.js.map +1 -1
- package/dist/adapters/commands/manifest.d.ts +0 -19
- package/dist/adapters/commands/manifest.d.ts.map +1 -1
- package/dist/adapters/commands/manifest.js +0 -34
- package/dist/adapters/commands/manifest.js.map +1 -1
- package/dist/adapters/commands/model.d.ts +0 -5
- package/dist/adapters/commands/model.d.ts.map +1 -1
- package/dist/adapters/commands/model.js +0 -5
- package/dist/adapters/commands/model.js.map +1 -1
- package/dist/adapters/commands/new.d.ts.map +1 -1
- package/dist/adapters/commands/new.js +0 -2
- package/dist/adapters/commands/new.js.map +1 -1
- package/dist/adapters/commands/registry.d.ts +0 -1
- package/dist/adapters/commands/registry.d.ts.map +1 -1
- package/dist/adapters/commands/registry.js +0 -8
- package/dist/adapters/commands/registry.js.map +1 -1
- package/dist/adapters/commands/session-view.d.ts.map +1 -1
- package/dist/adapters/commands/session-view.js +0 -2
- package/dist/adapters/commands/session-view.js.map +1 -1
- package/dist/adapters/commands/types.d.ts +0 -29
- package/dist/adapters/commands/types.d.ts.map +1 -1
- package/dist/adapters/commands/types.js.map +1 -1
- package/dist/adapters/commands/utils.d.ts +0 -3
- package/dist/adapters/commands/utils.d.ts.map +1 -1
- package/dist/adapters/commands/utils.js +0 -3
- package/dist/adapters/commands/utils.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +0 -4
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +5 -41
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/components.d.ts +0 -23
- package/dist/adapters/discord/components.d.ts.map +1 -1
- package/dist/adapters/discord/components.js +0 -23
- package/dist/adapters/discord/components.js.map +1 -1
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +1 -11
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/discord/format.d.ts +0 -1
- package/dist/adapters/discord/format.d.ts.map +1 -1
- package/dist/adapters/discord/format.js +0 -37
- package/dist/adapters/discord/format.js.map +1 -1
- package/dist/adapters/github/bot.d.ts +0 -44
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +1 -120
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/client.d.ts +0 -57
- package/dist/adapters/github/client.d.ts.map +1 -1
- package/dist/adapters/github/client.js +0 -59
- package/dist/adapters/github/client.js.map +1 -1
- package/dist/adapters/github/context.d.ts.map +1 -1
- package/dist/adapters/github/context.js +1 -8
- package/dist/adapters/github/context.js.map +1 -1
- package/dist/adapters/github/github-ops.d.ts +0 -55
- package/dist/adapters/github/github-ops.d.ts.map +1 -1
- package/dist/adapters/github/github-ops.js +0 -59
- package/dist/adapters/github/github-ops.js.map +1 -1
- package/dist/adapters/github/ids.d.ts +0 -27
- package/dist/adapters/github/ids.d.ts.map +1 -1
- package/dist/adapters/github/ids.js +0 -29
- package/dist/adapters/github/ids.js.map +1 -1
- package/dist/adapters/github/repo.d.ts +0 -25
- package/dist/adapters/github/repo.d.ts.map +1 -1
- package/dist/adapters/github/repo.js +0 -49
- package/dist/adapters/github/repo.js.map +1 -1
- package/dist/adapters/github/tool-pack.d.ts +0 -10
- package/dist/adapters/github/tool-pack.d.ts.map +1 -1
- package/dist/adapters/github/tool-pack.js +0 -10
- package/dist/adapters/github/tool-pack.js.map +1 -1
- package/dist/adapters/github/tools/checks.d.ts +0 -6
- package/dist/adapters/github/tools/checks.d.ts.map +1 -1
- package/dist/adapters/github/tools/checks.js +0 -7
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/tools/issue.d.ts +0 -5
- package/dist/adapters/github/tools/issue.d.ts.map +1 -1
- package/dist/adapters/github/tools/issue.js +0 -5
- package/dist/adapters/github/tools/issue.js.map +1 -1
- package/dist/adapters/github/tools/pr.d.ts +0 -7
- package/dist/adapters/github/tools/pr.d.ts.map +1 -1
- package/dist/adapters/github/tools/pr.js +0 -7
- package/dist/adapters/github/tools/pr.js.map +1 -1
- package/dist/adapters/github/tools/read.d.ts +0 -6
- package/dist/adapters/github/tools/read.d.ts.map +1 -1
- package/dist/adapters/github/tools/read.js +0 -8
- package/dist/adapters/github/tools/read.js.map +1 -1
- package/dist/adapters/github/tools/review-reply.d.ts +0 -5
- package/dist/adapters/github/tools/review-reply.d.ts.map +1 -1
- package/dist/adapters/github/tools/review-reply.js +0 -5
- package/dist/adapters/github/tools/review-reply.js.map +1 -1
- package/dist/adapters/github/tools/sync.d.ts +0 -6
- package/dist/adapters/github/tools/sync.d.ts.map +1 -1
- package/dist/adapters/github/tools/sync.js +0 -6
- package/dist/adapters/github/tools/sync.js.map +1 -1
- package/dist/adapters/github/types.d.ts +0 -88
- package/dist/adapters/github/types.d.ts.map +1 -1
- package/dist/adapters/github/types.js.map +1 -1
- package/dist/adapters/github/webhook.d.ts +0 -13
- package/dist/adapters/github/webhook.d.ts.map +1 -1
- package/dist/adapters/github/webhook.js +0 -16
- package/dist/adapters/github/webhook.js.map +1 -1
- package/dist/adapters/index.d.ts +3 -4
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/intake.d.ts +0 -17
- package/dist/adapters/intake.d.ts.map +1 -1
- package/dist/adapters/intake.js +6 -32
- package/dist/adapters/intake.js.map +1 -1
- package/dist/adapters/markdown-tables.d.ts +0 -10
- package/dist/adapters/markdown-tables.d.ts.map +1 -1
- package/dist/adapters/markdown-tables.js +1 -42
- package/dist/adapters/markdown-tables.js.map +1 -1
- package/dist/adapters/progressive-renderer.d.ts.map +1 -1
- package/dist/adapters/progressive-renderer.js +3 -25
- package/dist/adapters/progressive-renderer.js.map +1 -1
- package/dist/adapters/shared.d.ts +0 -57
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/shared.js +0 -71
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/assistant.d.ts +0 -49
- package/dist/adapters/slack/assistant.d.ts.map +1 -1
- package/dist/adapters/slack/assistant.js +0 -97
- package/dist/adapters/slack/assistant.js.map +1 -1
- package/dist/adapters/slack/auto-reply-context.d.ts +0 -7
- package/dist/adapters/slack/auto-reply-context.d.ts.map +1 -1
- package/dist/adapters/slack/auto-reply-context.js +0 -7
- package/dist/adapters/slack/auto-reply-context.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts +0 -9
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +0 -20
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +0 -116
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +7 -231
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +1 -3
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/slack/jev-context.d.ts +0 -13
- package/dist/adapters/slack/jev-context.d.ts.map +1 -1
- package/dist/adapters/slack/jev-context.js +0 -12
- package/dist/adapters/slack/jev-context.js.map +1 -1
- package/dist/adapters/slack/markdown.d.ts +0 -1
- package/dist/adapters/slack/markdown.d.ts.map +1 -1
- package/dist/adapters/slack/markdown.js +0 -5
- package/dist/adapters/slack/markdown.js.map +1 -1
- package/dist/adapters/slack/persona.d.ts +0 -9
- package/dist/adapters/slack/persona.d.ts.map +1 -1
- package/dist/adapters/slack/persona.js +0 -9
- package/dist/adapters/slack/persona.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +1 -45
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/session.d.ts +2 -1
- package/dist/adapters/slack/session.d.ts.map +1 -1
- package/dist/adapters/slack/session.js +2 -2
- package/dist/adapters/slack/session.js.map +1 -1
- package/dist/adapters/slack/stream-limits.d.ts +0 -25
- package/dist/adapters/slack/stream-limits.d.ts.map +1 -1
- package/dist/adapters/slack/stream-limits.js +0 -34
- package/dist/adapters/slack/stream-limits.js.map +1 -1
- package/dist/adapters/slack/task-intent.d.ts +0 -13
- package/dist/adapters/slack/task-intent.d.ts.map +1 -1
- package/dist/adapters/slack/task-intent.js +0 -7
- package/dist/adapters/slack/task-intent.js.map +1 -1
- package/dist/adapters/slack/task-status.d.ts +0 -1
- package/dist/adapters/slack/task-status.d.ts.map +1 -1
- package/dist/adapters/slack/task-status.js +1 -9
- package/dist/adapters/slack/task-status.js.map +1 -1
- package/dist/adapters/slack/tool-pack.d.ts +0 -6
- package/dist/adapters/slack/tool-pack.d.ts.map +1 -1
- package/dist/adapters/slack/tool-pack.js +0 -6
- package/dist/adapters/slack/tool-pack.js.map +1 -1
- package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -1
- package/dist/adapters/slack/tools/blockkit.js +0 -11
- package/dist/adapters/slack/tools/blockkit.js.map +1 -1
- package/dist/adapters/slack/types.d.ts +0 -19
- package/dist/adapters/slack/types.d.ts.map +1 -1
- package/dist/adapters/slack/types.js.map +1 -1
- package/dist/adapters/slack/update-diagnostics.d.ts +0 -1
- package/dist/adapters/slack/update-diagnostics.d.ts.map +1 -1
- package/dist/adapters/slack/update-diagnostics.js +1 -7
- package/dist/adapters/slack/update-diagnostics.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts +0 -6
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +1 -50
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +1 -8
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/adapters/types.d.ts +0 -57
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/adapters/web/admin/client-assets.d.ts +4 -0
- package/dist/adapters/web/admin/client-assets.d.ts.map +1 -0
- package/dist/adapters/web/admin/client-assets.js +1765 -0
- package/dist/adapters/web/admin/client-assets.js.map +1 -0
- package/dist/adapters/web/admin/portal.d.ts +0 -10
- package/dist/adapters/web/admin/portal.d.ts.map +1 -1
- package/dist/adapters/web/admin/portal.js +6 -1909
- package/dist/adapters/web/admin/portal.js.map +1 -1
- package/dist/adapters/web/admin/types.d.ts +0 -3
- package/dist/adapters/web/admin/types.d.ts.map +1 -1
- package/dist/adapters/web/admin/types.js.map +1 -1
- package/dist/adapters/web/login/oauth.d.ts.map +1 -1
- package/dist/adapters/web/login/oauth.js +0 -5
- package/dist/adapters/web/login/oauth.js.map +1 -1
- package/dist/adapters/web/login/portal.d.ts +0 -10
- package/dist/adapters/web/login/portal.d.ts.map +1 -1
- package/dist/adapters/web/login/portal.js +1 -35
- package/dist/adapters/web/login/portal.js.map +1 -1
- package/dist/adapters/web/login/types.d.ts +0 -5
- package/dist/adapters/web/login/types.d.ts.map +1 -1
- package/dist/adapters/web/login/types.js.map +1 -1
- package/dist/adapters/web/portal-shell.d.ts +0 -12
- package/dist/adapters/web/portal-shell.d.ts.map +1 -1
- package/dist/adapters/web/portal-shell.js +8 -25
- package/dist/adapters/web/portal-shell.js.map +1 -1
- package/dist/adapters/web/server.d.ts +0 -1
- package/dist/adapters/web/server.d.ts.map +1 -1
- package/dist/adapters/web/server.js +0 -2
- package/dist/adapters/web/server.js.map +1 -1
- package/dist/adapters/web/session-view/portal.d.ts.map +1 -1
- package/dist/adapters/web/session-view/portal.js +13 -24
- package/dist/adapters/web/session-view/portal.js.map +1 -1
- package/dist/adapters/web/session-view/types.d.ts.map +1 -1
- package/dist/adapters/web/session-view/types.js.map +1 -1
- package/dist/adapters/web/token-store.d.ts +0 -2
- package/dist/adapters/web/token-store.d.ts.map +1 -1
- package/dist/adapters/web/token-store.js +0 -2
- package/dist/adapters/web/token-store.js.map +1 -1
- package/dist/cli/arg-grammar.d.ts +0 -3
- package/dist/cli/arg-grammar.d.ts.map +1 -1
- package/dist/cli/arg-grammar.js +0 -3
- package/dist/cli/arg-grammar.js.map +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +0 -11
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/download.d.ts.map +1 -1
- package/dist/cli/download.js +2 -6
- package/dist/cli/download.js.map +1 -1
- package/dist/cli/office.d.ts.map +1 -1
- package/dist/cli/office.js +0 -31
- package/dist/cli/office.js.map +1 -1
- package/dist/cli/onboard.d.ts +0 -2
- package/dist/cli/onboard.d.ts.map +1 -1
- package/dist/cli/onboard.js +0 -30
- package/dist/cli/onboard.js.map +1 -1
- package/dist/cli/process-lifecycle.d.ts +0 -5
- package/dist/cli/process-lifecycle.d.ts.map +1 -1
- package/dist/cli/process-lifecycle.js +0 -6
- package/dist/cli/process-lifecycle.js.map +1 -1
- package/dist/cli/sessions.d.ts.map +1 -1
- package/dist/cli/sessions.js +0 -11
- package/dist/cli/sessions.js.map +1 -1
- package/dist/cli/types.d.ts +0 -5
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/dream/index.js +0 -2
- package/dist/dream/index.js.map +1 -1
- package/dist/env-manifest.d.ts +0 -21
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +0 -11
- package/dist/env-manifest.js.map +1 -1
- package/dist/events/index.d.ts +0 -51
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +0 -42
- package/dist/events/index.js.map +1 -1
- package/dist/events/scheduler.d.ts +0 -8
- package/dist/events/scheduler.d.ts.map +1 -1
- package/dist/events/scheduler.js +0 -8
- package/dist/events/scheduler.js.map +1 -1
- package/dist/file-guards.d.ts +0 -15
- package/dist/file-guards.d.ts.map +1 -1
- package/dist/file-guards.js +2 -26
- package/dist/file-guards.js.map +1 -1
- package/dist/harness/execution-env.d.ts +0 -15
- package/dist/harness/execution-env.d.ts.map +1 -1
- package/dist/harness/execution-env.js +4 -55
- package/dist/harness/execution-env.js.map +1 -1
- package/dist/harness/http.d.ts +0 -12
- package/dist/harness/http.d.ts.map +1 -1
- package/dist/harness/http.js +0 -34
- package/dist/harness/http.js.map +1 -1
- package/dist/harness/index.d.ts +0 -7
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +0 -7
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/jev.d.ts +0 -28
- package/dist/harness/jev.d.ts.map +1 -1
- package/dist/harness/jev.js +0 -45
- package/dist/harness/jev.js.map +1 -1
- package/dist/harness/mcp.d.ts +0 -19
- package/dist/harness/mcp.d.ts.map +1 -1
- package/dist/harness/mcp.js +0 -34
- package/dist/harness/mcp.js.map +1 -1
- package/dist/harness/models.d.ts +0 -19
- package/dist/harness/models.d.ts.map +1 -1
- package/dist/harness/models.js +0 -52
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/open-connector.d.ts +0 -12
- package/dist/harness/open-connector.d.ts.map +1 -1
- package/dist/harness/open-connector.js +0 -22
- package/dist/harness/open-connector.js.map +1 -1
- package/dist/harness/presenter.d.ts.map +1 -1
- package/dist/harness/presenter.js +15 -65
- package/dist/harness/presenter.js.map +1 -1
- package/dist/harness/prompt.d.ts +0 -11
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +0 -17
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +0 -25
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session.d.ts +11 -28
- package/dist/harness/session.d.ts.map +1 -1
- package/dist/harness/session.js +100 -38
- package/dist/harness/session.js.map +1 -1
- package/dist/harness/skills.d.ts +0 -22
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +0 -20
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/subagent-profiles.d.ts +0 -4
- package/dist/harness/subagent-profiles.d.ts.map +1 -1
- package/dist/harness/subagent-profiles.js +0 -29
- package/dist/harness/subagent-profiles.js.map +1 -1
- package/dist/harness/subagent.d.ts +0 -25
- package/dist/harness/subagent.d.ts.map +1 -1
- package/dist/harness/subagent.js +1 -70
- package/dist/harness/subagent.js.map +1 -1
- package/dist/harness/tools/event.d.ts.map +1 -1
- package/dist/harness/tools/event.js +0 -9
- package/dist/harness/tools/event.js.map +1 -1
- package/dist/harness/tools/generate-image.d.ts +0 -6
- package/dist/harness/tools/generate-image.d.ts.map +1 -1
- package/dist/harness/tools/generate-image.js.map +1 -1
- package/dist/harness/tools/host-fn-tool.d.ts +0 -17
- package/dist/harness/tools/host-fn-tool.d.ts.map +1 -1
- package/dist/harness/tools/host-fn-tool.js +0 -16
- package/dist/harness/tools/host-fn-tool.js.map +1 -1
- package/dist/harness/tools/index.d.ts +1 -7
- package/dist/harness/tools/index.d.ts.map +1 -1
- package/dist/harness/tools/index.js +3 -14
- package/dist/harness/tools/index.js.map +1 -1
- package/dist/harness/tools/jev-browser.d.ts +4 -94
- package/dist/harness/tools/jev-browser.d.ts.map +1 -1
- package/dist/harness/tools/jev-browser.js +203 -92
- package/dist/harness/tools/jev-browser.js.map +1 -1
- package/dist/harness/tools/jev.d.ts +0 -8
- package/dist/harness/tools/jev.d.ts.map +1 -1
- package/dist/harness/tools/jev.js +0 -11
- package/dist/harness/tools/jev.js.map +1 -1
- package/dist/harness/tools/pi-tools.d.ts +0 -11
- package/dist/harness/tools/pi-tools.d.ts.map +1 -1
- package/dist/harness/tools/pi-tools.js +0 -29
- package/dist/harness/tools/pi-tools.js.map +1 -1
- package/dist/harness/tools/react.d.ts +0 -5
- package/dist/harness/tools/react.d.ts.map +1 -1
- package/dist/harness/tools/react.js +0 -5
- package/dist/harness/tools/react.js.map +1 -1
- package/dist/harness/tools/secret-redaction.d.ts +0 -25
- package/dist/harness/tools/secret-redaction.d.ts.map +1 -1
- package/dist/harness/tools/secret-redaction.js +3 -36
- package/dist/harness/tools/secret-redaction.js.map +1 -1
- package/dist/harness/tools/subagent.d.ts +0 -34
- package/dist/harness/tools/subagent.d.ts.map +1 -1
- package/dist/harness/tools/subagent.js +0 -92
- package/dist/harness/tools/subagent.js.map +1 -1
- package/dist/harness/tools/task.d.ts +0 -1
- package/dist/harness/tools/task.d.ts.map +1 -1
- package/dist/harness/tools/task.js +0 -1
- package/dist/harness/tools/task.js.map +1 -1
- package/dist/harness/tools/types.d.ts +0 -16
- package/dist/harness/tools/types.d.ts.map +1 -1
- package/dist/harness/tools/types.js.map +1 -1
- package/dist/harness/types.d.ts +0 -76
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +0 -13
- package/dist/log.js.map +1 -1
- package/dist/main.js +0 -47
- package/dist/main.js.map +1 -1
- package/dist/observability/index.d.ts +0 -9
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +0 -9
- package/dist/observability/index.js.map +1 -1
- package/dist/observability/instrument.js +0 -5
- package/dist/observability/instrument.js.map +1 -1
- package/dist/observability/otel.js +0 -1
- package/dist/observability/otel.js.map +1 -1
- package/dist/observability/sentry.d.ts +0 -18
- package/dist/observability/sentry.d.ts.map +1 -1
- package/dist/observability/sentry.js +0 -36
- package/dist/observability/sentry.js.map +1 -1
- package/dist/observability/types.d.ts +0 -9
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/observability/types.js.map +1 -1
- package/dist/office/index.d.ts +0 -76
- package/dist/office/index.d.ts.map +1 -1
- package/dist/office/index.js +2 -153
- package/dist/office/index.js.map +1 -1
- package/dist/office/projection.d.ts +0 -29
- package/dist/office/projection.d.ts.map +1 -1
- package/dist/office/projection.js +0 -37
- package/dist/office/projection.js.map +1 -1
- package/dist/office/types.d.ts +0 -66
- package/dist/office/types.d.ts.map +1 -1
- package/dist/office/types.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +9 -27
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/session-lifecycle.d.ts +0 -10
- package/dist/runtime/session-lifecycle.d.ts.map +1 -1
- package/dist/runtime/session-lifecycle.js +0 -12
- package/dist/runtime/session-lifecycle.js.map +1 -1
- package/dist/runtime/types.d.ts +0 -28
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +0 -1
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +0 -2
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/identity.d.ts +0 -28
- package/dist/sandbox/identity.d.ts.map +1 -1
- package/dist/sandbox/identity.js +0 -28
- package/dist/sandbox/identity.js.map +1 -1
- package/dist/sandbox/index.d.ts +0 -18
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +0 -18
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/provisioner.d.ts +0 -61
- package/dist/sandbox/provisioner.d.ts.map +1 -1
- package/dist/sandbox/provisioner.js +3 -105
- package/dist/sandbox/provisioner.js.map +1 -1
- package/dist/sandbox/types.d.ts +0 -39
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +2 -5
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +31 -31
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts +0 -6
- package/dist/sessions/chat-history-sync.d.ts.map +1 -1
- package/dist/sessions/chat-history-sync.js +1 -33
- package/dist/sessions/chat-history-sync.js.map +1 -1
- package/dist/sessions/history-line.d.ts +0 -20
- package/dist/sessions/history-line.d.ts.map +1 -1
- package/dist/sessions/history-line.js +0 -20
- package/dist/sessions/history-line.js.map +1 -1
- package/dist/sessions/migrate-common.d.ts +0 -15
- package/dist/sessions/migrate-common.d.ts.map +1 -1
- package/dist/sessions/migrate-common.js +0 -19
- package/dist/sessions/migrate-common.js.map +1 -1
- package/dist/sessions/migrate-pi-084.d.ts.map +1 -1
- package/dist/sessions/migrate-pi-084.js +0 -7
- package/dist/sessions/migrate-pi-084.js.map +1 -1
- package/dist/sessions/migrate-v3.d.ts +0 -7
- package/dist/sessions/migrate-v3.d.ts.map +1 -1
- package/dist/sessions/migrate-v3.js +1 -67
- package/dist/sessions/migrate-v3.js.map +1 -1
- package/dist/sessions/session-key.d.ts +3 -17
- package/dist/sessions/session-key.d.ts.map +1 -1
- package/dist/sessions/session-key.js +8 -35
- package/dist/sessions/session-key.js.map +1 -1
- package/dist/sessions/session-store.d.ts +0 -6
- package/dist/sessions/session-store.d.ts.map +1 -1
- package/dist/sessions/session-store.js +8 -50
- package/dist/sessions/session-store.js.map +1 -1
- package/dist/sessions/store.d.ts +0 -59
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +6 -88
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +0 -17
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/settings/apply.d.ts +0 -6
- package/dist/settings/apply.d.ts.map +1 -1
- package/dist/settings/apply.js +0 -29
- package/dist/settings/apply.js.map +1 -1
- package/dist/settings/index.d.ts +0 -53
- package/dist/settings/index.d.ts.map +1 -1
- package/dist/settings/index.js +0 -77
- package/dist/settings/index.js.map +1 -1
- package/dist/settings/migrate.d.ts +0 -5
- package/dist/settings/migrate.d.ts.map +1 -1
- package/dist/settings/migrate.js +0 -17
- package/dist/settings/migrate.js.map +1 -1
- package/dist/types.d.ts +0 -159
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.d.ts +2 -36
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +128 -59
- package/dist/vault/index.js.map +1 -1
- package/dist/vault/types.d.ts +0 -15
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/types.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,26 @@ any release.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [1.0.0-beta.77]
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Provision the standard sandbox image with Node.js 24, Chromium, ffmpeg, pinned `agent-browser` 0.38.1, and a checksummed Google Workspace CLI so `jev_browser` and capture workflows work without runtime installation and current-page recording preserves hydrated browser state.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Run every `jev_browser` command through the conversation-authorized sandbox executor, preserve native snapshots, refs, frames, tabs, screenshots, HAR, and recording, serialize calls per runner, and make named-session continuity and close-only operations explicit.
|
|
21
|
+
- Bound autonomous browser failures and repeated action cycles, refresh current page evidence before reporting completion, and refuse to silently resurrect an explicitly closed named session as `about:blank`.
|
|
22
|
+
- Delegate persisted session behavior to public Pi session and harness APIs instead of maintaining duplicate storage semantics.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- Log LLM cancellation reasons and Pi run ids only while provider transport is active, avoiding false abort logs during authentication, payload hooks, retry waits, tool execution, or after structural requests finish.
|
|
27
|
+
|
|
28
|
+
### Security
|
|
29
|
+
|
|
30
|
+
- Harden state and credential ownership by preserving explicit vault mount targets outside secret directories, rejecting migration collisions, keeping private file writes atomic, and deriving session operations from authorized conversation identities.
|
|
31
|
+
|
|
12
32
|
## [1.0.0-beta.76]
|
|
13
33
|
|
|
14
34
|
### Changed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/login.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQrF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/login.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQrF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAYzE;AA4CD,qBAAa,mBAAoB,YAAW,cAAc;IAClD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBzD;CACF"}
|
|
@@ -20,7 +20,6 @@ export function parseLoginCommand(text) {
|
|
|
20
20
|
return parseSharedLogin(operation?.toLowerCase(), name);
|
|
21
21
|
if (verb === "copy" && operation && !name)
|
|
22
22
|
return { action: "copy_shared", name: operation };
|
|
23
|
-
// Backward-compatible provider arguments open the generic login page.
|
|
24
23
|
return operation ? null : { action: "setup" };
|
|
25
24
|
}
|
|
26
25
|
function parseSharedLogin(operation, name) {
|
|
@@ -33,8 +32,6 @@ function parseSharedLogin(operation, name) {
|
|
|
33
32
|
}
|
|
34
33
|
function ensureLoginVault(context) {
|
|
35
34
|
const { services, platformUserId, conversationId, vaultConversationId } = context;
|
|
36
|
-
// The vault target is a conversation on the same platform; a command may
|
|
37
|
-
// aim at another conversation's vault via vaultConversationId.
|
|
38
35
|
return credentialAuthorizationKey(services.sandbox, {
|
|
39
36
|
userId: platformUserId,
|
|
40
37
|
address: createOfficeAddress(context.address.platform, vaultConversationId ?? conversationId),
|
|
@@ -51,10 +48,6 @@ async function refreshCopiedVaultRuntime(context) {
|
|
|
51
48
|
if (!context.services.provisioner) {
|
|
52
49
|
return "The cached session was refreshed. The sandbox will pick up copied credentials on the next provision.";
|
|
53
50
|
}
|
|
54
|
-
// The provisioner names containers by runtime resource key, not by the
|
|
55
|
-
// credential key the vault copy used — the two identities differ in image
|
|
56
|
-
// mode (office key vs raw-conversation key). Removing by the wrong key
|
|
57
|
-
// would silently leave the real container running with stale mounts.
|
|
58
51
|
const resourceKey = runtimeResourceKey(context.services.sandbox, {
|
|
59
52
|
userId: context.platformUserId,
|
|
60
53
|
address: targetAddress,
|
|
@@ -85,7 +78,6 @@ export class LoginCommandHandler {
|
|
|
85
78
|
return true;
|
|
86
79
|
}
|
|
87
80
|
}
|
|
88
|
-
/** Surface a vault-manager failure to the user without failing the command. */
|
|
89
81
|
async function replyVaultError(context, error) {
|
|
90
82
|
await replySummary(context, "Vault", [error instanceof Error ? error.message : String(error)]);
|
|
91
83
|
}
|
|
@@ -124,7 +116,6 @@ async function copySharedProfile(context, name) {
|
|
|
124
116
|
await replyVaultError(context, error);
|
|
125
117
|
}
|
|
126
118
|
}
|
|
127
|
-
/** Issue a portal link for this conversation's vault, or for a shared profile. */
|
|
128
119
|
async function startLoginSetup(context, parsed) {
|
|
129
120
|
if (!context.services.portalBaseUrl) {
|
|
130
121
|
await replySummary(context, "Vault", portalNotConfiguredLines("Login"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/adapters/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import * as log from \"../../log.js\";\nimport { credentialAuthorizationKey, runtimeResourceKey } from \"../../sandbox/identity.js\";\nimport { sharedVaultKey } from \"../../vault/index.js\";\nimport { slashForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler, ParsedLoginCommand } from \"./types.js\";\nimport { portalNotConfiguredLines, replySummary } from \"./utils.js\";\nimport { createOfficeAddress } from \"../../office/index.js\";\n\nconst LOGIN_COMMANDS = slashForms(\"login\");\n\nconst SHARED_OPERATIONS = [\"create\", \"update\", \"delete\"] as const;\n\nexport function parseLoginCommand(text: string): ParsedLoginCommand | null {\n const matched = matchCommand(text, LOGIN_COMMANDS);\n if (!matched) return null;\n\n const [subcommand, operation, name, ...extra] = matched.args;\n if (!subcommand) return { action: \"setup\" };\n if (extra.length > 0) return null;\n\n const verb = subcommand.toLowerCase();\n if (verb === \"shared\") return parseSharedLogin(operation?.toLowerCase(), name);\n if (verb === \"copy\" && operation && !name) return { action: \"copy_shared\", name: operation };\n // Backward-compatible provider arguments open the generic login page.\n return operation ? null : { action: \"setup\" };\n}\n\nfunction parseSharedLogin(\n operation: string | undefined,\n name: string | undefined,\n): ParsedLoginCommand | null {\n if (operation === \"list\") return name ? null : { action: \"shared_list\" };\n const matched = SHARED_OPERATIONS.find((candidate) => candidate === operation);\n if (!matched || !name) return null;\n return { action: `shared_${matched}`, name };\n}\n\nfunction ensureLoginVault(context: CommandContext): string {\n const { services, platformUserId, conversationId, vaultConversationId } = context;\n // The vault target is a conversation on the same platform; a command may\n // aim at another conversation's vault via vaultConversationId.\n return credentialAuthorizationKey(services.sandbox, {\n userId: platformUserId,\n address: createOfficeAddress(context.address.platform, vaultConversationId ?? conversationId),\n });\n}\n\nasync function refreshCopiedVaultRuntime(context: CommandContext): Promise<string | undefined> {\n if (context.services.sandbox.type !== \"image\") return undefined;\n\n const targetAddress = createOfficeAddress(\n context.address.platform,\n context.vaultConversationId ?? context.conversationId,\n );\n const cleared = context.services.runtime?.refreshConversationEnvironment(targetAddress);\n if (cleared === false) {\n return \"A session is currently running, so the sandbox was not restarted. The copied credentials will be applied after the run finishes and the sandbox is recreated.\";\n }\n\n if (!context.services.provisioner) {\n return \"The cached session was refreshed. The sandbox will pick up copied credentials on the next provision.\";\n }\n\n // The provisioner names containers by runtime resource key, not by the\n // credential key the vault copy used — the two identities differ in image\n // mode (office key vs raw-conversation key). Removing by the wrong key\n // would silently leave the real container running with stale mounts.\n const resourceKey = runtimeResourceKey(context.services.sandbox, {\n userId: context.platformUserId,\n address: targetAddress,\n });\n await context.services.provisioner.remove(resourceKey);\n return \"The sandbox container was removed and will be recreated with the copied env and file mounts on the next message.\";\n}\n\nexport class LoginCommandHandler implements CommandHandler {\n async tryHandle(context: CommandContext): Promise<boolean> {\n const parsed = parseLoginCommand(context.commandText);\n if (!parsed) return false;\n\n if (!context.privateConversation) {\n await replySummary(context, \"Vault\", [\n \"為了保護你的憑證,`/login` 只能在與機器人的私訊中使用。\",\n \"請先私訊機器人,再重新執行 `/login`。\",\n ]);\n return true;\n }\n\n if (parsed.action === \"shared_list\") await listSharedProfiles(context);\n else if (parsed.action === \"shared_delete\") await deleteSharedProfile(context, parsed.name);\n else if (parsed.action === \"copy_shared\") await copySharedProfile(context, parsed.name);\n else await startLoginSetup(context, parsed);\n return true;\n }\n}\n\n/** Surface a vault-manager failure to the user without failing the command. */\nasync function replyVaultError(context: CommandContext, error: unknown): Promise<void> {\n await replySummary(context, \"Vault\", [error instanceof Error ? error.message : String(error)]);\n}\n\nasync function listSharedProfiles(context: CommandContext): Promise<void> {\n const profiles = context.services.vaultManager.listSharedVaults();\n await replySummary(\n context,\n \"Vault\",\n profiles.length > 0\n ? [\"Shared login profiles:\", ...profiles.map((name) => `- ${name}`)]\n : [\"No shared login profiles found.\"],\n );\n}\n\nasync function deleteSharedProfile(context: CommandContext, name: string): Promise<void> {\n try {\n const deleted = context.services.vaultManager.deleteSharedVault(name);\n await replySummary(context, \"Vault\", [\n deleted\n ? `Deleted shared login profile \\`${name}\\`.`\n : `Shared login profile \\`${name}\\` does not exist.`,\n ]);\n } catch (error) {\n await replyVaultError(context, error);\n }\n}\n\nasync function copySharedProfile(context: CommandContext, name: string): Promise<void> {\n try {\n const vaultId = ensureLoginVault(context);\n const result = context.services.vaultManager.copySharedVaultTo(name, vaultId);\n const refreshNote = await refreshCopiedVaultRuntime(context);\n await replySummary(context, \"Vault\", [\n `Copied shared login profile \\`${name}\\` into this conversation.`,\n \"Shared values overwrite matching conversation values; conversation-only values are kept.\",\n `Copied: ${result.envKeysCopied} env key(s), ${result.filesCopied} file(s).`,\n ...(refreshNote ? [refreshNote] : []),\n ]);\n } catch (error) {\n await replyVaultError(context, error);\n }\n}\n\n/** Issue a portal link for this conversation's vault, or for a shared profile. */\nasync function startLoginSetup(context: CommandContext, parsed: ParsedLoginCommand): Promise<void> {\n if (!context.services.portalBaseUrl) {\n await replySummary(context, \"Vault\", portalNotConfiguredLines(\"Login\"));\n return;\n }\n\n let vaultId: string;\n try {\n vaultId = resolveLoginVaultId(context, parsed);\n } catch (error) {\n log.logWarning(\n `[${context.conversationId}] Failed to prepare login vault for ${context.platform}/${context.platformUserId}`,\n error instanceof Error ? error.message : String(error),\n );\n await replySummary(context, \"Vault\", [\n \"Login setup failed on the server.\",\n \"請稍後重試,或聯絡管理員檢查 vault 儲存權限。\",\n ]);\n return;\n }\n\n const token = context.services.linkTokenStore.create(\n context.platform,\n context.platformUserId,\n context.conversationId,\n vaultId,\n \"\",\n );\n await replySummary(context, \"Vault\", [\n `${context.services.portalBaseUrl}/link?token=${token.token}`,\n `Target: ${loginVaultLabel(context, parsed, vaultId)} · Expires: 15 minutes`,\n ]);\n}\n\nfunction resolveLoginVaultId(context: CommandContext, parsed: ParsedLoginCommand): string {\n const isSharedSetup = parsed.action === \"shared_create\" || parsed.action === \"shared_update\";\n const vaultId = isSharedSetup ? (sharedVaultKey(parsed.name) ?? \"\") : ensureLoginVault(context);\n if (vaultId) return vaultId;\n throw new Error(\n isSharedSetup ? `Invalid shared login profile name: ${parsed.name}` : \"Invalid vault id\",\n );\n}\n\nfunction loginVaultLabel(\n context: CommandContext,\n parsed: ParsedLoginCommand,\n vaultId: string,\n): string {\n if (parsed.action === \"shared_create\" || parsed.action === \"shared_update\") {\n return `shared login profile (${parsed.name})`;\n }\n return context.services.sandbox.type === \"container\"\n ? `container vault (${vaultId})`\n : \"your vault\";\n}\n"]}
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/adapters/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import * as log from \"../../log.js\";\nimport { credentialAuthorizationKey, runtimeResourceKey } from \"../../sandbox/identity.js\";\nimport { sharedVaultKey } from \"../../vault/index.js\";\nimport { slashForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler, ParsedLoginCommand } from \"./types.js\";\nimport { portalNotConfiguredLines, replySummary } from \"./utils.js\";\nimport { createOfficeAddress } from \"../../office/index.js\";\n\nconst LOGIN_COMMANDS = slashForms(\"login\");\n\nconst SHARED_OPERATIONS = [\"create\", \"update\", \"delete\"] as const;\n\nexport function parseLoginCommand(text: string): ParsedLoginCommand | null {\n const matched = matchCommand(text, LOGIN_COMMANDS);\n if (!matched) return null;\n\n const [subcommand, operation, name, ...extra] = matched.args;\n if (!subcommand) return { action: \"setup\" };\n if (extra.length > 0) return null;\n\n const verb = subcommand.toLowerCase();\n if (verb === \"shared\") return parseSharedLogin(operation?.toLowerCase(), name);\n if (verb === \"copy\" && operation && !name) return { action: \"copy_shared\", name: operation };\n return operation ? null : { action: \"setup\" };\n}\n\nfunction parseSharedLogin(\n operation: string | undefined,\n name: string | undefined,\n): ParsedLoginCommand | null {\n if (operation === \"list\") return name ? null : { action: \"shared_list\" };\n const matched = SHARED_OPERATIONS.find((candidate) => candidate === operation);\n if (!matched || !name) return null;\n return { action: `shared_${matched}`, name };\n}\n\nfunction ensureLoginVault(context: CommandContext): string {\n const { services, platformUserId, conversationId, vaultConversationId } = context;\n return credentialAuthorizationKey(services.sandbox, {\n userId: platformUserId,\n address: createOfficeAddress(context.address.platform, vaultConversationId ?? conversationId),\n });\n}\n\nasync function refreshCopiedVaultRuntime(context: CommandContext): Promise<string | undefined> {\n if (context.services.sandbox.type !== \"image\") return undefined;\n\n const targetAddress = createOfficeAddress(\n context.address.platform,\n context.vaultConversationId ?? context.conversationId,\n );\n const cleared = context.services.runtime?.refreshConversationEnvironment(targetAddress);\n if (cleared === false) {\n return \"A session is currently running, so the sandbox was not restarted. The copied credentials will be applied after the run finishes and the sandbox is recreated.\";\n }\n\n if (!context.services.provisioner) {\n return \"The cached session was refreshed. The sandbox will pick up copied credentials on the next provision.\";\n }\n\n const resourceKey = runtimeResourceKey(context.services.sandbox, {\n userId: context.platformUserId,\n address: targetAddress,\n });\n await context.services.provisioner.remove(resourceKey);\n return \"The sandbox container was removed and will be recreated with the copied env and file mounts on the next message.\";\n}\n\nexport class LoginCommandHandler implements CommandHandler {\n async tryHandle(context: CommandContext): Promise<boolean> {\n const parsed = parseLoginCommand(context.commandText);\n if (!parsed) return false;\n\n if (!context.privateConversation) {\n await replySummary(context, \"Vault\", [\n \"為了保護你的憑證,`/login` 只能在與機器人的私訊中使用。\",\n \"請先私訊機器人,再重新執行 `/login`。\",\n ]);\n return true;\n }\n\n if (parsed.action === \"shared_list\") await listSharedProfiles(context);\n else if (parsed.action === \"shared_delete\") await deleteSharedProfile(context, parsed.name);\n else if (parsed.action === \"copy_shared\") await copySharedProfile(context, parsed.name);\n else await startLoginSetup(context, parsed);\n return true;\n }\n}\n\nasync function replyVaultError(context: CommandContext, error: unknown): Promise<void> {\n await replySummary(context, \"Vault\", [error instanceof Error ? error.message : String(error)]);\n}\n\nasync function listSharedProfiles(context: CommandContext): Promise<void> {\n const profiles = context.services.vaultManager.listSharedVaults();\n await replySummary(\n context,\n \"Vault\",\n profiles.length > 0\n ? [\"Shared login profiles:\", ...profiles.map((name) => `- ${name}`)]\n : [\"No shared login profiles found.\"],\n );\n}\n\nasync function deleteSharedProfile(context: CommandContext, name: string): Promise<void> {\n try {\n const deleted = context.services.vaultManager.deleteSharedVault(name);\n await replySummary(context, \"Vault\", [\n deleted\n ? `Deleted shared login profile \\`${name}\\`.`\n : `Shared login profile \\`${name}\\` does not exist.`,\n ]);\n } catch (error) {\n await replyVaultError(context, error);\n }\n}\n\nasync function copySharedProfile(context: CommandContext, name: string): Promise<void> {\n try {\n const vaultId = ensureLoginVault(context);\n const result = context.services.vaultManager.copySharedVaultTo(name, vaultId);\n const refreshNote = await refreshCopiedVaultRuntime(context);\n await replySummary(context, \"Vault\", [\n `Copied shared login profile \\`${name}\\` into this conversation.`,\n \"Shared values overwrite matching conversation values; conversation-only values are kept.\",\n `Copied: ${result.envKeysCopied} env key(s), ${result.filesCopied} file(s).`,\n ...(refreshNote ? [refreshNote] : []),\n ]);\n } catch (error) {\n await replyVaultError(context, error);\n }\n}\n\nasync function startLoginSetup(context: CommandContext, parsed: ParsedLoginCommand): Promise<void> {\n if (!context.services.portalBaseUrl) {\n await replySummary(context, \"Vault\", portalNotConfiguredLines(\"Login\"));\n return;\n }\n\n let vaultId: string;\n try {\n vaultId = resolveLoginVaultId(context, parsed);\n } catch (error) {\n log.logWarning(\n `[${context.conversationId}] Failed to prepare login vault for ${context.platform}/${context.platformUserId}`,\n error instanceof Error ? error.message : String(error),\n );\n await replySummary(context, \"Vault\", [\n \"Login setup failed on the server.\",\n \"請稍後重試,或聯絡管理員檢查 vault 儲存權限。\",\n ]);\n return;\n }\n\n const token = context.services.linkTokenStore.create(\n context.platform,\n context.platformUserId,\n context.conversationId,\n vaultId,\n \"\",\n );\n await replySummary(context, \"Vault\", [\n `${context.services.portalBaseUrl}/link?token=${token.token}`,\n `Target: ${loginVaultLabel(context, parsed, vaultId)} · Expires: 15 minutes`,\n ]);\n}\n\nfunction resolveLoginVaultId(context: CommandContext, parsed: ParsedLoginCommand): string {\n const isSharedSetup = parsed.action === \"shared_create\" || parsed.action === \"shared_update\";\n const vaultId = isSharedSetup ? (sharedVaultKey(parsed.name) ?? \"\") : ensureLoginVault(context);\n if (vaultId) return vaultId;\n throw new Error(\n isSharedSetup ? `Invalid shared login profile name: ${parsed.name}` : \"Invalid vault id\",\n );\n}\n\nfunction loginVaultLabel(\n context: CommandContext,\n parsed: ParsedLoginCommand,\n vaultId: string,\n): string {\n if (parsed.action === \"shared_create\" || parsed.action === \"shared_update\") {\n return `shared login profile (${parsed.name})`;\n }\n return context.services.sandbox.type === \"container\"\n ? `container vault (${vaultId})`\n : \"your vault\";\n}\n"]}
|
|
@@ -1,28 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Platform-agnostic command manifest — the single inventory that platform
|
|
3
|
-
* adapters derive their native slash-command registration and routing from,
|
|
4
|
-
* and that `isCommandText` and the handler grammars mirror.
|
|
5
|
-
*
|
|
6
|
-
* Adding a command means adding a manifest entry plus a handler in this
|
|
7
|
-
* directory; adapters pick up registration and routing from the entry instead
|
|
8
|
-
* of hand-restating the inventory (where a missed spot used to mean a silent
|
|
9
|
-
* no-response).
|
|
10
|
-
*
|
|
11
|
-
* Per CONTEXT.md, slash commands are a minimal chat control surface: detailed
|
|
12
|
-
* or infrequent settings belong in Admin, and bare commands are limited to
|
|
13
|
-
* `session`. `stop` is listed for platform registration/UI only — it is a
|
|
14
|
-
* magic word owned by conversation intake, not a command handler.
|
|
15
|
-
*/
|
|
16
1
|
import type { CommandManifestEntry } from "./types.js";
|
|
17
2
|
export type { CommandManifestEntry, SlackSlashRoute } from "./types.js";
|
|
18
|
-
/** Entry order is the Telegram command-menu order. */
|
|
19
3
|
export declare const COMMAND_MANIFEST: readonly CommandManifestEntry[];
|
|
20
4
|
export declare function commandManifestEntry(name: string): CommandManifestEntry;
|
|
21
|
-
/** Slash spellings of a command: `/<name>` and `/pi-<name>` for the name and each alias. */
|
|
22
5
|
export declare function slashForms(name: string): readonly string[];
|
|
23
|
-
/** Every accepted spelling: the bare name (when the command is bare) plus slash forms. */
|
|
24
6
|
export declare function commandForms(name: string): readonly string[];
|
|
25
|
-
/** Telegram `setMyCommands` payload (menu registration; routing is separate). */
|
|
26
7
|
export declare function telegramCommandMenu(): {
|
|
27
8
|
command: string;
|
|
28
9
|
description: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/manifest.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAExE,eAAO,MAAM,gBAAgB,EAAE,SAAS,oBAAoB,EAkF3D,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAIvE;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAM1D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAG5D;AAED,wBAAgB,mBAAmB,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAAE,CAKhF;AAED,wBAAgB,YAAY,CAAC,OAAO,SAAS,MAAM,EACjD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GACnC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAQ7C;AASD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD"}
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Platform-agnostic command manifest — the single inventory that platform
|
|
3
|
-
* adapters derive their native slash-command registration and routing from,
|
|
4
|
-
* and that `isCommandText` and the handler grammars mirror.
|
|
5
|
-
*
|
|
6
|
-
* Adding a command means adding a manifest entry plus a handler in this
|
|
7
|
-
* directory; adapters pick up registration and routing from the entry instead
|
|
8
|
-
* of hand-restating the inventory (where a missed spot used to mean a silent
|
|
9
|
-
* no-response).
|
|
10
|
-
*
|
|
11
|
-
* Per CONTEXT.md, slash commands are a minimal chat control surface: detailed
|
|
12
|
-
* or infrequent settings belong in Admin, and bare commands are limited to
|
|
13
|
-
* `session`. `stop` is listed for platform registration/UI only — it is a
|
|
14
|
-
* magic word owned by conversation intake, not a command handler.
|
|
15
|
-
*/
|
|
16
|
-
/** Entry order is the Telegram command-menu order. */
|
|
17
1
|
export const COMMAND_MANIFEST = [
|
|
18
2
|
{
|
|
19
3
|
name: "login",
|
|
@@ -50,12 +34,6 @@ export const COMMAND_MANIFEST = [
|
|
|
50
34
|
description: "Show sandbox status or boost limits",
|
|
51
35
|
arg: {
|
|
52
36
|
name: "action",
|
|
53
|
-
// Discord caps option descriptions at 100 characters (registration
|
|
54
|
-
// fails otherwise); commands.test.ts enforces the budget.
|
|
55
|
-
// The `door` action still works but is deliberately undocumented: the
|
|
56
|
-
// workspace posture follows the platform's own channel visibility
|
|
57
|
-
// automatically, and overriding it is an admin escape hatch, not a
|
|
58
|
-
// user-facing feature.
|
|
59
37
|
description: "'boost' temporarily applies the configured boost limits",
|
|
60
38
|
required: false,
|
|
61
39
|
},
|
|
@@ -109,7 +87,6 @@ export function commandManifestEntry(name) {
|
|
|
109
87
|
throw new Error(`Unknown command in manifest: ${name}`);
|
|
110
88
|
return entry;
|
|
111
89
|
}
|
|
112
|
-
/** Slash spellings of a command: `/<name>` and `/pi-<name>` for the name and each alias. */
|
|
113
90
|
export function slashForms(name) {
|
|
114
91
|
const entry = commandManifestEntry(name);
|
|
115
92
|
return [entry.name, ...(entry.aliases ?? [])].flatMap((spelling) => [
|
|
@@ -117,12 +94,10 @@ export function slashForms(name) {
|
|
|
117
94
|
`/pi-${spelling}`,
|
|
118
95
|
]);
|
|
119
96
|
}
|
|
120
|
-
/** Every accepted spelling: the bare name (when the command is bare) plus slash forms. */
|
|
121
97
|
export function commandForms(name) {
|
|
122
98
|
const entry = commandManifestEntry(name);
|
|
123
99
|
return [...(entry.bare ? [entry.name] : []), ...slashForms(name)];
|
|
124
100
|
}
|
|
125
|
-
/** Telegram `setMyCommands` payload (menu registration; routing is separate). */
|
|
126
101
|
export function telegramCommandMenu() {
|
|
127
102
|
return COMMAND_MANIFEST.filter((entry) => entry.telegramMenu).map((entry) => ({
|
|
128
103
|
command: entry.name,
|
|
@@ -138,15 +113,6 @@ export function matchCommand(text, aliases, options) {
|
|
|
138
113
|
const command = token.toLowerCase();
|
|
139
114
|
return aliases.includes(command) ? { command, args: tokens.slice(1) } : null;
|
|
140
115
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Chat-command text recognition, derived from the command manifest so the
|
|
143
|
-
* inventory has a single source of truth. Session resume uses it to keep
|
|
144
|
-
* command messages out of replayed history.
|
|
145
|
-
*
|
|
146
|
-
* The `pi-[\w-]+` alternative is a catch-all for platform-prefixed command
|
|
147
|
-
* names (including ones a platform registers but this build no longer
|
|
148
|
-
* handles), independent of the manifest.
|
|
149
|
-
*/
|
|
150
116
|
const COMMAND_NAMES = COMMAND_MANIFEST.flatMap((entry) => [entry.name].concat(entry.aliases ?? []));
|
|
151
117
|
const COMMAND_TEXT_PATTERN = new RegExp(`^\\/(?:pi-[\\w-]+|${COMMAND_NAMES.join("|")})(?:@\\w+)?(?:\\s|$)`, "i");
|
|
152
118
|
export function isCommandText(text) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/adapters/commands/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Platform-agnostic command manifest — the single inventory that platform\n * adapters derive their native slash-command registration and routing from,\n * and that `isCommandText` and the handler grammars mirror.\n *\n * Adding a command means adding a manifest entry plus a handler in this\n * directory; adapters pick up registration and routing from the entry instead\n * of hand-restating the inventory (where a missed spot used to mean a silent\n * no-response).\n *\n * Per CONTEXT.md, slash commands are a minimal chat control surface: detailed\n * or infrequent settings belong in Admin, and bare commands are limited to\n * `session`. `stop` is listed for platform registration/UI only — it is a\n * magic word owned by conversation intake, not a command handler.\n */\n\nimport type { CommandManifestEntry } from \"./types.js\";\n\nexport type { CommandManifestEntry, SlackSlashRoute } from \"./types.js\";\n\n/** Entry order is the Telegram command-menu order. */\nexport const COMMAND_MANIFEST: readonly CommandManifestEntry[] = [\n {\n name: \"login\",\n description: \"Store credentials in your private vault\",\n slackCommand: \"/pi-login\",\n slackRoute: { includeText: true, privateCommand: true },\n discord: true,\n telegramMenu: {},\n },\n {\n name: \"session\",\n description: \"Open the current session in the web viewer\",\n bare: true,\n slackCommand: \"/pi-session\",\n slackRoute: { thread: true },\n discord: true,\n telegramMenu: {},\n },\n {\n name: \"model\",\n description: \"Switch this conversation's LLM model\",\n arg: {\n name: \"model\",\n description: \"provider/model[:thinking], e.g. anthropic/claude-sonnet-4-6:off\",\n required: false,\n },\n slackCommand: \"/pi-model\",\n slackRoute: { includeText: true },\n discord: true,\n telegramMenu: {},\n },\n {\n name: \"sandbox\",\n description: \"Show sandbox status or boost limits\",\n arg: {\n name: \"action\",\n // Discord caps option descriptions at 100 characters (registration\n // fails otherwise); commands.test.ts enforces the budget.\n // The `door` action still works but is deliberately undocumented: the\n // workspace posture follows the platform's own channel visibility\n // automatically, and overriding it is an admin escape hatch, not a\n // user-facing feature.\n description: \"'boost' temporarily applies the configured boost limits\",\n required: false,\n },\n slackCommand: \"/pi-sandbox\",\n slackRoute: { includeText: true },\n discord: true,\n telegramMenu: { description: \"Show or boost sandbox limits\" },\n telegramCommand: true,\n },\n {\n name: \"autoreply\",\n aliases: [\"auto-reply\"],\n description: \"Enable, disable, or Jev-assist replies without mentions\",\n arg: {\n name: \"state\",\n description: \"on, off, or jev\",\n required: true,\n },\n slackCommand: \"/pi-auto-reply\",\n slackRoute: { includeText: true },\n },\n {\n name: \"stop\",\n description: \"Stop the current conversation\",\n magicWord: true,\n discord: true,\n telegramMenu: { description: \"Stop ongoing conversation\" },\n },\n {\n name: \"new\",\n description: \"Reset conversation history and start fresh\",\n slackCommand: \"/pi-new\",\n slackRoute: {},\n discord: true,\n telegramMenu: {},\n telegramCommand: true,\n },\n {\n name: \"admin\",\n description: \"Open the admin portal\",\n slackCommand: \"/pi-admin\",\n slackRoute: { thread: true },\n discord: true,\n telegramMenu: {},\n telegramCommand: true,\n },\n];\n\nexport function commandManifestEntry(name: string): CommandManifestEntry {\n const entry = COMMAND_MANIFEST.find((candidate) => candidate.name === name);\n if (!entry) throw new Error(`Unknown command in manifest: ${name}`);\n return entry;\n}\n\n/** Slash spellings of a command: `/<name>` and `/pi-<name>` for the name and each alias. */\nexport function slashForms(name: string): readonly string[] {\n const entry = commandManifestEntry(name);\n return [entry.name, ...(entry.aliases ?? [])].flatMap((spelling) => [\n `/${spelling}`,\n `/pi-${spelling}`,\n ]);\n}\n\n/** Every accepted spelling: the bare name (when the command is bare) plus slash forms. */\nexport function commandForms(name: string): readonly string[] {\n const entry = commandManifestEntry(name);\n return [...(entry.bare ? [entry.name] : []), ...slashForms(name)];\n}\n\n/** Telegram `setMyCommands` payload (menu registration; routing is separate). */\nexport function telegramCommandMenu(): { command: string; description: string }[] {\n return COMMAND_MANIFEST.filter((entry) => entry.telegramMenu).map((entry) => ({\n command: entry.name,\n description: entry.telegramMenu?.description ?? entry.description,\n }));\n}\n\nexport function matchCommand<Command extends string>(\n text: string,\n aliases: readonly Command[],\n options?: { stripMention?: boolean },\n): { command: Command; args: string[] } | null {\n const tokens = text.trim().split(/\\s+/).filter(Boolean);\n const first = tokens[0];\n if (first === undefined) return null;\n\n const token = options?.stripMention ? first.replace(/@\\w+$/i, \"\") : first;\n const command = token.toLowerCase() as Command;\n return aliases.includes(command) ? { command, args: tokens.slice(1) } : null;\n}\n\n/**\n * Chat-command text recognition, derived from the command manifest so the\n * inventory has a single source of truth. Session resume uses it to keep\n * command messages out of replayed history.\n *\n * The `pi-[\\w-]+` alternative is a catch-all for platform-prefixed command\n * names (including ones a platform registers but this build no longer\n * handles), independent of the manifest.\n */\nconst COMMAND_NAMES = COMMAND_MANIFEST.flatMap((entry) => [entry.name].concat(entry.aliases ?? []));\n\nconst COMMAND_TEXT_PATTERN = new RegExp(\n `^\\\\/(?:pi-[\\\\w-]+|${COMMAND_NAMES.join(\"|\")})(?:@\\\\w+)?(?:\\\\s|$)`,\n \"i\",\n);\n\nexport function isCommandText(text: string): boolean {\n return COMMAND_TEXT_PATTERN.test(text.trim());\n}\n"]}
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/adapters/commands/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CommandManifestEntry } from \"./types.js\";\n\nexport type { CommandManifestEntry, SlackSlashRoute } from \"./types.js\";\n\nexport const COMMAND_MANIFEST: readonly CommandManifestEntry[] = [\n {\n name: \"login\",\n description: \"Store credentials in your private vault\",\n slackCommand: \"/pi-login\",\n slackRoute: { includeText: true, privateCommand: true },\n discord: true,\n telegramMenu: {},\n },\n {\n name: \"session\",\n description: \"Open the current session in the web viewer\",\n bare: true,\n slackCommand: \"/pi-session\",\n slackRoute: { thread: true },\n discord: true,\n telegramMenu: {},\n },\n {\n name: \"model\",\n description: \"Switch this conversation's LLM model\",\n arg: {\n name: \"model\",\n description: \"provider/model[:thinking], e.g. anthropic/claude-sonnet-4-6:off\",\n required: false,\n },\n slackCommand: \"/pi-model\",\n slackRoute: { includeText: true },\n discord: true,\n telegramMenu: {},\n },\n {\n name: \"sandbox\",\n description: \"Show sandbox status or boost limits\",\n arg: {\n name: \"action\",\n description: \"'boost' temporarily applies the configured boost limits\",\n required: false,\n },\n slackCommand: \"/pi-sandbox\",\n slackRoute: { includeText: true },\n discord: true,\n telegramMenu: { description: \"Show or boost sandbox limits\" },\n telegramCommand: true,\n },\n {\n name: \"autoreply\",\n aliases: [\"auto-reply\"],\n description: \"Enable, disable, or Jev-assist replies without mentions\",\n arg: {\n name: \"state\",\n description: \"on, off, or jev\",\n required: true,\n },\n slackCommand: \"/pi-auto-reply\",\n slackRoute: { includeText: true },\n },\n {\n name: \"stop\",\n description: \"Stop the current conversation\",\n magicWord: true,\n discord: true,\n telegramMenu: { description: \"Stop ongoing conversation\" },\n },\n {\n name: \"new\",\n description: \"Reset conversation history and start fresh\",\n slackCommand: \"/pi-new\",\n slackRoute: {},\n discord: true,\n telegramMenu: {},\n telegramCommand: true,\n },\n {\n name: \"admin\",\n description: \"Open the admin portal\",\n slackCommand: \"/pi-admin\",\n slackRoute: { thread: true },\n discord: true,\n telegramMenu: {},\n telegramCommand: true,\n },\n];\n\nexport function commandManifestEntry(name: string): CommandManifestEntry {\n const entry = COMMAND_MANIFEST.find((candidate) => candidate.name === name);\n if (!entry) throw new Error(`Unknown command in manifest: ${name}`);\n return entry;\n}\n\nexport function slashForms(name: string): readonly string[] {\n const entry = commandManifestEntry(name);\n return [entry.name, ...(entry.aliases ?? [])].flatMap((spelling) => [\n `/${spelling}`,\n `/pi-${spelling}`,\n ]);\n}\n\nexport function commandForms(name: string): readonly string[] {\n const entry = commandManifestEntry(name);\n return [...(entry.bare ? [entry.name] : []), ...slashForms(name)];\n}\n\nexport function telegramCommandMenu(): { command: string; description: string }[] {\n return COMMAND_MANIFEST.filter((entry) => entry.telegramMenu).map((entry) => ({\n command: entry.name,\n description: entry.telegramMenu?.description ?? entry.description,\n }));\n}\n\nexport function matchCommand<Command extends string>(\n text: string,\n aliases: readonly Command[],\n options?: { stripMention?: boolean },\n): { command: Command; args: string[] } | null {\n const tokens = text.trim().split(/\\s+/).filter(Boolean);\n const first = tokens[0];\n if (first === undefined) return null;\n\n const token = options?.stripMention ? first.replace(/@\\w+$/i, \"\") : first;\n const command = token.toLowerCase() as Command;\n return aliases.includes(command) ? { command, args: tokens.slice(1) } : null;\n}\n\nconst COMMAND_NAMES = COMMAND_MANIFEST.flatMap((entry) => [entry.name].concat(entry.aliases ?? []));\n\nconst COMMAND_TEXT_PATTERN = new RegExp(\n `^\\\\/(?:pi-[\\\\w-]+|${COMMAND_NAMES.join(\"|\")})(?:@\\\\w+)?(?:\\\\s|$)`,\n \"i\",\n);\n\nexport function isCommandText(text: string): boolean {\n return COMMAND_TEXT_PATTERN.test(text.trim());\n}\n"]}
|
|
@@ -5,11 +5,6 @@ export declare class ModelCommandHandler implements CommandHandler {
|
|
|
5
5
|
private readonly modelRegistry;
|
|
6
6
|
constructor(modelRegistry: ModelRegistry);
|
|
7
7
|
tryHandle(context: CommandContext): Promise<boolean>;
|
|
8
|
-
/**
|
|
9
|
-
* Resolve the spec against the registry. A `:suffix` is first tried as part
|
|
10
|
-
* of the model id, then as a thinking level on the bare id — so a model
|
|
11
|
-
* whose real name contains a colon still wins over the suffix reading.
|
|
12
|
-
*/
|
|
13
8
|
private selectModel;
|
|
14
9
|
}
|
|
15
10
|
//# sourceMappingURL=model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/model.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAapG,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIrD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CA+BzE;AAoCD,qBAAa,mBAAoB,YAAW,cAAc;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa;IAA1C,YAA6B,aAAa,EAAE,aAAa,EAAI;IACvD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAsDzD;IAED
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/model.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAapG,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIrD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CA+BzE;AAoCD,qBAAa,mBAAoB,YAAW,cAAc;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa;IAA1C,YAA6B,aAAa,EAAE,aAAa,EAAI;IACvD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAsDzD;IAED,OAAO,CAAC,WAAW;CA6BpB"}
|
|
@@ -116,11 +116,6 @@ export class ModelCommandHandler {
|
|
|
116
116
|
]);
|
|
117
117
|
return true;
|
|
118
118
|
}
|
|
119
|
-
/**
|
|
120
|
-
* Resolve the spec against the registry. A `:suffix` is first tried as part
|
|
121
|
-
* of the model id, then as a thinking level on the bare id — so a model
|
|
122
|
-
* whose real name contains a colon still wins over the suffix reading.
|
|
123
|
-
*/
|
|
124
119
|
selectModel(provider, model, parsed) {
|
|
125
120
|
const exactModelId = parsed.modelCandidate ?? model;
|
|
126
121
|
if (this.modelRegistry.find(provider, exactModelId))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/adapters/commands/model.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { ThinkingLevel as PiAiThinkingLevel } from \"@earendil-works/pi-ai\";\nimport { resolveConversationSettings } from \"../../settings/index.js\";\nimport { applyConversationSettings } from \"../../settings/apply.js\";\nimport { slashForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler, ModelRegistry, ParsedModelCommand } from \"./types.js\";\nimport { replySummary } from \"./utils.js\";\n\nconst PI_AI_THINKING_LEVELS = [\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n] satisfies PiAiThinkingLevel[];\nconst THINKING_LEVELS = new Set<ThinkingLevel>([\"off\", ...PI_AI_THINKING_LEVELS]);\n\nexport type { ParsedModelCommand } from \"./types.js\";\n\nconst MODEL_COMMANDS = slashForms(\"model\");\n\nexport function parseModelCommand(text: string): ParsedModelCommand | null {\n const matched = matchCommand(text, MODEL_COMMANDS);\n if (!matched) return null;\n\n if (matched.args.length === 0) {\n return {};\n }\n\n if (matched.args.length !== 1) {\n return { error: \"invalid_spec\" };\n }\n\n const spec = matched.args[0];\n if (spec === undefined) {\n return { error: \"invalid_spec\" };\n }\n const slash = spec.indexOf(\"/\");\n if (slash <= 0 || slash === spec.length - 1) {\n return { error: \"invalid_spec\" };\n }\n\n const modelSpec = spec.slice(slash + 1);\n const parsedModel = parseModelThinkingLevel(modelSpec);\n if (parsedModel.error) {\n return { error: parsedModel.error };\n }\n\n return {\n provider: spec.slice(0, slash),\n ...parsedModel,\n };\n}\n\nfunction parseModelThinkingLevel(modelSpec: string): {\n model?: string;\n modelCandidate?: string;\n thinkingLevelCandidate?: string;\n thinkingLevel?: ThinkingLevel;\n error?: \"invalid_spec\";\n} {\n const colon = modelSpec.lastIndexOf(\":\");\n if (colon === 0 || colon === modelSpec.length - 1) {\n return { error: \"invalid_spec\" };\n }\n if (colon < 0) {\n return { model: modelSpec };\n }\n\n const suffix = modelSpec.slice(colon + 1);\n return {\n model: modelSpec.slice(0, colon),\n modelCandidate: modelSpec,\n thinkingLevelCandidate: suffix,\n ...(THINKING_LEVELS.has(suffix as ThinkingLevel)\n ? { thinkingLevel: suffix as ThinkingLevel }\n : {}),\n };\n}\n\nfunction formatModelSpec(provider: string, model: string, thinkingLevel?: ThinkingLevel): string {\n return `${provider}/${model}${thinkingLevel ? `:${thinkingLevel}` : \"\"}`;\n}\n\nconst USAGE_EXAMPLE = \"Example: `/pi-model anthropic/claude-sonnet-4-6:off`\";\n\ntype ModelSelection = { modelId: string; thinkingLevel?: ThinkingLevel } | { lines: string[] };\n\nexport class ModelCommandHandler implements CommandHandler {\n constructor(private readonly modelRegistry: ModelRegistry) {}\n async tryHandle(context: CommandContext): Promise<boolean> {\n const parsed = parseModelCommand(context.commandText);\n if (!parsed) return false;\n\n if (parsed.error) {\n await replySummary(context, \"Model\", [\n \"無效的模型參數,請使用 `provider/model[:thinking]`。\",\n USAGE_EXAMPLE,\n ]);\n return true;\n }\n\n const office = context.services.workspace.office(context.address);\n if (!parsed.provider || !parsed.model) {\n const current = resolveConversationSettings(office);\n await replySummary(context, \"Model\", [\n `Current: \\`${formatModelSpec(current.provider, current.model, current.thinkingLevel)}\\``,\n \"\",\n \"Usage: `/pi-model provider/model[:thinking]`\",\n USAGE_EXAMPLE,\n ]);\n return true;\n }\n\n const selection = this.selectModel(parsed.provider, parsed.model, parsed);\n if (\"lines\" in selection) {\n await replySummary(context, \"Model\", selection.lines);\n return true;\n }\n\n if (!context.services.runtime) {\n await replySummary(context, \"Model\", [\n \"Model command is not configured correctly on the server. Please try again later.\",\n ]);\n return true;\n }\n\n const result = applyConversationSettings(context.services.runtime, office, {\n provider: parsed.provider,\n model: selection.modelId,\n ...(selection.thinkingLevel ? { thinkingLevel: selection.thinkingLevel } : {}),\n });\n if (!result.ok) {\n await replySummary(context, \"Model\", [\n \"目前這個 conversation 有執行中的工作,請等它完成或先 `/stop` 後再切換模型。\",\n ]);\n return true;\n }\n\n await replySummary(context, \"Model\", [\n `Switched: \\`${formatModelSpec(parsed.provider, selection.modelId, selection.thinkingLevel)}\\``,\n \"下一則訊息會使用新模型。\",\n ]);\n return true;\n }\n\n /**\n * Resolve the spec against the registry. A `:suffix` is first tried as part\n * of the model id, then as a thinking level on the bare id — so a model\n * whose real name contains a colon still wins over the suffix reading.\n */\n private selectModel(provider: string, model: string, parsed: ParsedModelCommand): ModelSelection {\n const exactModelId = parsed.modelCandidate ?? model;\n if (this.modelRegistry.find(provider, exactModelId)) return { modelId: exactModelId };\n\n if (parsed.modelCandidate) {\n const suffix = parsed.thinkingLevelCandidate;\n if (suffix && !THINKING_LEVELS.has(suffix as ThinkingLevel)) {\n return {\n lines: [\n \"未知的 thinking level,請使用 `off`、`minimal`、`low`、`medium`、`high`、`xhigh` 或 `max`。\",\n USAGE_EXAMPLE,\n ],\n };\n }\n if (this.modelRegistry.find(provider, model)) {\n return {\n modelId: model,\n ...(parsed.thinkingLevel ? { thinkingLevel: parsed.thinkingLevel } : {}),\n };\n }\n }\n\n return {\n lines: [\n `找不到模型:\\`${formatModelSpec(provider, model, parsed.thinkingLevel)}\\``,\n \"請確認 provider/model 名稱,或先在 pi models.json 註冊自訂模型。\",\n ],\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/adapters/commands/model.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { ThinkingLevel as PiAiThinkingLevel } from \"@earendil-works/pi-ai\";\nimport { resolveConversationSettings } from \"../../settings/index.js\";\nimport { applyConversationSettings } from \"../../settings/apply.js\";\nimport { slashForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler, ModelRegistry, ParsedModelCommand } from \"./types.js\";\nimport { replySummary } from \"./utils.js\";\n\nconst PI_AI_THINKING_LEVELS = [\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n] satisfies PiAiThinkingLevel[];\nconst THINKING_LEVELS = new Set<ThinkingLevel>([\"off\", ...PI_AI_THINKING_LEVELS]);\n\nexport type { ParsedModelCommand } from \"./types.js\";\n\nconst MODEL_COMMANDS = slashForms(\"model\");\n\nexport function parseModelCommand(text: string): ParsedModelCommand | null {\n const matched = matchCommand(text, MODEL_COMMANDS);\n if (!matched) return null;\n\n if (matched.args.length === 0) {\n return {};\n }\n\n if (matched.args.length !== 1) {\n return { error: \"invalid_spec\" };\n }\n\n const spec = matched.args[0];\n if (spec === undefined) {\n return { error: \"invalid_spec\" };\n }\n const slash = spec.indexOf(\"/\");\n if (slash <= 0 || slash === spec.length - 1) {\n return { error: \"invalid_spec\" };\n }\n\n const modelSpec = spec.slice(slash + 1);\n const parsedModel = parseModelThinkingLevel(modelSpec);\n if (parsedModel.error) {\n return { error: parsedModel.error };\n }\n\n return {\n provider: spec.slice(0, slash),\n ...parsedModel,\n };\n}\n\nfunction parseModelThinkingLevel(modelSpec: string): {\n model?: string;\n modelCandidate?: string;\n thinkingLevelCandidate?: string;\n thinkingLevel?: ThinkingLevel;\n error?: \"invalid_spec\";\n} {\n const colon = modelSpec.lastIndexOf(\":\");\n if (colon === 0 || colon === modelSpec.length - 1) {\n return { error: \"invalid_spec\" };\n }\n if (colon < 0) {\n return { model: modelSpec };\n }\n\n const suffix = modelSpec.slice(colon + 1);\n return {\n model: modelSpec.slice(0, colon),\n modelCandidate: modelSpec,\n thinkingLevelCandidate: suffix,\n ...(THINKING_LEVELS.has(suffix as ThinkingLevel)\n ? { thinkingLevel: suffix as ThinkingLevel }\n : {}),\n };\n}\n\nfunction formatModelSpec(provider: string, model: string, thinkingLevel?: ThinkingLevel): string {\n return `${provider}/${model}${thinkingLevel ? `:${thinkingLevel}` : \"\"}`;\n}\n\nconst USAGE_EXAMPLE = \"Example: `/pi-model anthropic/claude-sonnet-4-6:off`\";\n\ntype ModelSelection = { modelId: string; thinkingLevel?: ThinkingLevel } | { lines: string[] };\n\nexport class ModelCommandHandler implements CommandHandler {\n constructor(private readonly modelRegistry: ModelRegistry) {}\n async tryHandle(context: CommandContext): Promise<boolean> {\n const parsed = parseModelCommand(context.commandText);\n if (!parsed) return false;\n\n if (parsed.error) {\n await replySummary(context, \"Model\", [\n \"無效的模型參數,請使用 `provider/model[:thinking]`。\",\n USAGE_EXAMPLE,\n ]);\n return true;\n }\n\n const office = context.services.workspace.office(context.address);\n if (!parsed.provider || !parsed.model) {\n const current = resolveConversationSettings(office);\n await replySummary(context, \"Model\", [\n `Current: \\`${formatModelSpec(current.provider, current.model, current.thinkingLevel)}\\``,\n \"\",\n \"Usage: `/pi-model provider/model[:thinking]`\",\n USAGE_EXAMPLE,\n ]);\n return true;\n }\n\n const selection = this.selectModel(parsed.provider, parsed.model, parsed);\n if (\"lines\" in selection) {\n await replySummary(context, \"Model\", selection.lines);\n return true;\n }\n\n if (!context.services.runtime) {\n await replySummary(context, \"Model\", [\n \"Model command is not configured correctly on the server. Please try again later.\",\n ]);\n return true;\n }\n\n const result = applyConversationSettings(context.services.runtime, office, {\n provider: parsed.provider,\n model: selection.modelId,\n ...(selection.thinkingLevel ? { thinkingLevel: selection.thinkingLevel } : {}),\n });\n if (!result.ok) {\n await replySummary(context, \"Model\", [\n \"目前這個 conversation 有執行中的工作,請等它完成或先 `/stop` 後再切換模型。\",\n ]);\n return true;\n }\n\n await replySummary(context, \"Model\", [\n `Switched: \\`${formatModelSpec(parsed.provider, selection.modelId, selection.thinkingLevel)}\\``,\n \"下一則訊息會使用新模型。\",\n ]);\n return true;\n }\n\n private selectModel(provider: string, model: string, parsed: ParsedModelCommand): ModelSelection {\n const exactModelId = parsed.modelCandidate ?? model;\n if (this.modelRegistry.find(provider, exactModelId)) return { modelId: exactModelId };\n\n if (parsed.modelCandidate) {\n const suffix = parsed.thinkingLevelCandidate;\n if (suffix && !THINKING_LEVELS.has(suffix as ThinkingLevel)) {\n return {\n lines: [\n \"未知的 thinking level,請使用 `off`、`minimal`、`low`、`medium`、`high`、`xhigh` 或 `max`。\",\n USAGE_EXAMPLE,\n ],\n };\n }\n if (this.modelRegistry.find(provider, model)) {\n return {\n modelId: model,\n ...(parsed.thinkingLevel ? { thinkingLevel: parsed.thinkingLevel } : {}),\n };\n }\n }\n\n return {\n lines: [\n `找不到模型:\\`${formatModelSpec(provider, model, parsed.thinkingLevel)}\\``,\n \"請確認 provider/model 名稱,或先在 pi models.json 註冊自訂模型。\",\n ],\n };\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/new.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjE,qBAAa,iBAAkB,YAAW,cAAc;IAChD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/new.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjE,qBAAa,iBAAkB,YAAW,cAAc;IAChD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAiCzD;CACF"}
|
|
@@ -20,8 +20,6 @@ export class NewCommandHandler {
|
|
|
20
20
|
return true;
|
|
21
21
|
}
|
|
22
22
|
await context.services.runtime.handleNewCommand({
|
|
23
|
-
sessionKey: context.sessionKey,
|
|
24
|
-
conversationId: context.conversationId,
|
|
25
23
|
bot: context.bot,
|
|
26
24
|
message: createConversationMessage({
|
|
27
25
|
platform: context.address.platform,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new.js","sourceRoot":"","sources":["../../../src/adapters/commands/new.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvC,MAAM,OAAO,iBAAiB;IAC5B,KAAK,CAAC,SAAS,CAAC,OAAuB;QACrC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC;YAAE,OAAO,KAAK,CAAC;QAEnE,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;YACjC,MAAM,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE;gBACzC,4CAA4C;aAC7C,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE;gBACzC,wDAAwD;gBACxD,yBAAyB;aAC1B,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC9C,
|
|
1
|
+
{"version":3,"file":"new.js","sourceRoot":"","sources":["../../../src/adapters/commands/new.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvC,MAAM,OAAO,iBAAiB;IAC5B,KAAK,CAAC,SAAS,CAAC,OAAuB;QACrC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC;YAAE,OAAO,KAAK,CAAC;QAEnE,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;YACjC,MAAM,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE;gBACzC,4CAA4C;aAC7C,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE;gBACzC,wDAAwD;gBACxD,yBAAyB;aAC1B,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC9C,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,OAAO,EAAE,yBAAyB,CAAC;gBACjC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ;gBAClC,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc;gBAC9C,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,EAAE,EAAE,UAAU,OAAO,CAAC,UAAU,EAAE;gBAClC,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,gBAAgB,EAAE,QAAQ;gBAC1B,MAAM,EAAE,OAAO,CAAC,cAAc;gBAC9B,QAAQ,EAAE,OAAO,CAAC,gBAAgB;gBAClC,IAAI,EAAE,OAAO,CAAC,WAAW;aAC1B,CAAC;SACH,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;CACF","sourcesContent":["import { createConversationMessage } from \"../index.js\";\nimport { slashForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler } from \"./types.js\";\nimport { replySummary } from \"./utils.js\";\n\nconst NEW_COMMANDS = slashForms(\"new\");\n\nexport class NewCommandHandler implements CommandHandler {\n async tryHandle(context: CommandContext): Promise<boolean> {\n if (!matchCommand(context.commandText, NEW_COMMANDS)) return false;\n\n if (!context.privateConversation) {\n await replySummary(context, \"New Session\", [\n \"為了避免誤清除共享上下文,`/new` 目前只能在與機器人的私訊 / DM 中使用。\",\n ]);\n return true;\n }\n\n if (!context.services.runtime) {\n await replySummary(context, \"New Session\", [\n \"New command is not configured correctly on the server.\",\n \"Please try again later.\",\n ]);\n return true;\n }\n\n await context.services.runtime.handleNewCommand({\n bot: context.bot,\n message: createConversationMessage({\n platform: context.address.platform,\n conversationId: context.address.conversationId,\n address: context.address,\n id: `memory:${context.sessionKey}`,\n sessionKey: context.sessionKey,\n conversationKind: \"direct\",\n userId: context.platformUserId,\n userName: context.platformUserName,\n text: context.commandText,\n }),\n });\n return true;\n }\n}\n"]}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { CommandContext, CommandHandler, ModelRegistry } from "./types.js";
|
|
2
2
|
export declare function defaultCommandHandlers(modelRegistry?: ModelRegistry): CommandHandler[];
|
|
3
|
-
/** Run handlers in order, returning true as soon as one accepts the command. */
|
|
4
3
|
export declare function dispatchCommand(handlers: readonly CommandHandler[], context: CommandContext): Promise<boolean>;
|
|
5
4
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/registry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/registry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYhF,wBAAgB,sBAAsB,CACpC,aAAa,GAAE,aAAoC,GAClD,cAAc,EAAE,CAUlB;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,SAAS,cAAc,EAAE,EACnC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CAKlB"}
|
|
@@ -7,13 +7,6 @@ import { ModelCommandHandler } from "./model.js";
|
|
|
7
7
|
import { NewCommandHandler } from "./new.js";
|
|
8
8
|
import { SandboxCommandHandler } from "./sandbox.js";
|
|
9
9
|
import { SessionViewCommandHandler } from "./session-view.js";
|
|
10
|
-
/**
|
|
11
|
-
* Handler factory per manifest command name. The manifest is the inventory
|
|
12
|
-
* authority; this map only binds each entry to its implementation, and
|
|
13
|
-
* `defaultCommandHandlers` verifies the binding is complete so a manifest
|
|
14
|
-
* entry without a handler fails at construction instead of dispatching into
|
|
15
|
-
* silence. Magic-word entries (routed by conversation intake) are exempt.
|
|
16
|
-
*/
|
|
17
10
|
const HANDLER_FACTORIES = {
|
|
18
11
|
admin: () => new AdminCommandHandler(),
|
|
19
12
|
autoreply: () => new AutoReplyCommandHandler(),
|
|
@@ -32,7 +25,6 @@ export function defaultCommandHandlers(modelRegistry = MikanModels.create()) {
|
|
|
32
25
|
return factory(modelRegistry);
|
|
33
26
|
});
|
|
34
27
|
}
|
|
35
|
-
/** Run handlers in order, returning true as soon as one accepts the command. */
|
|
36
28
|
export async function dispatchCommand(handlers, context) {
|
|
37
29
|
for (const handler of handlers) {
|
|
38
30
|
if (await handler.tryHandle(context))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/adapters/commands/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAG9D
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/adapters/commands/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,MAAM,iBAAiB,GAAqE;IAC1F,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,EAAE;IACtC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,uBAAuB,EAAE;IAC9C,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,EAAE;IACtC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,yBAAyB,EAAE;IAC9C,KAAK,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC,IAAI,mBAAmB,CAAC,aAAa,CAAC;IAChE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,qBAAqB,EAAE;IAC1C,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,iBAAiB,EAAE;CACnC,CAAC;AAEF,MAAM,UAAU,sBAAsB,CACpC,aAAa,GAAkB,WAAW,CAAC,MAAM,EAAE;IAEnD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxE,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,2BAA2B,KAAK,CAAC,IAAI,kDAAkD,CACxF,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAmC,EACnC,OAAuB;IAEvB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { MikanModels } from \"../../harness/index.js\";\nimport { AdminCommandHandler } from \"./admin.js\";\nimport { AutoReplyCommandHandler } from \"./auto-reply.js\";\nimport { LoginCommandHandler } from \"./login.js\";\nimport { COMMAND_MANIFEST } from \"./manifest.js\";\nimport { ModelCommandHandler } from \"./model.js\";\nimport { NewCommandHandler } from \"./new.js\";\nimport { SandboxCommandHandler } from \"./sandbox.js\";\nimport { SessionViewCommandHandler } from \"./session-view.js\";\nimport type { CommandContext, CommandHandler, ModelRegistry } from \"./types.js\";\n\nconst HANDLER_FACTORIES: Record<string, (modelRegistry: ModelRegistry) => CommandHandler> = {\n admin: () => new AdminCommandHandler(),\n autoreply: () => new AutoReplyCommandHandler(),\n login: () => new LoginCommandHandler(),\n session: () => new SessionViewCommandHandler(),\n model: (modelRegistry) => new ModelCommandHandler(modelRegistry),\n sandbox: () => new SandboxCommandHandler(),\n new: () => new NewCommandHandler(),\n};\n\nexport function defaultCommandHandlers(\n modelRegistry: ModelRegistry = MikanModels.create(),\n): CommandHandler[] {\n return COMMAND_MANIFEST.filter((entry) => !entry.magicWord).map((entry) => {\n const factory = HANDLER_FACTORIES[entry.name];\n if (!factory) {\n throw new Error(\n `Command manifest entry \"${entry.name}\" has no handler factory in commands/registry.ts`,\n );\n }\n return factory(modelRegistry);\n });\n}\n\nexport async function dispatchCommand(\n handlers: readonly CommandHandler[],\n context: CommandContext,\n): Promise<boolean> {\n for (const handler of handlers) {\n if (await handler.tryHandle(context)) return true;\n }\n return false;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-view.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/session-view.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"session-view.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/session-view.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjE,qBAAa,yBAA0B,YAAW,cAAc;IACxD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CA8CzD;CACF"}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { resolveExistingSessionFile } from "../web/session-view/portal.js";
|
|
2
2
|
import { commandForms, matchCommand } from "./manifest.js";
|
|
3
3
|
import { portalNotConfiguredLines, replySummaryPrivately } from "./utils.js";
|
|
4
|
-
// `session` is the only bare command (manifest `bare: true`), so its grammar
|
|
5
|
-
// includes the slash-less spelling alongside the derived slash forms.
|
|
6
4
|
const SESSION_VIEW_COMMANDS = commandForms("session");
|
|
7
5
|
export class SessionViewCommandHandler {
|
|
8
6
|
async tryHandle(context) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-view.js","sourceRoot":"","sources":["../../../src/adapters/commands/session-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE3D,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE7E,
|
|
1
|
+
{"version":3,"file":"session-view.js","sourceRoot":"","sources":["../../../src/adapters/commands/session-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE3D,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE7E,MAAM,qBAAqB,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AAEtD,MAAM,OAAO,yBAAyB;IACpC,KAAK,CAAC,SAAS,CAAC,OAAuB;QACrC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,qBAAqB,CAAC;YAAE,OAAO,KAAK,CAAC;QAE5E,IAAI,CAAC,OAAO,CAAC,mBAAmB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YAC7D,MAAM,qBAAqB,CAAC,OAAO,EAAE,SAAS,EAAE;gBAC9C,4CAA4C;aAC7C,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;YACpC,MAAM,qBAAqB,CAAC,OAAO,EAAE,SAAS,EAAE,wBAAwB,CAAC,gBAAgB,CAAC,CAAC,CAAC;YAC5F,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,WAAW,GAAG,0BAA0B,CAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,EACtD,OAAO,CAAC,UAAU,CACnB,CAAC;QACF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,qBAAqB,CAAC,OAAO,EAAE,SAAS,EAAE;gBAC9C,oBAAoB;gBACpB,2BAA2B;aAC5B,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG;aAC7B,gBAAgB,EAAE;aAClB,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;QAC5D,MAAM,gBAAgB,GAAG,YAAY,EAAE,QAAQ,IAAI,YAAY,EAAE,WAAW,CAAC;QAE7E,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,MAAM,CAAC;YAC1D,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,WAAW;YACX,gBAAgB;SACjB,CAAC,CAAC;QAEH,MAAM,qBAAqB,CAAC,OAAO,EAAE,SAAS,EAAE;YAC9C,GAAG,OAAO,CAAC,QAAQ,CAAC,aAAa,kBAAkB,KAAK,CAAC,KAAK,EAAE;YAChE,mBAAmB;SACpB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;CACF","sourcesContent":["import { resolveExistingSessionFile } from \"../web/session-view/portal.js\";\nimport { commandForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler } from \"./types.js\";\nimport { portalNotConfiguredLines, replySummaryPrivately } from \"./utils.js\";\n\nconst SESSION_VIEW_COMMANDS = commandForms(\"session\");\n\nexport class SessionViewCommandHandler implements CommandHandler {\n async tryHandle(context: CommandContext): Promise<boolean> {\n if (!matchCommand(context.commandText, SESSION_VIEW_COMMANDS)) return false;\n\n if (!context.privateConversation && !context.bot.postPrivate) {\n await replySummaryPrivately(context, \"Session\", [\n \"為了保護對話內容,`/session` 目前只能在與機器人的私訊 / DM 中使用。\",\n ]);\n return true;\n }\n\n if (!context.services.portalBaseUrl) {\n await replySummaryPrivately(context, \"Session\", portalNotConfiguredLines(\"Session viewer\"));\n return true;\n }\n\n const sessionFile = resolveExistingSessionFile(\n context.services.workspace.office(context.address).dir,\n context.sessionKey,\n );\n if (!sessionFile) {\n await replySummaryPrivately(context, \"Session\", [\n \"目前還沒有可查看的 session。\",\n \"先和機器人對話一次,建立 session 後再試。\",\n ]);\n return true;\n }\n\n const platformUser = context.bot\n .getMessagingInfo()\n .users.find((user) => user.id === context.platformUserId);\n const platformUserName = platformUser?.userName || platformUser?.displayName;\n\n const token = context.services.sessionViewTokenStore.create({\n platform: context.platform,\n platformUserId: context.platformUserId,\n conversationId: context.conversationId,\n sessionKey: context.sessionKey,\n sessionFile,\n platformUserName,\n });\n\n await replySummaryPrivately(context, \"Session\", [\n `${context.services.portalBaseUrl}/session?token=${token.token}`,\n \"Expires: 24 hours\",\n ]);\n return true;\n }\n}\n"]}
|
|
@@ -12,48 +12,24 @@ interface CommandArgSpec {
|
|
|
12
12
|
description: string;
|
|
13
13
|
required: boolean;
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Data for the Slack adapter's generic slash route (how the synthesized
|
|
17
|
-
* command event is built). All flags default to false.
|
|
18
|
-
*/
|
|
19
15
|
export interface SlackSlashRoute {
|
|
20
|
-
/** Append the slash payload's free text to the synthesized command text. */
|
|
21
16
|
includeText?: boolean;
|
|
22
|
-
/** Scope the event to the invoking thread (thread-scoped session key). */
|
|
23
17
|
thread?: boolean;
|
|
24
|
-
/** Outside DMs, mark the event `private_command` so replies stay between the bot and the user. */
|
|
25
18
|
privateCommand?: boolean;
|
|
26
19
|
}
|
|
27
20
|
export interface CommandManifestEntry {
|
|
28
|
-
/** Canonical name without slash, e.g. "login"; `/login` and `/pi-login` are derived. */
|
|
29
21
|
name: string;
|
|
30
22
|
description: string;
|
|
31
|
-
/** Extra accepted spellings beyond `name` (e.g. "autoreply"); each also gets a `pi-` form. */
|
|
32
23
|
aliases?: readonly string[];
|
|
33
|
-
/** Optional single free-text argument for platforms that register typed args. */
|
|
34
24
|
arg?: CommandArgSpec;
|
|
35
|
-
/** Accepted without a leading slash. Per CONTEXT.md, only `session`. */
|
|
36
25
|
bare?: boolean;
|
|
37
|
-
/**
|
|
38
|
-
* Routed by conversation intake as a magic word, never by a command
|
|
39
|
-
* handler. Such an entry exists for platform registration/UI only.
|
|
40
|
-
*/
|
|
41
26
|
magicWord?: boolean;
|
|
42
|
-
/** Slack slash-command name, e.g. "/pi-login". Absent = not a Slack slash command. */
|
|
43
27
|
slackCommand?: string;
|
|
44
|
-
/** Slack routing data; absent for `new`, whose Slack dispatch is bespoke. */
|
|
45
28
|
slackRoute?: SlackSlashRoute;
|
|
46
|
-
/** Registered as a Discord application command. */
|
|
47
29
|
discord?: boolean;
|
|
48
|
-
/** Listed in Telegram's command menu; `description` overrides the shared one. */
|
|
49
30
|
telegramMenu?: {
|
|
50
31
|
description?: string;
|
|
51
32
|
};
|
|
52
|
-
/**
|
|
53
|
-
* Registered as a native grammY command handler, bypassing conversation
|
|
54
|
-
* intake (no trigger/busy policy). Other menu commands reach the runtime
|
|
55
|
-
* through the catch-all message path.
|
|
56
|
-
*/
|
|
57
33
|
telegramCommand?: boolean;
|
|
58
34
|
}
|
|
59
35
|
export interface LinkTokenStoreLike {
|
|
@@ -110,24 +86,19 @@ export interface CommandContext {
|
|
|
110
86
|
export interface CommandHandler {
|
|
111
87
|
tryHandle(context: CommandContext): Promise<boolean>;
|
|
112
88
|
}
|
|
113
|
-
/** Minimal model lookup contract used by the model command. */
|
|
114
89
|
export interface ModelRegistry {
|
|
115
90
|
find(provider: string, modelId: string): Model<Api> | undefined;
|
|
116
91
|
}
|
|
117
92
|
export interface ParsedModelCommand {
|
|
118
93
|
provider?: string;
|
|
119
|
-
/** Model id without a thinking-level suffix, when one was supplied. */
|
|
120
94
|
model?: string;
|
|
121
|
-
/** Complete model id candidate, including a possible colon suffix. */
|
|
122
95
|
modelCandidate?: string;
|
|
123
|
-
/** Suffix kept for handler-side validation after exact model lookup. */
|
|
124
96
|
thinkingLevelCandidate?: string;
|
|
125
97
|
thinkingLevel?: ThinkingLevel;
|
|
126
98
|
error?: "invalid_spec";
|
|
127
99
|
}
|
|
128
100
|
export interface ParsedSandboxCommand {
|
|
129
101
|
action?: "boost" | "visibility";
|
|
130
|
-
/** Raw visibility argument; the handler validates it so typos get a usage reply. */
|
|
131
102
|
visibility?: string;
|
|
132
103
|
}
|
|
133
104
|
export type ParsedLoginCommand = {
|