@jetcrab/pi-desk 1.1.25 → 1.1.29-dev
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/package.json +1 -1
- package/src/app/api/work-sessions/search/route.ts +1 -0
- package/src/app/project-preview/page.tsx +1 -3
- package/src/client/l2_biz/project-preview/hooks/l2-use-project-preview.ts +1 -14
- package/src/client/l2_biz/project-preview/l2-project-preview-dialog.tsx +0 -1
- package/src/client/l2_biz/project-preview/l2-project-preview-page.tsx +0 -1
- package/src/client/l2_biz/project-preview/l2-project-preview.tsx +1 -4
- package/src/client/l2_biz/project-preview/views/l2-project-branch-select.tsx +42 -3
- package/src/client/l2_biz/workbench/git-workspace/l2-git-workspace-runtime.ts +11 -10
- package/src/client/l2_biz/workbench/hooks/l2-work-session-search.ts +52 -0
- package/src/client/l2_biz/workbench/hooks/l2-workbench-branch-picker.ts +42 -7
- package/src/client/l2_biz/workbench/hooks/l2-workbench-session-history.ts +143 -131
- package/src/client/l2_biz/workbench/hooks/l2-workbench-session-search.ts +97 -0
- package/src/client/l2_biz/workbench/l2-work-session-columns.tsx +8 -0
- package/src/client/l2_biz/workbench/l2-work-session-sidebar.tsx +129 -10
- package/src/client/l2_biz/workbench/l2-workbench-biz.ts +20 -2
- package/src/client/l2_biz/workbench/l2-workbench-branch-filter-preferences.ts +34 -0
- package/src/client/l2_biz/workbench/l2-workbench-branch-picker.tsx +34 -71
- package/src/client/l2_biz/workbench/l2-workbench-chat-input-runtime.ts +38 -1
- package/src/client/l2_biz/workbench/l2-workbench-chat-view.tsx +11 -1
- package/src/client/l2_biz/workbench/l2-workbench-picker-dialog.tsx +55 -215
- package/src/client/l2_biz/workbench/l2-workbench.tsx +20 -38
- package/src/client/l2_biz/workbench/views/l2-workbench-session-search.tsx +123 -0
- package/src/client/l3_modules/conversation/l3-conversation-messages.tsx +43 -4
- package/src/client/l3_modules/project-files/l3-markdown-preview.module.css +1 -1
- package/src/client/l3_modules/project-files/l3-project-document-git.ts +13 -29
- package/src/client/l3_modules/project-files/l3-project-document-view.tsx +1 -4
- package/src/client/l3_modules/project-files/l3-project-file-browser.module.css +14 -18
- package/src/client/l3_modules/project-files/l3-project-file-browser.tsx +52 -95
- package/src/client/l3_modules/project-files/l3-project-file-runtime.ts +52 -21
- package/src/client/l3_modules/project-files/l3-project-file-tabs.tsx +41 -62
- package/src/client/l3_modules/project-files/l3-project-git-runtime.ts +5 -4
- package/src/client/l3_modules/project-files/l3-use-project-refresh.ts +36 -0
- package/src/client/l3_modules/project-files/views/l3-project-search-results.tsx +2 -2
- package/src/client/l3_modules/project-files/views/l3-project-tree-folder.tsx +86 -0
- package/src/client/l4_foundation/ui/file-icons/README.md +1 -1
- package/src/client/l4_foundation/ui/file-icons/l4-file-icon.tsx +49 -2
- package/src/common/l2_biz/pi-session/l2-pi-session-contract.ts +11 -24
- package/src/common/l2_biz/project-preview/l2-project-preview-navigation.ts +5 -12
- package/src/common/l2_biz/work-session/l2-work-session-search-contract.ts +26 -0
- package/src/common/l2_biz/work-session/l2-work-session-tree-contract.ts +9 -1
- package/src/common/l2_biz/workbench/l2-workbench-locale-messages.ts +12 -0
- package/src/common/l2_biz/workbench/l2-workbench-picker-messages.ts +6 -2
- package/src/common/l3_modules/conversation/l3-conversation-locale-messages.ts +2 -0
- package/src/common/l3_modules/pi/l3-pi-session-search-contract.ts +26 -0
- package/src/common/l4_foundation/locale/l4-host-error-messages.ts +2 -0
- package/src/server/l1_entry/api/l1-work-session-branch-route.ts +21 -15
- package/src/server/l1_entry/api/l1-work-session-search-route.ts +38 -0
- package/src/server/l2_biz/work-session/l2-work-session-chat-runtime.ts +4 -2
- package/src/server/l2_biz/work-session/l2-work-session-manage.ts +46 -10
- package/src/server/l3_modules/work-session/l3-work-session.ts +11 -6
- package/src/server/l4_foundation/pi/l4-pi-chat-worker.ts +35 -2
- package/src/server/l4_foundation/pi/l4-pi-session-history-catalog.ts +62 -113
- package/src/server/l4_foundation/pi/l4-pi-session-search.ts +166 -0
- package/src/server/l4_foundation/pi/l4-pi-work-session-runtime.ts +66 -5
- package/src/server/l4_foundation/process/l4-process-tree.js +159 -40
- package/temp/build/pi-desk/release/.next/BUILD_ID +1 -1
- package/temp/build/pi-desk/release/.next/app-path-routes-manifest.json +1 -0
- package/temp/build/pi-desk/release/.next/build-manifest.json +2 -2
- package/temp/build/pi-desk/release/.next/prerender-manifest.json +3 -3
- package/temp/build/pi-desk/release/.next/required-server-files.js +3 -3
- package/temp/build/pi-desk/release/.next/required-server-files.json +3 -3
- package/temp/build/pi-desk/release/.next/routes-manifest.json +6 -0
- package/temp/build/pi-desk/release/.next/server/app/_global-error/page.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.html +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_not-found/page.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/auth/login/route.js +2 -2
- package/temp/build/pi-desk/release/.next/server/app/api/auth/logout/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/auth-settings/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/auth-settings/replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/capability-modes/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/capability-modes/replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/chat/context/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/chat/images/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/chat/messages/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/health/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/mcp-check/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/mcp-settings/del/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/mcp-settings/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/mcp-settings/replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/model-catalog/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/model-settings/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/model-settings/preview/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/model-settings/replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/pi/directories/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/pi/directory-entries/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/pi/directory-ignores/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/pi/directory-ignores/replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/pi/models/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/pi/session-user-messages/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/pi/sessions/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/search/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/settings-get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/settings-replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/add/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/apply/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/batch/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/browser-resources/[resourceGroup]/[...resourcePath]/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/del/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/enabled-set/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/host-runtime/[runtimeVersion]/[...resourcePath]/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/reload/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/update/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-files/get/route.js +2 -2
- package/temp/build/pi-desk/release/.next/server/app/api/project-files/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-files/reveal/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-files/search/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-git/get/route.js +2 -2
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-branches/list/route.js +2 -2
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-changes/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-diff/get/route.js +2 -2
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-heads/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-log/list/route.js +2 -2
- package/temp/build/pi-desk/release/.next/server/app/api/project-model-default/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-model-default/replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/skill-files/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/skill-files/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/skill-files/replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/skills/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/task-center/images/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/task-center/messages/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-session-git-branch/add/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-session-git-branch/replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-session-tree/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-session-tree-entry/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/add/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/branch/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/del/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/rename/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/replace/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/search/route.js +1 -0
- package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/search/route_client-reference-manifest.js +1 -0
- package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/sort/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/favicon.ico/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/login/page.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/page.js +138 -138
- package/temp/build/pi-desk/release/.next/server/app/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/project-preview/page.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/project-preview/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app-paths-manifest.json +1 -0
- package/temp/build/pi-desk/release/.next/server/chunks/23054.js +2 -2
- package/temp/build/pi-desk/release/.next/server/chunks/25406.js +8 -8
- package/temp/build/pi-desk/release/.next/server/chunks/27344.js +3 -3
- package/temp/build/pi-desk/release/.next/server/chunks/3108.js +3 -3
- package/temp/build/pi-desk/release/.next/server/chunks/35985.js +2 -2
- package/temp/build/pi-desk/release/.next/server/chunks/41856.js +1 -0
- package/temp/build/pi-desk/release/.next/server/chunks/62900.js +235 -0
- package/temp/build/pi-desk/release/.next/server/chunks/6917.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/81363.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/81912.js +3 -0
- package/temp/build/pi-desk/release/.next/server/chunks/92386.js +2 -2
- package/temp/build/pi-desk/release/.next/server/middleware-build-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/pages/500.html +1 -1
- package/temp/build/pi-desk/release/.next/server/server-reference-manifest.json +1 -1
- package/temp/build/pi-desk/release/.next/static/Yyfg-r17aYmEzlYYlIwDo/_buildManifest.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/10043-9d6c3735418ccaf9.js +238 -0
- package/temp/build/pi-desk/release/.next/static/chunks/11937-ac71fb0f7cef482a.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/30669-ffa76d39e0e25194.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/36643-f60e98278740073c.js +3 -0
- package/temp/build/pi-desk/release/.next/static/chunks/65232-a8571f78020eede2.js +15 -0
- package/temp/build/pi-desk/release/.next/static/chunks/{51474-8dc714cb76b2e60a.js → 65350-23bb961d87addf14.js} +3 -3
- package/temp/build/pi-desk/release/.next/static/chunks/app/_global-error/page-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/_not-found/page-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/login/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/logout/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/context/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/images/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/messages/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/health/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-check/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/del/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-catalog/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/preview/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directories/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-entries/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/models/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/session-user-messages/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/sessions/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/search/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/add/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/apply/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/batch/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/browser-resources/[resourceGroup]/[...resourcePath]/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/del/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/enabled-set/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/host-runtime/[runtimeVersion]/[...resourcePath]/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/reload/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/update/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/reveal/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/search/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-branches/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-changes/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-diff/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-heads/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-log/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/skills/list/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/images/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/messages/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/add/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree-entry/get/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/add/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/branch/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/del/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/rename/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/replace/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/search/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/sort/route-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/layout-2c6a573d3004516e.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/login/{page-0d3d4827802108e5.js → page-0df9df996aa68060.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/page-f78be007d97f0d95.js +158 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/project-preview/{page-038b6c14e03ed878.js → page-e1dbfcfc0f333e01.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/app-error-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/forbidden-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/unauthorized-295cb63da5f7262f.js +1 -0
- package/temp/build/pi-desk/release/.next/static/css/{1e780a4936aa6ba3.css → 2bb393927ba8f71d.css} +1 -1
- package/temp/build/pi-desk/release/.next/static/css/3a07dcc86ffdf88c.css +1 -0
- package/temp/build/pi-desk/release/.next/static/css/a677e7fbf6e2173e.css +1 -0
- package/temp/build/pi-desk/release/.next/trace-build +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/35348.js +0 -3
- package/temp/build/pi-desk/release/.next/server/chunks/56830.js +0 -235
- package/temp/build/pi-desk/release/.next/server/chunks/80780.js +0 -1
- package/temp/build/pi-desk/release/.next/static/6a4eIEjmpW5l8Qlgtzzzg/_buildManifest.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/11937-1d0a9822f2c7995b.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/14197-3d3ddd426ac06c9c.js +0 -3
- package/temp/build/pi-desk/release/.next/static/chunks/37313-d5970e2d0c270d22.js +0 -238
- package/temp/build/pi-desk/release/.next/static/chunks/65232-ef4e5a4174f62faf.js +0 -15
- package/temp/build/pi-desk/release/.next/static/chunks/79267-7d21d7cdbd7cfca1.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/_global-error/page-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/_not-found/page-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/login/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/logout/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/context/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/images/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/messages/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/health/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-check/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/del/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-catalog/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/preview/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directories/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-entries/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/models/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/session-user-messages/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/sessions/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/search/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/add/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/apply/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/batch/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/browser-resources/[resourceGroup]/[...resourcePath]/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/del/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/enabled-set/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/host-runtime/[runtimeVersion]/[...resourcePath]/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/reload/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/update/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/reveal/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/search/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-branches/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-changes/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-diff/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-heads/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-log/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/skills/list/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/images/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/messages/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/add/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree-entry/get/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/add/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/branch/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/del/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/rename/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/replace/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/sort/route-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/layout-20718f1503910291.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/page-18d63fd3920dfae0.js +0 -158
- package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/app-error-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/forbidden-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/unauthorized-9969fe0baa238786.js +0 -1
- package/temp/build/pi-desk/release/.next/static/css/2c3b0c0ff1f49c68.css +0 -1
- package/temp/build/pi-desk/release/.next/static/css/c43b04c244a64fb4.css +0 -1
- /package/temp/build/pi-desk/release/.next/static/{6a4eIEjmpW5l8Qlgtzzzg → Yyfg-r17aYmEzlYYlIwDo}/_ssgManifest.js +0 -0
|
@@ -26,13 +26,20 @@ import {
|
|
|
26
26
|
} from '@earendil-works/pi-coding-agent'
|
|
27
27
|
import { z } from 'zod'
|
|
28
28
|
import { findL4PiSessionFile } from './l4-pi-session-discovery'
|
|
29
|
+
import {
|
|
30
|
+
compactL4PiSessionPreview as compactPreview,
|
|
31
|
+
matchL4PiSessionSearch,
|
|
32
|
+
normalizeL4PiSessionSearch as normalizeSearch,
|
|
33
|
+
readL4PiSessionMessageText as messageText,
|
|
34
|
+
readL4PiSessionTimestamp as timestampMs,
|
|
35
|
+
type L4PiSessionSearchMatch,
|
|
36
|
+
type L4PiSessionSearchScope
|
|
37
|
+
} from './l4-pi-session-search'
|
|
29
38
|
|
|
30
39
|
const SCAN_CONCURRENCY = 10
|
|
31
|
-
const MATCH_PREVIEW_MAX_LENGTH = 120
|
|
32
|
-
const MATCH_PREVIEW_PREFIX_LENGTH = 16
|
|
33
40
|
const FIRST_MESSAGE_PREVIEW_MAX_LENGTH = 160
|
|
34
41
|
const CACHE_VALIDATION_INTERVAL_MS = 2_000
|
|
35
|
-
const CACHE_IDLE_MS =
|
|
42
|
+
const CACHE_IDLE_MS = 60_000
|
|
36
43
|
const CACHE_CWD_LIMIT = 8
|
|
37
44
|
const CACHE_TEXT_BYTES_LIMIT = 32 * 1024 * 1024
|
|
38
45
|
const CACHE_FILE_LIMIT = 4_096
|
|
@@ -41,7 +48,7 @@ const LEGACY_CACHE_FILE_NAME = 'pi-session-history.json'
|
|
|
41
48
|
const PERSISTED_CACHE_VERSION = 2
|
|
42
49
|
const CACHE_DISK_BYTES_LIMIT = 64 * 1024 * 1024
|
|
43
50
|
|
|
44
|
-
export type L4PiSessionHistorySearchScope =
|
|
51
|
+
export type L4PiSessionHistorySearchScope = L4PiSessionSearchScope
|
|
45
52
|
|
|
46
53
|
const DEFAULT_SEARCH_IN: readonly L4PiSessionHistorySearchScope[] = ['title', 'user']
|
|
47
54
|
|
|
@@ -72,13 +79,7 @@ interface L4PiSessionAssistantMessage {
|
|
|
72
79
|
text: string
|
|
73
80
|
}
|
|
74
81
|
|
|
75
|
-
export
|
|
76
|
-
scope: L4PiSessionHistorySearchScope
|
|
77
|
-
count: number
|
|
78
|
-
entryId: string | null
|
|
79
|
-
timestampMs: number | null
|
|
80
|
-
preview: string
|
|
81
|
-
}
|
|
82
|
+
export type L4PiSessionHistoryMatch = L4PiSessionSearchMatch
|
|
82
83
|
|
|
83
84
|
export interface L4PiSessionHistoryItem {
|
|
84
85
|
sessionId: string
|
|
@@ -184,6 +185,7 @@ interface L4PiSessionHistoryCatalogState {
|
|
|
184
185
|
epochs: Map<string, number>
|
|
185
186
|
activeLoads: Map<string, L4PiSessionHistoryCatalogLoad>
|
|
186
187
|
catalogs: Map<string, L4PiSessionHistoryCatalog>
|
|
188
|
+
cleanupTimer: ReturnType<typeof setTimeout> | null
|
|
187
189
|
}
|
|
188
190
|
|
|
189
191
|
interface L4PiSessionScanState {
|
|
@@ -365,7 +367,8 @@ function historyCatalogState(): L4PiSessionHistoryCatalogState {
|
|
|
365
367
|
globalThis.__piDeskPiSessionHistoryCatalogState = {
|
|
366
368
|
epochs: new Map(),
|
|
367
369
|
activeLoads: new Map(),
|
|
368
|
-
catalogs: new Map()
|
|
370
|
+
catalogs: new Map(),
|
|
371
|
+
cleanupTimer: null
|
|
369
372
|
}
|
|
370
373
|
}
|
|
371
374
|
return globalThis.__piDeskPiSessionHistoryCatalogState
|
|
@@ -375,37 +378,6 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
375
378
|
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
376
379
|
}
|
|
377
380
|
|
|
378
|
-
function timestampMs(value: unknown): number | null {
|
|
379
|
-
if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0) return value
|
|
380
|
-
if (typeof value !== 'string') return null
|
|
381
|
-
const parsed = Date.parse(value)
|
|
382
|
-
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
function normalizeSearch(value: string): string {
|
|
386
|
-
return value.trim().toLowerCase()
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
function compactPreview(text: string, maxLength: number): string {
|
|
390
|
-
const content = text.replace(/\s+/g, ' ').trim()
|
|
391
|
-
if (content.length <= maxLength) return content
|
|
392
|
-
return `${content.slice(0, maxLength - 1).trimEnd()}…`
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
function messageText(message: unknown): string {
|
|
396
|
-
if (!isRecord(message)) return ''
|
|
397
|
-
const content = message.content
|
|
398
|
-
if (typeof content === 'string') return content
|
|
399
|
-
if (!Array.isArray(content)) return ''
|
|
400
|
-
|
|
401
|
-
return content
|
|
402
|
-
.flatMap((part) => {
|
|
403
|
-
if (!isRecord(part) || part.type !== 'text' || typeof part.text !== 'string') return []
|
|
404
|
-
return [part.text]
|
|
405
|
-
})
|
|
406
|
-
.join('\n')
|
|
407
|
-
}
|
|
408
|
-
|
|
409
381
|
function messageTimestamp(entry: Record<string, unknown>, fallback: number): number {
|
|
410
382
|
const entryTimestamp = timestampMs(entry.timestamp)
|
|
411
383
|
if (entryTimestamp !== null) return entryTimestamp
|
|
@@ -696,11 +668,31 @@ async function refreshCatalog(
|
|
|
696
668
|
}
|
|
697
669
|
}
|
|
698
670
|
|
|
699
|
-
function
|
|
700
|
-
|
|
671
|
+
function scheduleCatalogRelease(state: L4PiSessionHistoryCatalogState): void {
|
|
672
|
+
if (state.cleanupTimer) clearTimeout(state.cleanupTimer)
|
|
673
|
+
state.cleanupTimer = null
|
|
674
|
+
if (state.catalogs.size === 0) return
|
|
675
|
+
const expiresAt = Math.min(
|
|
676
|
+
...Array.from(state.catalogs.values(), (catalog) => catalog.lastAccessedAt + CACHE_IDLE_MS)
|
|
677
|
+
)
|
|
678
|
+
state.cleanupTimer = setTimeout(
|
|
679
|
+
() => {
|
|
680
|
+
state.cleanupTimer = null
|
|
681
|
+
pruneCatalogs(Date.now(), state)
|
|
682
|
+
},
|
|
683
|
+
Math.max(0, expiresAt - Date.now())
|
|
684
|
+
)
|
|
685
|
+
state.cleanupTimer.unref()
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
function pruneCatalogs(
|
|
689
|
+
now: number,
|
|
690
|
+
state: L4PiSessionHistoryCatalogState = historyCatalogState()
|
|
691
|
+
): void {
|
|
701
692
|
for (const [cwd, catalog] of state.catalogs) {
|
|
702
|
-
if (now - catalog.lastAccessedAt
|
|
693
|
+
if (now - catalog.lastAccessedAt >= CACHE_IDLE_MS) state.catalogs.delete(cwd)
|
|
703
694
|
}
|
|
695
|
+
scheduleCatalogRelease(state)
|
|
704
696
|
}
|
|
705
697
|
|
|
706
698
|
function touchCatalog(catalog: L4PiSessionHistoryCatalog, now: number): L4PiSessionHistoryCatalog {
|
|
@@ -708,6 +700,7 @@ function touchCatalog(catalog: L4PiSessionHistoryCatalog, now: number): L4PiSess
|
|
|
708
700
|
const state = historyCatalogState()
|
|
709
701
|
state.catalogs.delete(catalog.cwd)
|
|
710
702
|
state.catalogs.set(catalog.cwd, catalog)
|
|
703
|
+
scheduleCatalogRelease(state)
|
|
711
704
|
return catalog
|
|
712
705
|
}
|
|
713
706
|
|
|
@@ -715,6 +708,7 @@ function storeCatalog(catalog: L4PiSessionHistoryCatalog, persist: boolean): voi
|
|
|
715
708
|
const state = historyCatalogState()
|
|
716
709
|
if (catalog.files.size > CACHE_FILE_LIMIT || catalog.textBytes > CACHE_TEXT_BYTES_LIMIT) {
|
|
717
710
|
state.catalogs.delete(catalog.cwd)
|
|
711
|
+
scheduleCatalogRelease(state)
|
|
718
712
|
if (persist) {
|
|
719
713
|
const path = persistedHistoryCachePath(catalog.cwd)
|
|
720
714
|
try {
|
|
@@ -747,6 +741,7 @@ function storeCatalog(catalog: L4PiSessionHistoryCatalog, persist: boolean): voi
|
|
|
747
741
|
state.catalogs.delete(oldest[0])
|
|
748
742
|
totalBytes -= oldest[1].textBytes
|
|
749
743
|
}
|
|
744
|
+
scheduleCatalogRelease(state)
|
|
750
745
|
if (persist) persistHistoryCatalog(catalog)
|
|
751
746
|
}
|
|
752
747
|
|
|
@@ -768,8 +763,9 @@ async function getCatalog(
|
|
|
768
763
|
const state = historyCatalogState()
|
|
769
764
|
const now = Date.now()
|
|
770
765
|
pruneCatalogs(now)
|
|
771
|
-
const
|
|
772
|
-
const
|
|
766
|
+
const cached = state.catalogs.get(cwd)
|
|
767
|
+
const catalog = cached ? touchCatalog(cached, now) : readPersistedHistoryCatalog(cwd)
|
|
768
|
+
const epoch = forceRefresh && state.activeLoads.has(cwd) ? incrementEpoch(cwd) : currentEpoch(cwd)
|
|
773
769
|
if (forceRefresh && catalog) catalog.dirty = true
|
|
774
770
|
const active = state.activeLoads.get(cwd)
|
|
775
771
|
if (active && active.epoch === epoch) return active.promise
|
|
@@ -783,10 +779,12 @@ async function getCatalog(
|
|
|
783
779
|
return touchCatalog(catalog, now)
|
|
784
780
|
}
|
|
785
781
|
|
|
786
|
-
const load = (async ()
|
|
782
|
+
const load: Promise<L4PiSessionHistoryCatalog> = Promise.resolve().then(async () => {
|
|
787
783
|
const refresh = await refreshCatalog(cwd, catalog)
|
|
788
784
|
const refreshed = refresh.catalog
|
|
789
|
-
if (currentEpoch(cwd) === epoch)
|
|
785
|
+
if (state.activeLoads.get(cwd)?.promise === load && currentEpoch(cwd) === epoch) {
|
|
786
|
+
storeCatalog(refreshed, refresh.changed)
|
|
787
|
+
}
|
|
790
788
|
console.info('[Pi Desk][PiSessionHistoryCatalog] 已更新历史会话内存投影', {
|
|
791
789
|
cwd,
|
|
792
790
|
sessionCount: refreshed.sessions.length,
|
|
@@ -795,43 +793,15 @@ async function getCatalog(
|
|
|
795
793
|
forceRefresh
|
|
796
794
|
})
|
|
797
795
|
return refreshed
|
|
798
|
-
})
|
|
796
|
+
})
|
|
799
797
|
state.activeLoads.set(cwd, { epoch, promise: load })
|
|
800
798
|
try {
|
|
801
799
|
return await load
|
|
802
800
|
} finally {
|
|
803
|
-
if (state.activeLoads.get(cwd)?.promise === load)
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
function previewForMatch(text: string, normalizedQuery: string): string {
|
|
808
|
-
const normalizedText = text.toLowerCase()
|
|
809
|
-
const matchIndex = normalizedText.indexOf(normalizedQuery)
|
|
810
|
-
if (matchIndex < 0) return ''
|
|
811
|
-
|
|
812
|
-
const start = Math.max(0, matchIndex - MATCH_PREVIEW_PREFIX_LENGTH)
|
|
813
|
-
const requiredEnd = matchIndex + normalizedQuery.length
|
|
814
|
-
const end = Math.min(text.length, Math.max(start + MATCH_PREVIEW_MAX_LENGTH, requiredEnd))
|
|
815
|
-
const content = text.slice(start, end).replace(/\s+/g, ' ').trim()
|
|
816
|
-
return `${start > 0 ? '…' : ''}${content}${end < text.length ? '…' : ''}`
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
function messageMatch(
|
|
820
|
-
scope: 'user' | 'assistant',
|
|
821
|
-
messages: readonly L4PiSessionUserMessage[] | readonly L4PiSessionAssistantMessage[],
|
|
822
|
-
normalizedQuery: string
|
|
823
|
-
): L4PiSessionHistoryMatch | null {
|
|
824
|
-
const matching = messages.filter((message) =>
|
|
825
|
-
message.text.toLowerCase().includes(normalizedQuery)
|
|
826
|
-
)
|
|
827
|
-
if (matching.length === 0) return null
|
|
828
|
-
const latest = matching.at(-1)!
|
|
829
|
-
return {
|
|
830
|
-
scope,
|
|
831
|
-
count: matching.length,
|
|
832
|
-
entryId: latest.entryId,
|
|
833
|
-
timestampMs: latest.timestampMs,
|
|
834
|
-
preview: previewForMatch(latest.text, normalizedQuery)
|
|
801
|
+
if (state.activeLoads.get(cwd)?.promise === load) {
|
|
802
|
+
state.activeLoads.delete(cwd)
|
|
803
|
+
state.epochs.delete(cwd)
|
|
804
|
+
}
|
|
835
805
|
}
|
|
836
806
|
}
|
|
837
807
|
|
|
@@ -854,33 +824,7 @@ function projectHistoryItem(
|
|
|
854
824
|
}
|
|
855
825
|
}
|
|
856
826
|
|
|
857
|
-
const matches
|
|
858
|
-
if (searchIn.has('title') && session.name?.toLowerCase().includes(normalizedQuery)) {
|
|
859
|
-
matches.push({
|
|
860
|
-
scope: 'title',
|
|
861
|
-
count: 1,
|
|
862
|
-
entryId: null,
|
|
863
|
-
timestampMs: null,
|
|
864
|
-
preview: compactPreview(session.name, FIRST_MESSAGE_PREVIEW_MAX_LENGTH)
|
|
865
|
-
})
|
|
866
|
-
}
|
|
867
|
-
if (searchIn.has('user')) {
|
|
868
|
-
const match = messageMatch('user', session.userMessages, normalizedQuery)
|
|
869
|
-
if (match) matches.push(match)
|
|
870
|
-
}
|
|
871
|
-
if (searchIn.has('assistant')) {
|
|
872
|
-
const match = messageMatch('assistant', session.assistantMessages, normalizedQuery)
|
|
873
|
-
if (match) matches.push(match)
|
|
874
|
-
}
|
|
875
|
-
if (searchIn.has('sessionId') && session.sessionId.toLowerCase().includes(normalizedQuery)) {
|
|
876
|
-
matches.push({
|
|
877
|
-
scope: 'sessionId',
|
|
878
|
-
count: 1,
|
|
879
|
-
entryId: null,
|
|
880
|
-
timestampMs: null,
|
|
881
|
-
preview: session.sessionId
|
|
882
|
-
})
|
|
883
|
-
}
|
|
827
|
+
const matches = matchL4PiSessionSearch(session, normalizedQuery, searchIn)
|
|
884
828
|
if (matches.length === 0) return null
|
|
885
829
|
|
|
886
830
|
return {
|
|
@@ -917,7 +861,10 @@ async function getSessionRecord(
|
|
|
917
861
|
): Promise<L4PiSessionHistoryRecord | null> {
|
|
918
862
|
const cwd = resolve(cwdInput)
|
|
919
863
|
pruneCatalogs(Date.now())
|
|
920
|
-
const
|
|
864
|
+
const memoryCatalog = historyCatalogState().catalogs.get(cwd)
|
|
865
|
+
const catalog = memoryCatalog
|
|
866
|
+
? touchCatalog(memoryCatalog, Date.now())
|
|
867
|
+
: readPersistedHistoryCatalog(cwd)
|
|
921
868
|
const previous = catalog?.sessions.find((session) => session.sessionId === sessionId)
|
|
922
869
|
const path = await findL4PiSessionFile(cwd, sessionId, previous?.path)
|
|
923
870
|
if (!path) return null
|
|
@@ -972,8 +919,10 @@ export function resolveCachedL4PiSessionHistoryPath(
|
|
|
972
919
|
cwd: string,
|
|
973
920
|
sessionId: string
|
|
974
921
|
): string | undefined {
|
|
922
|
+
pruneCatalogs(Date.now())
|
|
975
923
|
const catalog = historyCatalogState().catalogs.get(resolve(cwd))
|
|
976
924
|
if (!catalog || catalog.dirty) return undefined
|
|
925
|
+
touchCatalog(catalog, Date.now())
|
|
977
926
|
return catalog.sessions.find((session) => session.sessionId === sessionId)?.path
|
|
978
927
|
}
|
|
979
928
|
|
|
@@ -981,7 +930,7 @@ export function invalidateL4PiSessionHistoryCache(cwd?: string): void {
|
|
|
981
930
|
const state = historyCatalogState()
|
|
982
931
|
if (cwd) {
|
|
983
932
|
const normalizedCwd = resolve(cwd)
|
|
984
|
-
incrementEpoch(normalizedCwd)
|
|
933
|
+
if (state.activeLoads.has(normalizedCwd)) incrementEpoch(normalizedCwd)
|
|
985
934
|
const catalog = state.catalogs.get(normalizedCwd)
|
|
986
935
|
if (catalog) catalog.dirty = true
|
|
987
936
|
return
|
|
@@ -989,7 +938,7 @@ export function invalidateL4PiSessionHistoryCache(cwd?: string): void {
|
|
|
989
938
|
|
|
990
939
|
const affectedCwds = new Set([...state.catalogs.keys(), ...state.activeLoads.keys()])
|
|
991
940
|
for (const catalogCwd of affectedCwds) {
|
|
992
|
-
incrementEpoch(catalogCwd)
|
|
941
|
+
if (state.activeLoads.has(catalogCwd)) incrementEpoch(catalogCwd)
|
|
993
942
|
const catalog = state.catalogs.get(catalogCwd)
|
|
994
943
|
if (catalog) catalog.dirty = true
|
|
995
944
|
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import 'server-only'
|
|
2
|
+
|
|
3
|
+
import type { SessionManager } from '@earendil-works/pi-coding-agent'
|
|
4
|
+
|
|
5
|
+
export type L4PiSessionSearchScope = 'title' | 'user' | 'assistant' | 'sessionId'
|
|
6
|
+
|
|
7
|
+
export interface L4PiSessionSearchMatch {
|
|
8
|
+
scope: L4PiSessionSearchScope
|
|
9
|
+
count: number
|
|
10
|
+
entryId: string | null
|
|
11
|
+
timestampMs: number | null
|
|
12
|
+
preview: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface L4PiSessionSearchQuery {
|
|
16
|
+
query: string
|
|
17
|
+
searchIn: readonly L4PiSessionSearchScope[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const MATCH_PREVIEW_MAX_LENGTH = 120
|
|
21
|
+
const MATCH_PREVIEW_PREFIX_LENGTH = 16
|
|
22
|
+
|
|
23
|
+
export interface L4PiSessionSearchMessage {
|
|
24
|
+
entryId: string
|
|
25
|
+
timestampMs: number
|
|
26
|
+
text: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
30
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function readL4PiSessionTimestamp(value: unknown): number | null {
|
|
34
|
+
if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0) return value
|
|
35
|
+
if (typeof value !== 'string') return null
|
|
36
|
+
const parsed = Date.parse(value)
|
|
37
|
+
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function normalizeL4PiSessionSearch(value: string): string {
|
|
41
|
+
return value.trim().toLowerCase()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function compactL4PiSessionPreview(text: string, maxLength: number): string {
|
|
45
|
+
const content = text.replace(/\s+/g, ' ').trim()
|
|
46
|
+
if (content.length <= maxLength) return content
|
|
47
|
+
return `${content.slice(0, maxLength - 1).trimEnd()}…`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function readL4PiSessionMessageText(message: unknown): string {
|
|
51
|
+
if (!isRecord(message)) return ''
|
|
52
|
+
const content = message.content
|
|
53
|
+
if (typeof content === 'string') return content
|
|
54
|
+
if (!Array.isArray(content)) return ''
|
|
55
|
+
return content
|
|
56
|
+
.flatMap((part) => {
|
|
57
|
+
if (!isRecord(part) || part.type !== 'text' || typeof part.text !== 'string') return []
|
|
58
|
+
return [part.text]
|
|
59
|
+
})
|
|
60
|
+
.join('\n')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function previewForMatch(text: string, normalizedQuery: string): string {
|
|
64
|
+
const matchIndex = text.toLowerCase().indexOf(normalizedQuery)
|
|
65
|
+
if (matchIndex < 0) return ''
|
|
66
|
+
const start = Math.max(0, matchIndex - MATCH_PREVIEW_PREFIX_LENGTH)
|
|
67
|
+
const requiredEnd = matchIndex + normalizedQuery.length
|
|
68
|
+
const end = Math.min(text.length, Math.max(start + MATCH_PREVIEW_MAX_LENGTH, requiredEnd))
|
|
69
|
+
const content = text.slice(start, end).replace(/\s+/g, ' ').trim()
|
|
70
|
+
return `${start > 0 ? '…' : ''}${content}${end < text.length ? '…' : ''}`
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function messageMatch(
|
|
74
|
+
scope: 'user' | 'assistant',
|
|
75
|
+
messages: Iterable<L4PiSessionSearchMessage>,
|
|
76
|
+
normalizedQuery: string
|
|
77
|
+
): L4PiSessionSearchMatch | null {
|
|
78
|
+
let count = 0
|
|
79
|
+
let latest: L4PiSessionSearchMessage | undefined
|
|
80
|
+
for (const message of messages) {
|
|
81
|
+
if (!message.text.toLowerCase().includes(normalizedQuery)) continue
|
|
82
|
+
count += 1
|
|
83
|
+
latest = message
|
|
84
|
+
}
|
|
85
|
+
if (!latest) return null
|
|
86
|
+
return {
|
|
87
|
+
scope,
|
|
88
|
+
count,
|
|
89
|
+
entryId: latest.entryId,
|
|
90
|
+
timestampMs: latest.timestampMs,
|
|
91
|
+
preview: previewForMatch(latest.text, normalizedQuery)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function matchL4PiSessionSearch(
|
|
96
|
+
session: {
|
|
97
|
+
sessionId: string
|
|
98
|
+
name: string | null
|
|
99
|
+
userMessages: Iterable<L4PiSessionSearchMessage>
|
|
100
|
+
assistantMessages: Iterable<L4PiSessionSearchMessage>
|
|
101
|
+
},
|
|
102
|
+
normalizedQuery: string,
|
|
103
|
+
searchIn: ReadonlySet<L4PiSessionSearchScope>
|
|
104
|
+
): L4PiSessionSearchMatch[] {
|
|
105
|
+
if (!normalizedQuery) return []
|
|
106
|
+
const matches: L4PiSessionSearchMatch[] = []
|
|
107
|
+
if (searchIn.has('title') && session.name?.toLowerCase().includes(normalizedQuery)) {
|
|
108
|
+
matches.push({
|
|
109
|
+
scope: 'title',
|
|
110
|
+
count: 1,
|
|
111
|
+
entryId: null,
|
|
112
|
+
timestampMs: null,
|
|
113
|
+
preview: compactL4PiSessionPreview(session.name, 160)
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
if (searchIn.has('user')) {
|
|
117
|
+
const match = messageMatch('user', session.userMessages, normalizedQuery)
|
|
118
|
+
if (match) matches.push(match)
|
|
119
|
+
}
|
|
120
|
+
if (searchIn.has('assistant')) {
|
|
121
|
+
const match = messageMatch('assistant', session.assistantMessages, normalizedQuery)
|
|
122
|
+
if (match) matches.push(match)
|
|
123
|
+
}
|
|
124
|
+
if (searchIn.has('sessionId') && session.sessionId.toLowerCase().includes(normalizedQuery)) {
|
|
125
|
+
matches.push({
|
|
126
|
+
scope: 'sessionId',
|
|
127
|
+
count: 1,
|
|
128
|
+
entryId: null,
|
|
129
|
+
timestampMs: null,
|
|
130
|
+
preview: session.sessionId
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
return matches
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function searchL4PiSessionBranch(
|
|
137
|
+
sessionManager: SessionManager,
|
|
138
|
+
input: L4PiSessionSearchQuery
|
|
139
|
+
): L4PiSessionSearchMatch[] {
|
|
140
|
+
const branch = sessionManager.getBranch()
|
|
141
|
+
function* messages(role: 'user' | 'assistant'): Generator<L4PiSessionSearchMessage> {
|
|
142
|
+
for (const entry of branch) {
|
|
143
|
+
if (entry.type !== 'message' || entry.message.role !== role) continue
|
|
144
|
+
const text = readL4PiSessionMessageText(entry.message)
|
|
145
|
+
if (!text.trim()) continue
|
|
146
|
+
yield {
|
|
147
|
+
entryId: entry.id,
|
|
148
|
+
timestampMs:
|
|
149
|
+
readL4PiSessionTimestamp(entry.timestamp) ??
|
|
150
|
+
readL4PiSessionTimestamp(entry.message.timestamp) ??
|
|
151
|
+
0,
|
|
152
|
+
text
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return matchL4PiSessionSearch(
|
|
157
|
+
{
|
|
158
|
+
sessionId: sessionManager.getSessionId(),
|
|
159
|
+
name: sessionManager.getSessionName()?.trim() || null,
|
|
160
|
+
userMessages: messages('user'),
|
|
161
|
+
assistantMessages: messages('assistant')
|
|
162
|
+
},
|
|
163
|
+
normalizeL4PiSessionSearch(input.query),
|
|
164
|
+
new Set(input.searchIn)
|
|
165
|
+
)
|
|
166
|
+
}
|
|
@@ -4,6 +4,11 @@ import { existsSync } from 'node:fs'
|
|
|
4
4
|
import { resolve } from 'node:path'
|
|
5
5
|
import { ModelRuntime, SessionManager, type SessionEntry } from '@earendil-works/pi-coding-agent'
|
|
6
6
|
import type { PluginJsonObject, SessionPluginSource } from '@jetcrab/pi-desk-sdk'
|
|
7
|
+
import {
|
|
8
|
+
searchL4PiSessionBranch,
|
|
9
|
+
type L4PiSessionSearchMatch,
|
|
10
|
+
type L4PiSessionSearchQuery
|
|
11
|
+
} from './l4-pi-session-search'
|
|
7
12
|
import { getL4CapabilityModesStore } from '@server/l4_foundation/capability-modes/l4-capability-modes-store'
|
|
8
13
|
import {
|
|
9
14
|
L4PiChatWorker,
|
|
@@ -17,7 +22,7 @@ import {
|
|
|
17
22
|
type L4PiNativeCommandInfo,
|
|
18
23
|
type L4PiNativeToolInfo
|
|
19
24
|
} from './l4-pi-chat-worker'
|
|
20
|
-
import type
|
|
25
|
+
import { decodeL4PiImage, type L4PiInputImage } from './l4-pi-image'
|
|
21
26
|
import type { L4PiModelCatalog } from './l4-pi-model-catalog'
|
|
22
27
|
import { L4PiSessionBranchIndex, type L4PendingBranchAppend } from './l4-pi-session-branch'
|
|
23
28
|
import {
|
|
@@ -48,6 +53,19 @@ export class L4PiSessionBranchBlockedError extends Error {
|
|
|
48
53
|
}
|
|
49
54
|
}
|
|
50
55
|
|
|
56
|
+
export class L4PiSessionResendTargetError extends Error {
|
|
57
|
+
constructor(entryId: string) {
|
|
58
|
+
super(`Pi session resend target is not a user message: ${entryId}`)
|
|
59
|
+
this.name = 'L4PiSessionResendTargetError'
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface L4PiResendInput {
|
|
64
|
+
mode: 'resend'
|
|
65
|
+
entryId: string
|
|
66
|
+
onBranchChanged: () => Promise<void>
|
|
67
|
+
}
|
|
68
|
+
|
|
51
69
|
export class L4PiSessionCloneEmptyError extends Error {
|
|
52
70
|
constructor() {
|
|
53
71
|
super('Pi session has no durable entry to clone')
|
|
@@ -166,6 +184,11 @@ export class L4PiWorkSessionRuntime {
|
|
|
166
184
|
return projectL4PiChatSnapshot(this.sessionManager)
|
|
167
185
|
}
|
|
168
186
|
|
|
187
|
+
search(input: L4PiSessionSearchQuery): L4PiSessionSearchMatch[] {
|
|
188
|
+
this.assertActive()
|
|
189
|
+
return searchL4PiSessionBranch(this.sessionManager, input)
|
|
190
|
+
}
|
|
191
|
+
|
|
169
192
|
async readSessionTree(): Promise<L4PiSessionTree> {
|
|
170
193
|
this.assertActive()
|
|
171
194
|
const models = this.sessionManager.getEntries().some((entry) => entry.type === 'model_change')
|
|
@@ -290,9 +313,35 @@ export class L4PiWorkSessionRuntime {
|
|
|
290
313
|
await this.chatWorker.abortDirectBash()
|
|
291
314
|
}
|
|
292
315
|
|
|
293
|
-
async send(input: L4PiChatSendInput): Promise<{ tempId: string }> {
|
|
316
|
+
async send(input: L4PiChatSendInput | L4PiResendInput): Promise<{ tempId: string }> {
|
|
294
317
|
this.assertActive()
|
|
295
|
-
return this.chatWorker.send(input)
|
|
318
|
+
if (input.mode !== 'resend') return this.chatWorker.send(input)
|
|
319
|
+
|
|
320
|
+
const entry = this.sessionManager.getEntry(input.entryId)
|
|
321
|
+
if (!entry) throw new L4PiSessionEntryNotFoundError(input.entryId)
|
|
322
|
+
if (entry.type !== 'message' || entry.message.role !== 'user') {
|
|
323
|
+
throw new L4PiSessionResendTargetError(input.entryId)
|
|
324
|
+
}
|
|
325
|
+
const content = entry.message.content
|
|
326
|
+
const text =
|
|
327
|
+
typeof content === 'string'
|
|
328
|
+
? content
|
|
329
|
+
: content.flatMap((part) => (part.type === 'text' ? [part.text] : [])).join('')
|
|
330
|
+
const images =
|
|
331
|
+
typeof content === 'string'
|
|
332
|
+
? []
|
|
333
|
+
: content.flatMap((part) =>
|
|
334
|
+
part.type === 'image'
|
|
335
|
+
? [{ ...decodeL4PiImage(part.data).metadata, data: part.data }]
|
|
336
|
+
: []
|
|
337
|
+
)
|
|
338
|
+
const blockReason = this.chatWorker.readPluginReloadBlockReason()
|
|
339
|
+
if (blockReason) throw new L4PiSessionBranchBlockedError(blockReason)
|
|
340
|
+
const selection = await this.navigateBranch(input.entryId, true, input.onBranchChanged)
|
|
341
|
+
if (!selection.changed) {
|
|
342
|
+
throw new L4PiSessionBranchBlockedError('分支切换已取消,未重发消息')
|
|
343
|
+
}
|
|
344
|
+
return this.chatWorker.send({ mode: 'auto', text, images })
|
|
296
345
|
}
|
|
297
346
|
|
|
298
347
|
async interrupt(): Promise<void> {
|
|
@@ -375,10 +424,20 @@ export class L4PiWorkSessionRuntime {
|
|
|
375
424
|
}
|
|
376
425
|
|
|
377
426
|
async branch(entryId: string): Promise<L4PiBranchSelection> {
|
|
427
|
+
return this.navigateBranch(entryId)
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
private async navigateBranch(
|
|
431
|
+
entryId: string,
|
|
432
|
+
beforeUserMessage = false,
|
|
433
|
+
onBranchChanged?: () => Promise<void>
|
|
434
|
+
): Promise<L4PiBranchSelection> {
|
|
378
435
|
this.assertActive()
|
|
379
436
|
this.assertBranchable()
|
|
380
437
|
this.syncBranchIndex()
|
|
381
|
-
const selection =
|
|
438
|
+
const selection: L4PiBranchSelection = beforeUserMessage
|
|
439
|
+
? { ...resolveL4PiForkSelection(this.sessionManager, entryId), changed: true }
|
|
440
|
+
: resolveL4PiBranchSelection(this.sessionManager, entryId)
|
|
382
441
|
if (!selection.changed) return selection
|
|
383
442
|
|
|
384
443
|
const previousLeaf = this.sessionManager.getLeafId()
|
|
@@ -387,7 +446,7 @@ export class L4PiWorkSessionRuntime {
|
|
|
387
446
|
this.pendingBranchAppend = null
|
|
388
447
|
let changed = false
|
|
389
448
|
try {
|
|
390
|
-
changed = await this.chatWorker.navigateTree(selection.selectedEntryId)
|
|
449
|
+
changed = await this.chatWorker.navigateTree(selection.selectedEntryId, beforeUserMessage)
|
|
391
450
|
return changed
|
|
392
451
|
? selection
|
|
393
452
|
: {
|
|
@@ -402,6 +461,8 @@ export class L4PiWorkSessionRuntime {
|
|
|
402
461
|
if (changed || leaf !== previousLeaf) {
|
|
403
462
|
this.pendingBranchAppend = this.branchIndex.predictAppend(leaf)
|
|
404
463
|
this.branchIdValue = this.pendingBranchAppend.branchId
|
|
464
|
+
// 包括后置钩子抛错的已提交导航;刷新后再恢复消息,不能丢失临时消息。
|
|
465
|
+
await onBranchChanged?.()
|
|
405
466
|
} else {
|
|
406
467
|
this.pendingBranchAppend = previousPending
|
|
407
468
|
}
|