@openchambery/web 1.19.22-beta.1 → 2.0.0-beta.10
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/README.md +13 -7
- package/bin/cli-opencode.test.js +208 -0
- package/bin/cli.js +62 -9
- package/bin/lib/cli-startup.js +105 -2
- package/bin/lib/cli-startup.test.js +179 -0
- package/dist/assets/{AgentAvatar-CRaBJXKs.js → AgentAvatar-CzTtVMnI.js} +1 -1
- package/dist/assets/AssistantView-Cg1qQvVe.js +3 -0
- package/dist/assets/{DiagramView-D1LGK_s2.js → DiagramView-hOi72Wdx.js} +1 -1
- package/dist/assets/{FadeInOnReveal-B0kJo9Ii.js → FadeInOnReveal-DCqrQkkz.js} +1 -1
- package/dist/assets/Icon-B8fSTLdP.js +1 -0
- package/dist/assets/MarkdownRenderer-Cw74oVxV.js +2 -0
- package/dist/assets/{MarkdownRendererImpl-DfoCJ1Mq.js → MarkdownRendererImpl-YM7iRmzK.js} +3 -3
- package/dist/assets/MarkstreamRendererImpl-BDy_oGJQ.js +3 -0
- package/dist/assets/MobileDetailNavigation-iX_hb_Xt.js +1 -0
- package/dist/assets/{MobileShareBridge-2Yjn6wXg.js → MobileShareBridge-CAMUupwR.js} +2 -2
- package/dist/assets/MobileSurface-CHbdPcLH.js +2 -0
- package/dist/assets/{MultiRunWindow-tTbMFowS.js → MultiRunWindow-Ci1ODFFX.js} +1 -1
- package/dist/assets/{OnboardingScreen-CD2KtlF3.js → OnboardingScreen-O4cGdz5p.js} +1 -1
- package/dist/assets/OverlayScrollbar-CRfGtcmG.js +2 -0
- package/dist/assets/SettingsView-Dg8BtTV1.js +25 -0
- package/dist/assets/{SettingsWindow-zIa76s4t.js → SettingsWindow-B8d8qIQ7.js} +1 -1
- package/dist/assets/TerminalView-CMiw3s_c.js +8 -0
- package/dist/assets/{ToolOutputDialog-DNqA4uBl.js → ToolOutputDialog-ByaQYRTp.js} +2 -2
- package/dist/assets/appThemeRegistry-BGGHio8T.js +1 -0
- package/dist/assets/{assistant-attachment-cache-C0aRnFkj.js → assistant-attachment-cache-DphJleHr.js} +1 -1
- package/dist/assets/{button-CI7Q-Zw_.js → button-DIIrsMjW.js} +1 -1
- package/dist/assets/{collapsible-D5Phaykh.js → collapsible-CnvUeYst.js} +1 -1
- package/dist/assets/{context-menu-CubSDW2g.js → context-menu-BGBUpZEQ.js} +1 -1
- package/dist/assets/{desktopHosts-B1ixEylr.js → desktopHosts-JGFqhlaM.js} +1 -1
- package/dist/assets/{desktopRelayRestore-4JmFUw8r.js → desktopRelayRestore-CHEwrI93.js} +1 -1
- package/dist/assets/{diagram-DdLO8HZ9.js → diagram-rvn7_qBM.js} +1 -1
- package/dist/assets/{dialog-B6pnIYmp.js → dialog-CQ63sc9E.js} +1 -1
- package/dist/assets/es-Dsmc0A_3.js +15 -0
- package/dist/assets/fileMentionTouchSelection-BzzcWJCi.js +3 -0
- package/dist/assets/{fileQueries-DQc8EJUf.js → fileQueries-DN6gbLhM.js} +1 -1
- package/dist/assets/fr-C_ZlZDI2.js +13 -0
- package/dist/assets/gitApi-BF8vuoZc.js +10 -0
- package/dist/assets/{imageSource-BlAJJUEI.js → imageSource-BMztRu0c.js} +1 -1
- package/dist/assets/{input-D-__fwRi.js → input-BVu-iykl.js} +1 -1
- package/dist/assets/insertionBoundaries-EcAfGT2D.js +1 -0
- package/dist/assets/ja-BqqTaWTi.js +15 -0
- package/dist/assets/ko-DP2XPM37.js +15 -0
- package/dist/assets/main-B7t9lavz.js +2 -0
- package/dist/assets/main-D2BzpnUt.css +1 -0
- package/dist/assets/main-DWP-prNB.js +169 -0
- package/dist/assets/markdown-worker-bS5OgGO3.js +2 -0
- package/dist/assets/{markdownHeightCache-BhxqJOvf.js → markdownHeightCache-D9-B1wdY.js} +1 -1
- package/dist/assets/markdownTheme-DM5h1i18.js +1 -0
- package/dist/assets/mcpQueries-CfXrAkuU.js +1 -0
- package/dist/assets/miniChat-DgOrEQbN.js +2 -0
- package/dist/assets/mobile-Co_ZOHkZ.js +2 -0
- package/dist/assets/multirun-DelyUO6k.js +4 -0
- package/dist/assets/persistence-D0y7226-.js +3 -0
- package/dist/assets/pl-BCf5uLlK.js +15 -0
- package/dist/assets/platform-CurqO28D.js +6 -0
- package/dist/assets/{projectMeta-S1hJ7oBp.js → projectMeta-CPElzJ0n.js} +2 -2
- package/dist/assets/pt-BR-W09Q2pvn.js +15 -0
- package/dist/assets/{relay-image-stream-DM7atqJs.js → relay-image-stream-DrdVj99c.js} +1 -1
- package/dist/assets/renderElectronMiniChatApp-pOE93w86.js +2 -0
- package/dist/assets/renderMobileApp-F7ZSLcw8.js +28 -0
- package/dist/assets/runtime-fetch-Fs9ZV2V8.js +1 -0
- package/dist/assets/{runtimeConfig-CMkwoQ_X.js → runtimeConfig-DSS0KxG3.js} +1 -1
- package/dist/assets/runtimeEndpointReset-x2Wgx57R.js +149 -0
- package/dist/assets/sessionChangeSummary-BUGSYcHp.js +2 -0
- package/dist/assets/{sessionLookup-BrU3rFHJ.js → sessionLookup-Bss8M20i.js} +1 -1
- package/dist/assets/{sortable-tabs-strip-Fnfhf3K9.js → sortable-tabs-strip-CE7W7lJ9.js} +1 -1
- package/dist/assets/src-lS1keDVV.css +2 -0
- package/dist/assets/store-jaP79mqI.js +15 -0
- package/dist/assets/{terminalApi-xjqssKke.js → terminalApi-mDR2jXTo.js} +1 -1
- package/dist/assets/textarea-XD2oX_Ee.js +1 -0
- package/dist/assets/{tooltip-0T5jv0cu.js → tooltip-DYeQ_Hvy.js} +1 -1
- package/dist/assets/uk-BgFzz8m2.js +15 -0
- package/dist/assets/{url-_z7evzdK.js → url-CGbJbiJq.js} +1 -1
- package/dist/assets/{useAppFontEffects-C02YFyAv.js → useAppFontEffects-BAWHZ-t0.js} +64 -45
- package/dist/assets/{useAssistantUIStore-CMutVh9B.js → useAssistantUIStore-Bz4tRflF.js} +1 -1
- package/dist/assets/useDesktopWindowControlsLayout-hN_nLb7T.js +1 -0
- package/dist/assets/useEffectiveDirectory-Do9DQ453.js +1 -0
- package/dist/assets/{useFontPreferences-B1JYyzpK.js → useFontPreferences-Bjx8zkGM.js} +1 -1
- package/dist/assets/useMobileNavigationStore-BsY_gi_K.js +414 -0
- package/dist/assets/useSessionAutoCleanup-C4g5KmDf.js +2 -0
- package/dist/assets/useUIStore-syVmbuDA.js +1 -0
- package/dist/assets/{useWorkerHighlightedLines-C9z0ML1z.js → useWorkerHighlightedLines-B5QXxBok.js} +2 -2
- package/dist/assets/vendor-opencode-client-C12gfjag.js +12 -0
- package/dist/assets/{vendor-reactuses-core-BnW6GxJt.js → vendor-reactuses-core-Dq5ocTF8.js} +1 -1
- package/dist/assets/{vendor-yaml-DIcAK3EC.js → vendor-yaml-C9KlJAlj.js} +37 -37
- package/dist/assets/zh-CN-BhqSLgUY.js +15 -0
- package/dist/assets/zh-TW-BsaBgY-p.js +15 -0
- package/dist/index.html +12 -12
- package/dist/mini-chat.html +12 -12
- package/dist/mobile.html +12 -12
- package/package.json +3 -2
- package/server/index.js +423 -20
- package/server/lib/assistants/DOCUMENTATION.md +26 -21
- package/server/lib/assistants/assign.js +2 -1
- package/server/lib/assistants/contact-store.js +37 -19
- package/server/lib/assistants/contracts.js +11 -1
- package/server/lib/assistants/projection-history.test.js +454 -0
- package/server/lib/assistants/routes.js +11 -5
- package/server/lib/assistants/service.js +850 -294
- package/server/lib/assistants/service.test.js +588 -274
- package/server/lib/browser-provider/DOCUMENTATION.md +141 -0
- package/server/lib/browser-provider/contract.js +312 -0
- package/server/lib/browser-provider/host.js +421 -0
- package/server/lib/browser-provider/host.test.js +304 -0
- package/server/lib/browser-provider/routes.js +122 -0
- package/server/lib/browser-provider/routes.test.js +120 -0
- package/server/lib/browser-provider/selection-store.js +43 -0
- package/server/lib/browser-provider/selection-store.test.js +35 -0
- package/server/lib/conversations/DOCUMENTATION.md +5 -5
- package/server/lib/conversations/service.js +87 -57
- package/server/lib/conversations/service.test.js +132 -100
- package/server/lib/conversations/validation.js +11 -1
- package/server/lib/event-stream/DOCUMENTATION.md +3 -1
- package/server/lib/event-stream/directory-ws-bridge.js +13 -2
- package/server/lib/event-stream/global-hub.js +51 -5
- package/server/lib/event-stream/reasoning-projection.js +16 -1
- package/server/lib/event-stream/reasoning-projection.test.js +15 -0
- package/server/lib/event-stream/runtime.js +57 -20
- package/server/lib/event-stream/runtime.test.js +112 -0
- package/server/lib/llm/DOCUMENTATION.md +95 -84
- package/server/lib/llm/catalog.js +111 -45
- package/server/lib/llm/catalog.test.js +121 -59
- package/server/lib/llm/completions.js +41 -12
- package/server/lib/llm/completions.test.js +45 -4
- package/server/lib/llm/generate.js +516 -453
- package/server/lib/llm/generate.test.js +705 -484
- package/server/lib/llm/routes.js +8 -4
- package/server/lib/message-queue/DOCUMENTATION.md +5 -5
- package/server/lib/message-queue/opencode-adapter.js +191 -104
- package/server/lib/message-queue/opencode-adapter.test.js +328 -58
- package/server/lib/message-queue/runtime.js +15 -2
- package/server/lib/message-queue/runtime.test.js +6 -6
- package/server/lib/message-queue/worker.js +7 -1
- package/server/lib/notifications/DOCUMENTATION.md +3 -1
- package/server/lib/notifications/runtime.js +133 -31
- package/server/lib/notifications/runtime.test.js +103 -0
- package/server/lib/notifications/template-runtime.js +130 -38
- package/server/lib/notifications/template-runtime.test.js +96 -0
- package/server/lib/opencode/DOCUMENTATION.md +111 -16
- package/server/lib/opencode/agent-document.d.ts +28 -0
- package/server/lib/opencode/agent-document.js +280 -0
- package/server/lib/opencode/agent-document.test.js +137 -0
- package/server/lib/opencode/agents.js +96 -0
- package/server/lib/opencode/auth-state-runtime.js +5 -0
- package/server/lib/opencode/bootstrap-runtime.js +2 -0
- package/server/lib/opencode/config-entity-routes.js +117 -103
- package/server/lib/opencode/config-entity-routes.test.js +148 -10
- package/server/lib/opencode/config-hot-reload.integration.test.js +105 -0
- package/server/lib/opencode/ensure-cli.d.ts +8 -0
- package/server/lib/opencode/ensure-cli.js +238 -0
- package/server/lib/opencode/ensure-cli.test.js +119 -0
- package/server/lib/opencode/env-runtime.js +208 -111
- package/server/lib/opencode/env-runtime.test.js +211 -14
- package/server/lib/opencode/feature-routes-runtime.js +90 -5
- package/server/lib/opencode/feature-routes-runtime.test.js +25 -0
- package/server/lib/opencode/http-server-connections.js +98 -0
- package/server/lib/opencode/http-server-connections.test.js +321 -0
- package/server/lib/opencode/lifecycle.js +539 -95
- package/server/lib/opencode/lifecycle.test.js +698 -6
- package/server/lib/opencode/managed-capabilities-runtime.js +15 -2
- package/server/lib/opencode/managed-capabilities-runtime.test.js +1 -0
- package/server/lib/opencode/network-runtime.js +28 -16
- package/server/lib/opencode/network-runtime.test.js +68 -4
- package/server/lib/opencode/openchamber-routes.js +7 -1
- package/server/lib/opencode/opencode2-pin.js +139 -0
- package/server/lib/opencode/opencode2-pin.test.js +88 -0
- package/server/lib/opencode/opencode2-sidecar.e2e.test.js +326 -0
- package/server/lib/opencode/owned-runtime-upgrade.js +431 -0
- package/server/lib/opencode/owned-runtime-upgrade.test.js +160 -0
- package/server/lib/opencode/plugin-compatibility.js +15 -0
- package/server/lib/opencode/plugin-compatibility.test.js +21 -0
- package/server/lib/opencode/plugin-routes.js +3 -18
- package/server/lib/opencode/plugin-routes.test.js +9 -9
- package/server/lib/opencode/plugins.js +4 -3
- package/server/lib/opencode/plugins.test.js +12 -0
- package/server/lib/opencode/provider-catalog.js +58 -12
- package/server/lib/opencode/provider-catalog.test.js +48 -0
- package/server/lib/opencode/proxy.js +373 -28
- package/server/lib/opencode/proxy.test.js +353 -0
- package/server/lib/opencode/routes.js +333 -76
- package/server/lib/opencode/routes.test.js +315 -50
- package/server/lib/opencode/runtime-contract.js +401 -0
- package/server/lib/opencode/runtime-contract.test.js +214 -0
- package/server/lib/opencode/server-opencode-fetch.js +242 -0
- package/server/lib/opencode/server-opencode-fetch.test.js +130 -0
- package/server/lib/opencode/server-utils-runtime.js +35 -0
- package/server/lib/opencode/shared-service.integration.test.js +66 -0
- package/server/lib/opencode/shared-service.js +147 -0
- package/server/lib/opencode/shared-service.test.js +93 -0
- package/server/lib/opencode/shared.js +3 -3
- package/server/lib/opencode/shutdown-runtime.js +15 -6
- package/server/lib/opencode/shutdown-runtime.test.js +49 -1
- package/server/lib/opencode/skill-routes.js +26 -40
- package/server/lib/opencode/skill-routes.test.js +71 -7
- package/server/lib/opencode/skills.test.js +15 -0
- package/server/lib/opencode/startup-pipeline-runtime.js +4 -0
- package/server/lib/opencode/static-routes-runtime.js +3 -1
- package/server/lib/opencode/static-routes-runtime.test.js +33 -0
- package/server/lib/opencode/upgrade-screen.d.ts +30 -0
- package/server/lib/opencode/upgrade-screen.js +299 -0
- package/server/lib/opencode/upgrade-screen.test.js +196 -0
- package/server/lib/opencode/v1-migration-gate.js +157 -0
- package/server/lib/opencode/v1-migration-gate.test.js +111 -0
- package/server/lib/opencode/v2-client.js +60 -0
- package/server/lib/opencode/v2-plugin-host-shim/index.mjs +155 -0
- package/server/lib/opencode/v2-plugin-host-shim/package.json +4 -0
- package/server/lib/opencode/watcher.js +2 -1
- package/server/lib/opencode/watcher.test.js +1 -1
- package/server/lib/permission-auto-accept/DOCUMENTATION.md +5 -5
- package/server/lib/permission-auto-accept/runtime.js +14 -7
- package/server/lib/permission-auto-accept/runtime.test.js +27 -12
- package/server/lib/relay/reasoning-projection.e2e.test.ts +22 -7
- package/server/lib/scheduled-tasks/DOCUMENTATION.md +79 -39
- package/server/lib/scheduled-tasks/managed-tool-route.js +31 -1
- package/server/lib/scheduled-tasks/managed-tool-route.test.js +23 -0
- package/server/lib/scheduled-tasks/routes.js +27 -0
- package/server/lib/scheduled-tasks/routes.test.js +94 -0
- package/server/lib/scheduled-tasks/runtime.js +381 -310
- package/server/lib/scheduled-tasks/runtime.test.js +600 -309
- package/server/lib/session-goal/DOCUMENTATION.md +173 -22
- package/server/lib/session-goal/capability.js +57 -0
- package/server/lib/session-goal/capability.test.js +33 -0
- package/server/lib/session-goal/routes.js +240 -2
- package/server/lib/session-goal/routes.test.js +211 -0
- package/server/lib/session-goal/runtime.js +1617 -113
- package/server/lib/session-goal/runtime.test.js +1500 -70
- package/server/lib/session-index/DOCUMENTATION.md +18 -15
- package/server/lib/session-index/event-ingest.js +89 -16
- package/server/lib/session-index/event-ingest.test.js +73 -0
- package/server/lib/session-index/host-authority-snapshot.js +92 -0
- package/server/lib/session-index/routes.host-archive.test.js +201 -0
- package/server/lib/session-index/routes.js +63 -10
- package/server/lib/session-index/routes.test.js +8 -8
- package/server/lib/session-index/service.js +7 -1
- package/server/lib/session-index/sync-runtime.js +171 -41
- package/server/lib/session-index/sync-runtime.test.js +164 -9
- package/server/lib/session-metadata/DOCUMENTATION.md +96 -0
- package/server/lib/session-metadata/opencode-session-record.d.ts +57 -0
- package/server/lib/session-metadata/opencode-session-record.js +316 -0
- package/server/lib/session-metadata/opencode-session-record.test.js +242 -0
- package/server/lib/session-metadata/routes.js +197 -0
- package/server/lib/session-metadata/routes.test.js +156 -0
- package/server/lib/session-metadata/session-archive.d.ts +73 -0
- package/server/lib/session-metadata/session-archive.js +654 -0
- package/server/lib/session-metadata/session-archive.test.js +359 -0
- package/server/lib/session-metadata/session-metadata-store.d.ts +38 -0
- package/server/lib/session-metadata/session-metadata-store.js +422 -0
- package/server/lib/session-metadata/session-metadata-store.test.js +379 -0
- package/server/lib/session-metadata/session-projection.d.ts +41 -0
- package/server/lib/session-metadata/session-projection.js +279 -0
- package/server/lib/session-metadata/session-projection.test.js +64 -0
- package/server/lib/session-metadata/system-session.js +55 -0
- package/server/lib/session-metadata/system-session.test.js +55 -0
- package/server/lib/session-title/DOCUMENTATION.md +40 -7
- package/server/lib/session-title/native-runtime.test.js +167 -0
- package/server/lib/session-title/runtime.js +69 -44
- package/server/lib/session-title/session-access.js +46 -0
- package/server/lib/session-title/session-access.test.js +91 -0
- package/server/lib/session-turn-pages/DOCUMENTATION.md +12 -11
- package/server/lib/session-turn-pages/reconcile.service.js +1 -1
- package/server/lib/session-turn-pages/reconcile.service.test.js +16 -0
- package/server/lib/session-turn-pages/routes.js +123 -75
- package/server/lib/session-turn-pages/routes.test.js +566 -0
- package/server/lib/session-turn-pages/service.js +6 -2
- package/server/lib/session-turn-pages/service.test.js +34 -0
- package/server/lib/session-turn-pages/session-message-projection.d.ts +13 -0
- package/server/lib/session-turn-pages/session-message-projection.js +281 -0
- package/server/lib/small-model/DOCUMENTATION.md +101 -146
- package/server/lib/small-model/catalog.js +84 -54
- package/server/lib/small-model/catalog.test.js +111 -9
- package/server/lib/small-model/custom-api.js +68 -0
- package/server/lib/small-model/custom-api.test.js +64 -0
- package/server/lib/small-model/index.js +125 -241
- package/server/lib/small-model/resolve.js +35 -120
- package/server/lib/small-model/resolve.test.js +20 -110
- package/server/lib/small-model/routes.js +1 -3
- package/server/lib/small-model/summary-settings.test.js +157 -253
- package/server/opencode-proxy.test.js +63 -12
- package/dist/assets/AssistantView-BUveAgc4.js +0 -3
- package/dist/assets/Icon-BgdfPhNs.js +0 -1
- package/dist/assets/MarkdownRenderer-BbrbDH6-.js +0 -2
- package/dist/assets/MarkstreamRendererImpl-D2dsW5Lg.js +0 -3
- package/dist/assets/MobileDetailNavigation-B0aqKXd7.js +0 -1
- package/dist/assets/MobileSurface-DW7WfPsy.js +0 -2
- package/dist/assets/OverlayScrollbar-DrA0Vsg5.js +0 -2
- package/dist/assets/SettingsView-PkXIavr7.js +0 -25
- package/dist/assets/TerminalView-CDdzF4yi.js +0 -8
- package/dist/assets/appThemeRegistry-D5Yxg4YF.js +0 -1
- package/dist/assets/es-DA3MqOo0.js +0 -15
- package/dist/assets/fileMentionTouchSelection-DNeiqns-.js +0 -4
- package/dist/assets/fr-Dbz0CdIA.js +0 -13
- package/dist/assets/gitApi-DXyC4MiV.js +0 -7
- package/dist/assets/insertionBoundaries-KlOVrHHt.js +0 -1
- package/dist/assets/ja-DumanVQA.js +0 -15
- package/dist/assets/ko-C0IkiUjQ.js +0 -15
- package/dist/assets/main-BPS5ylib.js +0 -2
- package/dist/assets/main-Cpd9VWYs.js +0 -169
- package/dist/assets/main-qSeeJRW1.css +0 -1
- package/dist/assets/markdown-worker-CptoICmq.js +0 -2
- package/dist/assets/markdownTheme-DOfGg-A7.js +0 -1
- package/dist/assets/miniChat-B8_KLWiY.js +0 -2
- package/dist/assets/mobile-CtktKrXn.js +0 -2
- package/dist/assets/multirun-CYfP9Cfm.js +0 -4
- package/dist/assets/persistence-Ce3AnpEr.js +0 -3
- package/dist/assets/pl-B9No6MQp.js +0 -15
- package/dist/assets/platform-0w_Q9_ji.js +0 -2
- package/dist/assets/pt-BR-DyQ0WTDh.js +0 -15
- package/dist/assets/renderElectronMiniChatApp-iK14LWm8.js +0 -2
- package/dist/assets/renderMobileApp-DORLPWnb.js +0 -28
- package/dist/assets/runtime-fetch-zIalUnbb.js +0 -1
- package/dist/assets/runtimeEndpointReset-ChOxt-J7.js +0 -147
- package/dist/assets/sessionChangeSummary-NnxcqCTI.js +0 -2
- package/dist/assets/src-rS3zCcsC.css +0 -2
- package/dist/assets/store-5B_LDnLM.js +0 -15
- package/dist/assets/textarea-bHYxZtfH.js +0 -1
- package/dist/assets/uk-C_1KkqyP.js +0 -15
- package/dist/assets/useDesktopWindowControlsLayout-Dnr-jX0C.js +0 -1
- package/dist/assets/useEffectiveDirectory-CZLLyarc.js +0 -1
- package/dist/assets/useMobileNavigationStore-CoCiqNgm.js +0 -413
- package/dist/assets/useSessionAutoCleanup-xQyETQkG.js +0 -2
- package/dist/assets/useUIStore-Bxv3f23A.js +0 -1
- package/dist/assets/vendor-opencode-sdk-C07HQypa.js +0 -7
- package/dist/assets/zh-CN-uWILgBdt.js +0 -15
- package/dist/assets/zh-TW-MYfdvhbD.js +0 -15
- package/server/lib/small-model/call.js +0 -427
- package/server/lib/small-model/call.test.js +0 -382
- package/server/lib/small-model/opencode-session.js +0 -339
- package/server/lib/small-model/opencode-session.test.js +0 -177
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
OpenChamber-owned turn-window pagination and anchor reconcile for session messages.
|
|
6
6
|
|
|
7
|
-
1. **Turn pages** — clients request the last N **authored user turns** (default 3) rather than a raw message count. The host loops
|
|
7
|
+
1. **Turn pages** — clients request the last N **authored user turns** (default 3) rather than a raw message count. The host loops OpenCode v2 `message.list` pages (first page `limit` + `order=desc`; continuation `limit` + `cursor` from the previous body `cursor.next` — upstream rejects `order` together with `cursor` with 400) until the turn budget is met or history is exhausted.
|
|
8
8
|
2. **Anchor reconcile** — after SSE reconnect, clients request the gap from a stable turn-boundary anchor to the current head. The host scans newest→older, returns chronological gap records (including the anchor's overlap turn), and paginates via host-owned continuation tokens with page/byte/total budgets.
|
|
9
9
|
|
|
10
10
|
Exposed as:
|
|
@@ -16,7 +16,7 @@ Exposed as:
|
|
|
16
16
|
|
|
17
17
|
## Why this exists
|
|
18
18
|
|
|
19
|
-
Official OpenCode pagination is message-count based and uses **opaque** cursors (not message ids).
|
|
19
|
+
Official OpenCode pagination is message-count based and uses **opaque** cursors (not message ids). v2 pages arrive **newest-first**; `fetchPage` reverses each page to chronological **old→new** before aggregation. UI prepend/load-more needs a stable turn boundary so synthetic loop messages, subtasks, and compaction rows do not consume the turn budget. This module aggregates upstream pages on the host, returns chronological records, and exposes a continuous **host-owned opaque cursor** that points just before the earliest returned authored user.
|
|
20
20
|
|
|
21
21
|
## Scope
|
|
22
22
|
|
|
@@ -34,7 +34,7 @@ Official OpenCode pagination is message-count based and uses **opaque** cursors
|
|
|
34
34
|
| `scanLimit` | **omitted** | `10..200` when present | Optional override only. Host→OpenCode local page size; when omitted it resolves to `_inner_scanLimit`. Clients should omit this. |
|
|
35
35
|
| `before` | omitted | opaque string ≤ 8192 chars | Resume older history: host cursor (`oc1.…`) or raw OpenCode SDK cursor on first page |
|
|
36
36
|
| `directory` | omitted | path string | Forwarded to directory-scoped OpenCode client |
|
|
37
|
-
| `includeReasoning` | omitted (include) | strict `'false'` only disables | OpenChamber projection control. When `'false'`, drop `type=reasoning` parts from turn-page / reconcile / exact responses
|
|
37
|
+
| `includeReasoning` | omitted (include) | strict `'false'` only disables | OpenChamber projection control. When `'false'`, drop `type=reasoning` parts from turn-page / reconcile / exact responses. Host order is **normalize native SessionMessageInfo → slim/L1 bounds → reasoning strip** so `content`/`text` carriers cannot rebuild filtered parts or leak through `info` expansion. Missing or any other value keeps existing behavior (slim reasoning identity on turn pages; full parts on reconcile/exact). **Never forwarded to OpenCode.** Same contract on transcript-cache reads, official `session.messages` list proxy, and event SSE/WS send boundaries — see `event-stream/reasoning-projection.js`. |
|
|
38
38
|
|
|
39
39
|
Invalid `turns`, explicit invalid `scanLimit`, or `before` (malformed/stale host token, oversize) → HTTP 400.
|
|
40
40
|
|
|
@@ -66,7 +66,7 @@ Success `200`:
|
|
|
66
66
|
}
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
- `records`: chronological oldest → newest, including intermediate non-boundary rows (synthetic, tools, subtask, compaction) inside the window.
|
|
69
|
+
- `records`: chronological oldest → newest, including intermediate non-boundary rows (synthetic, tools, subtask, compaction) inside the window. Host projection drops v2 **control** SessionMessage rows (`idle`, `model-switched`, `agent-selected`, `agent-switched`, `location-switched`) so they never reach ChatMessage as empty Assistant headers. Native assistants project `content[]` once (never also top-level `text` when `content` is present). Wire `model.id` becomes domain `modelID`; `finish`/`error` on failed assistants (e.g. `provider.auth` 401) are preserved.
|
|
70
70
|
- `turnCount`: count of authored user boundaries in `records`.
|
|
71
71
|
- `cursor`: host-owned opaque token for the next `before=` request; `null` when `complete` is true. The token represents the position **just before** the earliest returned authored user (so the client can load older history without overlap).
|
|
72
72
|
- `complete`: `upstreamComplete && selected.length === accumulated.length`. True when upstream history is exhausted **and** `selectTurnRecords` did not trim any older scanned rows (nothing left for the client). When the scan window held more than N turns and older rows were trimmed, or when upstream stopped on a full page with a missing `nextCursor` (suspicious truncation), `complete` stays `false` with a `cursor` so the client can fetch / retry.
|
|
@@ -82,7 +82,7 @@ Every turn-page response summarizes `tool`, `reasoning`, and `file` parts plus m
|
|
|
82
82
|
|---|---|---|
|
|
83
83
|
| **L1** | Turn pages, reconcile response pages, message/session SSE fan-out, exact `GET /api/session/:sessionID/message/:messageID` | Any `info.summary.diffs` **array** is projected to a **slim file list** `[{ file, status?, additions, deletions }]` plus additive markers `summary.diffCount: number` and `summary.hasDiffs: boolean`. Patch/before/after/from/to and other heavy bodies are stripped. Other lightweight summary fields are preserved. `diffCount` equals the slim array length; `hasDiffs === diffCount > 0`. Consumers may use either the slim array or the markers. |
|
|
84
84
|
| **L2** | `GET /api/openchamber/sessions/:sessionID/changes?messageID=` (no `file`) | Host reads official `session.message` locally, returns only `{ files: [{ file, status?, additions, deletions }] }`. Never returns patch/before/after/from/to or the full message envelope. |
|
|
85
|
-
| **L3** | Same route with `file=` | Host
|
|
85
|
+
| **L3** | Same route with `file=` | Host currently still reads `info.summary.diffs` from the exact message payload when present. **v2 `SessionMessageInfo` has no `summary.diffs`**, so L3 fails closed with upstream 502 until a parent follow-up lands an authoritative per-message diff source. Do **not** substitute working-tree / `vcs.diff` here. When diffs are available, returns `{ diff: SnapshotFileDiff }` for the exact `file` string match. No match → HTTP 404 `{ error: 'change file not found', code: 'change_not_found' }`. Older hosts may ignore `file=` and answer 200 `{ files }` (L2 only). |
|
|
86
86
|
|
|
87
87
|
Exact message GET keeps the official `{ info, parts }` response shape and only applies L1 summary projection so materialize/recovery never relays raw multi-megabyte patch bodies through the generic proxy. Abort/45s timeout semantics match the turn-page routes. Global `/api` auth still applies.
|
|
88
88
|
|
|
@@ -126,7 +126,7 @@ On resume:
|
|
|
126
126
|
1. Strict decode / shape / length validation of the host token.
|
|
127
127
|
2. First `fetchPage` uses the token’s raw upstream `before`.
|
|
128
128
|
3. Locate `boundaryID` in that page; keep only records strictly older than it (`slice(0, index)` in old→new order). Boundary and newer rows are excluded.
|
|
129
|
-
4. If fewer than N turns remain, continue with that raw page’s `
|
|
129
|
+
4. If fewer than N turns remain, continue with that raw page’s `cursor.next` for older pages.
|
|
130
130
|
5. Each accumulated record records its upstream page’s request-before origin; when `complete=false`, the next host cursor encodes the earliest selected authored user’s origin + id.
|
|
131
131
|
|
|
132
132
|
A raw OpenCode SDK cursor (no `oc1.` prefix) is still accepted as the first `before` and is passed through unchanged to `fetchPage`.
|
|
@@ -146,14 +146,15 @@ A message is an authored user turn boundary when:
|
|
|
146
146
|
|
|
147
147
|
## Aggregation rules
|
|
148
148
|
|
|
149
|
-
-
|
|
150
|
-
- Continues paging with raw upstream `
|
|
151
|
-
- **Suspicious truncation:** an upstream page whose `records.length >= scanLimit` (full page) but `nextCursor == null` is treated as a non-authoritative cut (observed OpenCode
|
|
149
|
+
- `fetchPage` returns each page chronological **old→new** (v2 `data` is newest-first and is reversed there). Older pages are **prepended** while deduping by `info.id` (global order remains old→new).
|
|
150
|
+
- Continues paging with the raw upstream `cursor.next` (sent as `cursor`, never with `order`) until `turns` authored boundaries are collected or upstream reports no next cursor.
|
|
151
|
+
- **Suspicious truncation:** an upstream page whose `records.length >= scanLimit` (full page) but `nextCursor == null` is treated as a non-authoritative cut (observed OpenCode next-cursor race), not as end-of-history. The host stops scanning that round with `upstreamComplete=false`, so the response stays `complete=false` and still emits a boundary host cursor the client can retry. A short page (`records.length < scanLimit`) with no cursor, an empty page with no cursor, or an explicit `page.complete === true` remain authoritative exhaustion. Client no-growth handling still bounds retries if the upstream view stays truncated.
|
|
152
152
|
- Every upstream record must have a non-empty `info.id`; otherwise structured error, no partial `records`, HTTP 502.
|
|
153
153
|
- Hard scan caps (no partial success): **50 pages** / **5000 messages** → structured error, HTTP 413.
|
|
154
154
|
- Repeated / stalled cursor, or empty page that still carries a next cursor → structured error, no partial `records`, HTTP 502.
|
|
155
155
|
- Malformed upstream payloads and SDK/transport failures → HTTP 502 (`error: "upstream"`).
|
|
156
|
-
- `
|
|
156
|
+
- Native v2 `SessionMessageInfo` rows are projected to the external `{ info, parts }` record contract by `session-message-projection.js` (control rows such as `idle` / `model-switched` are dropped). The VS Code turn-page bridge imports the same module so both runtimes emit identical records.
|
|
157
|
+
- `AbortSignal` is forwarded to each `message.list` call; route also applies a 45s linked timeout.
|
|
157
158
|
- Request abort only when the client disconnects mid-flight: `req` aborted, or `res` `close` while `!res.writableEnded`. A normal GET request `close` after the response has ended must not abort.
|
|
158
159
|
|
|
159
160
|
## Anchor reconcile API
|
|
@@ -263,7 +264,7 @@ When the per-page budget fills before the gap is complete, the host returns `con
|
|
|
263
264
|
- `service.js` — `isUserAuthoredTurnBoundary`, `selectTurnRecords`, `encodeHostCursor`, `decodeHostCursor`, `projectMessageDiffSummaries` (L1), `projectSlimParts`, `createSessionTurnPageService({ fetchPage, maxScanPages?, maxScanMessages? })`
|
|
264
265
|
- `reconcile.service.js` — `encodeReconcileContinuation`, `decodeReconcileContinuation`, `createSessionReconcileService({ fetchPage, runtimeKey?, page/total budgets?, continuationSecret?, clock?, continuationTtlMs? })`
|
|
265
266
|
- `changes.service.js` — `createSessionChangesService({ fetchMessage, fetchDiff })` for L2/L3; injectable for unit tests
|
|
266
|
-
- `routes.js` — Express registration for turn-page, reconcile, Changes, and exact message GET; optional injected `sessionTurnPageService` / `sessionReconcileService` / `sessionChangesService` / `fetchExactMessage` for tests; default wires
|
|
267
|
+
- `routes.js` — Express registration for turn-page, reconcile, Changes, and exact message GET; optional injected `sessionTurnPageService` / `sessionReconcileService` / `sessionChangesService` / `fetchExactMessage` for tests; default wires `@opencode/client` `OpenCode.make` (`message.list` / `session.message`) via `buildOpenCodeUrl` + `getOpenCodeAuthHeaders`. Exact/not-found classification honors real client `_tag` (`MessageNotFoundError` / `SessionNotFoundError`) and preserves abort → HTTP 499 (never folds abort into 502).
|
|
267
268
|
- `service.test.js` / `routes.test.js` / `reconcile.service.test.js` / `reconcile.routes.test.js` / `changes.service.test.js` — unit contracts
|
|
268
269
|
|
|
269
270
|
## Registration
|
|
@@ -47,7 +47,7 @@ const PROCESS_CONTINUATION_SECRET = randomBytes(32);
|
|
|
47
47
|
const fail = (error) => ({ ok: false, error });
|
|
48
48
|
|
|
49
49
|
const recordId = (record) => {
|
|
50
|
-
const id = record?.info?.id;
|
|
50
|
+
const id = record?.info?.id ?? record?.id;
|
|
51
51
|
return typeof id === 'string' && id.length > 0 ? id : null;
|
|
52
52
|
};
|
|
53
53
|
|
|
@@ -686,4 +686,20 @@ describe('createSessionReconcileService', () => {
|
|
|
686
686
|
expect(result.ok).toBe(true);
|
|
687
687
|
expect(result.resetRequired).toBe(true);
|
|
688
688
|
});
|
|
689
|
+
|
|
690
|
+
it('locates a SessionMessageInfo anchor by top-level id', async () => {
|
|
691
|
+
const fetchPage = vi.fn(async () => pageResult([
|
|
692
|
+
{ id: 'msg_u1', type: 'user', time: { created: 1 }, text: 'hi' },
|
|
693
|
+
{ id: 'msg_a1', type: 'assistant', time: { created: 2, completed: 3 }, content: [{ type: 'text', text: 'ok' }] },
|
|
694
|
+
], null));
|
|
695
|
+
const service = createSessionReconcileService(serviceOptions(fetchPage));
|
|
696
|
+
const result = await service.reconcile({
|
|
697
|
+
sessionID: 'ses_1',
|
|
698
|
+
directory: '/repo',
|
|
699
|
+
anchor: 'msg_u1',
|
|
700
|
+
});
|
|
701
|
+
expect(result.ok).toBe(true);
|
|
702
|
+
expect(result.anchorFound).toBe(true);
|
|
703
|
+
expect(result.records.map((entry) => entry.id)).toEqual(['msg_u1', 'msg_a1']);
|
|
704
|
+
});
|
|
689
705
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { makeOpenCodeV2Client } from '../opencode/v2-client.js';
|
|
2
2
|
import { projectMessageSummaryDiffCounts } from '../event-stream/diff-summary.js';
|
|
3
3
|
import {
|
|
4
4
|
projectMessagesPayloadForReasoning,
|
|
@@ -18,6 +18,10 @@ import {
|
|
|
18
18
|
projectSlimParts,
|
|
19
19
|
SLIM_PARTS_PROJECTION,
|
|
20
20
|
} from './service.js';
|
|
21
|
+
import {
|
|
22
|
+
projectSessionMessage,
|
|
23
|
+
projectSessionMessageRecords as projectRecords,
|
|
24
|
+
} from './session-message-projection.js';
|
|
21
25
|
|
|
22
26
|
const TURNS_MIN = 1;
|
|
23
27
|
const TURNS_MAX = 10;
|
|
@@ -210,10 +214,57 @@ const requestSignal = (req, res) => {
|
|
|
210
214
|
return controller.signal;
|
|
211
215
|
};
|
|
212
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Host outbound order: normalize → slim/L1 bounds → reasoning strip.
|
|
219
|
+
* Slim/reasoning must run on `{info, parts}` so native `content` cannot
|
|
220
|
+
* rebuild filtered parts or leak through info expansion.
|
|
221
|
+
*/
|
|
222
|
+
const projectTurnPageRecords = (records, includeReasoning) =>
|
|
223
|
+
projectMessagesPayloadForReasoning(projectSlimParts(projectRecords(records)), includeReasoning);
|
|
224
|
+
|
|
225
|
+
const projectReconcileRecords = (records, includeReasoning) =>
|
|
226
|
+
projectMessagesPayloadForReasoning(
|
|
227
|
+
projectMessageDiffSummaries(projectRecords(records)),
|
|
228
|
+
includeReasoning,
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
const createV2FetchPage = ({ buildOpenCodeUrl, getOpenCodeAuthHeaders, logger }) => {
|
|
232
|
+
return async ({ sessionID, before, limit, signal }) => {
|
|
233
|
+
const baseUrl = buildOpenCodeUrl('/', '').replace(/\/$/, '');
|
|
234
|
+
const headers = typeof getOpenCodeAuthHeaders === 'function' ? getOpenCodeAuthHeaders() : {};
|
|
235
|
+
const client = makeOpenCodeV2Client({ baseUrl, authHeaders: headers });
|
|
236
|
+
|
|
237
|
+
// Upstream rejects `order` together with `cursor` (400); the cursor
|
|
238
|
+
// already encodes the desc direction of the first page.
|
|
239
|
+
const result = await client.message.list({
|
|
240
|
+
sessionID,
|
|
241
|
+
...(Number.isFinite(limit) ? { limit } : {}),
|
|
242
|
+
...(typeof before === 'string' && before.length > 0 ? { cursor: before } : { order: 'desc' }),
|
|
243
|
+
}, { signal });
|
|
244
|
+
|
|
245
|
+
const items = Array.isArray(result?.data) ? result.data : null;
|
|
246
|
+
if (!items) {
|
|
247
|
+
logger?.warn?.('[session-turn-pages] message.list malformed payload');
|
|
248
|
+
const error = new Error('upstream');
|
|
249
|
+
error.code = 'upstream';
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const next = result?.cursor?.next;
|
|
254
|
+
const nextCursor = typeof next === 'string' && next.length > 0 ? next : null;
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
records: items.slice().reverse(),
|
|
258
|
+
nextCursor,
|
|
259
|
+
complete: nextCursor == null,
|
|
260
|
+
};
|
|
261
|
+
};
|
|
262
|
+
};
|
|
263
|
+
|
|
213
264
|
const createSdkClient = ({ buildOpenCodeUrl, getOpenCodeAuthHeaders }) => {
|
|
214
265
|
const baseUrl = buildOpenCodeUrl('/', '').replace(/\/$/, '');
|
|
215
266
|
const headers = typeof getOpenCodeAuthHeaders === 'function' ? getOpenCodeAuthHeaders() : {};
|
|
216
|
-
return
|
|
267
|
+
return makeOpenCodeV2Client({ baseUrl, authHeaders: headers });
|
|
217
268
|
};
|
|
218
269
|
|
|
219
270
|
const throwUpstream = (logger, label) => {
|
|
@@ -223,89 +274,86 @@ const throwUpstream = (logger, label) => {
|
|
|
223
274
|
throw error;
|
|
224
275
|
};
|
|
225
276
|
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
...(Number.isFinite(limit) ? { limit } : {}),
|
|
234
|
-
...(typeof before === 'string' && before.length > 0 ? { before } : {}),
|
|
235
|
-
}, { signal });
|
|
236
|
-
|
|
237
|
-
if (result?.error) {
|
|
238
|
-
throwUpstream(logger, '[session-turn-pages] session.messages SDK error');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const data = result?.data;
|
|
242
|
-
const records = Array.isArray(data)
|
|
243
|
-
? data
|
|
244
|
-
: Array.isArray(data?.items)
|
|
245
|
-
? data.items
|
|
246
|
-
: null;
|
|
247
|
-
if (!records) {
|
|
248
|
-
throwUpstream(logger, '[session-turn-pages] session.messages malformed payload');
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const headerCursor = result?.response?.headers?.get?.('x-next-cursor');
|
|
252
|
-
const nextCursor = typeof headerCursor === 'string' && headerCursor.length > 0
|
|
253
|
-
? headerCursor
|
|
254
|
-
: null;
|
|
277
|
+
const getHttpStatus = (error) => {
|
|
278
|
+
const candidates = [error?.cause?.status, error?.status, error?.response?.status, error?.statusCode];
|
|
279
|
+
for (const value of candidates) {
|
|
280
|
+
if (Number.isFinite(value)) return value;
|
|
281
|
+
}
|
|
282
|
+
return undefined;
|
|
283
|
+
};
|
|
255
284
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
285
|
+
/**
|
|
286
|
+
* Real `@opencode/client` throws declared JSON bodies with `_tag`
|
|
287
|
+
* (e.g. MessageNotFoundError) — no HTTP status on the object. Also accept
|
|
288
|
+
* legacy status/code shapes from tests and older surfaces.
|
|
289
|
+
*/
|
|
290
|
+
const isNotFoundError = (error) => {
|
|
291
|
+
if (!error || typeof error !== 'object') return false;
|
|
292
|
+
const tag = error._tag ?? error.name;
|
|
293
|
+
if (tag === 'MessageNotFoundError' || tag === 'SessionNotFoundError') return true;
|
|
294
|
+
if (getHttpStatus(error) === 404) return true;
|
|
295
|
+
const code = error.code ?? error.type ?? error.error?.code ?? error.error?.type ?? error.error?._tag;
|
|
296
|
+
return code === 'not_found'
|
|
297
|
+
|| code === 'NotFound'
|
|
298
|
+
|| code === 'MessageNotFoundError'
|
|
299
|
+
|| code === 'SessionNotFoundError';
|
|
262
300
|
};
|
|
263
301
|
|
|
302
|
+
const isAbortError = (error) => (
|
|
303
|
+
error?.name === 'AbortError'
|
|
304
|
+
|| error?.code === 'aborted'
|
|
305
|
+
|| error?.cause?.name === 'AbortError'
|
|
306
|
+
);
|
|
307
|
+
|
|
264
308
|
const createSdkFetchMessage = ({ buildOpenCodeUrl, getOpenCodeAuthHeaders, logger }) => {
|
|
265
|
-
return async ({ sessionID, messageID,
|
|
309
|
+
return async ({ sessionID, messageID, signal }) => {
|
|
266
310
|
const client = createSdkClient({ buildOpenCodeUrl, getOpenCodeAuthHeaders });
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
messageID,
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
error.code = 'not_found';
|
|
278
|
-
throw error;
|
|
311
|
+
let result;
|
|
312
|
+
try {
|
|
313
|
+
result = await client.session.message({ sessionID, messageID }, { signal });
|
|
314
|
+
} catch (error) {
|
|
315
|
+
// Preserve abort so routes map 499; never fold into upstream 502.
|
|
316
|
+
if (isAbortError(error) || signal?.aborted) throw error;
|
|
317
|
+
if (isNotFoundError(error)) {
|
|
318
|
+
const notFound = new Error('not_found');
|
|
319
|
+
notFound.code = 'not_found';
|
|
320
|
+
throw notFound;
|
|
279
321
|
}
|
|
280
322
|
throwUpstream(logger, '[session-turn-pages] session.message SDK error');
|
|
281
323
|
}
|
|
282
324
|
|
|
283
|
-
const data = result?.data;
|
|
325
|
+
const data = result?.data ?? result;
|
|
284
326
|
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
285
327
|
throwUpstream(logger, '[session-turn-pages] session.message malformed payload');
|
|
286
328
|
}
|
|
287
|
-
|
|
329
|
+
const projected = projectSessionMessage(data);
|
|
330
|
+
// Control rows (idle / model-switched) are not chat messages.
|
|
331
|
+
if (!projected || !projected.info) {
|
|
332
|
+
const notFound = new Error('not_found');
|
|
333
|
+
notFound.code = 'not_found';
|
|
334
|
+
throw notFound;
|
|
335
|
+
}
|
|
336
|
+
return projected;
|
|
288
337
|
};
|
|
289
338
|
};
|
|
290
339
|
|
|
340
|
+
/**
|
|
341
|
+
* L3 diff source. v2 SessionMessageInfo has no summary.diffs; keep failure
|
|
342
|
+
* explicit until the parent lands an authoritative per-message diff API.
|
|
343
|
+
* Do not substitute working-tree / vcs.diff here.
|
|
344
|
+
*/
|
|
291
345
|
const createSdkFetchDiff = ({ buildOpenCodeUrl, getOpenCodeAuthHeaders, logger }) => {
|
|
292
346
|
return async ({ sessionID, messageID, directory, signal }) => {
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
throwUpstream(logger, '[session-changes] session.diff SDK error');
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const data = result?.data;
|
|
305
|
-
if (!Array.isArray(data)) {
|
|
306
|
-
throwUpstream(logger, '[session-changes] session.diff malformed payload');
|
|
347
|
+
const payload = await createSdkFetchMessage({
|
|
348
|
+
buildOpenCodeUrl,
|
|
349
|
+
getOpenCodeAuthHeaders,
|
|
350
|
+
logger,
|
|
351
|
+
})({ sessionID, messageID, directory, signal });
|
|
352
|
+
const diffs = payload?.info?.summary?.diffs;
|
|
353
|
+
if (!Array.isArray(diffs)) {
|
|
354
|
+
throwUpstream(logger, '[session-changes] session.message summary.diffs unavailable (L3 source pending)');
|
|
307
355
|
}
|
|
308
|
-
return
|
|
356
|
+
return diffs;
|
|
309
357
|
};
|
|
310
358
|
};
|
|
311
359
|
|
|
@@ -441,7 +489,7 @@ export const registerSessionTurnPageRoutes = (app, dependencies = {}) => {
|
|
|
441
489
|
|
|
442
490
|
const needsDefaultFetch = !injectedService || !injectedReconcileService;
|
|
443
491
|
const defaultFetchPage = needsDefaultFetch
|
|
444
|
-
?
|
|
492
|
+
? createV2FetchPage({ buildOpenCodeUrl, getOpenCodeAuthHeaders, logger })
|
|
445
493
|
: null;
|
|
446
494
|
|
|
447
495
|
const service = injectedService ?? createSessionTurnPageService({
|
|
@@ -514,8 +562,8 @@ export const registerSessionTurnPageRoutes = (app, dependencies = {}) => {
|
|
|
514
562
|
}
|
|
515
563
|
|
|
516
564
|
const includeReasoning = readIncludeReasoningQuery(req.query);
|
|
517
|
-
const records =
|
|
518
|
-
|
|
565
|
+
const records = projectReconcileRecords(
|
|
566
|
+
Array.isArray(result.records) ? result.records : [],
|
|
519
567
|
includeReasoning,
|
|
520
568
|
);
|
|
521
569
|
|
|
@@ -609,10 +657,10 @@ export const registerSessionTurnPageRoutes = (app, dependencies = {}) => {
|
|
|
609
657
|
|
|
610
658
|
// Turn-page responses (first packet and prepend) share slim-v1.
|
|
611
659
|
// Reconcile stays on the other route and keeps full parts.
|
|
612
|
-
//
|
|
660
|
+
// Normalize native SessionMessageInfo first, then slim, then reasoning strip.
|
|
613
661
|
const includeReasoning = readIncludeReasoningQuery(req.query);
|
|
614
|
-
const records =
|
|
615
|
-
|
|
662
|
+
const records = projectTurnPageRecords(
|
|
663
|
+
Array.isArray(result.records) ? result.records : [],
|
|
616
664
|
includeReasoning,
|
|
617
665
|
);
|
|
618
666
|
return res.status(200).json({
|
|
@@ -673,13 +721,13 @@ export const registerSessionTurnPageRoutes = (app, dependencies = {}) => {
|
|
|
673
721
|
projectMessagesPayloadForReasoning(projectExactMessagePayload(payload), includeReasoning),
|
|
674
722
|
);
|
|
675
723
|
} catch (error) {
|
|
676
|
-
if (error
|
|
724
|
+
if (isAbortError(error) || error?.code === 'aborted') {
|
|
677
725
|
if (!res.headersSent) {
|
|
678
726
|
return res.status(499).json({ error: SAFE_ERRORS.aborted });
|
|
679
727
|
}
|
|
680
728
|
return undefined;
|
|
681
729
|
}
|
|
682
|
-
if (error?.code === 'not_found') {
|
|
730
|
+
if (error?.code === 'not_found' || isNotFoundError(error)) {
|
|
683
731
|
if (!res.headersSent) {
|
|
684
732
|
return res.status(404).json({ error: 'not found', code: 'not_found' });
|
|
685
733
|
}
|