@openchambery/web 1.19.22-beta.1 → 2.0.0-beta.3
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-B_JQoreg.js} +1 -1
- package/dist/assets/AssistantView-ClQAfGOT.js +3 -0
- package/dist/assets/{DiagramView-D1LGK_s2.js → DiagramView-BNnda8qO.js} +1 -1
- package/dist/assets/{FadeInOnReveal-B0kJo9Ii.js → FadeInOnReveal-VYQTSAkr.js} +1 -1
- package/dist/assets/{Icon-BgdfPhNs.js → Icon-BiEQEcih.js} +1 -1
- package/dist/assets/MarkdownRenderer-CJHSsWin.js +2 -0
- package/dist/assets/{MarkdownRendererImpl-DfoCJ1Mq.js → MarkdownRendererImpl-DwrHFGUp.js} +3 -3
- package/dist/assets/{MarkstreamRendererImpl-D2dsW5Lg.js → MarkstreamRendererImpl-CSnbQMu3.js} +1 -1
- package/dist/assets/MobileDetailNavigation-BXr6AGLT.js +1 -0
- package/dist/assets/{MobileShareBridge-2Yjn6wXg.js → MobileShareBridge-D7OE9OP_.js} +2 -2
- package/dist/assets/MobileSurface-D2jUkX9l.js +2 -0
- package/dist/assets/{MultiRunWindow-tTbMFowS.js → MultiRunWindow-DF3iIFCd.js} +1 -1
- package/dist/assets/{OnboardingScreen-CD2KtlF3.js → OnboardingScreen-BjHmlwlw.js} +1 -1
- package/dist/assets/OverlayScrollbar-DLtWO_Gp.js +2 -0
- package/dist/assets/SettingsView-BRxELjow.js +25 -0
- package/dist/assets/{SettingsWindow-zIa76s4t.js → SettingsWindow-BI5swspb.js} +1 -1
- package/dist/assets/{TerminalView-CDdzF4yi.js → TerminalView-BU3x8-fr.js} +1 -1
- package/dist/assets/{ToolOutputDialog-DNqA4uBl.js → ToolOutputDialog-BEWhBcRd.js} +2 -2
- package/dist/assets/appThemeRegistry-4MR0F7Jz.js +1 -0
- package/dist/assets/{button-CI7Q-Zw_.js → button-DKuz3L8l.js} +1 -1
- package/dist/assets/collapsible-DXbDynN4.js +3 -0
- package/dist/assets/context-menu-CqolsLCm.js +1 -0
- package/dist/assets/{desktopHosts-B1ixEylr.js → desktopHosts-CoDkOnyS.js} +1 -1
- package/dist/assets/{desktopRelayRestore-4JmFUw8r.js → desktopRelayRestore-DDlVKyOE.js} +1 -1
- package/dist/assets/{diagram-DdLO8HZ9.js → diagram-D7T8HQgj.js} +1 -1
- package/dist/assets/{dialog-B6pnIYmp.js → dialog-DQYl3W_o.js} +1 -1
- package/dist/assets/es-CN3E_zXj.js +15 -0
- package/dist/assets/{fileMentionTouchSelection-DNeiqns-.js → fileMentionTouchSelection-BZ6ovBYH.js} +1 -1
- package/dist/assets/{fileQueries-DQc8EJUf.js → fileQueries-JrpcsOCs.js} +1 -1
- package/dist/assets/fr-9zZvQZD2.js +13 -0
- package/dist/assets/gitApi-CM42qUed.js +10 -0
- package/dist/assets/{imageSource-BlAJJUEI.js → imageSource-CIl0FL10.js} +1 -1
- package/dist/assets/{input-D-__fwRi.js → input-CzQy8UhV.js} +1 -1
- package/dist/assets/insertionBoundaries-CtkZ9720.js +1 -0
- package/dist/assets/ja-Dnjk_82N.js +15 -0
- package/dist/assets/ko-BxCEE99C.js +15 -0
- package/dist/assets/main-BILgBI3B.js +169 -0
- package/dist/assets/main-BeveiW6F.js +2 -0
- package/dist/assets/markdown-worker-bS5OgGO3.js +2 -0
- package/dist/assets/{markdownHeightCache-BhxqJOvf.js → markdownHeightCache-Cj1I5NDw.js} +1 -1
- package/dist/assets/{markdownTheme-DOfGg-A7.js → markdownTheme-CKac3wKC.js} +1 -1
- package/dist/assets/mcpQueries-D5mQymgM.js +1 -0
- package/dist/assets/miniChat-BgrzM3u7.js +2 -0
- package/dist/assets/mobile-DtYoQE8C.js +2 -0
- package/dist/assets/multirun-jy8dEI96.js +4 -0
- package/dist/assets/{persistence-Ce3AnpEr.js → persistence-C9LQpiOS.js} +2 -2
- package/dist/assets/pl-CNNsWnPM.js +15 -0
- package/dist/assets/platform-BQghHRfp.js +6 -0
- package/dist/assets/pt-BR-BZB2DJMp.js +15 -0
- package/dist/assets/renderElectronMiniChatApp-BGrrmeME.js +2 -0
- package/dist/assets/renderMobileApp-u3c4GtFC.js +28 -0
- package/dist/assets/{runtimeConfig-CMkwoQ_X.js → runtimeConfig-BIGBRGQI.js} +1 -1
- package/dist/assets/{runtimeEndpointReset-ChOxt-J7.js → runtimeEndpointReset-D2savkuw.js} +12 -12
- package/dist/assets/{sessionChangeSummary-NnxcqCTI.js → sessionChangeSummary-eIbpSfrO.js} +1 -1
- package/dist/assets/{sessionLookup-BrU3rFHJ.js → sessionLookup-myHe5ltu.js} +1 -1
- package/dist/assets/{sortable-tabs-strip-Fnfhf3K9.js → sortable-tabs-strip-BQtmHx9r.js} +1 -1
- package/dist/assets/src-CLN7Z-zx.css +2 -0
- package/dist/assets/store-DLCiZaA6.js +15 -0
- package/dist/assets/{terminalApi-xjqssKke.js → terminalApi-BxcdiduX.js} +1 -1
- package/dist/assets/{textarea-bHYxZtfH.js → textarea-CakKvqFw.js} +1 -1
- package/dist/assets/{tooltip-0T5jv0cu.js → tooltip-Cx5gTbdY.js} +1 -1
- package/dist/assets/uk-rwQrxeYM.js +15 -0
- package/dist/assets/{url-_z7evzdK.js → url-CDHnjlsm.js} +1 -1
- package/dist/assets/{useAppFontEffects-C02YFyAv.js → useAppFontEffects-CNeo0aZs.js} +59 -45
- package/dist/assets/{useAssistantUIStore-CMutVh9B.js → useAssistantUIStore-asNG6K7n.js} +1 -1
- package/dist/assets/useDesktopWindowControlsLayout-DBJ56qIo.js +1 -0
- package/dist/assets/useEffectiveDirectory-B4LvR8Gt.js +1 -0
- package/dist/assets/{useFontPreferences-B1JYyzpK.js → useFontPreferences-CUnQ4TVm.js} +1 -1
- package/dist/assets/useMobileNavigationStore-ZHJPxlHt.js +414 -0
- package/dist/assets/{useRuntimeAPIs-DSLXJybW.js → useRuntimeAPIs-DwLtO0c_.js} +1 -1
- package/dist/assets/useSessionAutoCleanup-BIVmrnYU.js +2 -0
- package/dist/assets/{useThemeSystem-DMzWVJaW.js → useThemeSystem-BlNUWH47.js} +1 -1
- package/dist/assets/useUIStore-CQYKJnrg.js +1 -0
- package/dist/assets/{useWorkerHighlightedLines-C9z0ML1z.js → useWorkerHighlightedLines-CJZbJDW3.js} +2 -2
- package/dist/assets/{vendor-base-ui-CnHfUmDN.js → vendor-base-ui-CDjyofeD.js} +1 -1
- package/dist/assets/{vendor-cmdk-CeAGfrLo.js → vendor-cmdk-BFH0UpXX.js} +1 -1
- package/dist/assets/{vendor-dnd-kit-accessibility-BY5LhhUB.js → vendor-dnd-kit-accessibility-BrR3AKvM.js} +1 -1
- package/dist/assets/{vendor-dnd-kit-core-CvWxUPdb.js → vendor-dnd-kit-core-CNfdvk6H.js} +1 -1
- package/dist/assets/{vendor-dnd-kit-sortable-hHdP9lLb.js → vendor-dnd-kit-sortable-DQUaTeGj.js} +1 -1
- package/dist/assets/{vendor-framer-motion-DFy_BSVd.js → vendor-framer-motion-4dogsUk3.js} +1 -1
- package/dist/assets/{vendor-legendapp-list-WE32lwNk.js → vendor-legendapp-list-BU7MdPZR.js} +1 -1
- package/dist/assets/{vendor-markstream-react-DX55XLGO.js → vendor-markstream-react-qHC2FykU.js} +3 -3
- package/dist/assets/vendor-opencode-client-BOe2qpQb.js +12 -0
- package/dist/assets/{vendor-pierre-diffs-DX7XTPG3.js → vendor-pierre-diffs-CUfqC003.js} +1 -1
- package/dist/assets/{vendor-react-DLPElpoQ.js → vendor-react-C94A0AHl.js} +1 -1
- package/dist/assets/{vendor-react-drawio-ECtEwvbc.js → vendor-react-drawio-FVlWqKVE.js} +1 -1
- package/dist/assets/{vendor-reactuses-core-BnW6GxJt.js → vendor-reactuses-core-C2A3EjUi.js} +1 -1
- package/dist/assets/{vendor-sonner-DVzioF3d.js → vendor-sonner-DNqHmUQs.js} +1 -1
- package/dist/assets/{vendor-stream-diffs-DWy3xSmp.js → vendor-stream-diffs-CwbKsmlv.js} +2 -2
- package/dist/assets/{vendor-tanstack-react-query-D7pys_c9.js → vendor-tanstack-react-query-D0iFK57C.js} +1 -1
- package/dist/assets/{vendor-tanstack-react-virtual-tlDgH6PG.js → vendor-tanstack-react-virtual-B2kV6cnT.js} +1 -1
- package/dist/assets/{vendor-yaml-DIcAK3EC.js → vendor-yaml-C9KlJAlj.js} +37 -37
- package/dist/assets/{vendor-zustand-B4dlGEM2.js → vendor-zustand-BqLKf6ZY.js} +1 -1
- package/dist/assets/zh-CN-BvmBDnkD.js +15 -0
- package/dist/assets/zh-TW-9wcHTX0y.js +15 -0
- package/dist/index.html +13 -13
- package/dist/mini-chat.html +13 -13
- package/dist/mobile.html +13 -13
- package/package.json +2 -2
- package/server/index.js +392 -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/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/directory-ws-bridge.js +13 -2
- package/server/lib/event-stream/global-hub.js +51 -5
- 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/runtime.js +5 -0
- package/server/lib/opencode/DOCUMENTATION.md +103 -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 +111 -102
- package/server/lib/opencode/config-entity-routes.test.js +123 -10
- package/server/lib/opencode/config-hot-reload.integration.test.js +105 -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 +80 -5
- package/server/lib/opencode/feature-routes-runtime.test.js +18 -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 +368 -28
- package/server/lib/opencode/proxy.test.js +338 -0
- package/server/lib/opencode/routes.js +303 -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/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 +86 -0
- package/server/lib/session-metadata/routes.js +193 -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 +36 -0
- package/server/lib/session-metadata/session-metadata-store.js +375 -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 +255 -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 +67 -42
- 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/MarkdownRenderer-BbrbDH6-.js +0 -2
- 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/appThemeRegistry-D5Yxg4YF.js +0 -1
- package/dist/assets/collapsible-D5Phaykh.js +0 -1
- package/dist/assets/context-menu-CubSDW2g.js +0 -1
- package/dist/assets/es-DA3MqOo0.js +0 -15
- 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/markdown-worker-CptoICmq.js +0 -2
- 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/pl-B9No6MQp.js +0 -15
- package/dist/assets/platform-0w_Q9_ji.js +0 -2
- package/dist/assets/projectMeta-S1hJ7oBp.js +0 -3
- 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/src-rS3zCcsC.css +0 -2
- package/dist/assets/store-5B_LDnLM.js +0 -15
- 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
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import fsPromises from 'fs/promises';
|
|
3
|
-
import os from 'os';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { createOpencodeClient } from '@opencode-ai/sdk/v2';
|
|
6
|
-
|
|
7
|
-
// Temporary OpenCode session path for providers that lack a dedicated
|
|
8
|
-
// small-model adapter (plugin providers, region/credential-chain, …).
|
|
9
|
-
// Auth, endpoint rewrite, and token refresh stay inside the OpenCode runtime.
|
|
10
|
-
|
|
11
|
-
export const SMALL_MODEL_AGENT_NAME = 'openchamber-smallmodel';
|
|
12
|
-
export const SESSION_SETTLE_TIMEOUT_MS = 60_000;
|
|
13
|
-
const SESSION_SETTLE_POLL_MS = 1_000;
|
|
14
|
-
const ARCHIVE_RETRY_MS = 25;
|
|
15
|
-
const INCOMPLETE_ASSISTANT_SETTLE_PROBES = 2;
|
|
16
|
-
|
|
17
|
-
const AGENT_MARKDOWN = `---
|
|
18
|
-
mode: primary
|
|
19
|
-
hidden: true
|
|
20
|
-
permissions:
|
|
21
|
-
- action: "*"
|
|
22
|
-
resource: "*"
|
|
23
|
-
effect: deny
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
You are a utility text generator. Reply with only the requested text. Do not use tools.
|
|
27
|
-
`;
|
|
28
|
-
|
|
29
|
-
/** @type {string | null} */
|
|
30
|
-
let tempDirectory = null;
|
|
31
|
-
/** @type {Promise<string> | null} */
|
|
32
|
-
let tempDirectoryInflight = null;
|
|
33
|
-
|
|
34
|
-
const isMissing = (result) =>
|
|
35
|
-
result?.error?.status === 404
|
|
36
|
-
|| result?.error?.statusCode === 404
|
|
37
|
-
|| result?.error?.code === 'not_found'
|
|
38
|
-
|| result?.status === 404;
|
|
39
|
-
|
|
40
|
-
const promptAdmitted = (result) =>
|
|
41
|
-
!result?.error
|
|
42
|
-
&& (result?.response?.status === 204
|
|
43
|
-
|| result?.status === 204
|
|
44
|
-
|| result?.data !== undefined
|
|
45
|
-
|| result?.response?.ok === true);
|
|
46
|
-
|
|
47
|
-
const sleep = (ms, signal) => new Promise((resolve, reject) => {
|
|
48
|
-
if (signal?.aborted) {
|
|
49
|
-
reject(signal.reason instanceof Error ? signal.reason : new Error('aborted'));
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
const timer = setTimeout(resolve, ms);
|
|
53
|
-
const onAbort = () => {
|
|
54
|
-
clearTimeout(timer);
|
|
55
|
-
reject(signal.reason instanceof Error ? signal.reason : new Error('aborted'));
|
|
56
|
-
};
|
|
57
|
-
signal?.addEventListener?.('abort', onAbort, { once: true });
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const sdkErrorMessage = (result, fallback) => {
|
|
61
|
-
const status = result?.error?.status ?? result?.error?.statusCode ?? result?.status;
|
|
62
|
-
const message = result?.error?.message || result?.error?.data?.message || fallback;
|
|
63
|
-
return status ? `${message} (${status})` : message;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const readMessageInfo = (message) => {
|
|
67
|
-
if (!message || typeof message !== 'object') return null;
|
|
68
|
-
if (message.info && typeof message.info === 'object') return message.info;
|
|
69
|
-
return message;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const assistantTextFromMessages = (messages) => {
|
|
73
|
-
if (!Array.isArray(messages) || messages.length === 0) return '';
|
|
74
|
-
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
75
|
-
const message = messages[i];
|
|
76
|
-
const info = readMessageInfo(message);
|
|
77
|
-
if (info?.role !== 'assistant') continue;
|
|
78
|
-
if (info.error) {
|
|
79
|
-
const detail = typeof info.error === 'string'
|
|
80
|
-
? info.error
|
|
81
|
-
: (info.error?.message || JSON.stringify(info.error));
|
|
82
|
-
throw new Error(`OpenCode small-model session assistant error: ${detail}`);
|
|
83
|
-
}
|
|
84
|
-
const parts = Array.isArray(message?.parts) ? message.parts : [];
|
|
85
|
-
const text = parts
|
|
86
|
-
.map((part) => (part?.type === 'text' && typeof part.text === 'string' ? part.text : ''))
|
|
87
|
-
.filter(Boolean)
|
|
88
|
-
.join('');
|
|
89
|
-
return text;
|
|
90
|
-
}
|
|
91
|
-
return '';
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const ensureTempDirectory = async () => {
|
|
95
|
-
if (tempDirectory) return tempDirectory;
|
|
96
|
-
if (!tempDirectoryInflight) {
|
|
97
|
-
tempDirectoryInflight = (async () => {
|
|
98
|
-
const root = await fsPromises.mkdtemp(path.join(os.tmpdir(), 'openchamber-smallmodel-'));
|
|
99
|
-
const agentDir = path.join(root, '.opencode', 'agent');
|
|
100
|
-
await fsPromises.mkdir(agentDir, { recursive: true });
|
|
101
|
-
await fsPromises.writeFile(
|
|
102
|
-
path.join(agentDir, `${SMALL_MODEL_AGENT_NAME}.md`),
|
|
103
|
-
AGENT_MARKDOWN,
|
|
104
|
-
'utf8',
|
|
105
|
-
);
|
|
106
|
-
tempDirectory = root;
|
|
107
|
-
return root;
|
|
108
|
-
})().finally(() => {
|
|
109
|
-
tempDirectoryInflight = null;
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
return tempDirectoryInflight;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const createClient = ({ buildOpenCodeUrl, getOpenCodeAuthHeaders, directory }) => {
|
|
116
|
-
const baseUrl = buildOpenCodeUrl('/', '').replace(/\/$/, '');
|
|
117
|
-
return createOpencodeClient({
|
|
118
|
-
baseUrl,
|
|
119
|
-
directory,
|
|
120
|
-
headers: getOpenCodeAuthHeaders(),
|
|
121
|
-
});
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const archiveCreatedSession = async (client, sessionID, directory) => {
|
|
125
|
-
const archiveAt = Date.now();
|
|
126
|
-
const update = () => client.session.update({
|
|
127
|
-
sessionID,
|
|
128
|
-
directory,
|
|
129
|
-
time: { archived: archiveAt },
|
|
130
|
-
});
|
|
131
|
-
let result = await update();
|
|
132
|
-
if (isMissing(result)) {
|
|
133
|
-
await sleep(ARCHIVE_RETRY_MS);
|
|
134
|
-
result = await update();
|
|
135
|
-
}
|
|
136
|
-
if (result?.error || isMissing(result)) {
|
|
137
|
-
throw new Error(`OpenCode small-model session archive failed: ${sdkErrorMessage(result, 'archive failed')}`);
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const waitForIdleAssistant = async ({ client, sessionID, directory, signal }) => {
|
|
142
|
-
let incompleteAssistantProbes = 0;
|
|
143
|
-
let emptyIdleProbes = 0;
|
|
144
|
-
|
|
145
|
-
for (;;) {
|
|
146
|
-
signal?.throwIfAborted?.();
|
|
147
|
-
|
|
148
|
-
let sessionBusy = false;
|
|
149
|
-
try {
|
|
150
|
-
const statusResult = await client.session.status({ directory }, { signal });
|
|
151
|
-
if (!statusResult?.error && statusResult?.data && typeof statusResult.data === 'object') {
|
|
152
|
-
const statusValue = statusResult.data[sessionID];
|
|
153
|
-
const type = statusValue?.type ?? statusValue?.status;
|
|
154
|
-
sessionBusy = type === 'busy' || type === 'retry';
|
|
155
|
-
}
|
|
156
|
-
} catch (error) {
|
|
157
|
-
if (signal?.aborted) throw error;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (sessionBusy) {
|
|
161
|
-
incompleteAssistantProbes = 0;
|
|
162
|
-
emptyIdleProbes = 0;
|
|
163
|
-
await sleep(SESSION_SETTLE_POLL_MS, signal);
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
try {
|
|
168
|
-
const messagesResult = await client.session.messages({
|
|
169
|
-
sessionID,
|
|
170
|
-
directory,
|
|
171
|
-
limit: 20,
|
|
172
|
-
}, { signal });
|
|
173
|
-
if (!messagesResult?.error && Array.isArray(messagesResult?.data)) {
|
|
174
|
-
const lastInfo = readMessageInfo(messagesResult.data.at(-1));
|
|
175
|
-
if (lastInfo?.role === 'assistant') {
|
|
176
|
-
emptyIdleProbes = 0;
|
|
177
|
-
if (lastInfo.error) {
|
|
178
|
-
const detail = typeof lastInfo.error === 'string'
|
|
179
|
-
? lastInfo.error
|
|
180
|
-
: (lastInfo.error?.message || JSON.stringify(lastInfo.error));
|
|
181
|
-
throw new Error(`OpenCode small-model session assistant error: ${detail}`);
|
|
182
|
-
}
|
|
183
|
-
if (lastInfo.time?.completed) {
|
|
184
|
-
return messagesResult.data;
|
|
185
|
-
}
|
|
186
|
-
incompleteAssistantProbes += 1;
|
|
187
|
-
if (incompleteAssistantProbes >= INCOMPLETE_ASSISTANT_SETTLE_PROBES) {
|
|
188
|
-
return messagesResult.data;
|
|
189
|
-
}
|
|
190
|
-
} else {
|
|
191
|
-
incompleteAssistantProbes = 0;
|
|
192
|
-
emptyIdleProbes += 1;
|
|
193
|
-
if (emptyIdleProbes >= 5 && lastInfo?.role === 'user') {
|
|
194
|
-
throw new Error('OpenCode small-model session ended without assistant response');
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
} catch (error) {
|
|
199
|
-
if (signal?.aborted) throw error;
|
|
200
|
-
if (error instanceof Error && error.message.startsWith('OpenCode small-model')) throw error;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
await sleep(SESSION_SETTLE_POLL_MS, signal);
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Generate text via a throwaway OpenCode session (deny-all hidden agent).
|
|
209
|
-
* Errors are never masked as empty success.
|
|
210
|
-
*
|
|
211
|
-
* @param {{
|
|
212
|
-
* buildOpenCodeUrl: (pathname: string, search?: string) => string,
|
|
213
|
-
* getOpenCodeAuthHeaders: () => Record<string, string>,
|
|
214
|
-
* providerID: string,
|
|
215
|
-
* modelID: string,
|
|
216
|
-
* prompt: string,
|
|
217
|
-
* system?: string,
|
|
218
|
-
* purpose?: string,
|
|
219
|
-
* directory?: string,
|
|
220
|
-
* }} options
|
|
221
|
-
*/
|
|
222
|
-
export async function generateViaOpenCodeSession({
|
|
223
|
-
buildOpenCodeUrl,
|
|
224
|
-
getOpenCodeAuthHeaders,
|
|
225
|
-
providerID,
|
|
226
|
-
modelID,
|
|
227
|
-
prompt,
|
|
228
|
-
system,
|
|
229
|
-
purpose,
|
|
230
|
-
settleTimeoutMs = SESSION_SETTLE_TIMEOUT_MS,
|
|
231
|
-
}) {
|
|
232
|
-
if (typeof prompt !== 'string' || !prompt.trim()) {
|
|
233
|
-
throw new Error('OpenCode small-model session requires a prompt');
|
|
234
|
-
}
|
|
235
|
-
if (typeof providerID !== 'string' || !providerID.trim() || typeof modelID !== 'string' || !modelID.trim()) {
|
|
236
|
-
throw new Error('OpenCode small-model session requires providerID and modelID');
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const purposeLabel = typeof purpose === 'string' && purpose.trim() ? purpose.trim() : 'utility';
|
|
240
|
-
const budgetMs = Number(settleTimeoutMs) > 0 ? Number(settleTimeoutMs) : SESSION_SETTLE_TIMEOUT_MS;
|
|
241
|
-
const workingDirectory = await ensureTempDirectory();
|
|
242
|
-
const client = createClient({
|
|
243
|
-
buildOpenCodeUrl,
|
|
244
|
-
getOpenCodeAuthHeaders,
|
|
245
|
-
directory: workingDirectory,
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
let sessionID = null;
|
|
249
|
-
const controller = new AbortController();
|
|
250
|
-
const timeout = setTimeout(() => {
|
|
251
|
-
controller.abort(new Error(`OpenCode small-model session timed out after ${budgetMs}ms`));
|
|
252
|
-
}, budgetMs);
|
|
253
|
-
|
|
254
|
-
try {
|
|
255
|
-
const createResult = await client.session.create({
|
|
256
|
-
directory: workingDirectory,
|
|
257
|
-
title: `[small-model] ${purposeLabel}`,
|
|
258
|
-
agent: SMALL_MODEL_AGENT_NAME,
|
|
259
|
-
metadata: {
|
|
260
|
-
openchamber: {
|
|
261
|
-
smallModel: { purpose: purposeLabel },
|
|
262
|
-
},
|
|
263
|
-
},
|
|
264
|
-
}, { signal: controller.signal });
|
|
265
|
-
|
|
266
|
-
sessionID = createResult?.data?.id;
|
|
267
|
-
if (createResult?.error || !sessionID) {
|
|
268
|
-
throw new Error(`OpenCode small-model session create failed: ${sdkErrorMessage(createResult, 'create failed')}`);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Archive before prompting so ordinary session lists never flash system sessions.
|
|
272
|
-
await archiveCreatedSession(client, sessionID, workingDirectory);
|
|
273
|
-
|
|
274
|
-
const promptResult = await client.session.promptAsync({
|
|
275
|
-
sessionID,
|
|
276
|
-
directory: workingDirectory,
|
|
277
|
-
agent: SMALL_MODEL_AGENT_NAME,
|
|
278
|
-
model: { providerID, modelID },
|
|
279
|
-
...(typeof system === 'string' && system.trim() ? { system: system.trim() } : {}),
|
|
280
|
-
parts: [{ type: 'text', text: prompt, synthetic: false }],
|
|
281
|
-
}, { signal: controller.signal });
|
|
282
|
-
|
|
283
|
-
if (!promptAdmitted(promptResult)) {
|
|
284
|
-
throw new Error(`OpenCode small-model prompt_async failed: ${sdkErrorMessage(promptResult, 'prompt_async failed')}`);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const messages = await waitForIdleAssistant({
|
|
288
|
-
client,
|
|
289
|
-
sessionID,
|
|
290
|
-
directory: workingDirectory,
|
|
291
|
-
signal: controller.signal,
|
|
292
|
-
});
|
|
293
|
-
const text = assistantTextFromMessages(messages);
|
|
294
|
-
if (!text.trim()) {
|
|
295
|
-
throw new Error('OpenCode small-model session returned no assistant text');
|
|
296
|
-
}
|
|
297
|
-
return text;
|
|
298
|
-
} finally {
|
|
299
|
-
clearTimeout(timeout);
|
|
300
|
-
if (sessionID) {
|
|
301
|
-
try {
|
|
302
|
-
await client.session.delete({ sessionID, directory: workingDirectory });
|
|
303
|
-
} catch (error) {
|
|
304
|
-
console.warn(
|
|
305
|
-
'[small-model] failed to delete temporary OpenCode session:',
|
|
306
|
-
error?.message || error,
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
/** Best-effort cleanup of the lazy temp directory (agent markdown + empty root). */
|
|
314
|
-
export async function stop() {
|
|
315
|
-
const dir = tempDirectory;
|
|
316
|
-
tempDirectory = null;
|
|
317
|
-
tempDirectoryInflight = null;
|
|
318
|
-
if (!dir) return;
|
|
319
|
-
try {
|
|
320
|
-
await fsPromises.rm(dir, { recursive: true, force: true });
|
|
321
|
-
} catch (error) {
|
|
322
|
-
// Sync fallback if async rm races a partially-created tree.
|
|
323
|
-
try {
|
|
324
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
325
|
-
} catch {
|
|
326
|
-
console.warn('[small-model] failed to remove temp directory:', error?.message || error);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/** @internal test helpers */
|
|
332
|
-
export const _test = {
|
|
333
|
-
getTempDirectory: () => tempDirectory,
|
|
334
|
-
resetTempDirectory: () => {
|
|
335
|
-
tempDirectory = null;
|
|
336
|
-
tempDirectoryInflight = null;
|
|
337
|
-
},
|
|
338
|
-
AGENT_MARKDOWN,
|
|
339
|
-
};
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import fsPromises from 'fs/promises';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
vi.mock('@opencode-ai/sdk/v2', () => ({
|
|
6
|
-
createOpencodeClient: vi.fn(),
|
|
7
|
-
}));
|
|
8
|
-
|
|
9
|
-
const { createOpencodeClient } = await import('@opencode-ai/sdk/v2');
|
|
10
|
-
const {
|
|
11
|
-
generateViaOpenCodeSession,
|
|
12
|
-
stop,
|
|
13
|
-
SMALL_MODEL_AGENT_NAME,
|
|
14
|
-
_test,
|
|
15
|
-
} = await import('./opencode-session.js');
|
|
16
|
-
|
|
17
|
-
const buildOpenCodeUrl = () => 'http://127.0.0.1:4096/';
|
|
18
|
-
const getOpenCodeAuthHeaders = () => ({ authorization: 'Bearer test' });
|
|
19
|
-
|
|
20
|
-
const completedAssistant = (text) => ({
|
|
21
|
-
info: {
|
|
22
|
-
role: 'assistant',
|
|
23
|
-
time: { completed: Date.now() },
|
|
24
|
-
},
|
|
25
|
-
parts: [{ type: 'text', text }],
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const createMockClient = ({
|
|
29
|
-
create = vi.fn(async () => ({ data: { id: 'ses_small_1' } })),
|
|
30
|
-
update = vi.fn(async () => ({ data: { id: 'ses_small_1' } })),
|
|
31
|
-
promptAsync = vi.fn(async () => ({ response: { status: 204 } })),
|
|
32
|
-
status = vi.fn(async () => ({ data: { ses_small_1: { type: 'idle' } } })),
|
|
33
|
-
messages = vi.fn(async () => ({ data: [completedAssistant('Hello from session')] })),
|
|
34
|
-
deleteSession = vi.fn(async () => ({ data: true })),
|
|
35
|
-
} = {}) => {
|
|
36
|
-
const client = {
|
|
37
|
-
session: {
|
|
38
|
-
create,
|
|
39
|
-
update,
|
|
40
|
-
promptAsync,
|
|
41
|
-
status,
|
|
42
|
-
messages,
|
|
43
|
-
delete: deleteSession,
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
createOpencodeClient.mockReturnValue(client);
|
|
47
|
-
return { client, create, update, promptAsync, status, messages, deleteSession };
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
describe('generateViaOpenCodeSession', () => {
|
|
51
|
-
beforeEach(() => {
|
|
52
|
-
createOpencodeClient.mockReset();
|
|
53
|
-
_test.resetTempDirectory();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
afterEach(async () => {
|
|
57
|
-
await stop();
|
|
58
|
-
_test.resetTempDirectory();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('creates a marked archived session, prompts, returns assistant text, and deletes', async () => {
|
|
62
|
-
const { create, update, promptAsync, deleteSession } = createMockClient();
|
|
63
|
-
|
|
64
|
-
const text = await generateViaOpenCodeSession({
|
|
65
|
-
buildOpenCodeUrl,
|
|
66
|
-
getOpenCodeAuthHeaders,
|
|
67
|
-
providerID: 'codebuddy',
|
|
68
|
-
modelID: 'codebuddy-flash',
|
|
69
|
-
prompt: 'Summarize this',
|
|
70
|
-
system: 'Be brief',
|
|
71
|
-
purpose: 'session-title',
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
expect(text).toBe('Hello from session');
|
|
75
|
-
expect(createOpencodeClient).toHaveBeenCalledWith(expect.objectContaining({
|
|
76
|
-
baseUrl: 'http://127.0.0.1:4096',
|
|
77
|
-
headers: { authorization: 'Bearer test' },
|
|
78
|
-
}));
|
|
79
|
-
|
|
80
|
-
const tempDir = create.mock.calls[0][0].directory;
|
|
81
|
-
expect(tempDir).toMatch(/openchamber-smallmodel-/);
|
|
82
|
-
expect(await fsPromises.readFile(
|
|
83
|
-
path.join(tempDir, '.opencode', 'agent', `${SMALL_MODEL_AGENT_NAME}.md`),
|
|
84
|
-
'utf8',
|
|
85
|
-
)).toContain('effect: deny');
|
|
86
|
-
|
|
87
|
-
expect(create).toHaveBeenCalledWith(expect.objectContaining({
|
|
88
|
-
directory: tempDir,
|
|
89
|
-
title: '[small-model] session-title',
|
|
90
|
-
agent: SMALL_MODEL_AGENT_NAME,
|
|
91
|
-
metadata: {
|
|
92
|
-
openchamber: {
|
|
93
|
-
smallModel: { purpose: 'session-title' },
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
}), expect.any(Object));
|
|
97
|
-
|
|
98
|
-
expect(update).toHaveBeenCalledWith(expect.objectContaining({
|
|
99
|
-
sessionID: 'ses_small_1',
|
|
100
|
-
directory: tempDir,
|
|
101
|
-
time: { archived: expect.any(Number) },
|
|
102
|
-
}));
|
|
103
|
-
|
|
104
|
-
expect(promptAsync).toHaveBeenCalledWith(expect.objectContaining({
|
|
105
|
-
sessionID: 'ses_small_1',
|
|
106
|
-
directory: tempDir,
|
|
107
|
-
agent: SMALL_MODEL_AGENT_NAME,
|
|
108
|
-
model: { providerID: 'codebuddy', modelID: 'codebuddy-flash' },
|
|
109
|
-
system: 'Be brief',
|
|
110
|
-
parts: [{ type: 'text', text: 'Summarize this', synthetic: false }],
|
|
111
|
-
}), expect.any(Object));
|
|
112
|
-
|
|
113
|
-
expect(deleteSession).toHaveBeenCalledWith({
|
|
114
|
-
sessionID: 'ses_small_1',
|
|
115
|
-
directory: tempDir,
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('throws on settle timeout and still best-effort deletes the session', async () => {
|
|
120
|
-
const { deleteSession } = createMockClient({
|
|
121
|
-
status: vi.fn(async () => ({ data: { ses_small_1: { type: 'busy' } } })),
|
|
122
|
-
messages: vi.fn(async () => ({ data: [] })),
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
await expect(generateViaOpenCodeSession({
|
|
126
|
-
buildOpenCodeUrl,
|
|
127
|
-
getOpenCodeAuthHeaders,
|
|
128
|
-
providerID: 'codebuddy',
|
|
129
|
-
modelID: 'codebuddy-flash',
|
|
130
|
-
prompt: 'hang',
|
|
131
|
-
purpose: 'commit',
|
|
132
|
-
settleTimeoutMs: 80,
|
|
133
|
-
})).rejects.toThrow(/timed out/);
|
|
134
|
-
expect(deleteSession).toHaveBeenCalled();
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('does not swallow a successful result when session.delete fails', async () => {
|
|
138
|
-
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
139
|
-
createMockClient({
|
|
140
|
-
deleteSession: vi.fn(async () => {
|
|
141
|
-
throw new Error('delete boom');
|
|
142
|
-
}),
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
const text = await generateViaOpenCodeSession({
|
|
146
|
-
buildOpenCodeUrl,
|
|
147
|
-
getOpenCodeAuthHeaders,
|
|
148
|
-
providerID: 'codebuddy',
|
|
149
|
-
modelID: 'codebuddy-flash',
|
|
150
|
-
prompt: 'ok',
|
|
151
|
-
purpose: 'commit',
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
expect(text).toBe('Hello from session');
|
|
155
|
-
expect(warn).toHaveBeenCalled();
|
|
156
|
-
warn.mockRestore();
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('throws when the assistant returns empty text', async () => {
|
|
160
|
-
createMockClient({
|
|
161
|
-
messages: vi.fn(async () => ({
|
|
162
|
-
data: [{
|
|
163
|
-
info: { role: 'assistant', time: { completed: Date.now() } },
|
|
164
|
-
parts: [{ type: 'text', text: ' ' }],
|
|
165
|
-
}],
|
|
166
|
-
})),
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
await expect(generateViaOpenCodeSession({
|
|
170
|
-
buildOpenCodeUrl,
|
|
171
|
-
getOpenCodeAuthHeaders,
|
|
172
|
-
providerID: 'codebuddy',
|
|
173
|
-
modelID: 'codebuddy-flash',
|
|
174
|
-
prompt: 'empty',
|
|
175
|
-
})).rejects.toThrow(/no assistant text/);
|
|
176
|
-
});
|
|
177
|
-
});
|