@co0ontty/wand 4.105.1 → 4.106.0
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/build-info.json +3 -3
- package/dist/cli.js +7 -2
- package/dist/distribution-manager.d.ts +2 -0
- package/dist/distribution-manager.js +23 -0
- package/dist/employee-input-scheduling.d.ts +2 -1
- package/dist/employee-knowledge-cli.d.ts +1 -1
- package/dist/employee-knowledge-cli.js +91 -20
- package/dist/employee-knowledge-content.js +1 -1
- package/dist/employee-knowledge-types.d.ts +1 -1
- package/dist/employee-knowledge-types.js +1 -1
- package/dist/employee-knowledge.d.ts +6 -3
- package/dist/employee-knowledge.js +54 -58
- package/dist/env-utils.js +1 -1
- package/dist/html-preview-policy.d.ts +4 -0
- package/dist/html-preview-policy.js +4 -0
- package/dist/ios-ota.d.ts +5 -0
- package/dist/ios-ota.js +11 -1
- package/dist/knowledge-skill.d.ts +2 -0
- package/dist/knowledge-skill.js +17 -0
- package/dist/knowledge-types.d.ts +36 -0
- package/dist/knowledge-types.js +8 -0
- package/dist/managed-skills-ensure.js +2 -0
- package/dist/middleware/api-scope.js +2 -0
- package/dist/path-repair.js +28 -6
- package/dist/pi-resource-catalog.d.ts +3 -1
- package/dist/pi-resource-catalog.js +25 -0
- package/dist/pi-session-settings.d.ts +2 -0
- package/dist/pi-session-settings.js +25 -0
- package/dist/process-manager.d.ts +2 -0
- package/dist/process-manager.js +35 -12
- package/dist/quick-terminal-session.d.ts +3 -0
- package/dist/quick-terminal-session.js +5 -0
- package/dist/retention-protection.d.ts +15 -0
- package/dist/retention-protection.js +134 -0
- package/dist/retention.d.ts +3 -2
- package/dist/retention.js +58 -76
- package/dist/server-employee-routes.js +1 -1
- package/dist/server-file-routes.js +84 -16
- package/dist/server-knowledge-routes.d.ts +4 -0
- package/dist/server-knowledge-routes.js +61 -0
- package/dist/server-local-preview-routes.js +28 -6
- package/dist/server-pi-defaults-routes.d.ts +1 -1
- package/dist/server-pi-defaults-routes.js +13 -20
- package/dist/server-session-lifecycle-routes.js +17 -17
- package/dist/server-session-list-routes.js +1 -1
- package/dist/server-task-routes.js +6 -0
- package/dist/server-update-routes.d.ts +1 -0
- package/dist/server-update-routes.js +62 -17
- package/dist/server-workspace-routes.js +5 -5
- package/dist/server.js +4 -2
- package/dist/session-questions.d.ts +7 -0
- package/dist/session-questions.js +25 -0
- package/dist/session-registry.d.ts +3 -0
- package/dist/session-registry.js +17 -0
- package/dist/session-request.d.ts +1 -1
- package/dist/session-request.js +6 -2
- package/dist/session-service.js +1 -1
- package/dist/storage/employees-repository.js +5 -2
- package/dist/storage/knowledge-repository.d.ts +35 -0
- package/dist/storage/knowledge-repository.js +208 -0
- package/dist/storage/mappers.js +1 -1
- package/dist/storage/migrations.js +51 -0
- package/dist/storage/sessions-repository.d.ts +2 -0
- package/dist/storage/sessions-repository.js +16 -0
- package/dist/storage/tasks-repository.d.ts +7 -0
- package/dist/storage/tasks-repository.js +21 -0
- package/dist/storage/workspaces-repository.d.ts +1 -0
- package/dist/storage/workspaces-repository.js +2 -1
- package/dist/storage.d.ts +3 -1
- package/dist/storage.js +4 -0
- package/dist/structured-session-manager.d.ts +3 -0
- package/dist/structured-session-manager.js +13 -4
- package/dist/task-action-types.d.ts +22 -0
- package/dist/task-action-types.js +1 -0
- package/dist/task-actions.d.ts +5 -0
- package/dist/task-actions.js +86 -0
- package/dist/task-execution-queue.d.ts +1 -1
- package/dist/task-execution-queue.js +4 -1
- package/dist/task-retention.d.ts +4 -2
- package/dist/task-retention.js +2 -0
- package/dist/types.d.ts +2 -1
- package/dist/web-ui/content/ai-teams.js +12 -12
- package/dist/web-ui/content/module-manifest.json +1 -1
- package/dist/web-ui/content/modules/00b168a19664439e/dropdown-surface.js +1 -0
- package/dist/web-ui/content/modules/059c5fb7f128d340/task-board-host.js +27 -0
- package/dist/web-ui/content/modules/07494f5a623e4471/chat-render.js +76 -0
- package/dist/web-ui/content/modules/{bc28252270bcc51a → 0a743ad3b4db6874}/chunk.js +1 -1
- package/dist/web-ui/content/modules/0d76e582a7a71b2f/chunk.js +1 -0
- package/dist/web-ui/content/modules/11af5d14b30e57b6/chunk.js +1 -0
- package/dist/web-ui/content/modules/16dab1297efd71a7/chunk.js +10 -0
- package/dist/web-ui/content/modules/182929e188c1ab3a/host.js +5 -0
- package/dist/web-ui/content/modules/1858670c0f84fec5/employee-profile.js +1 -0
- package/dist/web-ui/content/modules/{1cf252d2f64a6279 → 1eab7410d5586038}/chunk.js +1 -1
- package/dist/web-ui/content/modules/20c47dc0442f5a04/host.js +1 -0
- package/dist/web-ui/content/modules/226241b999d12008/host.js +1 -0
- package/dist/web-ui/content/modules/23c4b8d223ec64c5/host.js +61 -0
- package/dist/web-ui/content/modules/2882c97388ff4f7b/employee-card.js +1 -0
- package/dist/web-ui/content/modules/2a791cd2e14aa1e0/notice-view.js +1 -0
- package/dist/web-ui/content/modules/2c90c3be260e6cce/progress.js +1 -0
- package/dist/web-ui/content/modules/2d7be9935394f397/workspace-window.js +1 -0
- package/dist/web-ui/content/modules/2f801e53dda62770/chunk.js +1 -0
- package/dist/web-ui/content/modules/2f97ddba3842adaa/chunk.js +1 -0
- package/dist/web-ui/content/modules/31157ceb6d23b809/chunk.js +15 -0
- package/dist/web-ui/content/modules/389a5112332ec23a/host.js +1 -0
- package/dist/web-ui/content/modules/3ea13e8b3c2deaa4/panel-host.js +1 -0
- package/dist/web-ui/content/modules/3f8830f8ad28decc/chunk.js +3 -0
- package/dist/web-ui/content/modules/{70715360138f4d99 → 3fe11a75284ad8ae}/host.js +1 -1
- package/dist/web-ui/content/modules/{e0a1ae9163e77556 → 41445c6589dba325}/host.js +2 -2
- package/dist/web-ui/content/modules/{8b2f9a027ae1d7eb → 42e5c34002fcffb7}/chunk.js +1 -1
- package/dist/web-ui/content/modules/438807b8bf112cd0/chunk.js +1 -0
- package/dist/web-ui/content/modules/4861eca9a8a87ad0/chunk.js +1 -0
- package/dist/web-ui/content/modules/{78d06dfdc4b13d78 → 4970319a83432ec7}/chunk.js +1 -1
- package/dist/web-ui/content/modules/4a5d669c90f545cb/host.js +1 -0
- package/dist/web-ui/content/modules/4ba1e8c74bed7ef2/chunk.js +1 -0
- package/dist/web-ui/content/modules/5083a5dbb5b155b7/chunk.js +1 -0
- package/dist/web-ui/content/modules/50da446c1377c220/chunk.js +20 -0
- package/dist/web-ui/content/modules/52574891ef08e29b/host.js +30 -0
- package/dist/web-ui/content/modules/5705d25468274534/host.js +1 -0
- package/dist/web-ui/content/modules/579d486763d47c0d/chunk.js +1 -0
- package/dist/web-ui/content/modules/57c357d321db5df9/chunk.js +1 -0
- package/dist/web-ui/content/modules/5933ce8965aa4004/chunk.js +1 -0
- package/dist/web-ui/content/modules/5961ab2947c86ca1/shell-file-panel-drawer.js +1 -0
- package/dist/web-ui/content/modules/5b6e1369df7dea69/chunk.js +1 -0
- package/dist/web-ui/content/modules/5f298a8f43dd0589/chunk.js +1 -0
- package/dist/web-ui/content/modules/62e0023451f428cf/chunk.js +1 -0
- package/dist/web-ui/content/modules/6787bdcf56f743a5/host.js +1 -0
- package/dist/web-ui/content/modules/67c39b0398186a9f/host.js +1 -0
- package/dist/web-ui/content/modules/6b16f35c0627bafb/chunk.js +1 -0
- package/dist/web-ui/content/modules/6dd4f3e2f619f7a0/chunk.js +1 -0
- package/dist/web-ui/content/modules/70a2e13e0ccc8549/panel.js +1 -0
- package/dist/web-ui/content/modules/710db590e9707f73/runtime.js +338 -0
- package/dist/web-ui/content/modules/7249950f8771dbeb/workspaces-panel.js +4 -0
- package/dist/web-ui/content/modules/771439a41e737ee2/chunk.js +1 -0
- package/dist/web-ui/content/modules/{2061d4a88875b9f9 → 816eb9b3a000fb2c}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{c0384ffb4ef740a0 → 831b6c7b43e800be}/host.js +1 -1
- package/dist/web-ui/content/modules/87c7f50d9455d55e/chunk.js +1 -0
- package/dist/web-ui/content/modules/87dcd516ffd9f688/composer-surface-adapter.js +1 -0
- package/dist/web-ui/content/modules/8891ca8165435ca1/chunk.js +1 -0
- package/dist/web-ui/content/modules/8b7cd7bffdfd69e7/brand-identity.js +1 -0
- package/dist/web-ui/content/modules/8bf9917f6c3429f6/host.js +1 -0
- package/dist/web-ui/content/modules/8de8368570ab089d/chunk.js +57 -0
- package/dist/web-ui/content/modules/8e612d4881fa4118/home.js +6 -0
- package/dist/web-ui/content/modules/8e6178262ea63dec/markdown.js +1 -0
- package/dist/web-ui/content/modules/913187c92a98a1ac/chunk.js +1 -0
- package/dist/web-ui/content/modules/96f2ae970f8c576b/host.js +1 -0
- package/dist/web-ui/content/modules/97d7f267959fd385/chunk.js +1 -0
- package/dist/web-ui/content/modules/{22497085d7cdd83b → 9b12c2301f3a18f3}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{9f4e26a1c1867d65 → 9d941d6ff39861b8}/chunk.js +2 -2
- package/dist/web-ui/content/modules/9e163d54ff8fd1aa/chunk.js +1 -0
- package/dist/web-ui/content/modules/{0567e161e2cca41e → a2caed0139df4b21}/chunk.js +1 -1
- package/dist/web-ui/content/modules/a59734be368daa7e/chunk.js +1 -0
- package/dist/web-ui/content/modules/{e4503f8e6379ccdc → a61393bfa976d8d5}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{df5d48b4ff04b443 → b63e075f222a1266}/library-bridge.js +2 -2
- package/dist/web-ui/content/modules/b713cad51ca4c512/chunk.js +1 -0
- package/dist/web-ui/content/modules/ba89cd97627e6682/queue-view-adapter.js +1 -0
- package/dist/web-ui/content/modules/bd3daf04a8bf4422/chunk.js +1 -0
- package/dist/web-ui/content/modules/{aa7d409d04bbd736 → bd7dc4bb46731ee7}/chunk.js +1 -1
- package/dist/web-ui/content/modules/bf3ee58e0da44822/chunk.js +1 -0
- package/dist/web-ui/content/modules/c0a446100d969f3e/chunk.js +8 -0
- package/dist/web-ui/content/modules/c2f09c8a472f5d83/dialog-modal.js +4 -0
- package/dist/web-ui/content/modules/c33935155289c22d/chunk.js +3 -0
- package/dist/web-ui/content/modules/c351eb11e0bdec2c/sidebar-peek.js +1 -0
- package/dist/web-ui/content/modules/ca7ca5902a35d26e/chunk.js +1 -0
- package/dist/web-ui/content/modules/cba6f13c0b2aec1c/chunk.js +1 -0
- package/dist/web-ui/content/modules/d434edbb2f4672e5/chunk.js +1 -0
- package/dist/web-ui/content/modules/{d569c96d4acfdec3 → d47d75a78ae598e3}/chunk.js +25 -25
- package/dist/web-ui/content/modules/d49f106c4d106057/chunk.js +1 -0
- package/dist/web-ui/content/modules/d5d28ec375826ef2/chunk.js +3 -0
- package/dist/web-ui/content/modules/{7edec8f23f8e0834 → d6b16dedb9011c33}/chunk.js +1 -1
- package/dist/web-ui/content/modules/d6fffe2c2a3a738d/toast-region.js +1 -0
- package/dist/web-ui/content/modules/d8a7011760f61719/group-editor.js +1 -0
- package/dist/web-ui/content/modules/{bf0b693a654e2655 → d9e2b65e9679ad39}/host.js +3 -3
- package/dist/web-ui/content/modules/db521a246e14e5e4/chunk.js +4 -0
- package/dist/web-ui/content/modules/{7994dec16e8b1039 → dedd4a19bb70e327}/page.js +2 -2
- package/dist/web-ui/content/modules/e060508ecd50fa7e/chunk.js +1 -0
- package/dist/web-ui/content/modules/e5174201f9d918fb/chunk.js +1 -0
- package/dist/web-ui/content/modules/e63582a3bce48f7d/chunk.js +1 -0
- package/dist/web-ui/content/modules/ea8fe4b9999fd2aa/chunk.js +1 -0
- package/dist/web-ui/content/modules/{d7cdd7dca9a0c9f8 → eac72f69716dba05}/chunk.js +1 -1
- package/dist/web-ui/content/modules/ebc53dedc3945514/host.js +1 -0
- package/dist/web-ui/content/modules/{0d7f7d954382dc42 → ec33e17c00c1eb24}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{99e5cdf0c3bd0e3d → ed7405f064944215}/sha256.js +1 -1
- package/dist/web-ui/content/modules/f27a5d3c6c02a71c/chunk.js +1 -0
- package/dist/web-ui/content/modules/f383d892fef73483/chunk.js +1 -0
- package/dist/web-ui/content/modules/{084dca1ea52bf38e → f3cff7792ba39df8}/login-visual.js +1 -1
- package/dist/web-ui/content/modules/f43da7050badf54c/host.js +1 -0
- package/dist/web-ui/content/modules/face3dbf117d63e3/chunk.js +1 -0
- package/dist/web-ui/content/modules/fb2356eced24c4cc/host-bridge.js +1 -0
- package/dist/web-ui/content/styles.css +1 -1
- package/dist/web-ui/embedded-assets.d.ts +413 -420
- package/dist/web-ui/embedded-assets.js +5 -5
- package/dist/web-ui/group-chat-visibility.d.ts +1 -0
- package/dist/web-ui/group-chat-visibility.js +1 -1
- package/dist/web-ui/markdown.js +10 -36
- package/dist/web-ui/message-file-target.d.ts +8 -0
- package/dist/web-ui/message-file-target.js +105 -15
- package/dist/web-ui/page-route.js +2 -0
- package/dist/web-ui/react/local-preview/controller.d.ts +2 -2
- package/dist/web-ui/react/local-preview/controller.js +53 -10
- package/dist/web-ui/react/workspaces/types.d.ts +1 -0
- package/dist/web-ui/server-link-url.d.ts +3 -0
- package/dist/web-ui/server-link-url.js +18 -0
- package/package.json +2 -1
- package/skills/wand-knowledge/SKILL.md +47 -0
- package/skills/wand-knowledge/scripts/knowledge.mjs +18 -0
- package/dist/web-ui/content/modules/0341f0d00f88a16f/chunk.js +0 -1
- package/dist/web-ui/content/modules/069f5a4267b0a9e3/runtime.js +0 -279
- package/dist/web-ui/content/modules/0d62c22b7aed5f1f/host-bridge.js +0 -1
- package/dist/web-ui/content/modules/0da28408ec089cf7/chunk.js +0 -1
- package/dist/web-ui/content/modules/130e8905cc7f639c/toast-region.js +0 -1
- package/dist/web-ui/content/modules/186d6e3b44a3c539/host.js +0 -1
- package/dist/web-ui/content/modules/1870280f0e783c62/chunk.js +0 -4
- package/dist/web-ui/content/modules/19d3bc36fa1e9160/chunk.js +0 -1
- package/dist/web-ui/content/modules/1a0b5db535599f72/chunk.js +0 -1
- package/dist/web-ui/content/modules/1d1dc0fd8a0210aa/composer-surface-adapter.js +0 -1
- package/dist/web-ui/content/modules/23f15023aa2279a3/shell-file-panel-drawer.js +0 -1
- package/dist/web-ui/content/modules/2cab58e5d148844c/host.js +0 -1
- package/dist/web-ui/content/modules/32edeb64dbf339f6/chunk.js +0 -1
- package/dist/web-ui/content/modules/33daaeb4bf68c7ba/chunk.js +0 -9
- package/dist/web-ui/content/modules/37da177222b6308d/workspaces-panel.js +0 -4
- package/dist/web-ui/content/modules/3af7facf8a7588c7/chunk.js +0 -1
- package/dist/web-ui/content/modules/3b95dc1376e932ea/host.js +0 -1
- package/dist/web-ui/content/modules/3cbbad48df7998f8/chunk.js +0 -1
- package/dist/web-ui/content/modules/41cf79c899bc83c8/host.js +0 -1
- package/dist/web-ui/content/modules/444af9de1698eea0/host.js +0 -1
- package/dist/web-ui/content/modules/452327275cc5d8f8/host.js +0 -1
- package/dist/web-ui/content/modules/466310a17dac465f/chunk.js +0 -3
- package/dist/web-ui/content/modules/46f1b6c3274d399b/host.js +0 -1
- package/dist/web-ui/content/modules/47998d82dc65bfeb/sidebar-peek.js +0 -1
- package/dist/web-ui/content/modules/486a828390c5d44d/host.js +0 -30
- package/dist/web-ui/content/modules/4cc15b385bc6cc32/chunk.js +0 -1
- package/dist/web-ui/content/modules/4d5ab67f6c0ce19f/chunk.js +0 -1
- package/dist/web-ui/content/modules/54aaf60ac85dcb2b/chunk.js +0 -1
- package/dist/web-ui/content/modules/54c22eddaf009d00/chunk.js +0 -1
- package/dist/web-ui/content/modules/55b931232c672f4f/chunk.js +0 -1
- package/dist/web-ui/content/modules/583049de28ef2b02/panel.js +0 -1
- package/dist/web-ui/content/modules/5a2a58334d63e127/chunk.js +0 -20
- package/dist/web-ui/content/modules/5ba0668f5a22133b/home.js +0 -6
- package/dist/web-ui/content/modules/5cd5d3d65d966c5f/chunk.js +0 -1
- package/dist/web-ui/content/modules/6b41e59ab342482f/notice-view.js +0 -1
- package/dist/web-ui/content/modules/6b5445f41bef0a66/chunk.js +0 -1
- package/dist/web-ui/content/modules/6e8395f61c89b5aa/chunk.js +0 -1
- package/dist/web-ui/content/modules/6f74cede70164e19/chunk.js +0 -1
- package/dist/web-ui/content/modules/704690f5d6ab9157/chunk.js +0 -1
- package/dist/web-ui/content/modules/7dce56c1987e8d43/chunk.js +0 -29
- package/dist/web-ui/content/modules/80e92c14a6789896/progress.js +0 -1
- package/dist/web-ui/content/modules/8a828b4d087667dd/chunk.js +0 -1
- package/dist/web-ui/content/modules/8d6f223764846e18/brand-identity.js +0 -1
- package/dist/web-ui/content/modules/9136bae16758fd4c/chunk.js +0 -1
- package/dist/web-ui/content/modules/93fa5c35e4bcab96/chunk.js +0 -1
- package/dist/web-ui/content/modules/96fe39f39930d9e4/chunk.js +0 -8
- package/dist/web-ui/content/modules/9db41ad5ac96ffa2/chunk.js +0 -1
- package/dist/web-ui/content/modules/a073cb6d182ccd32/chunk.js +0 -1
- package/dist/web-ui/content/modules/a8cba9f1d6b49ef1/chunk.js +0 -1
- package/dist/web-ui/content/modules/a97b3b9b68f9ca38/chunk.js +0 -57
- package/dist/web-ui/content/modules/ac34ed6692b43ede/dropdown-surface.js +0 -1
- package/dist/web-ui/content/modules/aff19b31898aa157/chunk.js +0 -1
- package/dist/web-ui/content/modules/b2f6e088e6e45878/chunk.js +0 -1
- package/dist/web-ui/content/modules/b4446bf92e182bfb/employee-card.js +0 -1
- package/dist/web-ui/content/modules/b79c15aace456028/chunk.js +0 -6
- package/dist/web-ui/content/modules/b8c18baf7cfb61b1/chat-render.js +0 -76
- package/dist/web-ui/content/modules/b8c447171e3d60a0/chunk.js +0 -1
- package/dist/web-ui/content/modules/b945370f1fa784f9/chunk.js +0 -13
- package/dist/web-ui/content/modules/ba5fa76884e1f806/chunk.js +0 -1
- package/dist/web-ui/content/modules/bb1bb9460cc10fbe/host.js +0 -1
- package/dist/web-ui/content/modules/be7f1f9183a1247f/chunk.js +0 -3
- package/dist/web-ui/content/modules/bf7449bcf95e1454/chunk.js +0 -1
- package/dist/web-ui/content/modules/c091efd46e221c29/chunk.js +0 -1
- package/dist/web-ui/content/modules/c1ec2ebce8ea5dd8/dialog-modal.js +0 -4
- package/dist/web-ui/content/modules/c2f7bb50118f1603/chunk.js +0 -1
- package/dist/web-ui/content/modules/c369ce4eb71277e6/host.js +0 -1
- package/dist/web-ui/content/modules/c46b3501573953e9/chunk.js +0 -1
- package/dist/web-ui/content/modules/c577ad641502d509/panel-host.js +0 -1
- package/dist/web-ui/content/modules/c75976857c18f251/host.js +0 -1
- package/dist/web-ui/content/modules/c8eaffbedda0d3d0/queue-view-adapter.js +0 -3
- package/dist/web-ui/content/modules/cadd26ae50359434/chunk.js +0 -1
- package/dist/web-ui/content/modules/d37ff6684c9aeeec/chunk.js +0 -3
- package/dist/web-ui/content/modules/d48c1f89342bc4bc/workspace-window.js +0 -1
- package/dist/web-ui/content/modules/d859a83f486aab23/chunk.js +0 -15
- package/dist/web-ui/content/modules/d8b258a6455d77da/host.js +0 -5
- package/dist/web-ui/content/modules/d937e939122180b9/host.js +0 -1
- package/dist/web-ui/content/modules/e020beea3e7da7db/chunk.js +0 -1
- package/dist/web-ui/content/modules/e2feda63a603c64e/group-editor.js +0 -1
- package/dist/web-ui/content/modules/e70296674a841d60/chunk.js +0 -1
- package/dist/web-ui/content/modules/ec2f6b23d12d3a15/chunk.js +0 -1
- package/dist/web-ui/content/modules/ede751e1f2500d03/employee-profile.js +0 -1
- package/dist/web-ui/content/modules/ee4301b734e2fd43/chunk.js +0 -1
- package/dist/web-ui/content/modules/f4e6095edc32562c/markdown.js +0 -1
- package/dist/web-ui/content/modules/f7f0710962cab0e0/chunk.js +0 -10
- package/dist/web-ui/content/modules/fe30627fc1e59d4f/chunk.js +0 -1
- package/dist/web-ui/content/modules/ffbd3bcaecd8e814/task-board-host.js +0 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { asyncRoute } from "./express-async.js";
|
|
2
2
|
import { surfaceDomainError } from "./http-error.js";
|
|
3
3
|
import { sendRouteError } from "./server-request.js";
|
|
4
|
-
import { discoverPiResources,
|
|
4
|
+
import { discoverPiResources, resolvePiResourceSettingsPatch } from "./pi-resource-catalog.js";
|
|
5
5
|
import { defaultPiCliSessionSettings, effectivePiSessionSettings, mergePiSessionDefaults, patchPiSessionSettings, } from "./pi-session-settings.js";
|
|
6
6
|
const DOMAIN_MESSAGE = /^(Pi 设置必须是对象。|请选择有效的 Skills \/ MCP 列表。|资源选择不能包含路径、命令或其他设置。|资源选择必须是无重复的已安装资源 ID(每类最多64项)。|锁定技能必须是无重复的已安装 Skill ID(最多64项)。|CodeMode 请选择跟随 Pi、关闭、启用或仅 CodeMode。|CodeMode 必须是 off、on 或 only。|基础工具必须是无重复的 Pi 工具列表。|.+ 必须是是否启用(boolean)。|未知 Pi 设置:.+|所选 Skill 已不存在或已被停用,请重新选择;没有改用其他 Skill。|所选 MCP 已不存在,请重新选择;没有连接其他 MCP。)$/;
|
|
7
7
|
/**
|
|
@@ -10,7 +10,7 @@ const DOMAIN_MESSAGE = /^(Pi 设置必须是对象。|请选择有效的 Skills
|
|
|
10
10
|
* 之前只有「在某个会话里改一次,顺带成为新会话默认」这一条隐式路径,用户在设置页
|
|
11
11
|
* 找不到它;而会话里的写入又只能表达会话本身的选择。这里给出显式入口,语义与
|
|
12
12
|
* `StructuredSessionManager.setPiSettings` 写回默认的那一段保持一致(字段级合并、
|
|
13
|
-
*
|
|
13
|
+
* 新增资源必须真实存在、不可表达的值直接拒绝)。
|
|
14
14
|
*/
|
|
15
15
|
export function registerPiDefaultsRoutes(app, deps) {
|
|
16
16
|
const readDefaults = () => deps.storage.getPiSessionDefaults()
|
|
@@ -42,26 +42,19 @@ export function registerPiDefaultsRoutes(app, deps) {
|
|
|
42
42
|
}));
|
|
43
43
|
app.patch("/api/pi-settings/defaults", asyncRoute(async (req, res) => {
|
|
44
44
|
try {
|
|
45
|
-
|
|
45
|
+
let patch = req.body;
|
|
46
46
|
const current = readDefaults();
|
|
47
47
|
// 先按现有默认校验字段本身;再按「只合并本次改动」落库,与会话写入同一套语义。
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (next.autoResources === true) {
|
|
61
|
-
const reason = autoResourcesReason(next);
|
|
62
|
-
if (reason)
|
|
63
|
-
throw new Error(reason);
|
|
64
|
-
}
|
|
48
|
+
patchPiSessionSettings(current, patch);
|
|
49
|
+
if (patch.resources !== undefined || patch.lockedSkills !== undefined) {
|
|
50
|
+
const inventory = await discoverPiResources(deps.config, deps.config.defaultCwd);
|
|
51
|
+
patch = resolvePiResourceSettingsPatch(inventory, readDefaults(), patch);
|
|
52
|
+
}
|
|
53
|
+
const next = mergePiSessionDefaults(readDefaults(), patch);
|
|
54
|
+
if (next.autoResources === true) {
|
|
55
|
+
const reason = autoResourcesReason(next);
|
|
56
|
+
if (reason)
|
|
57
|
+
throw new Error(reason);
|
|
65
58
|
}
|
|
66
59
|
deps.storage.setPiSessionDefaults(next);
|
|
67
60
|
res.json({ settings: effectivePiSessionSettings(next, "cli") });
|
|
@@ -11,7 +11,7 @@ import { toSessionDetailDTO } from "./session-transport.js";
|
|
|
11
11
|
import { compactToolMessagesForTransport, windowMessagesForTransport } from "./message-truncator.js";
|
|
12
12
|
import { enrichStructuredMessages } from "./structured-client-protocol.js";
|
|
13
13
|
import { installedPiExtensions } from "./pi-extension-resources.js";
|
|
14
|
-
import { discoverPiResources,
|
|
14
|
+
import { discoverPiResources, resolvePiResourceSettingsPatch } from "./pi-resource-catalog.js";
|
|
15
15
|
import { effectivePiSessionSettings, patchPiSessionSettings } from "./pi-session-settings.js";
|
|
16
16
|
import { isProviderSessionId } from "./resume-policy.js";
|
|
17
17
|
import { sendRouteError } from "./server-request.js";
|
|
@@ -64,7 +64,7 @@ export function registerSessionLifecycleRoutes(app, ctx) {
|
|
|
64
64
|
if (body.mode !== undefined && !isExecutionMode(body.mode))
|
|
65
65
|
throw badRequest(`无效执行模式: ${String(body.mode)}`);
|
|
66
66
|
const initialInput = body.initialInput?.trim();
|
|
67
|
-
const origin = parseSessionCreationOrigin(body);
|
|
67
|
+
const origin = parseSessionCreationOrigin(body, interactiveShell);
|
|
68
68
|
const rawModel = typeof body.model === "string" ? body.model.trim() : "";
|
|
69
69
|
const rawCommand = body.command?.trim() ?? "";
|
|
70
70
|
const provider = interactiveShell
|
|
@@ -208,6 +208,14 @@ export function registerSessionLifecycleRoutes(app, ctx) {
|
|
|
208
208
|
sendRouteError(res, surfaceDomainError(error, /Wand Agent|harness|core/i) ?? error, "无法启动结构化会话。");
|
|
209
209
|
}
|
|
210
210
|
}));
|
|
211
|
+
app.put("/api/sessions/:id/quick-terminal", (req, res) => {
|
|
212
|
+
try {
|
|
213
|
+
res.json(sessionResponseDTO(sessions.claimQuickTerminal(req.params.id), req));
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
sendRouteError(res, error, "无法连接快捷终端。");
|
|
217
|
+
}
|
|
218
|
+
});
|
|
211
219
|
app.post("/api/sessions/:id/directory", (req, res) => {
|
|
212
220
|
const cwd = req.body?.cwd;
|
|
213
221
|
if (typeof cwd !== "string" || !cwd.trim()) {
|
|
@@ -306,6 +314,7 @@ export function registerSessionLifecycleRoutes(app, ctx) {
|
|
|
306
314
|
requirePiSession(id);
|
|
307
315
|
const { settings } = structured.getPiSettings(id);
|
|
308
316
|
const next = patchPiSessionSettings(settings, req.body);
|
|
317
|
+
let patch = req.body;
|
|
309
318
|
if (req.body.autoResources === true) {
|
|
310
319
|
const capabilities = await piSettingsResponse(id);
|
|
311
320
|
const runtime = decisions?.status();
|
|
@@ -315,26 +324,17 @@ export function registerSessionLifecycleRoutes(app, ctx) {
|
|
|
315
324
|
: capabilities.autoResourcesReason || "自动选择暂不可用。");
|
|
316
325
|
}
|
|
317
326
|
}
|
|
318
|
-
if (req.body.resources !== undefined || req.body.lockedSkills !== undefined) {
|
|
319
|
-
const inventory = await discoverPiResources(config, structured.get(id).cwd);
|
|
320
|
-
// Removed resources may be retained only when already selected, so users can deselect stale
|
|
321
|
-
// items one at a time. Any NEW ID must resolve; the runner always revalidates the full list.
|
|
322
|
-
if (req.body.resources !== undefined)
|
|
323
|
-
resolvePiResourceSelection(inventory, {
|
|
324
|
-
skills: next.resources.skills.filter((id) => !settings.resources?.skills.includes(id)),
|
|
325
|
-
mcpServers: next.resources.mcpServers.filter((id) => !settings.resources?.mcpServers.includes(id)),
|
|
326
|
-
});
|
|
327
|
-
if (req.body.lockedSkills !== undefined)
|
|
328
|
-
resolvePiResourceSelection(inventory, {
|
|
329
|
-
skills: next.lockedSkills.filter((id) => !settings.lockedSkills?.includes(id)), mcpServers: [],
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
327
|
if (next.goalMode && !settings.goalMode) {
|
|
333
328
|
const installed = await installedPiExtensions(config, structured.get(id).cwd);
|
|
334
329
|
if (!installed.some((item) => item.goal))
|
|
335
330
|
throw badRequest("目标模式不可用:请先在 Pi 中安装并启用 pi-goal。");
|
|
336
331
|
}
|
|
337
|
-
|
|
332
|
+
if (req.body.resources !== undefined || req.body.lockedSkills !== undefined) {
|
|
333
|
+
const inventory = await discoverPiResources(config, structured.get(id).cwd);
|
|
334
|
+
// A lock-only patch must release from the latest selection after asynchronous discovery.
|
|
335
|
+
patch = resolvePiResourceSettingsPatch(inventory, structured.getPiSettings(id).settings, patch);
|
|
336
|
+
}
|
|
337
|
+
structured.setPiSettings(id, patch);
|
|
338
338
|
// 回复「实际生效」的设置(CLI 的 CodeMode 只归一到 off/on),不把存库原值当生效值展示。
|
|
339
339
|
const saved = structured.getPiSettings(id);
|
|
340
340
|
res.json({ settings: effectivePiSessionSettings(saved.settings, saved.resolution.engine) });
|
|
@@ -88,7 +88,7 @@ export function registerSessionListRoutes(app, ctx) {
|
|
|
88
88
|
}
|
|
89
89
|
});
|
|
90
90
|
app.get("/api/sessions", (req, res) => {
|
|
91
|
-
res.json(sessions.listSlim().map((session) => toSessionListItemDTO(session)));
|
|
91
|
+
res.json(sessions.listSlim().filter(session => session.sessionSource !== "quick-terminal").map((session) => toSessionListItemDTO(session)));
|
|
92
92
|
});
|
|
93
93
|
app.get("/api/sessions/provider-usage", (_req, res) => {
|
|
94
94
|
res.json(storage.countInteractiveSessionsByProvider());
|
|
@@ -17,6 +17,7 @@ import { parseWandTaskAgent } from "./storage.js";
|
|
|
17
17
|
import { compactTransportAvatar } from "./fixed-employee-avatar.js";
|
|
18
18
|
import { canArchiveTask } from "./task-archive-policy.js";
|
|
19
19
|
import { TaskReadModel } from "./task-read-model.js";
|
|
20
|
+
import { readTaskActions } from "./task-actions.js";
|
|
20
21
|
import { refreshAutoBoardTaskTitles, taskTitleService } from "./task-title-service.js";
|
|
21
22
|
import { provisionalTaskTitleFromDescription } from "./task-title.js";
|
|
22
23
|
import { isWandTaskStatus, statusAfterWandTaskDispatch } from "./task-types.js";
|
|
@@ -217,6 +218,11 @@ export function registerTaskRoutes(app, deps) {
|
|
|
217
218
|
res.json(model.tasks.filter(task => workspaceId === undefined || task.workspaceId === workspaceId)
|
|
218
219
|
.map(task => taskDto(deps, task, model)));
|
|
219
220
|
});
|
|
221
|
+
app.get("/api/wand-task-actions", (req, res) => {
|
|
222
|
+
const workspaceId = typeof req.query.workspaceId === "string" ? req.query.workspaceId : undefined;
|
|
223
|
+
res.set("Cache-Control", "no-store");
|
|
224
|
+
res.json(readTaskActions(storage, sessions, workspaceId));
|
|
225
|
+
});
|
|
220
226
|
registerTaskCommentRoutes(app, deps);
|
|
221
227
|
app.get("/api/wand-task-agent-defaults", (_req, res) => {
|
|
222
228
|
res.json(readTaskBoardLastAgent(storage));
|
|
@@ -49,6 +49,7 @@ export interface PublicUpdateRoutesDependencies {
|
|
|
49
49
|
resolveMacosBetaDownload(fileName: string): Promise<DownloadAsset | null>;
|
|
50
50
|
resolveLatestIpa(): Promise<ResolvedUpdateAsset | null>;
|
|
51
51
|
resolveIosDownload(): Promise<DownloadAsset | null>;
|
|
52
|
+
resolveIosAppDownload?(appId: string, fileName?: string): Promise<DownloadAsset | null>;
|
|
52
53
|
}
|
|
53
54
|
export declare function registerPublicUpdateRoutes(app: Express, deps: PublicUpdateRoutesDependencies, publicOrigin?: string): void;
|
|
54
55
|
export declare class ServerUpdateState {
|
|
@@ -253,11 +253,15 @@ export function registerPublicUpdateRoutes(app, deps, publicOrigin) {
|
|
|
253
253
|
});
|
|
254
254
|
return;
|
|
255
255
|
}
|
|
256
|
-
const
|
|
256
|
+
const versionOrder = compareWandInstallOrder(payload.latestVersion, currentVersion);
|
|
257
|
+
const currentBuild = text(req.query.currentBuild);
|
|
258
|
+
const updateAvailable = versionOrder > 0 || (versionOrder === 0 && !!currentBuild
|
|
259
|
+
&& compareWandInstallOrder(payload.bundleBuild, currentBuild) > 0);
|
|
257
260
|
res.json({
|
|
258
261
|
updateAvailable,
|
|
259
262
|
currentVersion,
|
|
260
263
|
latestVersion: payload.latestVersion,
|
|
264
|
+
latestBuild: payload.bundleBuild,
|
|
261
265
|
downloadUrl: updateAvailable ? payload.downloadUrl : null,
|
|
262
266
|
installUrl: updateAvailable ? payload.installUrl : null,
|
|
263
267
|
manifestUrl: payload.manifestUrl,
|
|
@@ -291,22 +295,27 @@ export function registerPublicUpdateRoutes(app, deps, publicOrigin) {
|
|
|
291
295
|
res.setHeader("Cache-Control", "no-cache");
|
|
292
296
|
res.send(buildIosInstallPage({
|
|
293
297
|
title: payload.title,
|
|
294
|
-
version: payload.latestVersion,
|
|
298
|
+
version: iosAppId(req) ? `${payload.latestVersion}(${payload.bundleBuild})` : payload.latestVersion,
|
|
295
299
|
sizeLabel: formatIosAssetSize(payload.size),
|
|
296
300
|
installUrl: payload.installUrl ?? "#",
|
|
297
301
|
downloadUrl: payload.downloadUrl,
|
|
298
302
|
signed: payload.signed,
|
|
299
303
|
https: payload.origin.startsWith("https://"),
|
|
304
|
+
apps: await resolveIosInstallLinks(req, deps, publicOrigin),
|
|
300
305
|
}));
|
|
301
306
|
}));
|
|
302
307
|
app.get("/ios/download", asyncRoute(async (req, res) => {
|
|
303
|
-
const
|
|
308
|
+
const appId = iosAppId(req);
|
|
309
|
+
const asset = appId
|
|
310
|
+
? await deps.resolveIosAppDownload?.(appId, text(req.query.fileName) || undefined)
|
|
311
|
+
: await deps.resolveIosDownload();
|
|
304
312
|
if (!asset) {
|
|
305
313
|
res.status(404).json({ error: "当前没有可下载的 IPA 文件。" });
|
|
306
314
|
return;
|
|
307
315
|
}
|
|
308
316
|
// iOS 每次 debug 构建产出独立时间戳的 IPA,不清理会按构建次数堆积。
|
|
309
|
-
|
|
317
|
+
if (!appId)
|
|
318
|
+
await pruneQuietly(deps.pruneIosIpaDirectory?.bind(deps), asset.fileName, " iOS 构建包");
|
|
310
319
|
streamFileWithRange(req, res, {
|
|
311
320
|
filePath: asset.filePath,
|
|
312
321
|
size: asset.size,
|
|
@@ -316,9 +325,19 @@ export function registerPublicUpdateRoutes(app, deps, publicOrigin) {
|
|
|
316
325
|
});
|
|
317
326
|
}));
|
|
318
327
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
328
|
+
function iosAppId(req) {
|
|
329
|
+
if (req.query.app === undefined)
|
|
330
|
+
return undefined;
|
|
331
|
+
if (req.query.app !== "huniu-helper")
|
|
332
|
+
throw new HttpError(404, "unknown_app", "未知的 iOS 应用。");
|
|
333
|
+
return "huniu-helper";
|
|
334
|
+
}
|
|
335
|
+
async function resolveIosOtaPayload(req, deps, publicOrigin, selection) {
|
|
336
|
+
const appId = selection ? selection.appId : iosAppId(req);
|
|
337
|
+
const local = appId
|
|
338
|
+
? await deps.resolveIosAppDownload?.(appId, selection ? undefined : text(req.query.fileName) || undefined)
|
|
339
|
+
: await deps.resolveIosDownload();
|
|
340
|
+
const latest = appId ? null : await deps.resolveLatestIpa();
|
|
322
341
|
if (!latest && !local)
|
|
323
342
|
return null;
|
|
324
343
|
// Explicit ?origin= wins; then the deployment's configured publicOrigin
|
|
@@ -334,13 +353,17 @@ async function resolveIosOtaPayload(req, deps, publicOrigin) {
|
|
|
334
353
|
const size = local?.size ?? latest?.size ?? 0;
|
|
335
354
|
const latestVersion = latest?.version ?? "0.0.0";
|
|
336
355
|
const metadata = local
|
|
337
|
-
? await inspectIpa(local.filePath, { version: latestVersion }).catch(() =>
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
356
|
+
? await inspectIpa(local.filePath, { version: latestVersion }).catch((error) => {
|
|
357
|
+
if (appId)
|
|
358
|
+
throw error;
|
|
359
|
+
return {
|
|
360
|
+
bundleId: "com.wand.app",
|
|
361
|
+
bundleVersion: latestVersion,
|
|
362
|
+
bundleBuild: latestVersion,
|
|
363
|
+
title: "Wand",
|
|
364
|
+
signed: false,
|
|
365
|
+
};
|
|
366
|
+
})
|
|
344
367
|
: {
|
|
345
368
|
bundleId: "com.wand.app",
|
|
346
369
|
bundleVersion: latestVersion,
|
|
@@ -348,10 +371,17 @@ async function resolveIosOtaPayload(req, deps, publicOrigin) {
|
|
|
348
371
|
title: "Wand",
|
|
349
372
|
signed: false,
|
|
350
373
|
};
|
|
351
|
-
|
|
374
|
+
if (appId && metadata.bundleId !== "dev.tigertools.PlaylistBridge") {
|
|
375
|
+
throw new HttpError(503, "invalid_app_package", "所选 iOS 安装包身份不匹配。");
|
|
376
|
+
}
|
|
377
|
+
// Pin both manifest and IPA: publishing a new build must not change an in-flight install.
|
|
378
|
+
const suffix = appId ? `?app=${appId}&fileName=${encodeURIComponent(fileName)}` : "";
|
|
379
|
+
const downloadPath = appId ? `/ios/download${suffix}` : (latest?.downloadUrl ?? "/ios/download");
|
|
352
380
|
const downloadUrl = origin ? absoluteUrl(origin, downloadPath) : downloadPath;
|
|
353
|
-
const
|
|
354
|
-
const
|
|
381
|
+
const manifestPath = `/ios/manifest.plist${suffix}`;
|
|
382
|
+
const installPath = appId ? `/ios/install?app=${appId}` : "/ios/install";
|
|
383
|
+
const manifestUrl = origin ? absoluteUrl(origin, manifestPath) : manifestPath;
|
|
384
|
+
const installPageUrl = origin ? absoluteUrl(origin, installPath) : installPath;
|
|
355
385
|
const blockers = collectIosOtaBlockers({
|
|
356
386
|
signed: metadata.signed,
|
|
357
387
|
origin,
|
|
@@ -367,6 +397,7 @@ async function resolveIosOtaPayload(req, deps, publicOrigin) {
|
|
|
367
397
|
});
|
|
368
398
|
return {
|
|
369
399
|
latestVersion: metadata.bundleVersion || latestVersion,
|
|
400
|
+
bundleBuild: metadata.bundleBuild,
|
|
370
401
|
downloadUrl,
|
|
371
402
|
installUrl: origin ? buildItmsServicesUrl(manifestUrl) : null,
|
|
372
403
|
manifestUrl,
|
|
@@ -383,6 +414,20 @@ async function resolveIosOtaPayload(req, deps, publicOrigin) {
|
|
|
383
414
|
manifest,
|
|
384
415
|
};
|
|
385
416
|
}
|
|
417
|
+
async function resolveIosInstallLinks(req, deps, publicOrigin) {
|
|
418
|
+
const currentApp = iosAppId(req);
|
|
419
|
+
const selections = [{}, { appId: "huniu-helper" }];
|
|
420
|
+
// One missing/broken package must not hide the other app's valid installer.
|
|
421
|
+
const results = await Promise.allSettled(selections.map(selection => resolveIosOtaPayload(req, deps, publicOrigin, selection)));
|
|
422
|
+
return results.flatMap((result, index) => {
|
|
423
|
+
if (result.status !== "fulfilled" || !result.value?.otaReady)
|
|
424
|
+
return [];
|
|
425
|
+
return [{
|
|
426
|
+
title: result.value.title, url: result.value.installPageUrl,
|
|
427
|
+
current: selections[index].appId === currentApp,
|
|
428
|
+
}];
|
|
429
|
+
});
|
|
430
|
+
}
|
|
386
431
|
export class ServerUpdateState {
|
|
387
432
|
providerCliUpdateCache = null;
|
|
388
433
|
providerCliUpdateInFlight = false;
|
|
@@ -227,7 +227,7 @@ function workspaceWithCounts(storage, workspace, sessionCounts, includeArchived
|
|
|
227
227
|
const worktreeCount = storage.listWorkspaceTasks(workspace.id)
|
|
228
228
|
.filter((task) => (includeArchived || !task.archived) && task.worktree !== null)
|
|
229
229
|
.length;
|
|
230
|
-
const sessionCount = (sessionCounts ?? storage.countSessionsByWorkspace({ includeArchived, excludeSystemAiCalls: true })).get(workspace.id) ?? 0;
|
|
230
|
+
const sessionCount = (sessionCounts ?? storage.countSessionsByWorkspace({ includeArchived, excludeSystemAiCalls: true, excludeQuickTerminals: true })).get(workspace.id) ?? 0;
|
|
231
231
|
return { ...workspace, worktreeCount, sessionCount };
|
|
232
232
|
}
|
|
233
233
|
// ── Layout validation / sanitization(前端 PUT 与测试共用)──
|
|
@@ -341,7 +341,7 @@ export function registerWorkspaceRoutes(app, storage, sessions, titleOptions = {
|
|
|
341
341
|
// 列出所有项目(按创建时间降序:新建在前,打开不会改位置)
|
|
342
342
|
app.get("/api/workspaces", (req, res) => {
|
|
343
343
|
const includeArchived = req.query.includeArchived === "1";
|
|
344
|
-
const sessionCounts = storage.countSessionsByWorkspace({ includeArchived, excludeSystemAiCalls: true });
|
|
344
|
+
const sessionCounts = storage.countSessionsByWorkspace({ includeArchived, excludeSystemAiCalls: true, excludeQuickTerminals: true });
|
|
345
345
|
res.json(storage.listWorkspaces()
|
|
346
346
|
.filter((workspace) => !isGlobalWorkspace(workspace))
|
|
347
347
|
.map((workspace) => workspaceWithCounts(storage, workspace, sessionCounts, includeArchived)));
|
|
@@ -380,7 +380,7 @@ export function registerWorkspaceRoutes(app, storage, sessions, titleOptions = {
|
|
|
380
380
|
const archivedTaskIds = new Set(storage.listWorkspaceTasks(workspace.id)
|
|
381
381
|
.filter((task) => task.archived).map((task) => task.id));
|
|
382
382
|
const teamMarkers = teamSessionMarkers(storage);
|
|
383
|
-
const visibleSessions = storage.listSessionsByWorkspaceSlim(workspace.id).filter((session) => !isSystemAiCall(session)).map((session) => ({
|
|
383
|
+
const visibleSessions = storage.listSessionsByWorkspaceSlim(workspace.id).filter((session) => !isSystemAiCall(session) && session.sessionSource !== "quick-terminal").map((session) => ({
|
|
384
384
|
...workspaceSessionSummary(session, { workspaceName: workspace.name }, sessions, teamMarkersFor(teamMarkers, session.id)),
|
|
385
385
|
workspaceTaskId: session.workspaceTaskId,
|
|
386
386
|
})).filter((session) => includeArchived || (!session.archived
|
|
@@ -614,7 +614,7 @@ export function registerWorkspaceRoutes(app, storage, sessions, titleOptions = {
|
|
|
614
614
|
// Server-owned one-shot feature logs are not Agent work. Do not filter by employee,
|
|
615
615
|
// sessionSource=automation or generic automation IDs: those also carry dispatch,
|
|
616
616
|
// communication and scheduled work. Keep storage and employee audit history intact.
|
|
617
|
-
const sessionVisible = (session) => !isSystemAiCall(session)
|
|
617
|
+
const sessionVisible = (session) => !isSystemAiCall(session) && session.sessionSource !== "quick-terminal"
|
|
618
618
|
&& (includeArchived || !session.archived);
|
|
619
619
|
const workspaces = [...model.workspaces.values()];
|
|
620
620
|
// 群聊与成员派发标记一次查全:列表里每条会话只做 Map 命中,不逐个查库。
|
|
@@ -925,7 +925,7 @@ export function registerWorkspaceRoutes(app, storage, sessions, titleOptions = {
|
|
|
925
925
|
const workspace = storage.getWorkspace(task.workspaceId);
|
|
926
926
|
const teamMarkers = teamSessionMarkers(storage);
|
|
927
927
|
const card = storage.getWandTaskByWorkspaceTaskId(task.id);
|
|
928
|
-
const taskSessions = storage.listSessionsByWorkspaceTaskSlim(task.id).filter(session => !isSystemAiCall(session))
|
|
928
|
+
const taskSessions = storage.listSessionsByWorkspaceTaskSlim(task.id).filter(session => !isSystemAiCall(session) && session.sessionSource !== "quick-terminal")
|
|
929
929
|
.map(session => liveSession(session, sessions));
|
|
930
930
|
res.json({
|
|
931
931
|
...task,
|
package/dist/server.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerKnowledgeRoutes } from "./server-knowledge-routes.js";
|
|
1
2
|
import { OpenRouterFreeModelsService } from "./openrouter-free-models.js";
|
|
2
3
|
import { OpenCodeFreeModelsService, registerOpenCodeFreePool, adoptSystemOpenCodeFreeDefault } from "./opencode-system-fallback.js";
|
|
3
4
|
import { OPENCODE_FREE_GROUP_ID, OPENCODE_FREE_GROUP_NAME } from "./opencode-free-selection.js";
|
|
@@ -419,7 +420,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
419
420
|
storage, config, structured: structuredSessions, processes, sessions: sessionRegistry,
|
|
420
421
|
});
|
|
421
422
|
structuredSessions.setEmployeeInputAdmission({
|
|
422
|
-
canStart: (session, scheduling) => taskExecutionQueue.canStartSession(session, scheduling),
|
|
423
|
+
canStart: (session, scheduling, immediate) => taskExecutionQueue.canStartSession(session, scheduling, immediate),
|
|
423
424
|
schedule: employeeId => taskExecutionQueue.scheduleDrain(employeeId),
|
|
424
425
|
});
|
|
425
426
|
let apnsConfiguration = null;
|
|
@@ -688,6 +689,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
688
689
|
executionQueue: taskExecutionQueue,
|
|
689
690
|
notifyEmployeeChanged: (employeeId) => notifyAiTeamRun({ kind: "silicon-employee-definition", employeeId }),
|
|
690
691
|
});
|
|
692
|
+
registerKnowledgeRoutes(app, storage);
|
|
691
693
|
registerEmployeeImRoutes(app, { storage, im: employeeIm, requireAdmin });
|
|
692
694
|
registerDingTalkRoutes(app, { service: dingtalk, requireAdmin, install: () => dingtalkDws.install() });
|
|
693
695
|
registerAttentionRoutes(app, { sessions: sessionRegistry, runner: aiTeams });
|
|
@@ -1074,7 +1076,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
1074
1076
|
}, MODEL_CATALOG_AUTO_REFRESH_INTERVAL_MS);
|
|
1075
1077
|
modelCatalogRefreshTimer.unref();
|
|
1076
1078
|
}
|
|
1077
|
-
//
|
|
1079
|
+
// 每次扫描读取当前保留窗口;未完成、待验收和升级前任务归档不进入自动清理。
|
|
1078
1080
|
// 保存任务保留设置后走同一条扫描,不等下一小时。
|
|
1079
1081
|
const retentionDeps = {
|
|
1080
1082
|
storage,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConversationTurn, SessionSnapshot, StructuredQuestion, ToolUseBlock } from "./types.js";
|
|
2
|
+
export declare function sessionToolQuestions(block: ToolUseBlock): StructuredQuestion[];
|
|
3
|
+
/** One source session, latest assistant request only. Historical cards stay read-only. */
|
|
4
|
+
export declare function pendingSessionQuestions(session: Pick<SessionSnapshot, "status"> & {
|
|
5
|
+
archived?: boolean;
|
|
6
|
+
messages?: ConversationTurn[];
|
|
7
|
+
}): ToolUseBlock[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function sessionToolQuestions(block) {
|
|
2
|
+
if (block.semantic?.kind === "question_request")
|
|
3
|
+
return block.semantic.questions;
|
|
4
|
+
// Legacy Claude recordings predate the semantic projection.
|
|
5
|
+
if (block.name === "AskUserQuestion" && Array.isArray(block.input.questions))
|
|
6
|
+
return block.input.questions;
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
/** One source session, latest assistant request only. Historical cards stay read-only. */
|
|
10
|
+
export function pendingSessionQuestions(session) {
|
|
11
|
+
if (session.archived || ["failed", "stopped", "exited"].includes(session.status))
|
|
12
|
+
return [];
|
|
13
|
+
const turns = session.messages ?? [];
|
|
14
|
+
const results = new Set(turns.flatMap(turn => turn.content.flatMap(block => block.type === "tool_result" ? [block.tool_use_id] : [])));
|
|
15
|
+
for (let index = turns.length - 1; index >= 0; index--) {
|
|
16
|
+
const turn = turns[index];
|
|
17
|
+
if (turn.role === "user" && turn.content.some(block => block.type === "text" && block.text.trim()))
|
|
18
|
+
return [];
|
|
19
|
+
if (turn.role !== "assistant")
|
|
20
|
+
continue;
|
|
21
|
+
return turn.content.filter((block) => block.type === "tool_use"
|
|
22
|
+
&& sessionToolQuestions(block).length > 0 && !results.has(block.id));
|
|
23
|
+
}
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
@@ -39,6 +39,9 @@ export declare class SessionRegistry {
|
|
|
39
39
|
ownerOf(id: string): SessionOwner | null;
|
|
40
40
|
get(id: string): SessionSnapshot | null;
|
|
41
41
|
getLatest(id: string): SessionSnapshot | null;
|
|
42
|
+
claimQuickTerminal(id: string): SessionSnapshot;
|
|
43
|
+
/** Read-only runtime owner. Never hydrate a stored transcript to discover actions. */
|
|
44
|
+
getRuntimeSnapshot(id: string): SessionSnapshot | null;
|
|
42
45
|
/** Runtime facts and membership only; list/policy reads must not hydrate transcripts. */
|
|
43
46
|
getSlim(id: string): SessionSnapshot | null;
|
|
44
47
|
listSlim(options?: {
|
package/dist/session-registry.js
CHANGED
|
@@ -6,6 +6,8 @@ import { systemAiSessions } from "./system-ai-session-recorder.js";
|
|
|
6
6
|
import { cleanupWorktreeSync } from "./git-worktree.js";
|
|
7
7
|
import { inferProviderFromCommand } from "./session-provider.js";
|
|
8
8
|
import { enrichStructuredMessages } from "./structured-client-protocol.js";
|
|
9
|
+
import { canClaimQuickTerminal } from "./quick-terminal-session.js";
|
|
10
|
+
import { badRequest, notFound } from "./http-error.js";
|
|
9
11
|
export function deleteProviderNativeHistory(deleter, provider, providerSessionId, cwd) {
|
|
10
12
|
const id = providerSessionId.trim();
|
|
11
13
|
if (!id)
|
|
@@ -168,6 +170,21 @@ export class SessionRegistry {
|
|
|
168
170
|
getLatest(id) {
|
|
169
171
|
return this.get(id);
|
|
170
172
|
}
|
|
173
|
+
claimQuickTerminal(id) {
|
|
174
|
+
const snapshot = this.get(id);
|
|
175
|
+
if (!snapshot)
|
|
176
|
+
throw notFound("未找到该终端,可能已被删除。");
|
|
177
|
+
if (!canClaimQuickTerminal(snapshot))
|
|
178
|
+
throw badRequest("只有普通空白终端可以作为快捷终端。");
|
|
179
|
+
const updated = this.storage.claimQuickTerminal(id);
|
|
180
|
+
if (this.processes.getOwned(id))
|
|
181
|
+
this.processes.setSessionSource(id, updated.sessionSource);
|
|
182
|
+
return this.get(id);
|
|
183
|
+
}
|
|
184
|
+
/** Read-only runtime owner. Never hydrate a stored transcript to discover actions. */
|
|
185
|
+
getRuntimeSnapshot(id) {
|
|
186
|
+
return this.structured.get(id) ?? this.processes.getOwned(id) ?? null;
|
|
187
|
+
}
|
|
171
188
|
/** Runtime facts and membership only; list/policy reads must not hydrate transcripts. */
|
|
172
189
|
getSlim(id) {
|
|
173
190
|
const snapshot = this.structured.getSlim(id) ?? this.processes.getOwnedSlim(id) ?? this.storage.getSessionSlim(id);
|
|
@@ -3,7 +3,7 @@ export declare function parseExecutionMode(value: unknown, fallback: ExecutionMo
|
|
|
3
3
|
export declare function parseSessionCreationOrigin(body: {
|
|
4
4
|
sessionSource?: unknown;
|
|
5
5
|
automationId?: unknown;
|
|
6
|
-
} | null | undefined): {
|
|
6
|
+
} | null | undefined, allowQuickTerminal?: boolean): {
|
|
7
7
|
sessionSource: SessionSource;
|
|
8
8
|
automationId?: string;
|
|
9
9
|
};
|
package/dist/session-request.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isExecutionMode } from "./config.js";
|
|
2
2
|
import { isSystemAiCall } from "./system-ai-call.js";
|
|
3
|
+
import { badRequest } from "./http-error.js";
|
|
3
4
|
export function parseExecutionMode(value, fallback) {
|
|
4
5
|
if (value === undefined)
|
|
5
6
|
return fallback;
|
|
@@ -8,9 +9,12 @@ export function parseExecutionMode(value, fallback) {
|
|
|
8
9
|
}
|
|
9
10
|
return value;
|
|
10
11
|
}
|
|
11
|
-
export function parseSessionCreationOrigin(body) {
|
|
12
|
+
export function parseSessionCreationOrigin(body, allowQuickTerminal = false) {
|
|
12
13
|
const rawSource = body?.sessionSource;
|
|
13
|
-
if (rawSource
|
|
14
|
+
if (rawSource === "quick-terminal" && (!allowQuickTerminal || body?.automationId !== undefined)) {
|
|
15
|
+
throw badRequest("快捷终端只允许无自动化绑定的空白 PTY shell。");
|
|
16
|
+
}
|
|
17
|
+
if (rawSource !== undefined && rawSource !== "interactive" && rawSource !== "automation" && rawSource !== "startup" && rawSource !== "quick-terminal") {
|
|
14
18
|
throw new Error("sessionSource 必须是 interactive、automation 或 startup。");
|
|
15
19
|
}
|
|
16
20
|
const rawAutomationId = body?.automationId;
|
package/dist/session-service.js
CHANGED
|
@@ -102,7 +102,7 @@ export function sessionSortTimestamp(snapshot) {
|
|
|
102
102
|
return Number.isFinite(timestamp) ? timestamp : 0;
|
|
103
103
|
}
|
|
104
104
|
export function buildSessionListEntries(sessions) {
|
|
105
|
-
return sessions.map((session) => ({
|
|
105
|
+
return sessions.filter(session => session.sessionSource !== "quick-terminal").map((session) => ({
|
|
106
106
|
type: "managed",
|
|
107
107
|
key: `session-${session.id}`,
|
|
108
108
|
sortTimestamp: sessionSortTimestamp(session),
|
|
@@ -262,15 +262,18 @@ export class EmployeeRepository {
|
|
|
262
262
|
if (accessToken && this.resolveEmployeeKnowledgeAccess(accessToken) !== employeeId) {
|
|
263
263
|
throw new Error("知识库访问已失效,请等待新的会话执行。");
|
|
264
264
|
}
|
|
265
|
-
|
|
265
|
+
const deleted = this.db.prepare("DELETE FROM employee_knowledge WHERE employee_id = ? AND id = ?")
|
|
266
266
|
.run(employeeId, entryId).changes === 1;
|
|
267
|
+
if (deleted)
|
|
268
|
+
this.s.invalidateKnowledgeNamespace("personal", employeeId);
|
|
269
|
+
return deleted;
|
|
267
270
|
});
|
|
268
271
|
}
|
|
269
272
|
clearEmployeeKnowledge(employeeId) {
|
|
270
273
|
this.s.transaction(() => {
|
|
271
274
|
this.requireKnowledgeEmployee(employeeId);
|
|
272
275
|
this.db.prepare("DELETE FROM employee_knowledge WHERE employee_id = ?").run(employeeId);
|
|
273
|
-
this.
|
|
276
|
+
this.s.invalidateKnowledgeNamespace("personal", employeeId);
|
|
274
277
|
});
|
|
275
278
|
}
|
|
276
279
|
/** Opaque per-execution capability: no employee selector, app token or DB secret in model prompts. */
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
2
|
+
import type { WandStorage } from "../storage.js";
|
|
3
|
+
import { type KnowledgeAccess, type KnowledgeDocument, type KnowledgeDocumentInput, type KnowledgeLibrary, type KnowledgeScope } from "../knowledge-types.js";
|
|
4
|
+
export declare class KnowledgeRepository {
|
|
5
|
+
#private;
|
|
6
|
+
private readonly db;
|
|
7
|
+
private readonly s;
|
|
8
|
+
constructor(db: DatabaseSync, s: WandStorage);
|
|
9
|
+
knowledgeOwners(): {
|
|
10
|
+
employees: Array<{
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
}>;
|
|
14
|
+
projects: Array<{
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
readOnly: boolean;
|
|
18
|
+
}>;
|
|
19
|
+
};
|
|
20
|
+
readKnowledgeLibrary(scope: KnowledgeScope, ownerId: string, query?: string, accessToken?: string): KnowledgeLibrary;
|
|
21
|
+
getKnowledgeDocument(scope: KnowledgeScope, ownerId: string, id: string, accessToken?: string): KnowledgeDocument;
|
|
22
|
+
createKnowledgeDocument(scope: KnowledgeScope, ownerId: string, input: KnowledgeDocumentInput, accessToken?: string): {
|
|
23
|
+
entry: KnowledgeDocument;
|
|
24
|
+
created: boolean;
|
|
25
|
+
};
|
|
26
|
+
updateKnowledgeDocument(scope: KnowledgeScope, ownerId: string, id: string, revision: number, input: KnowledgeDocumentInput, accessToken?: string): KnowledgeDocument;
|
|
27
|
+
deleteKnowledgeDocument(scope: KnowledgeScope, ownerId: string, id: string, revision: number, accessToken?: string): void;
|
|
28
|
+
invalidateKnowledgeNamespace(scope: KnowledgeScope, ownerId: string): void;
|
|
29
|
+
/** Only persisted bindings count; legacy UI identity projections are not authority. */
|
|
30
|
+
knowledgeSessionScope(sessionId: string): KnowledgeAccess | null;
|
|
31
|
+
issueKnowledgeAccess(sessionId: string, now?: number): string;
|
|
32
|
+
resolveKnowledgeAccess(token: string, now?: number): KnowledgeAccess | null;
|
|
33
|
+
revokeKnowledgeAccess(token: string): void;
|
|
34
|
+
revokeSessionKnowledgeAccess(sessionId: string): void;
|
|
35
|
+
}
|