botmux 3.11.0 → 3.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.runtime-build-id +1 -1
- package/dist/adapters/backend/riff-backend.d.ts +18 -0
- package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
- package/dist/adapters/backend/riff-backend.js +154 -2
- package/dist/adapters/backend/riff-backend.js.map +1 -1
- package/dist/adapters/cli/coco.js +3 -3
- package/dist/adapters/cli/coco.js.map +1 -1
- package/dist/adapters/cli/codex.js +2 -2
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/kimi.d.ts.map +1 -1
- package/dist/adapters/cli/kimi.js +22 -8
- package/dist/adapters/cli/kimi.js.map +1 -1
- package/dist/adapters/cli/pi.d.ts.map +1 -1
- package/dist/adapters/cli/pi.js +3 -1
- package/dist/adapters/cli/pi.js.map +1 -1
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +4 -1
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/dashboard-command.d.ts +23 -0
- package/dist/cli/dashboard-command.d.ts.map +1 -0
- package/dist/cli/dashboard-command.js +61 -0
- package/dist/cli/dashboard-command.js.map +1 -0
- package/dist/cli/dashboard-endpoint.d.ts +3 -3
- package/dist/cli/dashboard-endpoint.d.ts.map +1 -1
- package/dist/cli/dashboard-endpoint.js +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +101 -49
- package/dist/cli.js.map +1 -1
- package/dist/codex-rpc-engine.d.ts +33 -3
- package/dist/codex-rpc-engine.d.ts.map +1 -1
- package/dist/codex-rpc-engine.js +182 -20
- package/dist/codex-rpc-engine.js.map +1 -1
- package/dist/codex-rpc-lifecycle.d.ts +42 -7
- package/dist/codex-rpc-lifecycle.d.ts.map +1 -1
- package/dist/codex-rpc-lifecycle.js +73 -7
- package/dist/codex-rpc-lifecycle.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/core/command-handler.d.ts +3 -2
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +19 -4
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +16 -11
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +17 -1
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +13 -1
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/dispatch.d.ts +9 -10
- package/dist/core/dispatch.d.ts.map +1 -1
- package/dist/core/dispatch.js +17 -10
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/maintenance.d.ts.map +1 -1
- package/dist/core/maintenance.js +5 -0
- package/dist/core/maintenance.js.map +1 -1
- package/dist/core/role-resolver.d.ts +5 -2
- package/dist/core/role-resolver.d.ts.map +1 -1
- package/dist/core/role-resolver.js +55 -23
- package/dist/core/role-resolver.js.map +1 -1
- package/dist/core/session-manager.d.ts +2 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +20 -18
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/skills/cli-admin-command.d.ts.map +1 -1
- package/dist/core/skills/cli-admin-command.js +142 -3
- package/dist/core/skills/cli-admin-command.js.map +1 -1
- package/dist/core/skills/frontmatter.d.ts.map +1 -1
- package/dist/core/skills/frontmatter.js +44 -7
- package/dist/core/skills/frontmatter.js.map +1 -1
- package/dist/core/skills/im-command.d.ts +6 -0
- package/dist/core/skills/im-command.d.ts.map +1 -1
- package/dist/core/skills/im-command.js +34 -7
- package/dist/core/skills/im-command.js.map +1 -1
- package/dist/core/skills/install-command.d.ts +4 -0
- package/dist/core/skills/install-command.d.ts.map +1 -0
- package/dist/core/skills/install-command.js +89 -0
- package/dist/core/skills/install-command.js.map +1 -0
- package/dist/core/skills/package.d.ts.map +1 -1
- package/dist/core/skills/package.js +10 -3
- package/dist/core/skills/package.js.map +1 -1
- package/dist/core/skills/policy.d.ts +5 -1
- package/dist/core/skills/policy.d.ts.map +1 -1
- package/dist/core/skills/policy.js +66 -3
- package/dist/core/skills/policy.js.map +1 -1
- package/dist/core/skills/references.d.ts +9 -1
- package/dist/core/skills/references.d.ts.map +1 -1
- package/dist/core/skills/references.js +35 -2
- package/dist/core/skills/references.js.map +1 -1
- package/dist/core/skills/registry-paths.d.ts +1 -0
- package/dist/core/skills/registry-paths.d.ts.map +1 -1
- package/dist/core/skills/registry-paths.js +3 -0
- package/dist/core/skills/registry-paths.js.map +1 -1
- package/dist/core/skills/session-resolver.d.ts +2 -1
- package/dist/core/skills/session-resolver.d.ts.map +1 -1
- package/dist/core/skills/session-resolver.js +1 -0
- package/dist/core/skills/session-resolver.js.map +1 -1
- package/dist/core/skills/session-runtime.d.ts.map +1 -1
- package/dist/core/skills/session-runtime.js +2 -0
- package/dist/core/skills/session-runtime.js.map +1 -1
- package/dist/core/skills/sources.d.ts +23 -0
- package/dist/core/skills/sources.d.ts.map +1 -1
- package/dist/core/skills/sources.js +128 -12
- package/dist/core/skills/sources.js.map +1 -1
- package/dist/core/skills/types.d.ts +22 -1
- package/dist/core/skills/types.d.ts.map +1 -1
- package/dist/core/terminal-write-auth.d.ts +4 -4
- package/dist/core/terminal-write-auth.d.ts.map +1 -1
- package/dist/core/terminal-write-auth.js +18 -6
- package/dist/core/terminal-write-auth.js.map +1 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +52 -1
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +1 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +101 -12
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/auth.d.ts +21 -11
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +39 -25
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/bot-onboarding.js +2 -114
- package/dist/dashboard/bot-onboarding.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +0 -1
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +0 -1
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/connector-api.d.ts.map +1 -1
- package/dist/dashboard/connector-api.js +66 -6
- package/dist/dashboard/connector-api.js.map +1 -1
- package/dist/dashboard/dashboard-summary-endpoint.d.ts +39 -0
- package/dist/dashboard/dashboard-summary-endpoint.d.ts.map +1 -0
- package/dist/dashboard/dashboard-summary-endpoint.js +50 -0
- package/dist/dashboard/dashboard-summary-endpoint.js.map +1 -0
- package/dist/dashboard/dashboard-summary.d.ts +62 -0
- package/dist/dashboard/dashboard-summary.d.ts.map +1 -0
- package/dist/dashboard/dashboard-summary.js +106 -0
- package/dist/dashboard/dashboard-summary.js.map +1 -0
- package/dist/dashboard/public-redact.d.ts.map +1 -1
- package/dist/dashboard/public-redact.js +3 -0
- package/dist/dashboard/public-redact.js.map +1 -1
- package/dist/dashboard/skill-install-request.js +10 -11
- package/dist/dashboard/skill-install-request.js.map +1 -1
- package/dist/dashboard/skill-pack-response.d.ts +15 -0
- package/dist/dashboard/skill-pack-response.d.ts.map +1 -0
- package/dist/dashboard/skill-pack-response.js +32 -0
- package/dist/dashboard/skill-pack-response.js.map +1 -0
- package/dist/dashboard/web/connectors-page.d.ts +69 -0
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
- package/dist/dashboard/web/connectors-page.js +47 -7
- package/dist/dashboard/web/connectors-page.js.map +1 -1
- package/dist/dashboard/web/feed-group-picker.d.ts +13 -0
- package/dist/dashboard/web/feed-group-picker.d.ts.map +1 -0
- package/dist/dashboard/web/feed-group-picker.js +45 -0
- package/dist/dashboard/web/feed-group-picker.js.map +1 -0
- package/dist/dashboard/web/groups-page.d.ts.map +1 -1
- package/dist/dashboard/web/groups-page.js +2 -5
- package/dist/dashboard/web/groups-page.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +309 -40
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/preferences.d.ts +4 -2
- package/dist/dashboard/web/preferences.d.ts.map +1 -1
- package/dist/dashboard/web/preferences.js +14 -6
- package/dist/dashboard/web/preferences.js.map +1 -1
- package/dist/dashboard/web/roles-page.d.ts.map +1 -1
- package/dist/dashboard/web/roles-page.js +36 -4
- package/dist/dashboard/web/roles-page.js.map +1 -1
- package/dist/dashboard/web/roles.d.ts +3 -1
- package/dist/dashboard/web/roles.d.ts.map +1 -1
- package/dist/dashboard/web/roles.js +10 -2
- package/dist/dashboard/web/roles.js.map +1 -1
- package/dist/dashboard/web/schedules-page.d.ts.map +1 -1
- package/dist/dashboard/web/schedules-page.js +8 -2
- package/dist/dashboard/web/schedules-page.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +101 -5
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts +3 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +13 -6
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/skills/bot-assignments-tab.d.ts +27 -0
- package/dist/dashboard/web/skills/bot-assignments-tab.d.ts.map +1 -0
- package/dist/dashboard/web/skills/bot-assignments-tab.js +257 -0
- package/dist/dashboard/web/skills/bot-assignments-tab.js.map +1 -0
- package/dist/dashboard/web/skills/delivery-settings-tab.d.ts +25 -0
- package/dist/dashboard/web/skills/delivery-settings-tab.d.ts.map +1 -0
- package/dist/dashboard/web/skills/delivery-settings-tab.js +20 -0
- package/dist/dashboard/web/skills/delivery-settings-tab.js.map +1 -0
- package/dist/dashboard/web/skills/shared.d.ts +86 -0
- package/dist/dashboard/web/skills/shared.d.ts.map +1 -0
- package/dist/dashboard/web/skills/shared.js +178 -0
- package/dist/dashboard/web/skills/shared.js.map +1 -0
- package/dist/dashboard/web/skills/skill-library-tab.d.ts +75 -0
- package/dist/dashboard/web/skills/skill-library-tab.d.ts.map +1 -0
- package/dist/dashboard/web/skills/skill-library-tab.js +108 -0
- package/dist/dashboard/web/skills/skill-library-tab.js.map +1 -0
- package/dist/dashboard/web/skills/skill-packs-tab.d.ts +21 -0
- package/dist/dashboard/web/skills/skill-packs-tab.d.ts.map +1 -0
- package/dist/dashboard/web/skills/skill-packs-tab.js +185 -0
- package/dist/dashboard/web/skills/skill-packs-tab.js.map +1 -0
- package/dist/dashboard/web/skills/types.d.ts +95 -0
- package/dist/dashboard/web/skills/types.d.ts.map +1 -0
- package/dist/dashboard/web/skills/types.js +2 -0
- package/dist/dashboard/web/skills/types.js.map +1 -0
- package/dist/dashboard/web/skills/use-skills-data.d.ts +31 -0
- package/dist/dashboard/web/skills/use-skills-data.d.ts.map +1 -0
- package/dist/dashboard/web/skills/use-skills-data.js +86 -0
- package/dist/dashboard/web/skills/use-skills-data.js.map +1 -0
- package/dist/dashboard/web/skills-page.d.ts +34 -31
- package/dist/dashboard/web/skills-page.d.ts.map +1 -1
- package/dist/dashboard/web/skills-page.js +321 -176
- package/dist/dashboard/web/skills-page.js.map +1 -1
- package/dist/dashboard/webhook-routes.d.ts +18 -0
- package/dist/dashboard/webhook-routes.d.ts.map +1 -1
- package/dist/dashboard/webhook-routes.js +35 -1
- package/dist/dashboard/webhook-routes.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/{bot-defaults-page-GED4FEMS.js → bot-defaults-page-HL655CNR.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-HK7NIBJG.js → chunk-5PAYQ3KT.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-KRHWZEXU.js → chunk-5ZL7NLR5.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-6ALR252E.js +1 -0
- package/dist/dashboard-web/chunks/{chunk-VBXJOJFH.js → chunk-BFUTTYVK.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-ELL53D62.js +55 -0
- package/dist/dashboard-web/chunks/connectors-page-3QQACF23.js +1 -0
- package/dist/dashboard-web/chunks/groups-page-SDZMJ7UV.js +8 -0
- package/dist/dashboard-web/chunks/{insights-page-54UBPPOC.js → insights-page-ZZ3JEJ6L.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-PORHVKRH.js → monitor-room-ROJ5GZ4N.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-XGA7AXNL.js → monitoring-page-IATV7KJF.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-AO3AFG45.js → office-page-TYO5OIIT.js} +1 -1
- package/dist/dashboard-web/chunks/{overview-page-F5BUTYR6.js → overview-page-VJUULZF2.js} +1 -1
- package/dist/dashboard-web/chunks/roles-page-7RJJKZGK.js +1 -0
- package/dist/dashboard-web/chunks/schedules-page-JTEJ5IXW.js +1 -0
- package/dist/dashboard-web/chunks/sessions-page-KD7HDT3U.js +8 -0
- package/dist/dashboard-web/chunks/{settings-page-OJAZLZQT.js → settings-page-7CTTFBRS.js} +1 -1
- package/dist/dashboard-web/chunks/skills-page-57NZECJ3.js +4 -0
- package/dist/dashboard-web/chunks/{team-federation-page-ZJVAP7HW.js → team-federation-page-6YYIMJG3.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-GYWTRGO2.js → v3-page-ZGKBSBK3.js} +1 -1
- package/dist/dashboard-web/chunks/{whiteboards-page-MSDAG6P7.js → whiteboards-page-AACJF6DB.js} +1 -1
- package/dist/dashboard-web/style.css +1952 -377
- package/dist/dashboard.js +316 -47
- package/dist/dashboard.js.map +1 -1
- package/dist/desktop/main/ipc.js +1 -1
- package/dist/desktop/main/runtime-service.js +2 -2
- package/dist/desktop/main/runtime-service.js.map +1 -1
- package/dist/desktop/shared/types.d.ts +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +5 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +5 -1
- package/dist/i18n/zh.js.map +1 -1
- package/dist/index-daemon.js +6 -1
- package/dist/index-daemon.js.map +1 -1
- package/dist/services/adopt-input-sequence.d.ts +52 -0
- package/dist/services/adopt-input-sequence.d.ts.map +1 -0
- package/dist/services/adopt-input-sequence.js +50 -0
- package/dist/services/adopt-input-sequence.js.map +1 -0
- package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
- package/dist/services/bridge-fallback-gate.js +34 -11
- package/dist/services/bridge-fallback-gate.js.map +1 -1
- package/dist/services/codex-bridge-queue.d.ts +103 -7
- package/dist/services/codex-bridge-queue.d.ts.map +1 -1
- package/dist/services/codex-bridge-queue.js +291 -17
- package/dist/services/codex-bridge-queue.js.map +1 -1
- package/dist/services/codex-transcript.d.ts +4 -3
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/connector-store.d.ts +14 -1
- package/dist/services/connector-store.d.ts.map +1 -1
- package/dist/services/connector-store.js.map +1 -1
- package/dist/services/connector-topic-template.d.ts +7 -0
- package/dist/services/connector-topic-template.d.ts.map +1 -0
- package/dist/services/connector-topic-template.js +210 -0
- package/dist/services/connector-topic-template.js.map +1 -0
- package/dist/services/project-scanner.d.ts +33 -0
- package/dist/services/project-scanner.d.ts.map +1 -1
- package/dist/services/project-scanner.js +40 -1
- package/dist/services/project-scanner.js.map +1 -1
- package/dist/services/skill-pack-store.d.ts +50 -0
- package/dist/services/skill-pack-store.d.ts.map +1 -0
- package/dist/services/skill-pack-store.js +270 -0
- package/dist/services/skill-pack-store.js.map +1 -0
- package/dist/services/skill-registry-store.d.ts +8 -0
- package/dist/services/skill-registry-store.d.ts.map +1 -1
- package/dist/services/skill-registry-store.js +100 -68
- package/dist/services/skill-registry-store.js.map +1 -1
- package/dist/services/structured-bridge-clis.d.ts +8 -1
- package/dist/services/structured-bridge-clis.d.ts.map +1 -1
- package/dist/services/structured-bridge-clis.js +13 -0
- package/dist/services/structured-bridge-clis.js.map +1 -1
- package/dist/services/submit-confirmation.d.ts +50 -0
- package/dist/services/submit-confirmation.d.ts.map +1 -1
- package/dist/services/submit-confirmation.js +82 -0
- package/dist/services/submit-confirmation.js.map +1 -1
- package/dist/services/todo-state.d.ts +74 -0
- package/dist/services/todo-state.d.ts.map +1 -0
- package/dist/services/todo-state.js +351 -0
- package/dist/services/todo-state.js.map +1 -0
- package/dist/setup/agent-preset.d.ts.map +1 -1
- package/dist/setup/agent-preset.js +2 -0
- package/dist/setup/agent-preset.js.map +1 -1
- package/dist/setup/owner-identity.d.ts +47 -0
- package/dist/setup/owner-identity.d.ts.map +1 -0
- package/dist/setup/owner-identity.js +196 -0
- package/dist/setup/owner-identity.js.map +1 -0
- package/dist/setup/register-app.d.ts +4 -3
- package/dist/setup/register-app.d.ts.map +1 -1
- package/dist/setup/register-app.js.map +1 -1
- package/dist/setup/setup-args.d.ts +1 -1
- package/dist/setup/setup-args.d.ts.map +1 -1
- package/dist/setup/setup-args.js +7 -3
- package/dist/setup/setup-args.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/async-serial-queue.d.ts +9 -0
- package/dist/utils/async-serial-queue.d.ts.map +1 -0
- package/dist/utils/async-serial-queue.js +13 -0
- package/dist/utils/async-serial-queue.js.map +1 -0
- package/dist/utils/child-env.d.ts +25 -0
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +47 -0
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/runtime-screen-status.d.ts +52 -0
- package/dist/utils/runtime-screen-status.d.ts.map +1 -0
- package/dist/utils/runtime-screen-status.js +60 -0
- package/dist/utils/runtime-screen-status.js.map +1 -0
- package/dist/worker.js +1697 -468
- package/dist/worker.js.map +1 -1
- package/dist/workflows/definition.d.ts +44 -44
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/chunk-6J5LS5AU.js +0 -51
- package/dist/dashboard-web/chunks/connectors-page-EELM66G3.js +0 -1
- package/dist/dashboard-web/chunks/groups-page-WKUV6E42.js +0 -8
- package/dist/dashboard-web/chunks/roles-page-M5GIASJU.js +0 -1
- package/dist/dashboard-web/chunks/schedules-page-O232WQRR.js +0 -1
- package/dist/dashboard-web/chunks/sessions-page-YFRPSTIL.js +0 -6
- package/dist/dashboard-web/chunks/skills-page-EFZQPWV4.js +0 -4
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
// 任务态(openTodos):从 Claude / Codex 的 transcript 里提取「当前 TODO 完成度」。
|
|
2
|
+
//
|
|
3
|
+
// 会话状态重设计 P2:运行态(进程忙/闲)与任务态(活干完没)正交。运行态已由
|
|
4
|
+
// worker 的 readyPattern/busyPattern 探测;任务态这里从 CLI 自己维护的待办列表读:
|
|
5
|
+
// - Claude Code:`TodoWrite` 工具调用,input.todos[] 每项 {content,status,activeForm}
|
|
6
|
+
// - Codex:`update_plan` 函数调用,arguments.plan[] 每项 {step,status}
|
|
7
|
+
// 两者都是「整表快照、后写覆盖前写」,所以取 transcript 里最后一次调用即当前状态。
|
|
8
|
+
// status 口径统一为 pending / in_progress / completed(与 insight/classify 同源)。
|
|
9
|
+
//
|
|
10
|
+
// 读不到(其它 CLI、无 transcript、从未写过 todo)返回 null —— 由调用方标「未知/不
|
|
11
|
+
// 支持」,绝不硬猜完成度。纯解析函数 parseOpenTodos 无 fs 依赖,便于单测。
|
|
12
|
+
import { statSync } from 'node:fs';
|
|
13
|
+
import { scanJsonlFromOffset } from './jsonl-cursor.js';
|
|
14
|
+
import { resolveSessionTranscriptPath } from './transcript-resolver.js';
|
|
15
|
+
function normalizeTodoStatus(value) {
|
|
16
|
+
return value === 'pending' || value === 'in_progress' || value === 'completed' ? value : null;
|
|
17
|
+
}
|
|
18
|
+
/** 清洗单条文字:转字符串、trim、限长(防超长步骤撑爆浮层)。 */
|
|
19
|
+
function cleanTodoText(v) {
|
|
20
|
+
const s = typeof v === 'string' ? v : v == null ? '' : String(v);
|
|
21
|
+
const t = s.replace(/\s+/g, ' ').trim();
|
|
22
|
+
return t.length > 120 ? `${t.slice(0, 119)}…` : t;
|
|
23
|
+
}
|
|
24
|
+
/** 把一组 {status,text} 折叠成完成度 + 清单。无任何有效状态返回 null(= 没有有效
|
|
25
|
+
* 待办快照,别当成「0 项已交付」,那会让刚清空 todo 的会话和从没建 todo 的会话表现
|
|
26
|
+
* 一致)。 */
|
|
27
|
+
function summarize(entries) {
|
|
28
|
+
const valid = entries.filter((e) => e.status !== null);
|
|
29
|
+
if (valid.length === 0)
|
|
30
|
+
return null;
|
|
31
|
+
let done = 0;
|
|
32
|
+
let hasInProgress = false;
|
|
33
|
+
const items = [];
|
|
34
|
+
for (const e of valid) {
|
|
35
|
+
if (e.status === 'completed')
|
|
36
|
+
done++;
|
|
37
|
+
else if (e.status === 'in_progress')
|
|
38
|
+
hasInProgress = true;
|
|
39
|
+
items.push({ status: e.status, text: cleanTodoText(e.text) });
|
|
40
|
+
}
|
|
41
|
+
return { total: valid.length, done, remaining: valid.length - done, hasInProgress, items };
|
|
42
|
+
}
|
|
43
|
+
/** 从单条已解析的 transcript 记录里取 todo 快照;不是 todo 记录返回 null。
|
|
44
|
+
* Claude:assistant 消息里 name==='TodoWrite' 的 tool_use,input.todos[]。
|
|
45
|
+
* Codex:response_item 里 payload.type==='function_call' 且 name==='update_plan',
|
|
46
|
+
* arguments.plan[](arguments 可能是 JSON 字符串)。 */
|
|
47
|
+
export function todoSnapshotFromEntry(entry, kind) {
|
|
48
|
+
if (!entry || typeof entry !== 'object')
|
|
49
|
+
return null;
|
|
50
|
+
if (kind === 'claude') {
|
|
51
|
+
const content = entry?.message?.content;
|
|
52
|
+
if (!Array.isArray(content))
|
|
53
|
+
return null;
|
|
54
|
+
let latest = null;
|
|
55
|
+
for (const block of content) {
|
|
56
|
+
if (block?.type !== 'tool_use')
|
|
57
|
+
continue;
|
|
58
|
+
const name = typeof block.name === 'string' ? block.name.trim().toLowerCase() : '';
|
|
59
|
+
if (name !== 'todowrite')
|
|
60
|
+
continue;
|
|
61
|
+
const todos = block?.input?.todos;
|
|
62
|
+
if (!Array.isArray(todos))
|
|
63
|
+
continue;
|
|
64
|
+
// 同一条消息里若出现多次(罕见),后者覆盖前者。
|
|
65
|
+
latest = summarize(todos.map((t) => ({ status: normalizeTodoStatus(t?.status), text: t?.content ?? t?.activeForm }))) ?? latest;
|
|
66
|
+
}
|
|
67
|
+
return latest;
|
|
68
|
+
}
|
|
69
|
+
// codex
|
|
70
|
+
const payload = entry?.payload ?? {};
|
|
71
|
+
if (entry?.type !== 'response_item' || payload?.type !== 'function_call')
|
|
72
|
+
return null;
|
|
73
|
+
const name = typeof payload.name === 'string' ? payload.name.trim().toLowerCase() : '';
|
|
74
|
+
if (name !== 'update_plan')
|
|
75
|
+
return null;
|
|
76
|
+
const args = parseArgs(payload.arguments ?? payload.input);
|
|
77
|
+
const plan = args?.plan;
|
|
78
|
+
if (!Array.isArray(plan))
|
|
79
|
+
return null;
|
|
80
|
+
return summarize(plan.map((p) => ({ status: normalizeTodoStatus(p?.status), text: p?.step })));
|
|
81
|
+
}
|
|
82
|
+
function parseArgs(raw) {
|
|
83
|
+
if (raw && typeof raw === 'object' && !Array.isArray(raw))
|
|
84
|
+
return raw;
|
|
85
|
+
if (typeof raw !== 'string')
|
|
86
|
+
return null;
|
|
87
|
+
try {
|
|
88
|
+
const parsed = JSON.parse(raw);
|
|
89
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export function newTodoFoldState(kind) {
|
|
96
|
+
return {
|
|
97
|
+
kind,
|
|
98
|
+
latestSnapshot: null,
|
|
99
|
+
claudeTasks: kind === 'claude'
|
|
100
|
+
? { tasks: new Map(), pendingCreate: new Map(), sawAnyTask: false }
|
|
101
|
+
: undefined,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** 把单条已解析记录折叠进状态(就地修改)。 */
|
|
105
|
+
export function foldTodoEntry(state, entry) {
|
|
106
|
+
const snap = todoSnapshotFromEntry(entry, state.kind);
|
|
107
|
+
if (snap)
|
|
108
|
+
state.latestSnapshot = snap; // 后写覆盖:整表快照语义
|
|
109
|
+
if (state.kind === 'claude' && state.claudeTasks)
|
|
110
|
+
foldClaudeTaskEntry(state.claudeTasks, entry);
|
|
111
|
+
}
|
|
112
|
+
/** 折叠出末态:TodoWrite/update_plan 快照优先,claude 缺失时回退 Task* 重放。 */
|
|
113
|
+
export function finalizeTodoFold(state) {
|
|
114
|
+
if (state.latestSnapshot)
|
|
115
|
+
return state.latestSnapshot;
|
|
116
|
+
if (state.kind === 'claude' && state.claudeTasks)
|
|
117
|
+
return finalizeClaudeTaskState(state.claudeTasks);
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
/** 从整份 transcript(已按行解析的记录数组)取当前任务态。
|
|
121
|
+
* - codex:update_plan 是整表快照,取最后一次即可。
|
|
122
|
+
* - claude:两种方言二选一——
|
|
123
|
+
* · 开源版 Claude Code 用 TodoWrite(整表快照,取最后一次);
|
|
124
|
+
* · 本 botmux 环境用 Task* 工具(TaskCreate/TaskUpdate 增量),需按记录重放
|
|
125
|
+
* 累积成末态。TodoWrite 优先(真快照);没有 TodoWrite 时回退到 Task* 重放。 */
|
|
126
|
+
export function parseOpenTodos(entries, kind) {
|
|
127
|
+
const state = newTodoFoldState(kind);
|
|
128
|
+
for (const entry of entries)
|
|
129
|
+
foldTodoEntry(state, entry);
|
|
130
|
+
return finalizeTodoFold(state);
|
|
131
|
+
}
|
|
132
|
+
// ── Claude Code 内建 Task* 工具(本 botmux 环境)的增量重放 ────────────────────
|
|
133
|
+
// 与开源版 TodoWrite(整表快照)不同,本环境的任务清单是增量事件:
|
|
134
|
+
// · TaskCreate:input={subject,description,activeForm},无 taskId——分配的 id 在
|
|
135
|
+
// 紧邻的 tool_result 文本里「Task #N created successfully: ...」。新任务初始
|
|
136
|
+
// 状态 pending。
|
|
137
|
+
// · TaskUpdate:input={taskId, status?, ...},status ∈ pending/in_progress/
|
|
138
|
+
// completed/deleted。deleted 从清单移除(工具语义:永久删除)。
|
|
139
|
+
// 按 tool_use.id 关联 TaskCreate 与其结果,重放出 Map<taskId,status> 末态,再折叠
|
|
140
|
+
// 成 OpenTodos。整个清单没有任何任务时返回 null(= 未用过任务清单,别当已交付)。
|
|
141
|
+
// 拆成 foldClaudeTaskEntry(逐行)+ finalizeClaudeTaskState(末态),供增量游标读跨
|
|
142
|
+
// 多次读盘持续累积同一份 tasks/pendingCreate。
|
|
143
|
+
function foldClaudeTaskEntry(ts, entry) {
|
|
144
|
+
const content = entry?.message?.content;
|
|
145
|
+
if (!Array.isArray(content))
|
|
146
|
+
return;
|
|
147
|
+
for (const block of content) {
|
|
148
|
+
if (block?.type === 'tool_use') {
|
|
149
|
+
const name = typeof block.name === 'string' ? block.name.trim().toLowerCase() : '';
|
|
150
|
+
if (name === 'taskcreate') {
|
|
151
|
+
if (typeof block.id === 'string') {
|
|
152
|
+
const subject = block?.input?.subject ?? block?.input?.activeForm ?? '';
|
|
153
|
+
ts.pendingCreate.set(block.id, typeof subject === 'string' ? subject : String(subject ?? ''));
|
|
154
|
+
}
|
|
155
|
+
ts.sawAnyTask = true;
|
|
156
|
+
}
|
|
157
|
+
else if (name === 'taskupdate') {
|
|
158
|
+
const id = taskIdString(block?.input?.taskId);
|
|
159
|
+
const st = block?.input?.status;
|
|
160
|
+
if (id) {
|
|
161
|
+
ts.sawAnyTask = true;
|
|
162
|
+
if (st === 'deleted')
|
|
163
|
+
ts.tasks.delete(id);
|
|
164
|
+
else {
|
|
165
|
+
const norm = normalizeTodoStatus(st);
|
|
166
|
+
// status 缺省的 TaskUpdate(只改 subject/owner 等)不动状态,但要确保
|
|
167
|
+
// 该任务已在册(默认 pending),否则纯元数据更新会丢任务。
|
|
168
|
+
const cur = ts.tasks.get(id) ?? { status: 'pending', text: '' };
|
|
169
|
+
const newSubject = typeof block?.input?.subject === 'string' ? block.input.subject : cur.text;
|
|
170
|
+
ts.tasks.set(id, { status: norm ?? cur.status, text: newSubject });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else if (block?.type === 'tool_result') {
|
|
176
|
+
const forId = typeof block.tool_use_id === 'string' ? block.tool_use_id : '';
|
|
177
|
+
if (forId && ts.pendingCreate.has(forId)) {
|
|
178
|
+
const subject = ts.pendingCreate.get(forId) ?? '';
|
|
179
|
+
ts.pendingCreate.delete(forId);
|
|
180
|
+
const assigned = extractCreatedTaskId(block.content);
|
|
181
|
+
if (assigned && !ts.tasks.has(assigned))
|
|
182
|
+
ts.tasks.set(assigned, { status: 'pending', text: subject });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function finalizeClaudeTaskState(ts) {
|
|
188
|
+
if (!ts.sawAnyTask || ts.tasks.size === 0)
|
|
189
|
+
return null;
|
|
190
|
+
return summarize([...ts.tasks.values()]);
|
|
191
|
+
}
|
|
192
|
+
function taskIdString(v) {
|
|
193
|
+
if (typeof v === 'string' && v.trim())
|
|
194
|
+
return v.trim();
|
|
195
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
196
|
+
return String(v);
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
/** 从 TaskCreate 的 tool_result 文本里抓分配的任务号:「Task #N created successfully」。
|
|
200
|
+
* content 可能是纯字符串,或 [{type:'text',text}] 数组。 */
|
|
201
|
+
function extractCreatedTaskId(content) {
|
|
202
|
+
let text = '';
|
|
203
|
+
if (typeof content === 'string')
|
|
204
|
+
text = content;
|
|
205
|
+
else if (Array.isArray(content)) {
|
|
206
|
+
text = content.map((b) => (typeof b?.text === 'string' ? b.text : '')).join('\n');
|
|
207
|
+
}
|
|
208
|
+
const m = text.match(/Task #(\d+) created/i);
|
|
209
|
+
return m ? m[1] : null;
|
|
210
|
+
}
|
|
211
|
+
// ── 增量游标读取(对齐 cost-calculator 的 fd+offset 增量扫描思路)──────────────
|
|
212
|
+
// dashboard 每次 /api/sessions、以及每个 working→idle 状态边沿都会对会话调一次。
|
|
213
|
+
// 关键:触发读盘的那个状态边沿,恰是 transcript 刚追加完本轮输出(含 todo 快照)
|
|
214
|
+
// 的时刻——size 变了,任何「(mtime,size) 不变才命中」的缓存在此刻必 miss。若那时
|
|
215
|
+
// 走全量 readFileSync+JSON.parse,31MiB 文件实测 ~330ms 全程阻塞 daemon 主线程。
|
|
216
|
+
// 故改为「记住上次读到的字节前沿 offset + 折叠状态,只 fold 新追加的行」:
|
|
217
|
+
// · 文件按 (dev,ino) 认身份,size 未变→直接返缓存;size 增长(append-only)→
|
|
218
|
+
// 从 offset 增量扫到末尾,fold 进沿用的 TodoFoldState(快照 last-write-wins、
|
|
219
|
+
// Task* 增量重放都天然支持继续累积);
|
|
220
|
+
// · ino 变/被截断/首次→冷读全量;冷读遇 >32MiB 直接 fail-closed 返 null,
|
|
221
|
+
// 绝不返旧 cache 冒充当前(否则越界前的旧 pending 会被永久当成当前状态)。
|
|
222
|
+
const MAX_TODO_TRANSCRIPT_BYTES = 32 * 1024 * 1024;
|
|
223
|
+
const TODO_CACHE_MAX_ENTRIES = 512;
|
|
224
|
+
const todoFileCache = new Map();
|
|
225
|
+
export function __resetTodoStateCacheForTest() {
|
|
226
|
+
todoFileCache.clear();
|
|
227
|
+
}
|
|
228
|
+
function todoKindForCli(cliId) {
|
|
229
|
+
switch (cliId) {
|
|
230
|
+
case 'claude-code':
|
|
231
|
+
case 'seed':
|
|
232
|
+
case 'relay':
|
|
233
|
+
case 'aiden':
|
|
234
|
+
return 'claude';
|
|
235
|
+
case 'codex':
|
|
236
|
+
case 'traex':
|
|
237
|
+
return 'codex';
|
|
238
|
+
default:
|
|
239
|
+
return null; // 其它 CLI 暂不支持任务态提取
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/** 读某会话当前 openTodos。定位 transcript → 增量游标读 → 折叠出最后一次 todo 快照。
|
|
243
|
+
* 任何一步失败(不支持的 CLI、无 transcript、冷读越界、解析失败)都返回 null。
|
|
244
|
+
* fresh=true 绕过 resolver 对「尚未落盘的懒创建 transcript」的 30s miss 负缓存——
|
|
245
|
+
* spawn 时 rollout 常还没落盘,首个状态边沿读若不置 fresh 会在 30s 内持续吃 miss,
|
|
246
|
+
* 徽标要等 30s 后某次边沿才出现(镜像 cost-calculator 的 fresh 语义)。 */
|
|
247
|
+
export function readSessionOpenTodos(q) {
|
|
248
|
+
const kind = todoKindForCli(q.cliId);
|
|
249
|
+
if (!kind)
|
|
250
|
+
return null;
|
|
251
|
+
const resolved = resolveSessionTranscriptPath({
|
|
252
|
+
cliId: q.cliId,
|
|
253
|
+
sessionId: q.sessionId,
|
|
254
|
+
cliSessionId: q.cliSessionId,
|
|
255
|
+
cwd: q.cwd,
|
|
256
|
+
larkAppId: q.larkAppId,
|
|
257
|
+
fresh: q.fresh,
|
|
258
|
+
});
|
|
259
|
+
// resolver 的 kind 与我们的 todo dialect 需一致。traex rollout 与 codex 逐字节同构
|
|
260
|
+
// (response_item + function_call),按 codex 方言解析。
|
|
261
|
+
if (!resolved)
|
|
262
|
+
return null;
|
|
263
|
+
const resolvedKind = resolved.kind === 'claude' ? 'claude'
|
|
264
|
+
: resolved.kind === 'codex' || resolved.kind === 'traex' ? 'codex'
|
|
265
|
+
: null;
|
|
266
|
+
if (resolvedKind !== kind)
|
|
267
|
+
return null;
|
|
268
|
+
const path = resolved.path;
|
|
269
|
+
let st = null;
|
|
270
|
+
try {
|
|
271
|
+
st = statSync(path);
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
st = null;
|
|
275
|
+
}
|
|
276
|
+
if (!st || !st.isFile()) {
|
|
277
|
+
todoFileCache.delete(path);
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
const cached = todoFileCache.get(path);
|
|
281
|
+
const sameFile = !!cached && cached.dev === st.dev && cached.ino === st.ino;
|
|
282
|
+
// >32MiB 一律 fail-closed 返 null,绝不返旧 cache——增量路径也一样。冷读越界会全量
|
|
283
|
+
// 阻塞主线程;增量路径遇「同 inode 被整体覆盖成超大文件」若按 append 续读,既读错
|
|
284
|
+
// 前缀又可能扫超大 delta。故在选路前先按总大小一刀切,语义一致、最省心。
|
|
285
|
+
if (st.size > MAX_TODO_TRANSCRIPT_BYTES) {
|
|
286
|
+
todoFileCache.delete(path);
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
// append-only 增量续读:size 未变→无新行,直接返缓存;size 增长→只扫 [offset,size)。
|
|
290
|
+
if (sameFile && st.size >= cached.offset) {
|
|
291
|
+
if (st.size === cached.offset)
|
|
292
|
+
return cached.todos;
|
|
293
|
+
return readIncremental(path, st, cached);
|
|
294
|
+
}
|
|
295
|
+
// 冷读(首次 / 文件被替换或截断)。
|
|
296
|
+
return readCold(path, st, kind);
|
|
297
|
+
}
|
|
298
|
+
/** 从 offset 增量扫到末尾,把新完整行 fold 进沿用的折叠状态。读失败则丢缓存回退冷读。 */
|
|
299
|
+
function readIncremental(path, st, cached) {
|
|
300
|
+
let scanError = false;
|
|
301
|
+
const cursor = scanJsonlFromOffset(path, cached.offset, {
|
|
302
|
+
endOffset: st.size,
|
|
303
|
+
onLine: (line) => foldJsonLine(cached.fold, line),
|
|
304
|
+
onError: () => { scanError = true; },
|
|
305
|
+
});
|
|
306
|
+
if (!cursor || scanError) {
|
|
307
|
+
todoFileCache.delete(path);
|
|
308
|
+
return readCold(path, st, cached.fold.kind);
|
|
309
|
+
}
|
|
310
|
+
cached.dev = st.dev;
|
|
311
|
+
cached.ino = st.ino;
|
|
312
|
+
cached.offset = cursor.newOffset;
|
|
313
|
+
cached.todos = finalizeTodoFold(cached.fold);
|
|
314
|
+
return cached.todos;
|
|
315
|
+
}
|
|
316
|
+
/** 冷读:从头折叠整份文件,建立新的缓存条目(含折叠状态 + 字节前沿)。 */
|
|
317
|
+
function readCold(path, st, kind) {
|
|
318
|
+
const fold = newTodoFoldState(kind);
|
|
319
|
+
let scanError = false;
|
|
320
|
+
const cursor = scanJsonlFromOffset(path, 0, {
|
|
321
|
+
endOffset: st.size,
|
|
322
|
+
onLine: (line) => foldJsonLine(fold, line),
|
|
323
|
+
onError: () => { scanError = true; },
|
|
324
|
+
});
|
|
325
|
+
if (!cursor || scanError) {
|
|
326
|
+
todoFileCache.delete(path);
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
const todos = finalizeTodoFold(fold);
|
|
330
|
+
if (todoFileCache.size >= TODO_CACHE_MAX_ENTRIES && !todoFileCache.has(path)) {
|
|
331
|
+
const oldest = todoFileCache.keys().next().value;
|
|
332
|
+
if (oldest !== undefined)
|
|
333
|
+
todoFileCache.delete(oldest);
|
|
334
|
+
}
|
|
335
|
+
todoFileCache.set(path, { dev: st.dev, ino: st.ino, offset: cursor.newOffset, fold, todos });
|
|
336
|
+
return todos;
|
|
337
|
+
}
|
|
338
|
+
/** 解析并折叠单行 JSONL;半写/损坏行跳过(任务态是 advisory)。 */
|
|
339
|
+
function foldJsonLine(fold, line) {
|
|
340
|
+
if (!line.trim())
|
|
341
|
+
return;
|
|
342
|
+
try {
|
|
343
|
+
const parsed = JSON.parse(line);
|
|
344
|
+
if (parsed && typeof parsed === 'object')
|
|
345
|
+
foldTodoEntry(fold, parsed);
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
// 跳过半写/损坏行。
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=todo-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todo-state.js","sourceRoot":"","sources":["../../src/services/todo-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-preset.d.ts","sourceRoot":"","sources":["../../src/setup/agent-preset.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gFAAgF;IAChF,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"agent-preset.d.ts","sourceRoot":"","sources":["../../src/setup/agent-preset.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gFAAgF;IAChF,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,QAiBb,CAAC;AAEb;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAchE;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMtD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGpF;AAYD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAgBnD"}
|
|
@@ -36,6 +36,8 @@ export const PRESET_GUIDE = [
|
|
|
36
36
|
'如果你是一个 AI agent,请按下面的步骤帮用户用这份预设配置他自己的 botmux 机器人:',
|
|
37
37
|
'1. 让用户用【他自己】的飞书/Lark 应用凭证跑 `botmux setup`;larkAppId/larkAppSecret/allowedUsers 必须由他本人填写,',
|
|
38
38
|
' 绝不要从本文件或任何他人处复制粘贴密钥。',
|
|
39
|
+
' 新建 Bot 时也不要复制当前 session 中 daemon 注入的 `BOTMUX_OWNER_OPEN_ID` 或来源 Bot 的任何 `ou_`:`open_id` 只属于签发它的应用。',
|
|
40
|
+
' 请改用完整邮箱、手机号或 `on_`,让 setup 在目标应用下解析并校验 owner。',
|
|
39
41
|
'2. setup 时把 CLI 适配器设为本预设的 `cliId`,模型设为 `model`(如有)。',
|
|
40
42
|
'3. 把本预设的 `teamRole` 写为该 bot 的 team 级角色内容,把 `capability` 设为它的能力标签。',
|
|
41
43
|
'4. 完成后让用户 `botmux restart` 使配置生效。',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-preset.js","sourceRoot":"","sources":["../../src/setup/agent-preset.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agent-preset.js","sourceRoot":"","sources":["../../src/setup/agent-preset.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared owner-identity boundary for every Bot onboarding path.
|
|
3
|
+
*
|
|
4
|
+
* An `ou_` open_id is meaningful only to the app that issued/observed it; even
|
|
5
|
+
* `BOTMUX_OWNER_OPEN_ID` belongs to the source `BOTMUX_LARK_APP_ID`. Never copy
|
|
6
|
+
* it into another/new app. Normalize an authenticated source owner before app
|
|
7
|
+
* creation, then validate owner entries through the target app before
|
|
8
|
+
* persisting them. Reject unknown `ou_` values before app creation; target-app
|
|
9
|
+
* network/scope failures remain inconclusive unless the identity is definitively
|
|
10
|
+
* unusable.
|
|
11
|
+
*
|
|
12
|
+
* Keep new Dashboard, interactive, scripted, and Agent-driven onboarding paths
|
|
13
|
+
* on these helpers. A format-only sister path can otherwise reintroduce the
|
|
14
|
+
* same lockout while every existing onboarding regression test remains green.
|
|
15
|
+
*/
|
|
16
|
+
import { type Brand } from '../im/lark/lark-hosts.js';
|
|
17
|
+
/**
|
|
18
|
+
* Validate an open_id with the app that is supposed to own it. Prefer the
|
|
19
|
+
* cross-app-stable union_id; never preserve an open_id the app cannot prove.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveScannerAllowedUser(appId: string, appSecret: string, openId: string, brand?: Brand): Promise<string | undefined>;
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the verified Open Platform session email into a stable owner entry.
|
|
24
|
+
* An inconclusive request keeps the verified email for runtime retry; a clean
|
|
25
|
+
* empty response proves the account is not addressable in this tenant.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveSessionEmailAllowedUser(appId: string, appSecret: string, email: string, brand?: Brand): Promise<string | undefined>;
|
|
28
|
+
/**
|
|
29
|
+
* Best-effort detection of owner entries that are definitively unusable by the
|
|
30
|
+
* target app. Transient/scope errors remain inconclusive and are not rejected.
|
|
31
|
+
*/
|
|
32
|
+
export declare function detectUnusableOwnerEntries(appId: string, appSecret: string, brand: Brand, entries: string[]): Promise<string[]>;
|
|
33
|
+
export interface ManagedOwnerContext {
|
|
34
|
+
sourceAppId?: string;
|
|
35
|
+
sourceOwnerOpenId?: string;
|
|
36
|
+
creatingApp: boolean;
|
|
37
|
+
targetAppId?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A managed Agent sees the daemon-frozen session owner as an app-scoped
|
|
41
|
+
* BOTMUX_OWNER_OPEN_ID. This is not the current-turn sender. When the Agent
|
|
42
|
+
* creates/configures another bot, copying that ou_ verbatim locks the owner
|
|
43
|
+
* out. Convert only that exact injected identity through the source app; leave
|
|
44
|
+
* explicitly supplied co-owners untouched.
|
|
45
|
+
*/
|
|
46
|
+
export declare function normalizeManagedOwnerEntries(rawAllowedUsers: string | undefined, context: ManagedOwnerContext, resolveStableOwner: (sourceAppId: string, sourceOwnerOpenId: string) => Promise<string | undefined>): Promise<string | undefined>;
|
|
47
|
+
//# sourceMappingURL=owner-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-identity.d.ts","sourceRoot":"","sources":["../../src/setup/owner-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,KAAK,KAAK,EAAa,MAAM,0BAA0B,CAAC;AAoBjE;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,KAAgB,GACtB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAW7B;AAED;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,KAAgB,GACtB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe7B;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAgEnB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,4BAA4B,CAChD,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,OAAO,EAAE,mBAAmB,EAC5B,kBAAkB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAClG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA8C7B"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared owner-identity boundary for every Bot onboarding path.
|
|
3
|
+
*
|
|
4
|
+
* An `ou_` open_id is meaningful only to the app that issued/observed it; even
|
|
5
|
+
* `BOTMUX_OWNER_OPEN_ID` belongs to the source `BOTMUX_LARK_APP_ID`. Never copy
|
|
6
|
+
* it into another/new app. Normalize an authenticated source owner before app
|
|
7
|
+
* creation, then validate owner entries through the target app before
|
|
8
|
+
* persisting them. Reject unknown `ou_` values before app creation; target-app
|
|
9
|
+
* network/scope failures remain inconclusive unless the identity is definitively
|
|
10
|
+
* unusable.
|
|
11
|
+
*
|
|
12
|
+
* Keep new Dashboard, interactive, scripted, and Agent-driven onboarding paths
|
|
13
|
+
* on these helpers. A format-only sister path can otherwise reintroduce the
|
|
14
|
+
* same lockout while every existing onboarding regression test remains green.
|
|
15
|
+
*/
|
|
16
|
+
import { sdkDomain } from '../im/lark/lark-hosts.js';
|
|
17
|
+
import { isMobileEntry, normalizeMobileEntry } from './bot-config-editor.js';
|
|
18
|
+
/** open_id belongs to another app. Retrying with the same app can never fix it. */
|
|
19
|
+
const CROSS_APP_OPEN_ID_CODE = 99992361;
|
|
20
|
+
const DEFINITIVE_USER_ID_CODES = new Set([CROSS_APP_OPEN_ID_CODE, 41012, 40001]);
|
|
21
|
+
function larkErrorCode(err) {
|
|
22
|
+
const value = err;
|
|
23
|
+
for (const candidate of [value?.response?.data?.code, value?.data?.code, value?.code]) {
|
|
24
|
+
if (typeof candidate === 'number')
|
|
25
|
+
return candidate;
|
|
26
|
+
if (typeof candidate === 'string' && /^\d+$/.test(candidate))
|
|
27
|
+
return Number(candidate);
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Validate an open_id with the app that is supposed to own it. Prefer the
|
|
33
|
+
* cross-app-stable union_id; never preserve an open_id the app cannot prove.
|
|
34
|
+
*/
|
|
35
|
+
export async function resolveScannerAllowedUser(appId, appSecret, openId, brand = 'feishu') {
|
|
36
|
+
try {
|
|
37
|
+
const { Client } = await import('@larksuiteoapi/node-sdk');
|
|
38
|
+
const client = new Client({ appId, appSecret, domain: sdkDomain(brand), disableTokenCache: false });
|
|
39
|
+
const res = await client.contact.v3.user.get({
|
|
40
|
+
path: { user_id: openId },
|
|
41
|
+
params: { user_id_type: 'open_id' },
|
|
42
|
+
});
|
|
43
|
+
if (res.code === 0 && res.data?.user)
|
|
44
|
+
return res.data.user.union_id ?? openId;
|
|
45
|
+
}
|
|
46
|
+
catch { /* do not trust an open_id that this app could not validate */ }
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the verified Open Platform session email into a stable owner entry.
|
|
51
|
+
* An inconclusive request keeps the verified email for runtime retry; a clean
|
|
52
|
+
* empty response proves the account is not addressable in this tenant.
|
|
53
|
+
*/
|
|
54
|
+
export async function resolveSessionEmailAllowedUser(appId, appSecret, email, brand = 'feishu') {
|
|
55
|
+
try {
|
|
56
|
+
const { Client } = await import('@larksuiteoapi/node-sdk');
|
|
57
|
+
const client = new Client({ appId, appSecret, domain: sdkDomain(brand), disableTokenCache: false });
|
|
58
|
+
const res = await client.contact.v3.user.batchGetId({
|
|
59
|
+
params: { user_id_type: 'union_id' },
|
|
60
|
+
data: { emails: [email], include_resigned: false },
|
|
61
|
+
});
|
|
62
|
+
if (res?.code === 0) {
|
|
63
|
+
const list = res.data?.user_list ?? [];
|
|
64
|
+
const hit = list.find(user => typeof user?.user_id === 'string' && user.user_id);
|
|
65
|
+
return hit ? hit.user_id : undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch { /* unable to disprove the verified session email */ }
|
|
69
|
+
return email;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Best-effort detection of owner entries that are definitively unusable by the
|
|
73
|
+
* target app. Transient/scope errors remain inconclusive and are not rejected.
|
|
74
|
+
*/
|
|
75
|
+
export async function detectUnusableOwnerEntries(appId, appSecret, brand, entries) {
|
|
76
|
+
if (!appSecret)
|
|
77
|
+
return [];
|
|
78
|
+
let client;
|
|
79
|
+
try {
|
|
80
|
+
const { Client } = await import('@larksuiteoapi/node-sdk');
|
|
81
|
+
client = new Client({ appId, appSecret, domain: sdkDomain(brand), disableTokenCache: false });
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
const unusable = [];
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
try {
|
|
89
|
+
if (entry.startsWith('ou_') || entry.startsWith('on_')) {
|
|
90
|
+
// ou_ and on_ share ONE definitive-miss test so the two id shapes can
|
|
91
|
+
// never drift apart. A prior ou_-only `code === 99992361` check let a
|
|
92
|
+
// target-app-invalid open_id (41012 / 40001) or a code:0-without-user
|
|
93
|
+
// response slip through and be written as the sole owner — the same
|
|
94
|
+
// lockout this module exists to prevent.
|
|
95
|
+
const res = await client.contact.v3.user.get({
|
|
96
|
+
path: { user_id: entry },
|
|
97
|
+
params: { user_id_type: entry.startsWith('ou_') ? 'open_id' : 'union_id' },
|
|
98
|
+
});
|
|
99
|
+
// A clean response without a target-app open_id is a definitive miss
|
|
100
|
+
// (cross-app open_id, or a union_id this app cannot resolve).
|
|
101
|
+
// Permission/scope failures remain inconclusive so onboarding can
|
|
102
|
+
// proceed while newly granted Contact scopes propagate.
|
|
103
|
+
if ((res?.code === 0 && !res?.data?.user?.open_id)
|
|
104
|
+
|| DEFINITIVE_USER_ID_CODES.has(Number(res?.code))) {
|
|
105
|
+
unusable.push(entry);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (isMobileEntry(entry)) {
|
|
109
|
+
const res = await client.contact.v3.user.batchGetId({
|
|
110
|
+
params: { user_id_type: 'open_id' },
|
|
111
|
+
data: { mobiles: [normalizeMobileEntry(entry)], include_resigned: false },
|
|
112
|
+
});
|
|
113
|
+
if (res?.code === 0) {
|
|
114
|
+
const list = res.data?.user_list ?? [];
|
|
115
|
+
if (!list.some(user => user?.user_id))
|
|
116
|
+
unusable.push(entry);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const res = await client.contact.v3.user.batchGetId({
|
|
121
|
+
params: { user_id_type: 'open_id' },
|
|
122
|
+
data: { emails: [entry], include_resigned: false },
|
|
123
|
+
});
|
|
124
|
+
if (res?.code === 0) {
|
|
125
|
+
const list = res.data?.user_list ?? [];
|
|
126
|
+
if (!list.some(user => user?.user_id))
|
|
127
|
+
unusable.push(entry);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
// The SDK often throws Axios errors for the same cross-app response that
|
|
133
|
+
// mocks expose as a normal payload. Preserve the definitive verdict in
|
|
134
|
+
// both transport shapes; every other throw remains inconclusive. ou_ and
|
|
135
|
+
// on_ use the SAME definitive-code set here too — an ou_-only 99992361
|
|
136
|
+
// check would drop 41012 / 40001 that arrive as a throw.
|
|
137
|
+
const code = larkErrorCode(err);
|
|
138
|
+
if ((entry.startsWith('ou_') || entry.startsWith('on_'))
|
|
139
|
+
&& code !== undefined && DEFINITIVE_USER_ID_CODES.has(code)) {
|
|
140
|
+
unusable.push(entry);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return unusable;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* A managed Agent sees the daemon-frozen session owner as an app-scoped
|
|
148
|
+
* BOTMUX_OWNER_OPEN_ID. This is not the current-turn sender. When the Agent
|
|
149
|
+
* creates/configures another bot, copying that ou_ verbatim locks the owner
|
|
150
|
+
* out. Convert only that exact injected identity through the source app; leave
|
|
151
|
+
* explicitly supplied co-owners untouched.
|
|
152
|
+
*/
|
|
153
|
+
export async function normalizeManagedOwnerEntries(rawAllowedUsers, context, resolveStableOwner) {
|
|
154
|
+
if (!rawAllowedUsers)
|
|
155
|
+
return rawAllowedUsers;
|
|
156
|
+
const entries = rawAllowedUsers.split(',').map(entry => entry.trim()).filter(Boolean);
|
|
157
|
+
const openIds = entries.filter(entry => entry.startsWith('ou_'));
|
|
158
|
+
if (context.creatingApp && openIds.length === 0)
|
|
159
|
+
return rawAllowedUsers;
|
|
160
|
+
if (!context.creatingApp
|
|
161
|
+
&& context.targetAppId
|
|
162
|
+
&& context.targetAppId === context.sourceAppId)
|
|
163
|
+
return rawAllowedUsers;
|
|
164
|
+
const sourceOwner = context.sourceOwnerOpenId;
|
|
165
|
+
const canResolveSourceOwner = !!context.sourceAppId
|
|
166
|
+
&& !!sourceOwner
|
|
167
|
+
&& entries.includes(sourceOwner);
|
|
168
|
+
// No open_id can belong to an app that does not exist yet. Reject unknown
|
|
169
|
+
// ou_ entries before the irreversible create-app side effect; only the exact
|
|
170
|
+
// daemon-authenticated session owner may be converted through its source app.
|
|
171
|
+
const unconvertible = context.creatingApp
|
|
172
|
+
? openIds.filter(entry => !canResolveSourceOwner || entry !== sourceOwner)
|
|
173
|
+
: [];
|
|
174
|
+
if (unconvertible.length > 0) {
|
|
175
|
+
throw new Error('--allowed-users 在创建新 Bot 时不能使用 app-scoped open_id:' +
|
|
176
|
+
`${unconvertible.join(', ')};请改用完整邮箱、手机号或 on_ union_id。`);
|
|
177
|
+
}
|
|
178
|
+
if (!canResolveSourceOwner)
|
|
179
|
+
return rawAllowedUsers;
|
|
180
|
+
const stable = await resolveStableOwner(context.sourceAppId, sourceOwner);
|
|
181
|
+
if (!stable?.startsWith('on_')) {
|
|
182
|
+
throw new Error('--allowed-users 不能把当前 Bot 的 app-scoped open_id 直接用于另一个 Bot;' +
|
|
183
|
+
'无法解析跨应用 union_id,请改用完整邮箱、手机号或 on_ union_id。');
|
|
184
|
+
}
|
|
185
|
+
const normalized = [];
|
|
186
|
+
const seen = new Set();
|
|
187
|
+
for (const entry of entries) {
|
|
188
|
+
const next = entry === sourceOwner ? stable : entry;
|
|
189
|
+
if (seen.has(next))
|
|
190
|
+
continue;
|
|
191
|
+
seen.add(next);
|
|
192
|
+
normalized.push(next);
|
|
193
|
+
}
|
|
194
|
+
return normalized.join(',');
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=owner-identity.js.map
|