@jingyi0605/codingns 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/public/assets/{AdaptiveButlerPage-BsgVNRAa.js → AdaptiveButlerPage-b7s6F_sd.js} +1 -1
- package/dist/public/assets/{App-tPcbyRdS.js → App-B0q8uDA-.js} +3 -3
- package/dist/public/assets/{BootstrapPage--MDOigQi.js → BootstrapPage-jFfl7KNK.js} +1 -1
- package/dist/public/assets/{ConversationPage-BBss5ED8.js → ConversationPage-sj_rn4q0.js} +1 -1
- package/dist/public/assets/{DesktopDetachPreviewPage-CB8DoqwU.js → DesktopDetachPreviewPage-C5c88SOX.js} +1 -1
- package/dist/public/assets/{DesktopWindowPage-GtIx5m8K.js → DesktopWindowPage-BdKUZrKG.js} +1 -1
- package/dist/public/assets/{FileContextPanel-BcM7AIT4.js → FileContextPanel-lM5mBcfn.js} +1 -1
- package/dist/public/assets/{GitSidebar-CMtkaxuI.js → GitSidebar-CmXAhyjo.js} +1 -1
- package/dist/public/assets/{MobileCreateSessionSheet-CrFY41_8.js → MobileCreateSessionSheet-CceV0-AH.js} +1 -1
- package/dist/public/assets/{MobileTopHeaderFrame-DGVOzXyg.js → MobileTopHeaderFrame-_I0t7cC_.js} +1 -1
- package/dist/public/assets/{MobileWorkspaceSwitcherHeader-DLkACTnQ.js → MobileWorkspaceSwitcherHeader-DhaM9fgx.js} +1 -1
- package/dist/public/assets/{RelayConnectEntryPage-0MPPjxtQ.js → RelayConnectEntryPage-CMtDWyGS.js} +1 -1
- package/dist/public/assets/{ServerSettingsModal-vgOhwus4.js → ServerSettingsModal-Rkgn3jft.js} +1 -1
- package/dist/public/assets/{SessionIndexPage-KK626Ra9.js → SessionIndexPage-BOumP3ij.js} +1 -1
- package/dist/public/assets/{SettingsPage-B3edBJIo.js → SettingsPage-vx_c-00-.js} +1 -1
- package/dist/public/assets/{TerminalManagerPanel-BxlhZp8c.js → TerminalManagerPanel-D9JHCS6d.js} +1 -1
- package/dist/public/assets/{TerminalPage-B6Rdhylx.js → TerminalPage-CBIKHI33.js} +1 -1
- package/dist/public/assets/{TerminalRuntimeFallbackModal-BVLfrpSa.js → TerminalRuntimeFallbackModal-W5NjqFEz.js} +1 -1
- package/dist/public/assets/{ToolFilesPage-N_gwwUjD.js → ToolFilesPage-DWtpaN_7.js} +1 -1
- package/dist/public/assets/{ToolGitPage-DOcuuWM1.js → ToolGitPage-MpGXsw4_.js} +1 -1
- package/dist/public/assets/{ToolProcessesPage-D-FfJ7Re.js → ToolProcessesPage-B1jHQKhZ.js} +1 -1
- package/dist/public/assets/{ToolsHomePage-CHfPxd20.js → ToolsHomePage-CJrn8ZFl.js} +1 -1
- package/dist/public/assets/{WorkbenchLandingPage-CTTnfovY.js → WorkbenchLandingPage-CJQ1V5U-.js} +1 -1
- package/dist/public/assets/{WorkbenchLayout-CbpJg0g1.js → WorkbenchLayout-D48i71PU.js} +3 -3
- package/dist/public/assets/{WorkbenchModal-Bt_1fYmM.js → WorkbenchModal-BYNuMIoV.js} +1 -1
- package/dist/public/assets/WorkbenchShellRoute-CGKjy4J-.js +1 -0
- package/dist/public/assets/{WorkspaceDebugDetailPage-s7yuDIxR.js → WorkspaceDebugDetailPage-DCAYgays.js} +1 -1
- package/dist/public/assets/{WorkspaceDetailPage-Cf-gVpqK.js → WorkspaceDetailPage-D5v-nUIi.js} +1 -1
- package/dist/public/assets/{WorkspaceHomePage-COf6I8sT.js → WorkspaceHomePage-I5G1p5SR.js} +1 -1
- package/dist/public/assets/{client-runtime-manager-DGdKvYzx.js → client-runtime-manager-CdJP7nUp.js} +1 -1
- package/dist/public/assets/{file-tree-icon-BeHqeru9.js → file-tree-icon-BFwaPxKs.js} +6 -6
- package/dist/public/assets/{index-CuzMc7q2.js → index-CjewzOUG.js} +3 -3
- package/dist/public/assets/{index-CcaQt50x.css → index-VVxfF0s5.css} +1 -1
- package/dist/public/assets/{login-direct-candidate-resolver-DEP_xCmR.js → login-direct-candidate-resolver-C-mo698r.js} +1 -1
- package/dist/public/assets/{model-switch-api-c6kcbBGm.js → model-switch-api-Br0ivfe5.js} +1 -1
- package/dist/public/assets/{preferences-service-CV6Ih0BG.js → preferences-service-CnaTvZq2.js} +1 -1
- package/dist/public/assets/{realtime-client-CRCx5xBt.js → realtime-client-BlQRqVmm.js} +1 -1
- package/dist/public/assets/{relay-entry-C751A-Sm.js → relay-entry-D7OgZZN-.js} +1 -1
- package/dist/public/assets/{terminal-runtime-meta-CRAVR-8G.js → terminal-runtime-meta-BCtAYB0E.js} +1 -1
- package/dist/public/assets/{useRegisteredDebugTemplates-D6YtNS0r.js → useRegisteredDebugTemplates-CXmxu69X.js} +1 -1
- package/dist/public/index.html +2 -2
- package/dist/server/main.js +2 -0
- package/dist/server/main.js.map +1 -1
- package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +1 -0
- package/dist/server/modules/assistant-capability/assistant-capability-controller.js +1 -0
- package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -1
- package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +1 -0
- package/dist/server/modules/assistant-capability/assistant-capability-service.js +1 -0
- package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -1
- package/dist/server/modules/browser-runtime/browser-runtime-controller.d.ts +2 -1
- package/dist/server/modules/browser-runtime/browser-runtime-controller.js +1 -0
- package/dist/server/modules/browser-runtime/browser-runtime-controller.js.map +1 -1
- package/dist/server/modules/browser-runtime/browser-runtime-service.d.ts +4 -1
- package/dist/server/modules/browser-runtime/browser-runtime-service.js +40 -0
- package/dist/server/modules/browser-runtime/browser-runtime-service.js.map +1 -1
- package/dist/server/modules/browser-runtime/browser-task-payload.d.ts +2 -0
- package/dist/server/modules/browser-runtime/browser-task-payload.js.map +1 -1
- package/dist/server/modules/git/git-command-helper-process.js +0 -18
- package/dist/server/modules/git/git-command-helper-process.js.map +1 -1
- package/dist/server/modules/git/git-command-runner.js +0 -18
- package/dist/server/modules/git/git-command-runner.js.map +1 -1
- package/dist/server/modules/sessions/session-live-runtime-service.js +46 -3
- package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
- package/dist/server/modules/sessions/workspace-session-runtime-context-service.d.ts +1 -0
- package/dist/server/modules/sessions/workspace-session-runtime-context-service.js +11 -2
- package/dist/server/modules/sessions/workspace-session-runtime-context-service.js.map +1 -1
- package/dist/server/modules/skills/builtin-skills/codingns-workspace-session/SKILL.md +2 -2
- package/dist/server/shared/http/error-handler.js +53 -19
- package/dist/server/shared/http/error-handler.js.map +1 -1
- package/dist/server/shared/utils/install-console-timestamp-prefix.d.ts +1 -0
- package/dist/server/shared/utils/install-console-timestamp-prefix.js +28 -0
- package/dist/server/shared/utils/install-console-timestamp-prefix.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.d.ts +42 -0
- package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js +346 -0
- package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js +80 -0
- package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/index.d.ts +18 -0
- package/node_modules/@codingns/session-sync-core/dist/index.js +19 -0
- package/node_modules/@codingns/session-sync-core/dist/index.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.d.ts +18 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.js +659 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-shared.d.ts +11 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-shared.js +72 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-shared.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/patch-builder.d.ts +67 -0
- package/node_modules/@codingns/session-sync-core/dist/patch-builder.js +752 -0
- package/node_modules/@codingns/session-sync-core/dist/patch-builder.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +48 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +1184 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-session-store.d.ts +11 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-session-store.js +105 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-session-store.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +84 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +2436 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +47 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +1480 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +33 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +684 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/legna-code.d.ts +9 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/legna-code.js +17 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/legna-code.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode-permissions.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode-permissions.js +8 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode-permissions.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.d.ts +48 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js +373 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +61 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +1191 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/utils.d.ts +27 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +415 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/registry.d.ts +7 -0
- package/node_modules/@codingns/session-sync-core/dist/registry.js +22 -0
- package/node_modules/@codingns/session-sync-core/dist/registry.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.d.ts +24 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +329 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.d.ts +30 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +939 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js +16 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +70 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +2571 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.d.ts +21 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js +561 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.d.ts +38 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.js +911 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/legna-runtime.d.ts +15 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/legna-runtime.js +16 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/legna-runtime.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.d.ts +38 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js +970 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.d.ts +21 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js +168 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +152 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/types.js +2 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/types.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/services.d.ts +28 -0
- package/node_modules/@codingns/session-sync-core/dist/services.js +148 -0
- package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.d.ts +6 -0
- package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js +9 -0
- package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/types.d.ts +198 -0
- package/node_modules/@codingns/session-sync-core/dist/types.js +2 -0
- package/node_modules/@codingns/session-sync-core/dist/types.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/package.json +33 -0
- package/package.json +6 -4
- package/vendor/node-pty-fork/LICENSE +69 -0
- package/vendor/node-pty-fork/README.md +91 -0
- package/vendor/node-pty-fork/binding.gyp +117 -0
- package/vendor/node-pty-fork/deps/.editorconfig +2 -0
- package/vendor/node-pty-fork/deps/winpty/.drone.yml +17 -0
- package/vendor/node-pty-fork/deps/winpty/.gitattributes +19 -0
- package/vendor/node-pty-fork/deps/winpty/LICENSE +21 -0
- package/vendor/node-pty-fork/deps/winpty/Makefile +166 -0
- package/vendor/node-pty-fork/deps/winpty/README.md +151 -0
- package/vendor/node-pty-fork/deps/winpty/RELEASES.md +280 -0
- package/vendor/node-pty-fork/deps/winpty/VERSION.txt +1 -0
- package/vendor/node-pty-fork/deps/winpty/configure +167 -0
- package/vendor/node-pty-fork/deps/winpty/misc/BufferResizeTests.cc +90 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ChangeScreenBuffer.cc +53 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ClearConsole.cc +72 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ConinMode.cc +117 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ConinMode.ps1 +116 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ConoutMode.cc +113 -0
- package/vendor/node-pty-fork/deps/winpty/misc/DebugClient.py +42 -0
- package/vendor/node-pty-fork/deps/winpty/misc/DebugServer.py +63 -0
- package/vendor/node-pty-fork/deps/winpty/misc/DumpLines.py +5 -0
- package/vendor/node-pty-fork/deps/winpty/misc/EnableExtendedFlags.txt +46 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Font-Report-June2016/CP437-Consolas.txt +528 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Font-Report-June2016/CP437-Lucida.txt +633 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Font-Report-June2016/CP932.txt +630 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Font-Report-June2016/CP936.txt +630 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Font-Report-June2016/CP949.txt +630 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Font-Report-June2016/CP950.txt +630 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Font-Report-June2016/MinimumWindowWidths.txt +16 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Font-Report-June2016/Results.txt +4 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Font-Report-June2016/Windows10SetFontBugginess.txt +144 -0
- package/vendor/node-pty-fork/deps/winpty/misc/FontSurvey.cc +100 -0
- package/vendor/node-pty-fork/deps/winpty/misc/FormatChar.h +21 -0
- package/vendor/node-pty-fork/deps/winpty/misc/FreezePerfTest.cc +62 -0
- package/vendor/node-pty-fork/deps/winpty/misc/GetCh.cc +20 -0
- package/vendor/node-pty-fork/deps/winpty/misc/GetConsolePos.cc +41 -0
- package/vendor/node-pty-fork/deps/winpty/misc/GetFont.cc +261 -0
- package/vendor/node-pty-fork/deps/winpty/misc/IdentifyConsoleWindow.ps1 +51 -0
- package/vendor/node-pty-fork/deps/winpty/misc/IsNewConsole.cc +87 -0
- package/vendor/node-pty-fork/deps/winpty/misc/MouseInputNotes.txt +90 -0
- package/vendor/node-pty-fork/deps/winpty/misc/MoveConsoleWindow.cc +34 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Notes.txt +219 -0
- package/vendor/node-pty-fork/deps/winpty/misc/OSVersion.cc +27 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ScreenBufferFreezeInactive.cc +101 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ScreenBufferTest.cc +671 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ScreenBufferTest2.cc +151 -0
- package/vendor/node-pty-fork/deps/winpty/misc/SelectAllTest.cc +45 -0
- package/vendor/node-pty-fork/deps/winpty/misc/SetBufferSize.cc +32 -0
- package/vendor/node-pty-fork/deps/winpty/misc/SetCursorPos.cc +10 -0
- package/vendor/node-pty-fork/deps/winpty/misc/SetFont.cc +145 -0
- package/vendor/node-pty-fork/deps/winpty/misc/SetWindowRect.cc +36 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ShowArgv.cc +12 -0
- package/vendor/node-pty-fork/deps/winpty/misc/ShowConsoleInput.cc +40 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Spew.py +5 -0
- package/vendor/node-pty-fork/deps/winpty/misc/TestUtil.cc +172 -0
- package/vendor/node-pty-fork/deps/winpty/misc/UnicodeDoubleWidthTest.cc +102 -0
- package/vendor/node-pty-fork/deps/winpty/misc/UnicodeWideTest1.cc +246 -0
- package/vendor/node-pty-fork/deps/winpty/misc/UnicodeWideTest2.cc +130 -0
- package/vendor/node-pty-fork/deps/winpty/misc/UnixEcho.cc +89 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Utf16Echo.cc +46 -0
- package/vendor/node-pty-fork/deps/winpty/misc/VeryLargeRead.cc +122 -0
- package/vendor/node-pty-fork/deps/winpty/misc/VkEscapeTest.cc +56 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Win10ResizeWhileFrozen.cc +52 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Win10WrapTest1.cc +57 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Win10WrapTest2.cc +30 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Win32Echo1.cc +26 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Win32Echo2.cc +19 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Win32Test1.cc +46 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Win32Test2.cc +70 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Win32Test3.cc +78 -0
- package/vendor/node-pty-fork/deps/winpty/misc/Win32Write1.cc +44 -0
- package/vendor/node-pty-fork/deps/winpty/misc/WindowsBugCrashReader.cc +27 -0
- package/vendor/node-pty-fork/deps/winpty/misc/WriteConsole.cc +106 -0
- package/vendor/node-pty-fork/deps/winpty/misc/build32.sh +9 -0
- package/vendor/node-pty-fork/deps/winpty/misc/build64.sh +9 -0
- package/vendor/node-pty-fork/deps/winpty/misc/color-test.sh +212 -0
- package/vendor/node-pty-fork/deps/winpty/misc/font-notes.txt +300 -0
- package/vendor/node-pty-fork/deps/winpty/misc/winbug-15048.cc +201 -0
- package/vendor/node-pty-fork/deps/winpty/ship/build-pty4j-libpty.bat +36 -0
- package/vendor/node-pty-fork/deps/winpty/ship/common_ship.py +53 -0
- package/vendor/node-pty-fork/deps/winpty/ship/make_msvc_package.py +165 -0
- package/vendor/node-pty-fork/deps/winpty/ship/ship.py +108 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Agent.cc +605 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Agent.h +103 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/AgentCreateDesktop.cc +84 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/AgentCreateDesktop.h +28 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/ConsoleFont.cc +632 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/ConsoleFont.h +28 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/ConsoleInput.cc +852 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/ConsoleInput.h +109 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/ConsoleInputReencoding.cc +121 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/ConsoleInputReencoding.h +36 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/ConsoleLine.cc +152 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/ConsoleLine.h +41 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Coord.h +87 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/DebugShowInput.cc +239 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/DebugShowInput.h +32 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/DefaultInputMap.cc +422 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/DefaultInputMap.h +28 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/DsrSender.h +30 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/EventLoop.cc +99 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/EventLoop.h +47 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/InputMap.cc +246 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/InputMap.h +114 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/LargeConsoleRead.cc +71 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/LargeConsoleRead.h +68 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/NamedPipe.cc +378 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/NamedPipe.h +125 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Scraper.cc +699 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Scraper.h +103 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/SimplePool.h +75 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/SmallRect.h +143 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Terminal.cc +535 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Terminal.h +69 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/UnicodeEncoding.h +157 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/UnicodeEncodingTest.cc +189 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Win32Console.cc +107 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Win32Console.h +67 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Win32ConsoleBuffer.cc +193 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/Win32ConsoleBuffer.h +99 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/main.cc +114 -0
- package/vendor/node-pty-fork/deps/winpty/src/agent/subdir.mk +61 -0
- package/vendor/node-pty-fork/deps/winpty/src/configurations.gypi +60 -0
- package/vendor/node-pty-fork/deps/winpty/src/debugserver/DebugServer.cc +117 -0
- package/vendor/node-pty-fork/deps/winpty/src/debugserver/subdir.mk +41 -0
- package/vendor/node-pty-fork/deps/winpty/src/include/winpty.h +242 -0
- package/vendor/node-pty-fork/deps/winpty/src/include/winpty_constants.h +131 -0
- package/vendor/node-pty-fork/deps/winpty/src/libwinpty/AgentLocation.cc +75 -0
- package/vendor/node-pty-fork/deps/winpty/src/libwinpty/AgentLocation.h +28 -0
- package/vendor/node-pty-fork/deps/winpty/src/libwinpty/LibWinptyException.h +54 -0
- package/vendor/node-pty-fork/deps/winpty/src/libwinpty/WinptyInternal.h +72 -0
- package/vendor/node-pty-fork/deps/winpty/src/libwinpty/subdir.mk +46 -0
- package/vendor/node-pty-fork/deps/winpty/src/libwinpty/winpty.cc +970 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/AgentMsg.h +38 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/BackgroundDesktop.cc +122 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/BackgroundDesktop.h +73 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/Buffer.cc +103 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/Buffer.h +102 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/DebugClient.cc +187 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/DebugClient.h +38 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/GenRandom.cc +138 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/GenRandom.h +55 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/GetCommitHash.bat +13 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/Mutex.h +54 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/OsModule.h +63 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/OwnedHandle.cc +36 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/OwnedHandle.h +45 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/PrecompiledHeader.h +43 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/StringBuilder.h +227 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/StringBuilderTest.cc +114 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/StringUtil.cc +55 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/StringUtil.h +80 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/TimeMeasurement.h +63 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/UnixCtrlChars.h +45 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/UpdateGenVersion.bat +20 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WindowsSecurity.cc +460 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WindowsSecurity.h +104 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WindowsVersion.cc +252 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WindowsVersion.h +29 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WinptyAssert.cc +55 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WinptyAssert.h +64 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WinptyException.cc +57 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WinptyException.h +43 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WinptyVersion.cc +42 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/WinptyVersion.h +27 -0
- package/vendor/node-pty-fork/deps/winpty/src/shared/winpty_snprintf.h +99 -0
- package/vendor/node-pty-fork/deps/winpty/src/subdir.mk +5 -0
- package/vendor/node-pty-fork/deps/winpty/src/tests/subdir.mk +28 -0
- package/vendor/node-pty-fork/deps/winpty/src/tests/trivial_test.cc +158 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/InputHandler.cc +114 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/InputHandler.h +56 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/OutputHandler.cc +80 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/OutputHandler.h +53 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/Util.cc +86 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/Util.h +31 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/WakeupFd.cc +70 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/WakeupFd.h +42 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/main.cc +729 -0
- package/vendor/node-pty-fork/deps/winpty/src/unix-adapter/subdir.mk +41 -0
- package/vendor/node-pty-fork/deps/winpty/src/winpty.gyp +206 -0
- package/vendor/node-pty-fork/deps/winpty/vcbuild.bat +83 -0
- package/vendor/node-pty-fork/lib/conpty_console_list_agent.js +20 -0
- package/vendor/node-pty-fork/lib/conpty_console_list_agent.js.map +1 -0
- package/vendor/node-pty-fork/lib/eventEmitter2.js +47 -0
- package/vendor/node-pty-fork/lib/eventEmitter2.js.map +1 -0
- package/vendor/node-pty-fork/lib/eventEmitter2.test.js +30 -0
- package/vendor/node-pty-fork/lib/eventEmitter2.test.js.map +1 -0
- package/vendor/node-pty-fork/lib/index.js +51 -0
- package/vendor/node-pty-fork/lib/index.js.map +1 -0
- package/vendor/node-pty-fork/lib/interfaces.js +7 -0
- package/vendor/node-pty-fork/lib/interfaces.js.map +1 -0
- package/vendor/node-pty-fork/lib/shared/conout.js +11 -0
- package/vendor/node-pty-fork/lib/shared/conout.js.map +1 -0
- package/vendor/node-pty-fork/lib/terminal.js +190 -0
- package/vendor/node-pty-fork/lib/terminal.js.map +1 -0
- package/vendor/node-pty-fork/lib/terminal.test.js +139 -0
- package/vendor/node-pty-fork/lib/terminal.test.js.map +1 -0
- package/vendor/node-pty-fork/lib/testUtils.test.js +28 -0
- package/vendor/node-pty-fork/lib/testUtils.test.js.map +1 -0
- package/vendor/node-pty-fork/lib/types.js +7 -0
- package/vendor/node-pty-fork/lib/types.js.map +1 -0
- package/vendor/node-pty-fork/lib/unixTerminal.js +304 -0
- package/vendor/node-pty-fork/lib/unixTerminal.js.map +1 -0
- package/vendor/node-pty-fork/lib/unixTerminal.test.js +330 -0
- package/vendor/node-pty-fork/lib/unixTerminal.test.js.map +1 -0
- package/vendor/node-pty-fork/lib/utils.js +17 -0
- package/vendor/node-pty-fork/lib/utils.js.map +1 -0
- package/vendor/node-pty-fork/lib/windowsConoutConnection.js +122 -0
- package/vendor/node-pty-fork/lib/windowsConoutConnection.js.map +1 -0
- package/vendor/node-pty-fork/lib/windowsPtyAgent.js +324 -0
- package/vendor/node-pty-fork/lib/windowsPtyAgent.js.map +1 -0
- package/vendor/node-pty-fork/lib/windowsPtyAgent.test.js +90 -0
- package/vendor/node-pty-fork/lib/windowsPtyAgent.test.js.map +1 -0
- package/vendor/node-pty-fork/lib/windowsTerminal.js +201 -0
- package/vendor/node-pty-fork/lib/windowsTerminal.js.map +1 -0
- package/vendor/node-pty-fork/lib/windowsTerminal.test.js +203 -0
- package/vendor/node-pty-fork/lib/windowsTerminal.test.js.map +1 -0
- package/vendor/node-pty-fork/lib/worker/conoutSocketWorker.js +22 -0
- package/vendor/node-pty-fork/lib/worker/conoutSocketWorker.js.map +1 -0
- package/vendor/node-pty-fork/package.json +35 -0
- package/vendor/node-pty-fork/scripts/apply-patches.mjs +341 -0
- package/vendor/node-pty-fork/scripts/fetch-upstream.mjs +41 -0
- package/vendor/node-pty-fork/scripts/install-smoke.cjs +59 -0
- package/vendor/node-pty-fork/scripts/smoke-load.cjs +10 -0
- package/vendor/node-pty-fork/scripts/sync-upstream.mjs +29 -0
- package/vendor/node-pty-fork/scripts/verify-runtime.cjs +54 -0
- package/vendor/node-pty-fork/scripts/verify-runtime.test.cjs +22 -0
- package/vendor/node-pty-fork/scripts/verify-tarball.cjs +80 -0
- package/vendor/node-pty-fork/src/conpty_console_list_agent.ts +19 -0
- package/vendor/node-pty-fork/src/eventEmitter2.test.ts +30 -0
- package/vendor/node-pty-fork/src/eventEmitter2.ts +48 -0
- package/vendor/node-pty-fork/src/index.ts +51 -0
- package/vendor/node-pty-fork/src/interfaces.ts +129 -0
- package/vendor/node-pty-fork/src/native.d.ts +56 -0
- package/vendor/node-pty-fork/src/shared/conout.ts +15 -0
- package/vendor/node-pty-fork/src/terminal.test.ts +119 -0
- package/vendor/node-pty-fork/src/terminal.ts +211 -0
- package/vendor/node-pty-fork/src/testUtils.test.ts +23 -0
- package/vendor/node-pty-fork/src/tsconfig.json +22 -0
- package/vendor/node-pty-fork/src/types.ts +15 -0
- package/vendor/node-pty-fork/src/unix/pty.cc +826 -0
- package/vendor/node-pty-fork/src/unix/spawn-helper.cc +23 -0
- package/vendor/node-pty-fork/src/unixTerminal.test.ts +335 -0
- package/vendor/node-pty-fork/src/unixTerminal.ts +320 -0
- package/vendor/node-pty-fork/src/utils.ts +9 -0
- package/vendor/node-pty-fork/src/win/conpty.cc +500 -0
- package/vendor/node-pty-fork/src/win/conpty_console_list.cc +43 -0
- package/vendor/node-pty-fork/src/win/path_util.cc +73 -0
- package/vendor/node-pty-fork/src/win/path_util.h +22 -0
- package/vendor/node-pty-fork/src/win/winpty.cc +322 -0
- package/vendor/node-pty-fork/src/windowsConoutConnection.ts +79 -0
- package/vendor/node-pty-fork/src/windowsPtyAgent.test.ts +94 -0
- package/vendor/node-pty-fork/src/windowsPtyAgent.ts +323 -0
- package/vendor/node-pty-fork/src/windowsTerminal.test.ts +214 -0
- package/vendor/node-pty-fork/src/windowsTerminal.ts +208 -0
- package/vendor/node-pty-fork/src/worker/conoutSocketWorker.ts +22 -0
- package/vendor/node-pty-fork/typings/node-pty.d.ts +203 -0
- package/dist/public/assets/WorkbenchShellRoute-DyaMnPfS.js +0 -1
- package/dist/server/modules/channels/wechat-claw-client.d.ts +0 -51
- package/dist/server/modules/channels/wechat-claw-client.js +0 -245
- package/dist/server/modules/channels/wechat-claw-client.js.map +0 -1
|
@@ -0,0 +1,1191 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { ensureText, nextTimestamp, normalizeWorkspacePath, sliceHistory } from "./utils.js";
|
|
6
|
+
import { buildMessageRawRef, normalizeOpenCodePartMessage, buildSessionRawStoreRef, firstValidNumber, normalizeOpenCodeMessageEnvelopes, parseSessionIdFromRawStoreRef, readInteger, toIsoTimestamp, toJsonRecord, workspaceMatches } from "./opencode-shared.js";
|
|
7
|
+
import { createOpenCodeMessagePermissionOptions } from "./opencode-permissions.js";
|
|
8
|
+
import { loadDatabaseSync } from "../sqlite/node-sqlite.js";
|
|
9
|
+
const DEFAULT_DATA_DIR = join(homedir(), ".local", "share", "opencode");
|
|
10
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 10_000;
|
|
11
|
+
const DEFAULT_POLL_INTERVAL_MS = 800;
|
|
12
|
+
const MIN_POLL_INTERVAL_MS = 200;
|
|
13
|
+
const DEFAULT_SERVER_PAGE_LIMIT = 100;
|
|
14
|
+
const TIMEOUT_WARNING_THRESHOLD_MS = 15_000;
|
|
15
|
+
const MAX_CONSECUTIVE_TIMEOUTS = 5;
|
|
16
|
+
const OPENCODE_SUBMIT_TIMEOUT_AMBIGUOUS = "OPENCODE_SUBMIT_TIMEOUT_AMBIGUOUS";
|
|
17
|
+
const OPENCODE_DISCOVERY_CACHE_MAX_AGE_MS = 3_000;
|
|
18
|
+
const OPENCODE_DISCOVERY_CACHE_LIMIT = 32;
|
|
19
|
+
export class OpenCodeAdapter {
|
|
20
|
+
options;
|
|
21
|
+
providerId = "opencode";
|
|
22
|
+
discoveryCache = new Map();
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
this.options = options;
|
|
25
|
+
}
|
|
26
|
+
async detectSessions(workspacePath, options) {
|
|
27
|
+
const discovery = await this.detectSessionsDetailed(workspacePath, options);
|
|
28
|
+
return discovery.sessions;
|
|
29
|
+
}
|
|
30
|
+
async detectSessionsDetailed(workspacePath, options) {
|
|
31
|
+
const startedAt = Date.now();
|
|
32
|
+
const targetPath = normalizeWorkspacePath(workspacePath);
|
|
33
|
+
const cacheKey = targetPath || "__all__";
|
|
34
|
+
const cached = this.discoveryCache.get(cacheKey);
|
|
35
|
+
if (cached && Date.now() - cached.cachedAt <= OPENCODE_DISCOVERY_CACHE_MAX_AGE_MS) {
|
|
36
|
+
this.touchDiscoveryCache(cacheKey, cached.result);
|
|
37
|
+
return cached.result;
|
|
38
|
+
}
|
|
39
|
+
const knownSessions = (options?.knownSessions ?? []).filter((session) => session.provider === this.providerId &&
|
|
40
|
+
workspaceMatches(targetPath, normalizeWorkspacePath(session.workspacePath)));
|
|
41
|
+
const serverDiscovery = await this.tryDetectSessionsFromServer(targetPath, knownSessions);
|
|
42
|
+
if (serverDiscovery) {
|
|
43
|
+
const sessions = [...serverDiscovery.sessions].sort((left, right) => (right.lastMessageAt ?? "").localeCompare(left.lastMessageAt ?? ""));
|
|
44
|
+
const diagnostic = {
|
|
45
|
+
provider: this.providerId,
|
|
46
|
+
status: serverDiscovery.isComplete ? "success" : "partial",
|
|
47
|
+
durationMs: Date.now() - startedAt,
|
|
48
|
+
sessionCount: sessions.length,
|
|
49
|
+
isComplete: serverDiscovery.isComplete,
|
|
50
|
+
errorMessage: null,
|
|
51
|
+
scannedFiles: 0,
|
|
52
|
+
skippedByMtimeSize: 0,
|
|
53
|
+
parsedFiles: 0,
|
|
54
|
+
bytesRead: 0
|
|
55
|
+
};
|
|
56
|
+
const result = {
|
|
57
|
+
...serverDiscovery,
|
|
58
|
+
sessions,
|
|
59
|
+
providerDiagnostics: [diagnostic]
|
|
60
|
+
};
|
|
61
|
+
this.touchDiscoveryCache(cacheKey, result);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
const rows = this.withReadonlyDb((db) => {
|
|
65
|
+
return db.prepare(`SELECT
|
|
66
|
+
s.id AS id,
|
|
67
|
+
s.parent_id AS parent_id,
|
|
68
|
+
s.directory AS directory,
|
|
69
|
+
s.title AS title,
|
|
70
|
+
s.time_created AS time_created,
|
|
71
|
+
s.time_updated AS time_updated,
|
|
72
|
+
s.time_archived AS time_archived,
|
|
73
|
+
COALESCE(stats.message_count, 0) AS message_count,
|
|
74
|
+
stats.last_message_time_ms AS last_message_time_ms
|
|
75
|
+
FROM session s
|
|
76
|
+
LEFT JOIN (
|
|
77
|
+
SELECT
|
|
78
|
+
session_id,
|
|
79
|
+
COUNT(*) AS message_count,
|
|
80
|
+
MAX(COALESCE(time_updated, time_created)) AS last_message_time_ms
|
|
81
|
+
FROM message
|
|
82
|
+
GROUP BY session_id
|
|
83
|
+
) AS stats
|
|
84
|
+
ON stats.session_id = s.id`).all();
|
|
85
|
+
});
|
|
86
|
+
const sessions = rows
|
|
87
|
+
.map((row) => this.normalizeSqliteSessionSummaryRow(row))
|
|
88
|
+
.filter((summary) => summary !== null)
|
|
89
|
+
.filter((summary) => workspaceMatches(targetPath, normalizeWorkspacePath(summary.workspacePath)))
|
|
90
|
+
.sort((left, right) => (right.lastMessageAt ?? "").localeCompare(left.lastMessageAt ?? ""));
|
|
91
|
+
const diagnostic = {
|
|
92
|
+
provider: this.providerId,
|
|
93
|
+
status: "success",
|
|
94
|
+
durationMs: Date.now() - startedAt,
|
|
95
|
+
sessionCount: sessions.length,
|
|
96
|
+
isComplete: true,
|
|
97
|
+
errorMessage: null,
|
|
98
|
+
scannedFiles: 0,
|
|
99
|
+
skippedByMtimeSize: 0,
|
|
100
|
+
parsedFiles: 0,
|
|
101
|
+
bytesRead: 0
|
|
102
|
+
};
|
|
103
|
+
const result = {
|
|
104
|
+
sessions,
|
|
105
|
+
isComplete: true,
|
|
106
|
+
providerDiagnostics: [diagnostic]
|
|
107
|
+
};
|
|
108
|
+
this.touchDiscoveryCache(cacheKey, result);
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
async readRecentSessionHistory(providerSessionId, rawStoreRef, _totalMessageCount, limit) {
|
|
112
|
+
return this.readSessionHistory(providerSessionId, rawStoreRef, null, limit, "backward");
|
|
113
|
+
}
|
|
114
|
+
async readSessionHistory(providerSessionId, rawStoreRef, cursor, limit, direction = "forward") {
|
|
115
|
+
const sessionId = this.resolveSessionId(providerSessionId, rawStoreRef);
|
|
116
|
+
const serverMessages = await this.tryReadSessionMessagesFromServer(sessionId);
|
|
117
|
+
const messages = serverMessages ?? this.readSessionMessagesFromSqlite(sessionId);
|
|
118
|
+
return sliceHistory(messages, cursor, limit, direction);
|
|
119
|
+
}
|
|
120
|
+
subscribeSession(providerSessionId, rawStoreRef, cursor, limit, onEvent) {
|
|
121
|
+
const sessionId = this.resolveSessionId(providerSessionId, rawStoreRef);
|
|
122
|
+
const pollIntervalMs = this.resolvePollIntervalMs();
|
|
123
|
+
const normalizedRawStoreRef = buildSessionRawStoreRef(sessionId);
|
|
124
|
+
let currentCursor = cursor;
|
|
125
|
+
let closed = false;
|
|
126
|
+
let inFlight = false;
|
|
127
|
+
const timer = setInterval(() => {
|
|
128
|
+
if (closed || inFlight) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
inFlight = true;
|
|
132
|
+
void this.readSessionHistory(sessionId, normalizedRawStoreRef, currentCursor, limit, "forward")
|
|
133
|
+
.then(async (page) => {
|
|
134
|
+
if (page.messages.length === 0) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
currentCursor = page.cursor;
|
|
138
|
+
await onEvent({
|
|
139
|
+
messages: page.messages,
|
|
140
|
+
cursor: page.cursor
|
|
141
|
+
});
|
|
142
|
+
})
|
|
143
|
+
.catch(() => {
|
|
144
|
+
return;
|
|
145
|
+
})
|
|
146
|
+
.finally(() => {
|
|
147
|
+
inFlight = false;
|
|
148
|
+
});
|
|
149
|
+
}, pollIntervalMs);
|
|
150
|
+
return {
|
|
151
|
+
close() {
|
|
152
|
+
closed = true;
|
|
153
|
+
clearInterval(timer);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
async resumeSession(providerSessionId, rawStoreRef) {
|
|
158
|
+
const sessionId = this.resolveSessionId(providerSessionId, rawStoreRef);
|
|
159
|
+
if (!(await this.tryAssertSessionExistsOnServer(sessionId))) {
|
|
160
|
+
this.assertSessionExistsOnSqlite(sessionId);
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
provider: this.providerId,
|
|
164
|
+
providerSessionId: sessionId,
|
|
165
|
+
resumedAt: nextTimestamp(),
|
|
166
|
+
rawStoreRef: buildSessionRawStoreRef(sessionId)
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
async startSession(workspacePath, options) {
|
|
170
|
+
const session = await this.createSessionOnServer(workspacePath);
|
|
171
|
+
const initialPrompt = options.initialPrompt?.trim() ?? "";
|
|
172
|
+
const acceptedAt = initialPrompt ? nextTimestamp() : null;
|
|
173
|
+
if (initialPrompt) {
|
|
174
|
+
try {
|
|
175
|
+
await this.postTextPrompt(session.id, initialPrompt, undefined, workspacePath);
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (!isOpenCodeSubmitTimeoutAmbiguous(error)
|
|
179
|
+
|| !(await this.findAcceptedUserMessage(session.id, initialPrompt, acceptedAt, workspacePath))) {
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const summary = await this.readSessionSummaryFromServer(session.id, workspacePath)
|
|
185
|
+
.catch(() => null);
|
|
186
|
+
const sessionSummary = summary ?? this.normalizeServerSessionSummary(session, new Map()) ?? {
|
|
187
|
+
provider: this.providerId,
|
|
188
|
+
providerSessionId: session.id,
|
|
189
|
+
title: ensureText(session.title).trim() || session.id,
|
|
190
|
+
workspacePath,
|
|
191
|
+
rawStoreRef: buildSessionRawStoreRef(session.id),
|
|
192
|
+
isArchived: false,
|
|
193
|
+
lastMessageAt: nextTimestamp(),
|
|
194
|
+
messageCount: options.initialPrompt?.trim() ? 1 : 0,
|
|
195
|
+
parentProviderSessionId: null,
|
|
196
|
+
isSubagent: false,
|
|
197
|
+
subagentLabel: null
|
|
198
|
+
};
|
|
199
|
+
this.discoveryCache.clear();
|
|
200
|
+
return {
|
|
201
|
+
session: sessionSummary,
|
|
202
|
+
initialCursor: null
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
async forkSession(providerSessionId, rawWorkspacePath, options) {
|
|
206
|
+
const sourceSessionId = this.resolveSessionId(providerSessionId, options.rawStoreRef);
|
|
207
|
+
const workspacePath = rawWorkspacePath.trim() || rawWorkspacePath;
|
|
208
|
+
if (options.sourceType === "message" && !(options.sourceMessageId?.trim())) {
|
|
209
|
+
throw new Error("FORK_SOURCE_MESSAGE_ID_REQUIRED");
|
|
210
|
+
}
|
|
211
|
+
const forked = this.cloneSessionFromSqlite({
|
|
212
|
+
sourceSessionId,
|
|
213
|
+
workspacePath,
|
|
214
|
+
sourceType: options.sourceType,
|
|
215
|
+
sourceMessageId: options.sourceMessageId?.trim() || null,
|
|
216
|
+
sourceMessageSnapshot: options.sourceMessageSnapshot ?? null
|
|
217
|
+
});
|
|
218
|
+
this.discoveryCache.clear();
|
|
219
|
+
return {
|
|
220
|
+
session: {
|
|
221
|
+
provider: this.providerId,
|
|
222
|
+
providerSessionId: forked.providerSessionId,
|
|
223
|
+
title: forked.title,
|
|
224
|
+
workspacePath,
|
|
225
|
+
rawStoreRef: buildSessionRawStoreRef(forked.providerSessionId),
|
|
226
|
+
isArchived: false,
|
|
227
|
+
lastMessageAt: forked.lastMessageAt,
|
|
228
|
+
messageCount: forked.inheritedPrefixMessageCount,
|
|
229
|
+
parentProviderSessionId: null,
|
|
230
|
+
isSubagent: false,
|
|
231
|
+
subagentLabel: null
|
|
232
|
+
},
|
|
233
|
+
forkMethod: options.sourceType === "session" ? "native_session_fork" : "native_message_fork",
|
|
234
|
+
forkSourceType: options.sourceType,
|
|
235
|
+
inheritedPrefixMessageCount: forked.inheritedPrefixMessageCount,
|
|
236
|
+
providerSourceMessageId: forked.providerSourceMessageId
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
async sendMessage(providerSessionId, rawStoreRef, content, clientRequestId, permissionMode) {
|
|
240
|
+
const sessionId = this.resolveSessionId(providerSessionId, rawStoreRef);
|
|
241
|
+
const trimmed = content.trim();
|
|
242
|
+
if (!trimmed) {
|
|
243
|
+
throw new Error("INVALID_INPUT");
|
|
244
|
+
}
|
|
245
|
+
const acceptedAt = nextTimestamp();
|
|
246
|
+
try {
|
|
247
|
+
await this.postTextPrompt(sessionId, trimmed, permissionMode);
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
if (!isOpenCodeSubmitTimeoutAmbiguous(error)) {
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
const acceptedMessage = await this.findAcceptedUserMessage(sessionId, trimmed, acceptedAt);
|
|
254
|
+
if (!acceptedMessage) {
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
this.discoveryCache.clear();
|
|
258
|
+
return {
|
|
259
|
+
acceptedAt: acceptedMessage.timestamp,
|
|
260
|
+
clientRequestId,
|
|
261
|
+
message: acceptedMessage
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const message = await this.findAcceptedUserMessage(sessionId, trimmed, acceptedAt)
|
|
265
|
+
?? buildSyntheticAcceptedMessage(sessionId, trimmed, acceptedAt);
|
|
266
|
+
const resolvedAcceptedAt = message.timestamp || acceptedAt;
|
|
267
|
+
this.discoveryCache.clear();
|
|
268
|
+
return {
|
|
269
|
+
acceptedAt: resolvedAcceptedAt,
|
|
270
|
+
clientRequestId,
|
|
271
|
+
message
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
async readSessionTitle(providerSessionId, rawStoreRef) {
|
|
275
|
+
const sessionId = this.resolveSessionId(providerSessionId, rawStoreRef);
|
|
276
|
+
const serverTitle = await this.tryReadSessionTitleFromServer(sessionId);
|
|
277
|
+
if (serverTitle) {
|
|
278
|
+
return serverTitle;
|
|
279
|
+
}
|
|
280
|
+
const row = this.withReadonlyDb((db) => {
|
|
281
|
+
return db.prepare(`SELECT title FROM session WHERE id = ? LIMIT 1`).get(sessionId);
|
|
282
|
+
});
|
|
283
|
+
if (!row) {
|
|
284
|
+
throw new Error("PROVIDER_SESSION_NOT_FOUND");
|
|
285
|
+
}
|
|
286
|
+
const title = ensureText(row.title).trim();
|
|
287
|
+
if (title) {
|
|
288
|
+
return title;
|
|
289
|
+
}
|
|
290
|
+
return this.readFirstUserMessageTitleFromSqlite(sessionId) || sessionId;
|
|
291
|
+
}
|
|
292
|
+
async renameSessionTitle(providerSessionId, rawStoreRef, title) {
|
|
293
|
+
const sessionId = this.resolveSessionId(providerSessionId, rawStoreRef);
|
|
294
|
+
const nextTitle = title.trim();
|
|
295
|
+
if (!nextTitle) {
|
|
296
|
+
throw new Error("INVALID_INPUT");
|
|
297
|
+
}
|
|
298
|
+
const response = await this.fetchJson(`/session/${encodeURIComponent(sessionId)}`, {
|
|
299
|
+
method: "PATCH",
|
|
300
|
+
headers: {
|
|
301
|
+
"content-type": "application/json"
|
|
302
|
+
},
|
|
303
|
+
body: JSON.stringify({
|
|
304
|
+
title: nextTitle
|
|
305
|
+
})
|
|
306
|
+
});
|
|
307
|
+
this.discoveryCache.clear();
|
|
308
|
+
return ensureText(response.data.title).trim() || nextTitle;
|
|
309
|
+
}
|
|
310
|
+
async updateSessionArchiveState(_providerSessionId, _rawStoreRef, _isArchived) {
|
|
311
|
+
throw new Error("OPENCODE_ARCHIVE_NOT_SUPPORTED");
|
|
312
|
+
}
|
|
313
|
+
async deleteSession(providerSessionId, rawStoreRef) {
|
|
314
|
+
const sessionId = this.resolveSessionId(providerSessionId, rawStoreRef);
|
|
315
|
+
let deleted = false;
|
|
316
|
+
try {
|
|
317
|
+
await this.fetchJson(`/session/${encodeURIComponent(sessionId)}`, {
|
|
318
|
+
method: "DELETE"
|
|
319
|
+
});
|
|
320
|
+
deleted = true;
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
if (!(error instanceof Error)
|
|
324
|
+
|| (error.message !== "SERVER_UNAVAILABLE"
|
|
325
|
+
&& error.message !== "SERVER_TIMEOUT"
|
|
326
|
+
&& error.message !== "PROVIDER_SESSION_NOT_FOUND"
|
|
327
|
+
&& !error.message.startsWith("OPENCODE_HTTP_"))) {
|
|
328
|
+
throw error;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const deletedFromSqlite = this.withWritableDb((db) => {
|
|
332
|
+
const partChanges = Number(db.prepare("DELETE FROM part WHERE session_id = ?").run(sessionId).changes);
|
|
333
|
+
const messageChanges = Number(db.prepare("DELETE FROM message WHERE session_id = ?").run(sessionId).changes);
|
|
334
|
+
const sessionChanges = Number(db.prepare("DELETE FROM session WHERE id = ?").run(sessionId).changes);
|
|
335
|
+
return partChanges + messageChanges + sessionChanges;
|
|
336
|
+
});
|
|
337
|
+
this.discoveryCache.clear();
|
|
338
|
+
if (!deleted && deletedFromSqlite === 0) {
|
|
339
|
+
throw new Error("PROVIDER_SESSION_NOT_FOUND");
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
getProviderCapabilities() {
|
|
343
|
+
return {
|
|
344
|
+
provider: this.providerId,
|
|
345
|
+
canStartSession: true,
|
|
346
|
+
canResumeSession: true,
|
|
347
|
+
canSendMessage: true,
|
|
348
|
+
inRunInputMode: "none",
|
|
349
|
+
supportsSubagents: true,
|
|
350
|
+
supportsInterrupt: true,
|
|
351
|
+
supportsStructuredToolCalls: true,
|
|
352
|
+
supportsTokenUsage: false,
|
|
353
|
+
supportsAttachments: false,
|
|
354
|
+
supportsPermissionPrompt: false,
|
|
355
|
+
supportsCheckpoint: false,
|
|
356
|
+
supportsTodo: true,
|
|
357
|
+
supportsSessionDiff: true,
|
|
358
|
+
supportsPermissionRequests: true,
|
|
359
|
+
supportsSessionFork: true,
|
|
360
|
+
supportsSessionDelete: true,
|
|
361
|
+
supportsSessionShare: true,
|
|
362
|
+
supportsAsyncPrompt: true,
|
|
363
|
+
supportsNativeAgents: true,
|
|
364
|
+
limitations: [
|
|
365
|
+
"当前 OpenCode 先以 server 为主链路;server 不可达时只对历史读取做 sqlite 只读兜底。",
|
|
366
|
+
"附件上传、权限回复和分享管理还没有接到当前 UI。"
|
|
367
|
+
]
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
async getSessionCapabilities() {
|
|
371
|
+
return this.getProviderCapabilities();
|
|
372
|
+
}
|
|
373
|
+
touchDiscoveryCache(cacheKey, result) {
|
|
374
|
+
this.discoveryCache.delete(cacheKey);
|
|
375
|
+
this.discoveryCache.set(cacheKey, {
|
|
376
|
+
cachedAt: Date.now(),
|
|
377
|
+
result
|
|
378
|
+
});
|
|
379
|
+
while (this.discoveryCache.size > OPENCODE_DISCOVERY_CACHE_LIMIT) {
|
|
380
|
+
const oldestKey = this.discoveryCache.keys().next().value;
|
|
381
|
+
if (!oldestKey) {
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
this.discoveryCache.delete(oldestKey);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
async tryDetectSessionsFromServer(targetPath, knownSessions) {
|
|
388
|
+
try {
|
|
389
|
+
const response = await this.fetchJson("/session", {
|
|
390
|
+
workspacePath: targetPath,
|
|
391
|
+
query: {
|
|
392
|
+
directory: targetPath || undefined,
|
|
393
|
+
roots: "true"
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
const ids = response.data
|
|
397
|
+
.map((session) => ensureText(session.id).trim())
|
|
398
|
+
.filter((value) => value.length > 0);
|
|
399
|
+
const metadata = this.readSessionMetadata(ids);
|
|
400
|
+
const serverSessions = response.data
|
|
401
|
+
.map((session) => this.normalizeServerSessionSummary(session, metadata))
|
|
402
|
+
.filter((summary) => summary !== null)
|
|
403
|
+
.filter((summary) => workspaceMatches(targetPath, normalizeWorkspacePath(summary.workspacePath)))
|
|
404
|
+
.sort((left, right) => (right.lastMessageAt ?? "").localeCompare(left.lastMessageAt ?? ""));
|
|
405
|
+
const mergedSessions = new Map(serverSessions.map((session) => [session.providerSessionId, session]));
|
|
406
|
+
const missingKnownSessions = knownSessions.filter((session) => !mergedSessions.has(session.providerSessionId));
|
|
407
|
+
let isComplete = true;
|
|
408
|
+
if (missingKnownSessions.length > 0) {
|
|
409
|
+
const recoveredSessions = this.readSessionSummariesByIds(missingKnownSessions.map((session) => session.providerSessionId), targetPath);
|
|
410
|
+
if (recoveredSessions === null) {
|
|
411
|
+
isComplete = false;
|
|
412
|
+
}
|
|
413
|
+
else if (recoveredSessions.length > 0) {
|
|
414
|
+
isComplete = false;
|
|
415
|
+
for (const session of recoveredSessions) {
|
|
416
|
+
if (!mergedSessions.has(session.providerSessionId)) {
|
|
417
|
+
mergedSessions.set(session.providerSessionId, session);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return {
|
|
423
|
+
sessions: [...mergedSessions.values()].sort((left, right) => (right.lastMessageAt ?? "").localeCompare(left.lastMessageAt ?? "")),
|
|
424
|
+
isComplete
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
if (isServerUnavailableError(error) || isServerTimeoutError(error)) {
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
throw error;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
async tryReadSessionMessagesFromServer(sessionId) {
|
|
435
|
+
try {
|
|
436
|
+
return await this.readSessionMessagesFromServer(sessionId);
|
|
437
|
+
}
|
|
438
|
+
catch (error) {
|
|
439
|
+
if (isServerUnavailableError(error)) {
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
throw error;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
async readSessionMessagesFromServer(sessionId) {
|
|
446
|
+
const envelopes = [];
|
|
447
|
+
let before = null;
|
|
448
|
+
while (true) {
|
|
449
|
+
const response = await this.fetchJson(`/session/${encodeURIComponent(sessionId)}/message`, {
|
|
450
|
+
query: {
|
|
451
|
+
limit: String(DEFAULT_SERVER_PAGE_LIMIT),
|
|
452
|
+
before: before ?? undefined
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
envelopes.push(...response.data);
|
|
456
|
+
const nextCursor = response.headers.get("x-next-cursor");
|
|
457
|
+
if (!nextCursor) {
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
before = nextCursor;
|
|
461
|
+
}
|
|
462
|
+
return normalizeOpenCodeMessageEnvelopes(sessionId, sessionId, envelopes);
|
|
463
|
+
}
|
|
464
|
+
async createSessionOnServer(workspacePath) {
|
|
465
|
+
const response = await this.fetchJson("/session", {
|
|
466
|
+
workspacePath,
|
|
467
|
+
method: "POST",
|
|
468
|
+
headers: {
|
|
469
|
+
"content-type": "application/json"
|
|
470
|
+
},
|
|
471
|
+
query: {
|
|
472
|
+
directory: workspacePath
|
|
473
|
+
},
|
|
474
|
+
body: JSON.stringify({
|
|
475
|
+
directory: workspacePath
|
|
476
|
+
})
|
|
477
|
+
});
|
|
478
|
+
const sessionId = ensureText(response.data.id).trim();
|
|
479
|
+
if (!sessionId) {
|
|
480
|
+
throw new Error("PROVIDER_SESSION_ID_REQUIRED");
|
|
481
|
+
}
|
|
482
|
+
return {
|
|
483
|
+
id: sessionId,
|
|
484
|
+
title: response.data.title
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
async postTextPrompt(sessionId, text, permissionMode, workspacePath) {
|
|
488
|
+
await this.fetchJson(`/session/${encodeURIComponent(sessionId)}/message`, {
|
|
489
|
+
workspacePath,
|
|
490
|
+
method: "POST",
|
|
491
|
+
headers: {
|
|
492
|
+
"content-type": "application/json"
|
|
493
|
+
},
|
|
494
|
+
timeoutErrorMessage: OPENCODE_SUBMIT_TIMEOUT_AMBIGUOUS,
|
|
495
|
+
body: JSON.stringify({
|
|
496
|
+
...createOpenCodeMessagePermissionOptions(permissionMode),
|
|
497
|
+
parts: [
|
|
498
|
+
{
|
|
499
|
+
type: "text",
|
|
500
|
+
text
|
|
501
|
+
}
|
|
502
|
+
]
|
|
503
|
+
})
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
async findAcceptedUserMessage(sessionId, content, minTimestamp = null, workspacePath) {
|
|
507
|
+
try {
|
|
508
|
+
const response = await this.fetchJson(`/session/${encodeURIComponent(sessionId)}/message`, {
|
|
509
|
+
query: {
|
|
510
|
+
limit: "20"
|
|
511
|
+
},
|
|
512
|
+
workspacePath
|
|
513
|
+
});
|
|
514
|
+
const messages = normalizeOpenCodeMessageEnvelopes(sessionId, sessionId, response.data.reverse());
|
|
515
|
+
const trimmed = content.trim();
|
|
516
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
517
|
+
const message = messages[index];
|
|
518
|
+
if (message?.role === "user"
|
|
519
|
+
&& message.content.trim() === trimmed
|
|
520
|
+
&& isTimestampOnOrAfter(message.timestamp, minTimestamp)) {
|
|
521
|
+
return message;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return null;
|
|
525
|
+
}
|
|
526
|
+
catch {
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
async readSessionSummaryFromServer(sessionId, workspacePath) {
|
|
531
|
+
const response = await this.fetchJson(`/session/${encodeURIComponent(sessionId)}`, {
|
|
532
|
+
workspacePath
|
|
533
|
+
});
|
|
534
|
+
const metadata = this.readSessionMetadata([sessionId]);
|
|
535
|
+
return this.normalizeServerSessionSummary(response.data, metadata);
|
|
536
|
+
}
|
|
537
|
+
async tryReadSessionTitleFromServer(sessionId) {
|
|
538
|
+
try {
|
|
539
|
+
const response = await this.fetchJson(`/session/${encodeURIComponent(sessionId)}`);
|
|
540
|
+
const title = ensureText(response.data.title).trim();
|
|
541
|
+
return title || sessionId;
|
|
542
|
+
}
|
|
543
|
+
catch (error) {
|
|
544
|
+
if (isServerUnavailableError(error)) {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
throw error;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
async tryAssertSessionExistsOnServer(sessionId) {
|
|
551
|
+
try {
|
|
552
|
+
await this.fetchJson(`/session/${encodeURIComponent(sessionId)}`);
|
|
553
|
+
return true;
|
|
554
|
+
}
|
|
555
|
+
catch (error) {
|
|
556
|
+
if (isServerUnavailableError(error)) {
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
if (error instanceof Error && error.message === "PROVIDER_SESSION_NOT_FOUND") {
|
|
560
|
+
throw error;
|
|
561
|
+
}
|
|
562
|
+
throw error;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
async resolveBaseUrl(refresh = false, workspacePath = null) {
|
|
566
|
+
const resolved = this.options.baseUrlResolver
|
|
567
|
+
? await this.options.baseUrlResolver({ refresh, workspacePath })
|
|
568
|
+
: this.options.baseUrl?.trim();
|
|
569
|
+
if (!resolved) {
|
|
570
|
+
throw new Error("SERVER_UNAVAILABLE");
|
|
571
|
+
}
|
|
572
|
+
return resolved.trim().replace(/\/+$/, "");
|
|
573
|
+
}
|
|
574
|
+
resolveDbPath() {
|
|
575
|
+
const configuredPath = this.options.dbPath?.trim();
|
|
576
|
+
if (configuredPath) {
|
|
577
|
+
return configuredPath;
|
|
578
|
+
}
|
|
579
|
+
const dataDir = this.options.dataDir?.trim() || DEFAULT_DATA_DIR;
|
|
580
|
+
return join(dataDir, "opencode.db");
|
|
581
|
+
}
|
|
582
|
+
resolvePollIntervalMs() {
|
|
583
|
+
const configured = this.options.pollIntervalMs;
|
|
584
|
+
if (!Number.isFinite(configured)) {
|
|
585
|
+
return DEFAULT_POLL_INTERVAL_MS;
|
|
586
|
+
}
|
|
587
|
+
return Math.max(MIN_POLL_INTERVAL_MS, Math.floor(configured));
|
|
588
|
+
}
|
|
589
|
+
resolveRequestTimeoutMs() {
|
|
590
|
+
const configured = this.options.requestTimeoutMs;
|
|
591
|
+
if (!Number.isFinite(configured)) {
|
|
592
|
+
return DEFAULT_REQUEST_TIMEOUT_MS;
|
|
593
|
+
}
|
|
594
|
+
return Math.max(1_000, Math.floor(configured));
|
|
595
|
+
}
|
|
596
|
+
cloneSessionFromSqlite(input) {
|
|
597
|
+
const forkedSessionId = `ses_${randomUUID().replaceAll("-", "")}`;
|
|
598
|
+
const nowMs = Date.now();
|
|
599
|
+
return this.withWritableDb((db) => {
|
|
600
|
+
const sourceSession = db.prepare(`SELECT
|
|
601
|
+
id,
|
|
602
|
+
project_id,
|
|
603
|
+
parent_id,
|
|
604
|
+
slug,
|
|
605
|
+
directory,
|
|
606
|
+
title,
|
|
607
|
+
version,
|
|
608
|
+
share_url,
|
|
609
|
+
summary_additions,
|
|
610
|
+
summary_deletions,
|
|
611
|
+
summary_files,
|
|
612
|
+
summary_diffs,
|
|
613
|
+
revert,
|
|
614
|
+
permission,
|
|
615
|
+
time_created,
|
|
616
|
+
time_updated,
|
|
617
|
+
time_compacting,
|
|
618
|
+
time_archived,
|
|
619
|
+
workspace_id
|
|
620
|
+
FROM session
|
|
621
|
+
WHERE id = ?
|
|
622
|
+
LIMIT 1`).get(input.sourceSessionId);
|
|
623
|
+
if (!sourceSession) {
|
|
624
|
+
throw new Error("PROVIDER_SESSION_NOT_FOUND");
|
|
625
|
+
}
|
|
626
|
+
const sourceMessageRows = db.prepare(`SELECT id, time_created, time_updated, data
|
|
627
|
+
FROM message
|
|
628
|
+
WHERE session_id = ?
|
|
629
|
+
ORDER BY COALESCE(time_updated, time_created), time_created, id`).all(input.sourceSessionId);
|
|
630
|
+
const readPartRows = db.prepare(`SELECT id, message_id, time_created, time_updated, data
|
|
631
|
+
FROM part
|
|
632
|
+
WHERE session_id = ? AND message_id = ?
|
|
633
|
+
ORDER BY COALESCE(time_updated, time_created), time_created, id`);
|
|
634
|
+
const insertSession = db.prepare(`INSERT INTO session (
|
|
635
|
+
id,
|
|
636
|
+
project_id,
|
|
637
|
+
parent_id,
|
|
638
|
+
slug,
|
|
639
|
+
directory,
|
|
640
|
+
title,
|
|
641
|
+
version,
|
|
642
|
+
share_url,
|
|
643
|
+
summary_additions,
|
|
644
|
+
summary_deletions,
|
|
645
|
+
summary_files,
|
|
646
|
+
summary_diffs,
|
|
647
|
+
revert,
|
|
648
|
+
permission,
|
|
649
|
+
time_created,
|
|
650
|
+
time_updated,
|
|
651
|
+
time_compacting,
|
|
652
|
+
time_archived,
|
|
653
|
+
workspace_id
|
|
654
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
655
|
+
const insertMessage = db.prepare(`INSERT INTO message (
|
|
656
|
+
id,
|
|
657
|
+
session_id,
|
|
658
|
+
time_created,
|
|
659
|
+
time_updated,
|
|
660
|
+
data
|
|
661
|
+
) VALUES (?, ?, ?, ?, ?)`);
|
|
662
|
+
const insertPart = db.prepare(`INSERT INTO part (
|
|
663
|
+
id,
|
|
664
|
+
message_id,
|
|
665
|
+
session_id,
|
|
666
|
+
time_created,
|
|
667
|
+
time_updated,
|
|
668
|
+
data
|
|
669
|
+
) VALUES (?, ?, ?, ?, ?, ?)`);
|
|
670
|
+
let derivedTitle = null;
|
|
671
|
+
insertSession.run(forkedSessionId, ensureText(sourceSession.project_id).trim() || "global", null, buildForkSlug(ensureText(sourceSession.slug).trim(), forkedSessionId), input.workspacePath, "", ensureText(sourceSession.version).trim() || "v1", ensureNullableText(sourceSession.share_url), readInteger(sourceSession.summary_additions), readInteger(sourceSession.summary_deletions), readInteger(sourceSession.summary_files), ensureNullableText(sourceSession.summary_diffs), ensureNullableText(sourceSession.revert), ensureNullableText(sourceSession.permission), readInteger(sourceSession.time_created) ?? nowMs, nowMs, readInteger(sourceSession.time_compacting), null, ensureNullableText(sourceSession.workspace_id));
|
|
672
|
+
let inheritedPrefixMessageCount = 0;
|
|
673
|
+
let providerSourceMessageId = null;
|
|
674
|
+
let lastMessageAtMs = firstValidNumber(sourceSession.time_updated, sourceSession.time_created);
|
|
675
|
+
let reachedAnchor = false;
|
|
676
|
+
for (const messageRow of sourceMessageRows) {
|
|
677
|
+
const sourceMessageRowId = ensureText(messageRow.id).trim();
|
|
678
|
+
if (!sourceMessageRowId) {
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
const partRows = readPartRows.all(input.sourceSessionId, sourceMessageRowId);
|
|
682
|
+
const includedPartRows = [];
|
|
683
|
+
for (const partRow of partRows) {
|
|
684
|
+
const sourcePartId = ensureText(partRow.id).trim();
|
|
685
|
+
if (!sourcePartId) {
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
includedPartRows.push(partRow);
|
|
689
|
+
const normalized = normalizeOpenCodePartMessage({
|
|
690
|
+
sessionId: input.sourceSessionId,
|
|
691
|
+
providerSessionId: input.sourceSessionId,
|
|
692
|
+
partId: sourcePartId,
|
|
693
|
+
messageId: sourceMessageRowId,
|
|
694
|
+
partPayload: toJsonRecord(partRow.data) ?? {},
|
|
695
|
+
messagePayload: toJsonRecord(messageRow.data) ?? {},
|
|
696
|
+
defaultTimestamp: toIsoTimestamp(firstValidNumber(partRow.time_created, messageRow.time_created, messageRow.time_updated), null) ?? nextTimestamp()
|
|
697
|
+
});
|
|
698
|
+
if (normalized) {
|
|
699
|
+
inheritedPrefixMessageCount += 1;
|
|
700
|
+
lastMessageAtMs = Date.parse(normalized.timestamp);
|
|
701
|
+
if (derivedTitle === null) {
|
|
702
|
+
derivedTitle = resolveOpenCodeMessageTitle(normalized);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
if (input.sourceType === "message" && normalized?.messageId === input.sourceMessageId) {
|
|
706
|
+
providerSourceMessageId = sourcePartId;
|
|
707
|
+
if (input.sourceMessageSnapshot) {
|
|
708
|
+
includedPartRows[includedPartRows.length - 1] = {
|
|
709
|
+
...partRow,
|
|
710
|
+
data: applyOpenCodeForkSourceSnapshot(toJsonRecord(partRow.data) ?? {}, input.sourceMessageSnapshot)
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
reachedAnchor = true;
|
|
714
|
+
break;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
if (includedPartRows.length === 0) {
|
|
718
|
+
continue;
|
|
719
|
+
}
|
|
720
|
+
const forkedMessageId = randomUUID();
|
|
721
|
+
insertMessage.run(forkedMessageId, forkedSessionId, readInteger(messageRow.time_created) ?? nowMs, readInteger(messageRow.time_updated) ?? readInteger(messageRow.time_created) ?? nowMs, JSON.stringify(toJsonRecord(messageRow.data) ?? {}));
|
|
722
|
+
for (const partRow of includedPartRows) {
|
|
723
|
+
insertPart.run(randomUUID(), forkedMessageId, forkedSessionId, readInteger(partRow.time_created) ?? nowMs, readInteger(partRow.time_updated) ?? readInteger(partRow.time_created) ?? nowMs, JSON.stringify(toJsonRecord(partRow.data) ?? {}));
|
|
724
|
+
}
|
|
725
|
+
if (reachedAnchor) {
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (input.sourceType === "message" && !reachedAnchor) {
|
|
730
|
+
throw new Error("FORK_SOURCE_MESSAGE_NOT_FOUND");
|
|
731
|
+
}
|
|
732
|
+
const resolvedTitle = derivedTitle ?? "";
|
|
733
|
+
db.prepare("UPDATE session SET title = ? WHERE id = ?").run(resolvedTitle, forkedSessionId);
|
|
734
|
+
return {
|
|
735
|
+
providerSessionId: forkedSessionId,
|
|
736
|
+
title: resolvedTitle,
|
|
737
|
+
lastMessageAt: toIsoTimestamp(lastMessageAtMs, nextTimestamp()),
|
|
738
|
+
inheritedPrefixMessageCount,
|
|
739
|
+
providerSourceMessageId
|
|
740
|
+
};
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
readFirstUserMessageTitleFromSqlite(sessionId) {
|
|
744
|
+
return this.withReadonlyDb((db) => {
|
|
745
|
+
const rows = db.prepare(`SELECT
|
|
746
|
+
message.id AS message_id,
|
|
747
|
+
message.time_created AS message_time_created,
|
|
748
|
+
message.time_updated AS message_time_updated,
|
|
749
|
+
message.data AS message_data,
|
|
750
|
+
part.id AS part_id,
|
|
751
|
+
part.time_created AS part_time_created,
|
|
752
|
+
part.time_updated AS part_time_updated,
|
|
753
|
+
part.data AS part_data
|
|
754
|
+
FROM message
|
|
755
|
+
INNER JOIN part
|
|
756
|
+
ON part.message_id = message.id
|
|
757
|
+
AND part.session_id = message.session_id
|
|
758
|
+
WHERE message.session_id = ?
|
|
759
|
+
ORDER BY COALESCE(part.time_updated, part.time_created, message.time_updated, message.time_created),
|
|
760
|
+
COALESCE(part.time_created, message.time_created),
|
|
761
|
+
message.id,
|
|
762
|
+
part.id`).all(sessionId);
|
|
763
|
+
for (const row of rows) {
|
|
764
|
+
const messageId = ensureText(row.message_id).trim();
|
|
765
|
+
const partId = ensureText(row.part_id).trim();
|
|
766
|
+
if (!messageId || !partId) {
|
|
767
|
+
continue;
|
|
768
|
+
}
|
|
769
|
+
const normalized = normalizeOpenCodePartMessage({
|
|
770
|
+
sessionId,
|
|
771
|
+
providerSessionId: sessionId,
|
|
772
|
+
messageId,
|
|
773
|
+
partId,
|
|
774
|
+
messagePayload: toJsonRecord(row.message_data) ?? {},
|
|
775
|
+
partPayload: toJsonRecord(row.part_data) ?? {},
|
|
776
|
+
defaultTimestamp: toIsoTimestamp(firstValidNumber(row.part_time_created, row.part_time_updated, row.message_time_created, row.message_time_updated), null) ?? nextTimestamp()
|
|
777
|
+
});
|
|
778
|
+
const title = normalized ? resolveOpenCodeMessageTitle(normalized) : null;
|
|
779
|
+
if (title) {
|
|
780
|
+
return title;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
return null;
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
async fetchJson(pathname, input = {}) {
|
|
787
|
+
return this.fetchJsonWithRetry(pathname, input, false);
|
|
788
|
+
}
|
|
789
|
+
async fetchJsonWithRetry(pathname, input, refresh, timeoutState = createTimeoutRetryState()) {
|
|
790
|
+
const url = new URL(pathname, `${await this.resolveBaseUrl(refresh, input.workspacePath ?? null)}/`);
|
|
791
|
+
if (input.query) {
|
|
792
|
+
for (const [key, value] of Object.entries(input.query)) {
|
|
793
|
+
if (value) {
|
|
794
|
+
url.searchParams.set(key, value);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
const controller = new AbortController();
|
|
799
|
+
const timer = setTimeout(() => {
|
|
800
|
+
controller.abort();
|
|
801
|
+
}, this.resolveRequestTimeoutMs());
|
|
802
|
+
let response;
|
|
803
|
+
try {
|
|
804
|
+
response = await fetch(url, {
|
|
805
|
+
method: input.method ?? "GET",
|
|
806
|
+
headers: input.headers,
|
|
807
|
+
body: input.body,
|
|
808
|
+
signal: controller.signal
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
catch (error) {
|
|
812
|
+
clearTimeout(timer);
|
|
813
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
814
|
+
if (!isTimeoutRetryableMethod(input.method)) {
|
|
815
|
+
throw new Error(input.timeoutErrorMessage ?? "SERVER_TIMEOUT");
|
|
816
|
+
}
|
|
817
|
+
const nextTimeoutState = advanceTimeoutRetryState(timeoutState);
|
|
818
|
+
if (!shouldSurfaceTimeout(nextTimeoutState)) {
|
|
819
|
+
if (!refresh && this.options.baseUrlResolver) {
|
|
820
|
+
return this.fetchJsonWithRetry(pathname, input, true, nextTimeoutState);
|
|
821
|
+
}
|
|
822
|
+
return this.fetchJsonWithRetry(pathname, input, refresh, nextTimeoutState);
|
|
823
|
+
}
|
|
824
|
+
throw new Error("SERVER_TIMEOUT");
|
|
825
|
+
}
|
|
826
|
+
if (!refresh && this.options.baseUrlResolver) {
|
|
827
|
+
return this.fetchJsonWithRetry(pathname, input, true, timeoutState);
|
|
828
|
+
}
|
|
829
|
+
throw new Error("SERVER_UNAVAILABLE");
|
|
830
|
+
}
|
|
831
|
+
clearTimeout(timer);
|
|
832
|
+
if (!response.ok) {
|
|
833
|
+
const detail = await safeReadResponseText(response);
|
|
834
|
+
const mapped = mapOpenCodeHttpError(response.status, detail);
|
|
835
|
+
if (!refresh && isServerUnavailableError(mapped) && this.options.baseUrlResolver) {
|
|
836
|
+
return this.fetchJsonWithRetry(pathname, input, true);
|
|
837
|
+
}
|
|
838
|
+
throw mapped;
|
|
839
|
+
}
|
|
840
|
+
const text = await response.text();
|
|
841
|
+
return {
|
|
842
|
+
data: text.length > 0 ? JSON.parse(text) : undefined,
|
|
843
|
+
headers: response.headers
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
withReadonlyDb(run) {
|
|
847
|
+
const dbPath = this.resolveDbPath();
|
|
848
|
+
if (!existsSync(dbPath)) {
|
|
849
|
+
throw new Error("OPENCODE_DB_NOT_FOUND");
|
|
850
|
+
}
|
|
851
|
+
const DatabaseSync = loadDatabaseSync();
|
|
852
|
+
let db = null;
|
|
853
|
+
try {
|
|
854
|
+
db = new DatabaseSync(dbPath, { open: true, readOnly: true });
|
|
855
|
+
return run(db);
|
|
856
|
+
}
|
|
857
|
+
finally {
|
|
858
|
+
db?.close();
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
withWritableDb(run) {
|
|
862
|
+
const dbPath = this.resolveDbPath();
|
|
863
|
+
if (!existsSync(dbPath)) {
|
|
864
|
+
throw new Error("OPENCODE_DB_NOT_FOUND");
|
|
865
|
+
}
|
|
866
|
+
const DatabaseSync = loadDatabaseSync();
|
|
867
|
+
let db = null;
|
|
868
|
+
try {
|
|
869
|
+
db = new DatabaseSync(dbPath, { open: true });
|
|
870
|
+
db.exec("BEGIN IMMEDIATE");
|
|
871
|
+
const result = run(db);
|
|
872
|
+
db.exec("COMMIT");
|
|
873
|
+
return result;
|
|
874
|
+
}
|
|
875
|
+
catch (error) {
|
|
876
|
+
try {
|
|
877
|
+
db?.exec("ROLLBACK");
|
|
878
|
+
}
|
|
879
|
+
catch {
|
|
880
|
+
// 这里优先保留原始异常,回滚失败只做吞吐。
|
|
881
|
+
}
|
|
882
|
+
throw error;
|
|
883
|
+
}
|
|
884
|
+
finally {
|
|
885
|
+
db?.close();
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
resolveSessionId(providerSessionId, rawStoreRef) {
|
|
889
|
+
const explicit = providerSessionId.trim();
|
|
890
|
+
if (explicit.length > 0) {
|
|
891
|
+
return explicit;
|
|
892
|
+
}
|
|
893
|
+
const parsed = parseSessionIdFromRawStoreRef(rawStoreRef);
|
|
894
|
+
if (parsed) {
|
|
895
|
+
return parsed;
|
|
896
|
+
}
|
|
897
|
+
throw new Error("PROVIDER_SESSION_ID_REQUIRED");
|
|
898
|
+
}
|
|
899
|
+
assertSessionExistsOnSqlite(sessionId) {
|
|
900
|
+
const row = this.withReadonlyDb((db) => {
|
|
901
|
+
return db.prepare(`SELECT EXISTS(SELECT 1 FROM session WHERE id = ?) AS session_exists`).get(sessionId);
|
|
902
|
+
});
|
|
903
|
+
const exists = readInteger(row?.session_exists);
|
|
904
|
+
if (exists !== 1) {
|
|
905
|
+
throw new Error("PROVIDER_SESSION_NOT_FOUND");
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
normalizeSqliteSessionSummaryRow(row) {
|
|
909
|
+
const sessionId = ensureText(row.id).trim();
|
|
910
|
+
if (!sessionId) {
|
|
911
|
+
return null;
|
|
912
|
+
}
|
|
913
|
+
const workspacePath = ensureText(row.directory).trim();
|
|
914
|
+
const summaryUpdatedAtMs = firstValidNumber(row.last_message_time_ms, row.time_updated, row.time_created);
|
|
915
|
+
const lastMessageAt = toIsoTimestamp(summaryUpdatedAtMs, null);
|
|
916
|
+
const title = ensureText(row.title).trim() || sessionId;
|
|
917
|
+
const parentProviderSessionId = ensureText(row.parent_id).trim() || null;
|
|
918
|
+
const isArchived = row.time_archived !== null && row.time_archived !== undefined;
|
|
919
|
+
return {
|
|
920
|
+
provider: this.providerId,
|
|
921
|
+
providerSessionId: sessionId,
|
|
922
|
+
title,
|
|
923
|
+
workspacePath,
|
|
924
|
+
rawStoreRef: buildSessionRawStoreRef(sessionId),
|
|
925
|
+
isArchived,
|
|
926
|
+
lastMessageAt,
|
|
927
|
+
messageCount: Math.max(0, readInteger(row.message_count) ?? 0),
|
|
928
|
+
parentProviderSessionId,
|
|
929
|
+
isSubagent: Boolean(parentProviderSessionId),
|
|
930
|
+
subagentLabel: null
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
normalizeServerSessionSummary(session, metadataById) {
|
|
934
|
+
const sessionId = ensureText(session.id).trim();
|
|
935
|
+
if (!sessionId) {
|
|
936
|
+
return null;
|
|
937
|
+
}
|
|
938
|
+
const metadata = metadataById.get(sessionId);
|
|
939
|
+
const time = toJsonRecord(session.time);
|
|
940
|
+
const summaryUpdatedAtMs = firstValidNumber(time?.updated, time?.created);
|
|
941
|
+
const parentProviderSessionId = ensureText(session.parentID).trim()
|
|
942
|
+
|| ensureText(session.parent_id).trim()
|
|
943
|
+
|| metadata?.parentProviderSessionId
|
|
944
|
+
|| null;
|
|
945
|
+
const workspacePath = ensureText(session.directory).trim();
|
|
946
|
+
return {
|
|
947
|
+
provider: this.providerId,
|
|
948
|
+
providerSessionId: sessionId,
|
|
949
|
+
title: ensureText(session.title).trim() || sessionId,
|
|
950
|
+
workspacePath,
|
|
951
|
+
rawStoreRef: buildSessionRawStoreRef(sessionId),
|
|
952
|
+
isArchived: metadata?.isArchived ?? false,
|
|
953
|
+
lastMessageAt: toIsoTimestamp(summaryUpdatedAtMs, null),
|
|
954
|
+
messageCount: metadata?.messageCount ?? 0,
|
|
955
|
+
parentProviderSessionId,
|
|
956
|
+
isSubagent: Boolean(parentProviderSessionId),
|
|
957
|
+
subagentLabel: null
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
readSessionMetadata(sessionIds) {
|
|
961
|
+
if (sessionIds.length === 0 || !existsSync(this.resolveDbPath())) {
|
|
962
|
+
return new Map();
|
|
963
|
+
}
|
|
964
|
+
return this.withReadonlyDb((db) => {
|
|
965
|
+
const placeholders = sessionIds.map(() => "?").join(", ");
|
|
966
|
+
const rows = db.prepare(`SELECT
|
|
967
|
+
s.id AS id,
|
|
968
|
+
s.parent_id AS parent_id,
|
|
969
|
+
s.time_archived AS time_archived,
|
|
970
|
+
COALESCE(stats.message_count, 0) AS message_count
|
|
971
|
+
FROM session s
|
|
972
|
+
LEFT JOIN (
|
|
973
|
+
SELECT session_id, COUNT(*) AS message_count
|
|
974
|
+
FROM message
|
|
975
|
+
GROUP BY session_id
|
|
976
|
+
) AS stats
|
|
977
|
+
ON stats.session_id = s.id
|
|
978
|
+
WHERE s.id IN (${placeholders})`).all(...sessionIds);
|
|
979
|
+
return new Map(rows
|
|
980
|
+
.map((row) => {
|
|
981
|
+
const sessionId = ensureText(row.id).trim();
|
|
982
|
+
if (!sessionId) {
|
|
983
|
+
return null;
|
|
984
|
+
}
|
|
985
|
+
return [
|
|
986
|
+
sessionId,
|
|
987
|
+
{
|
|
988
|
+
parentProviderSessionId: ensureText(row.parent_id).trim() || null,
|
|
989
|
+
isArchived: row.time_archived !== null && row.time_archived !== undefined,
|
|
990
|
+
messageCount: Math.max(0, readInteger(row.message_count) ?? 0)
|
|
991
|
+
}
|
|
992
|
+
];
|
|
993
|
+
})
|
|
994
|
+
.filter((entry) => entry !== null));
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
readSessionSummariesByIds(sessionIds, targetPath) {
|
|
998
|
+
if (sessionIds.length === 0) {
|
|
999
|
+
return [];
|
|
1000
|
+
}
|
|
1001
|
+
if (!existsSync(this.resolveDbPath())) {
|
|
1002
|
+
return null;
|
|
1003
|
+
}
|
|
1004
|
+
return this.withReadonlyDb((db) => {
|
|
1005
|
+
const placeholders = sessionIds.map(() => "?").join(", ");
|
|
1006
|
+
const rows = db.prepare(`SELECT
|
|
1007
|
+
s.id AS id,
|
|
1008
|
+
s.parent_id AS parent_id,
|
|
1009
|
+
s.directory AS directory,
|
|
1010
|
+
s.title AS title,
|
|
1011
|
+
s.time_created AS time_created,
|
|
1012
|
+
s.time_updated AS time_updated,
|
|
1013
|
+
s.time_archived AS time_archived,
|
|
1014
|
+
COALESCE(stats.message_count, 0) AS message_count,
|
|
1015
|
+
stats.last_message_time_ms AS last_message_time_ms
|
|
1016
|
+
FROM session s
|
|
1017
|
+
LEFT JOIN (
|
|
1018
|
+
SELECT
|
|
1019
|
+
session_id,
|
|
1020
|
+
COUNT(*) AS message_count,
|
|
1021
|
+
MAX(COALESCE(time_updated, time_created)) AS last_message_time_ms
|
|
1022
|
+
FROM message
|
|
1023
|
+
GROUP BY session_id
|
|
1024
|
+
) AS stats
|
|
1025
|
+
ON stats.session_id = s.id
|
|
1026
|
+
WHERE s.id IN (${placeholders})`).all(...sessionIds);
|
|
1027
|
+
return rows
|
|
1028
|
+
.map((row) => this.normalizeSqliteSessionSummaryRow(row))
|
|
1029
|
+
.filter((summary) => summary !== null)
|
|
1030
|
+
.filter((summary) => workspaceMatches(targetPath, normalizeWorkspacePath(summary.workspacePath)));
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
readSessionMessagesFromSqlite(sessionId) {
|
|
1034
|
+
this.assertSessionExistsOnSqlite(sessionId);
|
|
1035
|
+
const rows = this.withReadonlyDb((db) => {
|
|
1036
|
+
return db.prepare(`SELECT
|
|
1037
|
+
p.id AS part_id,
|
|
1038
|
+
p.message_id AS message_id,
|
|
1039
|
+
p.time_created AS part_time_created,
|
|
1040
|
+
p.data AS part_data,
|
|
1041
|
+
m.time_created AS message_time_created,
|
|
1042
|
+
m.data AS message_data
|
|
1043
|
+
FROM part p
|
|
1044
|
+
INNER JOIN message m
|
|
1045
|
+
ON m.id = p.message_id
|
|
1046
|
+
WHERE p.session_id = ?
|
|
1047
|
+
ORDER BY p.time_created ASC, p.rowid ASC`).all(sessionId);
|
|
1048
|
+
});
|
|
1049
|
+
const envelopes = rows.reduce((map, row) => {
|
|
1050
|
+
const messageId = ensureText(row.message_id).trim();
|
|
1051
|
+
const partId = ensureText(row.part_id).trim();
|
|
1052
|
+
const messagePayload = toJsonRecord(row.message_data);
|
|
1053
|
+
const partPayload = toJsonRecord(row.part_data);
|
|
1054
|
+
if (!messageId || !partId || !messagePayload || !partPayload) {
|
|
1055
|
+
return map;
|
|
1056
|
+
}
|
|
1057
|
+
const existing = map.get(messageId) ?? {
|
|
1058
|
+
info: {
|
|
1059
|
+
...messagePayload,
|
|
1060
|
+
id: messageId,
|
|
1061
|
+
sessionID: sessionId,
|
|
1062
|
+
time: {
|
|
1063
|
+
...(toJsonRecord(messagePayload.time) ?? {}),
|
|
1064
|
+
created: firstValidNumber(row.message_time_created) ?? undefined
|
|
1065
|
+
}
|
|
1066
|
+
},
|
|
1067
|
+
parts: []
|
|
1068
|
+
};
|
|
1069
|
+
const parts = Array.isArray(existing.parts) ? existing.parts : [];
|
|
1070
|
+
parts.push({
|
|
1071
|
+
...partPayload,
|
|
1072
|
+
id: partId,
|
|
1073
|
+
sessionID: sessionId,
|
|
1074
|
+
messageID: messageId
|
|
1075
|
+
});
|
|
1076
|
+
existing.parts = parts;
|
|
1077
|
+
map.set(messageId, existing);
|
|
1078
|
+
return map;
|
|
1079
|
+
}, new Map());
|
|
1080
|
+
return normalizeOpenCodeMessageEnvelopes(sessionId, sessionId, [...envelopes.values()]);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
function ensureNullableText(value) {
|
|
1084
|
+
const normalized = ensureText(value).trim();
|
|
1085
|
+
return normalized || null;
|
|
1086
|
+
}
|
|
1087
|
+
function resolveOpenCodeMessageTitle(message) {
|
|
1088
|
+
if (message.role !== "user" || message.kind !== "text") {
|
|
1089
|
+
return null;
|
|
1090
|
+
}
|
|
1091
|
+
const title = message.content.trim().replace(/\s+/g, " ");
|
|
1092
|
+
return title || null;
|
|
1093
|
+
}
|
|
1094
|
+
function buildForkSlug(sourceSlug, forkedSessionId) {
|
|
1095
|
+
const base = sourceSlug.trim() || "session";
|
|
1096
|
+
const suffix = forkedSessionId.slice(0, 8);
|
|
1097
|
+
return `${base}-fork-${suffix}`;
|
|
1098
|
+
}
|
|
1099
|
+
function buildSyntheticAcceptedMessage(sessionId, content, timestamp) {
|
|
1100
|
+
const rawRef = `${buildMessageRawRef(sessionId, `accepted-${Date.parse(timestamp)}`)}#synthetic`;
|
|
1101
|
+
return {
|
|
1102
|
+
messageId: `opencode-accepted-${Date.parse(timestamp)}`,
|
|
1103
|
+
provider: "opencode",
|
|
1104
|
+
providerSessionId: sessionId,
|
|
1105
|
+
role: "user",
|
|
1106
|
+
kind: "text",
|
|
1107
|
+
content,
|
|
1108
|
+
toolCall: null,
|
|
1109
|
+
timestamp,
|
|
1110
|
+
sequence: 1,
|
|
1111
|
+
rawRef
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
function mapOpenCodeHttpError(statusCode, detail) {
|
|
1115
|
+
if (statusCode === 404) {
|
|
1116
|
+
return new Error("PROVIDER_SESSION_NOT_FOUND");
|
|
1117
|
+
}
|
|
1118
|
+
if (statusCode >= 500) {
|
|
1119
|
+
return new Error("SERVER_UNAVAILABLE");
|
|
1120
|
+
}
|
|
1121
|
+
if (statusCode === 409 && /active|running|busy/i.test(detail)) {
|
|
1122
|
+
return new Error("ACTIVE_RUN_EXISTS");
|
|
1123
|
+
}
|
|
1124
|
+
return new Error(detail || `OPENCODE_HTTP_${statusCode}`);
|
|
1125
|
+
}
|
|
1126
|
+
function applyOpenCodeForkSourceSnapshot(partPayload, snapshot) {
|
|
1127
|
+
if (!snapshot) {
|
|
1128
|
+
return partPayload;
|
|
1129
|
+
}
|
|
1130
|
+
const nextPart = { ...partPayload };
|
|
1131
|
+
const targetKey = typeof nextPart.text === "string"
|
|
1132
|
+
? "text"
|
|
1133
|
+
: typeof nextPart.content === "string"
|
|
1134
|
+
? "content"
|
|
1135
|
+
: typeof nextPart.message === "string"
|
|
1136
|
+
? "message"
|
|
1137
|
+
: snapshot.kind === "thinking"
|
|
1138
|
+
? "thinking"
|
|
1139
|
+
: "text";
|
|
1140
|
+
nextPart[targetKey] = snapshot.content;
|
|
1141
|
+
return nextPart;
|
|
1142
|
+
}
|
|
1143
|
+
async function safeReadResponseText(response) {
|
|
1144
|
+
try {
|
|
1145
|
+
return (await response.text()).trim();
|
|
1146
|
+
}
|
|
1147
|
+
catch {
|
|
1148
|
+
return "";
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
function isServerUnavailableError(error) {
|
|
1152
|
+
return error instanceof Error && error.message === "SERVER_UNAVAILABLE";
|
|
1153
|
+
}
|
|
1154
|
+
function isServerTimeoutError(error) {
|
|
1155
|
+
return error instanceof Error && error.message === "SERVER_TIMEOUT";
|
|
1156
|
+
}
|
|
1157
|
+
function createTimeoutRetryState() {
|
|
1158
|
+
return {
|
|
1159
|
+
startedAtMs: Date.now(),
|
|
1160
|
+
timeoutCount: 0
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
function advanceTimeoutRetryState(state) {
|
|
1164
|
+
return {
|
|
1165
|
+
startedAtMs: state.startedAtMs,
|
|
1166
|
+
timeoutCount: state.timeoutCount + 1
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
function isTimeoutRetryableMethod(method) {
|
|
1170
|
+
const normalized = (method ?? "GET").trim().toUpperCase();
|
|
1171
|
+
return normalized === "GET" || normalized === "HEAD" || normalized === "OPTIONS";
|
|
1172
|
+
}
|
|
1173
|
+
function shouldSurfaceTimeout(state) {
|
|
1174
|
+
return (state.timeoutCount >= MAX_CONSECUTIVE_TIMEOUTS
|
|
1175
|
+
|| Date.now() - state.startedAtMs >= TIMEOUT_WARNING_THRESHOLD_MS);
|
|
1176
|
+
}
|
|
1177
|
+
function isOpenCodeSubmitTimeoutAmbiguous(error) {
|
|
1178
|
+
return error instanceof Error && error.message === OPENCODE_SUBMIT_TIMEOUT_AMBIGUOUS;
|
|
1179
|
+
}
|
|
1180
|
+
function isTimestampOnOrAfter(timestamp, minTimestamp) {
|
|
1181
|
+
if (!minTimestamp) {
|
|
1182
|
+
return true;
|
|
1183
|
+
}
|
|
1184
|
+
const timestampMs = Date.parse(timestamp);
|
|
1185
|
+
const minTimestampMs = Date.parse(minTimestamp);
|
|
1186
|
+
if (!Number.isFinite(timestampMs) || !Number.isFinite(minTimestampMs)) {
|
|
1187
|
+
return timestamp >= minTimestamp;
|
|
1188
|
+
}
|
|
1189
|
+
return timestampMs >= minTimestampMs;
|
|
1190
|
+
}
|
|
1191
|
+
//# sourceMappingURL=opencode.js.map
|