@openchambery/web 1.19.13-beta.1 → 1.19.13-beta.2
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/assets/{AgentAvatar-CiQIIM0d.js → AgentAvatar-mbvX7YlW.js} +1 -1
- package/dist/assets/AssistantView-D5c557Oe.js +2 -0
- package/dist/assets/DiagramView-CjNUrHsU.js +1 -0
- package/dist/assets/FadeInOnReveal-moBbL8Ll.js +1 -0
- package/dist/assets/{Icon-CeKHYyKZ.js → Icon-CkzzhaLr.js} +1 -1
- package/dist/assets/MarkdownRenderer-BHfbAwVO.js +2 -0
- package/dist/assets/MarkdownRendererImpl-CkBoUibc.js +7 -0
- package/dist/assets/{MarkstreamRendererImpl-B-odd2Gz.js → MarkstreamRendererImpl-BrXUOI9g.js} +1 -1
- package/dist/assets/MobileDetailNavigation-aY9-HwBN.js +1 -0
- package/dist/assets/MobileShareBridge-CRt_8DmM.js +4 -0
- package/dist/assets/MobileSurface-CIhtF-CU.js +2 -0
- package/dist/assets/{MultiRunWindow-BT5Dwgzu.js → MultiRunWindow-DDq6C8t7.js} +1 -1
- package/dist/assets/OnboardingScreen-j0iCyH7f.js +1 -0
- package/dist/assets/{OverlayScrollbar-DUghqFGg.js → OverlayScrollbar-CDC5B3RH.js} +1 -1
- package/dist/assets/SettingsView-DFWWMvAj.js +25 -0
- package/dist/assets/{SettingsWindow-DfEGfyr8.js → SettingsWindow-CnYfBplB.js} +1 -1
- package/dist/assets/TerminalView-D5CQFVVm.js +8 -0
- package/dist/assets/ToolOutputDialog-VMI7TQFT.js +10 -0
- package/dist/assets/{appThemeRegistry-CIZ-shMD.js → appThemeRegistry-UIrP0-5h.js} +1 -1
- package/dist/assets/assistant-attachment-cache-C0aRnFkj.js +1 -0
- package/dist/assets/{button-DFPOdZ0g.js → button-xx1UOBA5.js} +1 -1
- package/dist/assets/{clipboard-C05anBwU.js → clipboard-CUasgPiF.js} +1 -1
- package/dist/assets/{collapsible-oGbEvbe1.js → collapsible-CACHBRYZ.js} +1 -1
- package/dist/assets/{context-menu-DGz4_2hs.js → context-menu-CYbm4wBZ.js} +1 -1
- package/dist/assets/desktopHosts-DILvrAok.js +1 -0
- package/dist/assets/desktopRelayRestore-t8asCr3m.js +1 -0
- package/dist/assets/{diagram-Csk5GpDC.js → diagram-u0BC9uuY.js} +1 -1
- package/dist/assets/{dialog-rrqB-H6q.js → dialog-BwQ3rY_x.js} +1 -1
- package/dist/assets/dualLimitLru-D8Sphgua.js +1 -0
- package/dist/assets/{es-FE0sJ9EC.js → es-CRjOwvYM.js} +1 -1
- package/dist/assets/fileQueries-Bgly-E8f.js +1 -0
- package/dist/assets/{fr-DNDCSfGt.js → fr-D9taEN9L.js} +1 -1
- package/dist/assets/{gitApi-_P0FsoXe.js → gitApi-Bu4W3bgD.js} +1 -1
- package/dist/assets/imageSource-BlAJJUEI.js +1 -0
- package/dist/assets/{input-BO3r20op.js → input-CI730njs.js} +1 -1
- package/dist/assets/insertionBoundaries-B1AqxsBD.js +4 -0
- package/dist/assets/{ja-BDwrk0cM.js → ja-CYQ5aoWp.js} +1 -1
- package/dist/assets/{ko-BeeU2o4I.js → ko-BwASV0Q0.js} +1 -1
- package/dist/assets/main-CqcB6tKc.js +169 -0
- package/dist/assets/main-DG-k0j8A.js +2 -0
- package/dist/assets/markdown-worker-CptoICmq.js +2 -0
- package/dist/assets/markdownHeightCache-DEjGKLv8.js +3 -0
- package/dist/assets/markdownTheme-DOfGg-A7.js +1 -0
- package/dist/assets/miniChat-BQtYQrsh.js +2 -0
- package/dist/assets/mobile-8iyqtXkr.js +2 -0
- package/dist/assets/{multirun-CxhTsmRq.js → multirun-CG_FCb_Z.js} +1 -1
- package/dist/assets/persistence-YbQKzHUQ.js +3 -0
- package/dist/assets/{pl-BYuzpcI5.js → pl-DUI1vPil.js} +1 -1
- package/dist/assets/platform-DzsGqlGW.js +2 -0
- package/dist/assets/projectMeta-DMpMDWE1.js +3 -0
- package/dist/assets/{pt-BR-Bn7cwEzv.js → pt-BR-CZQFJllP.js} +1 -1
- package/dist/assets/relay-image-stream-DM7atqJs.js +2 -0
- package/dist/assets/renderElectronMiniChatApp-DBzRdJl8.js +2 -0
- package/dist/assets/renderMobileApp-CIseqCyn.js +28 -0
- package/dist/assets/runtime-auth-D66yq6ie.js +1 -0
- package/dist/assets/runtime-fetch-zIalUnbb.js +1 -0
- package/dist/assets/runtime-switch-LvWDU-SL.js +1 -0
- package/dist/assets/runtimeConfig-D8nJYB-e.js +2 -0
- package/dist/assets/{runtimeEndpointReset-BBLFgl85.js → runtimeEndpointReset-CSub_ecV.js} +6 -6
- package/dist/assets/{sessionChangeSummary-DDVT7O5J.js → sessionChangeSummary-DQDZ5HW-.js} +1 -1
- package/dist/assets/{sessionLookup-C8VZn0gJ.js → sessionLookup-BiBD-4wC.js} +1 -1
- package/dist/assets/sortable-tabs-strip-Dom6Sthu.js +1 -0
- package/dist/assets/src-AA-5nXsF.css +2 -0
- package/dist/assets/{store-n94dSb3M.js → store-CSnH_QXM.js} +2 -2
- package/dist/assets/terminalApi-noa4Cdbh.js +1 -0
- package/dist/assets/{textarea-BjX-KhMN.js → textarea-BfNtUdJE.js} +1 -1
- package/dist/assets/{tooltip-CQGqGAG_.js → tooltip-DPxumadF.js} +1 -1
- package/dist/assets/{uk-CwpbHEa3.js → uk-C1FYZlmA.js} +1 -1
- package/dist/assets/{url-BMjqccCo.js → url-CVhsI9kR.js} +1 -1
- package/dist/assets/{useAppFontEffects-BIFw36SA.js → useAppFontEffects-qHt5uaFN.js} +32 -32
- package/dist/assets/useAssistantUIStore-CLPCNoj_.js +1 -0
- package/dist/assets/useDesktopWindowControlsLayout-BipyIXiK.js +1 -0
- package/dist/assets/{useEffectiveDirectory-DJSYYkVp.js → useEffectiveDirectory-DSNCCbCt.js} +1 -1
- package/dist/assets/useFontPreferences-CB-cGo3I.js +1 -0
- package/dist/assets/useMobileNavigationStore-C1NJGAik.js +413 -0
- package/dist/assets/useSessionAutoCleanup-Dcn6Unvd.js +2 -0
- package/dist/assets/useUIStore-CxOoCv7B.js +1 -0
- package/dist/assets/useWorkerHighlightedLines-CzpT4M7V.js +7 -0
- package/dist/assets/{utils-81nUI_xp.js → utils-BHTVlVov.js} +1 -1
- package/dist/assets/{zh-CN-BpzFZ-LU.js → zh-CN-C96qP1ip.js} +1 -1
- package/dist/assets/{zh-TW-Bopgc5Eo.js → zh-TW-BsRk1Rbb.js} +1 -1
- package/dist/index.html +12 -9
- package/dist/mini-chat.html +12 -9
- package/dist/mobile.html +12 -9
- package/package.json +1 -1
- package/server/lib/assistant-delivery-parts.js +19 -1
- package/server/lib/assistants/DOCUMENTATION.md +39 -7
- package/server/lib/assistants/cards.js +16 -2
- package/server/lib/assistants/cards.test.js +16 -1
- package/server/lib/assistants/contact-attachments.http.test.js +436 -0
- package/server/lib/assistants/contact-attachments.js +814 -0
- package/server/lib/assistants/contact-attachments.p1.test.js +307 -0
- package/server/lib/assistants/contact-attachments.test.js +249 -0
- package/server/lib/assistants/contact-store.js +494 -25
- package/server/lib/assistants/contact-store.test.js +403 -1
- package/server/lib/assistants/contact-tools.js +6 -5
- package/server/lib/assistants/contact-tools.test.js +24 -6
- package/server/lib/assistants/contracts.js +41 -1
- package/server/lib/assistants/harness.test.js +124 -0
- package/server/lib/assistants/routes.js +46 -1
- package/server/lib/assistants/service.js +258 -66
- package/server/lib/assistants/service.test.js +400 -30
- package/server/lib/fs/prompt-attachment-store.js +663 -0
- package/server/lib/fs/prompt-attachment-store.test.js +263 -0
- package/server/lib/fs/routes.js +28 -72
- package/server/lib/fs/routes.test.js +15 -30
- package/server/lib/opencode/core-routes.js +2 -1
- package/dist/assets/AssistantView-YmeyxehG.js +0 -2
- package/dist/assets/DiagramView-BpZb-G9P.js +0 -1
- package/dist/assets/FadeInOnReveal-nf6-ZCrs.js +0 -1
- package/dist/assets/MarkdownRenderer-wpeGdciL.js +0 -2
- package/dist/assets/MarkdownRendererImpl-Peu0GVSQ.js +0 -7
- package/dist/assets/MobileDetailNavigation-CtYke_1C.js +0 -1
- package/dist/assets/MobileShareBridge-DIfOl8EZ.js +0 -4
- package/dist/assets/MobileSurface-_KoX75Ff.js +0 -2
- package/dist/assets/OnboardingScreen-BPusUgFG.js +0 -1
- package/dist/assets/SettingsView-BwQpbIZl.js +0 -25
- package/dist/assets/TerminalView-8402vpcO.js +0 -8
- package/dist/assets/ToolOutputDialog-B5RdkhsG.js +0 -10
- package/dist/assets/desktopHosts-BVJXQq1S.js +0 -1
- package/dist/assets/desktopRelayRestore-RDfuj1M7.js +0 -1
- package/dist/assets/fileQueries-BcdWOPlD.js +0 -1
- package/dist/assets/insertionBoundaries-CWoioTdE.js +0 -4
- package/dist/assets/main-CLj_WS1o.js +0 -2
- package/dist/assets/main-CnSZ89pD.js +0 -169
- package/dist/assets/markdown-worker-CZWE1F1M.js +0 -2
- package/dist/assets/markdownHeightCache-Cdd3hkMl.js +0 -3
- package/dist/assets/markdownTheme-DIB8WVmz.js +0 -2
- package/dist/assets/miniChat-B9c3y2pD.js +0 -2
- package/dist/assets/mobile-DvbXUfNS.js +0 -2
- package/dist/assets/persistence-CVTWFaqe.js +0 -3
- package/dist/assets/platform-BY_Gtsqr.js +0 -2
- package/dist/assets/projectMeta-Dl5iPCB6.js +0 -3
- package/dist/assets/renderElectronMiniChatApp-CkJ51qCh.js +0 -2
- package/dist/assets/renderMobileApp-DcjQPhWw.js +0 -28
- package/dist/assets/runtimeConfig-Bsk2kWsW.js +0 -2
- package/dist/assets/sortable-tabs-strip-s7UUxsa6.js +0 -1
- package/dist/assets/src-BpHDMgud.css +0 -2
- package/dist/assets/terminalApi-C54_rKEK.js +0 -1
- package/dist/assets/useAssistantUIStore-Cg9bsT4b.js +0 -1
- package/dist/assets/useDesktopWindowControlsLayout-DoygEcN4.js +0 -1
- package/dist/assets/useFontPreferences-B5_apbBC.js +0 -1
- package/dist/assets/useMobileNavigationStore-DuTu0Mzh.js +0 -413
- package/dist/assets/useSessionAutoCleanup-C-L9teva.js +0 -1
- package/dist/assets/useUIStore-DwpQTjLO.js +0 -1
- package/dist/assets/useWorkerHighlightedLines-DxTfgdEi.js +0 -7
package/dist/index.html
CHANGED
|
@@ -552,25 +552,28 @@
|
|
|
552
552
|
opacity: 0.72;
|
|
553
553
|
}
|
|
554
554
|
</style>
|
|
555
|
-
<script type="module" crossorigin src="/assets/main-
|
|
555
|
+
<script type="module" crossorigin src="/assets/main-DG-k0j8A.js"></script>
|
|
556
556
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
|
|
557
|
+
<link rel="modulepreload" crossorigin href="/assets/runtime-auth-D66yq6ie.js">
|
|
558
|
+
<link rel="modulepreload" crossorigin href="/assets/runtime-switch-LvWDU-SL.js">
|
|
559
|
+
<link rel="modulepreload" crossorigin href="/assets/runtime-fetch-zIalUnbb.js">
|
|
557
560
|
<link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
|
|
558
561
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
|
|
559
|
-
<link rel="modulepreload" crossorigin href="/assets/useUIStore-
|
|
562
|
+
<link rel="modulepreload" crossorigin href="/assets/useUIStore-CxOoCv7B.js">
|
|
560
563
|
<link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
|
|
561
564
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-DLPElpoQ.js">
|
|
562
565
|
<link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
|
|
563
|
-
<link rel="modulepreload" crossorigin href="/assets/persistence-
|
|
564
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-
|
|
565
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-
|
|
566
|
+
<link rel="modulepreload" crossorigin href="/assets/persistence-YbQKzHUQ.js">
|
|
567
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-DILvrAok.js">
|
|
568
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-t8asCr3m.js">
|
|
566
569
|
<link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-C07HQypa.js">
|
|
567
570
|
<link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
|
|
568
|
-
<link rel="modulepreload" crossorigin href="/assets/platform-
|
|
569
|
-
<link rel="modulepreload" crossorigin href="/assets/terminalApi-
|
|
571
|
+
<link rel="modulepreload" crossorigin href="/assets/platform-DzsGqlGW.js">
|
|
572
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-noa4Cdbh.js">
|
|
570
573
|
<link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
|
|
571
574
|
<link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
|
|
572
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
573
|
-
<link rel="stylesheet" crossorigin href="/assets/src-
|
|
575
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-D8nJYB-e.js">
|
|
576
|
+
<link rel="stylesheet" crossorigin href="/assets/src-AA-5nXsF.css">
|
|
574
577
|
</head>
|
|
575
578
|
<body class="h-full bg-background text-foreground">
|
|
576
579
|
<!-- Keep the startup layer outside #root. React replaces every child of
|
package/dist/mini-chat.html
CHANGED
|
@@ -74,25 +74,28 @@
|
|
|
74
74
|
}
|
|
75
75
|
</style>
|
|
76
76
|
|
|
77
|
-
<script type="module" crossorigin src="/assets/miniChat-
|
|
77
|
+
<script type="module" crossorigin src="/assets/miniChat-BQtYQrsh.js"></script>
|
|
78
78
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
|
|
79
|
+
<link rel="modulepreload" crossorigin href="/assets/runtime-auth-D66yq6ie.js">
|
|
80
|
+
<link rel="modulepreload" crossorigin href="/assets/runtime-switch-LvWDU-SL.js">
|
|
81
|
+
<link rel="modulepreload" crossorigin href="/assets/runtime-fetch-zIalUnbb.js">
|
|
79
82
|
<link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
|
|
80
83
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
|
|
81
|
-
<link rel="modulepreload" crossorigin href="/assets/useUIStore-
|
|
84
|
+
<link rel="modulepreload" crossorigin href="/assets/useUIStore-CxOoCv7B.js">
|
|
82
85
|
<link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
|
|
83
86
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-DLPElpoQ.js">
|
|
84
87
|
<link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
|
|
85
|
-
<link rel="modulepreload" crossorigin href="/assets/persistence-
|
|
86
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-
|
|
87
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-
|
|
88
|
+
<link rel="modulepreload" crossorigin href="/assets/persistence-YbQKzHUQ.js">
|
|
89
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-DILvrAok.js">
|
|
90
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-t8asCr3m.js">
|
|
88
91
|
<link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-C07HQypa.js">
|
|
89
92
|
<link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
|
|
90
|
-
<link rel="modulepreload" crossorigin href="/assets/platform-
|
|
91
|
-
<link rel="modulepreload" crossorigin href="/assets/terminalApi-
|
|
93
|
+
<link rel="modulepreload" crossorigin href="/assets/platform-DzsGqlGW.js">
|
|
94
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-noa4Cdbh.js">
|
|
92
95
|
<link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
|
|
93
96
|
<link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
|
|
94
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
95
|
-
<link rel="stylesheet" crossorigin href="/assets/src-
|
|
97
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-D8nJYB-e.js">
|
|
98
|
+
<link rel="stylesheet" crossorigin href="/assets/src-AA-5nXsF.css">
|
|
96
99
|
</head>
|
|
97
100
|
<body class="h-full bg-background text-foreground">
|
|
98
101
|
<div id="root" class="h-full">
|
package/dist/mobile.html
CHANGED
|
@@ -63,25 +63,28 @@
|
|
|
63
63
|
})();
|
|
64
64
|
</script>
|
|
65
65
|
|
|
66
|
-
<script type="module" crossorigin src="/assets/mobile-
|
|
66
|
+
<script type="module" crossorigin src="/assets/mobile-8iyqtXkr.js"></script>
|
|
67
67
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
|
|
68
|
+
<link rel="modulepreload" crossorigin href="/assets/runtime-auth-D66yq6ie.js">
|
|
69
|
+
<link rel="modulepreload" crossorigin href="/assets/runtime-switch-LvWDU-SL.js">
|
|
70
|
+
<link rel="modulepreload" crossorigin href="/assets/runtime-fetch-zIalUnbb.js">
|
|
68
71
|
<link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
|
|
69
72
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
|
|
70
|
-
<link rel="modulepreload" crossorigin href="/assets/useUIStore-
|
|
73
|
+
<link rel="modulepreload" crossorigin href="/assets/useUIStore-CxOoCv7B.js">
|
|
71
74
|
<link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
|
|
72
75
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-DLPElpoQ.js">
|
|
73
76
|
<link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
|
|
74
|
-
<link rel="modulepreload" crossorigin href="/assets/persistence-
|
|
75
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-
|
|
76
|
-
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-
|
|
77
|
+
<link rel="modulepreload" crossorigin href="/assets/persistence-YbQKzHUQ.js">
|
|
78
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopHosts-DILvrAok.js">
|
|
79
|
+
<link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-t8asCr3m.js">
|
|
77
80
|
<link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-C07HQypa.js">
|
|
78
81
|
<link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
|
|
79
|
-
<link rel="modulepreload" crossorigin href="/assets/platform-
|
|
80
|
-
<link rel="modulepreload" crossorigin href="/assets/terminalApi-
|
|
82
|
+
<link rel="modulepreload" crossorigin href="/assets/platform-DzsGqlGW.js">
|
|
83
|
+
<link rel="modulepreload" crossorigin href="/assets/terminalApi-noa4Cdbh.js">
|
|
81
84
|
<link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
|
|
82
85
|
<link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
|
|
83
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
84
|
-
<link rel="stylesheet" crossorigin href="/assets/src-
|
|
86
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-D8nJYB-e.js">
|
|
87
|
+
<link rel="stylesheet" crossorigin href="/assets/src-AA-5nXsF.css">
|
|
85
88
|
</head>
|
|
86
89
|
<body class="h-full bg-background text-foreground">
|
|
87
90
|
<div id="root" class="h-full"></div>
|
package/package.json
CHANGED
|
@@ -22,5 +22,23 @@ export const validAssistantDeliveryParts = (parts, { allowAttachmentRefs = false
|
|
|
22
22
|
}
|
|
23
23
|
const filenameOk = part.filename === undefined
|
|
24
24
|
|| (typeof part.filename === 'string' && part.filename.length > 0 && part.filename.length <= MAX_STRING_LENGTH);
|
|
25
|
-
|
|
25
|
+
const fileKeysOk = allowAttachmentRefs
|
|
26
|
+
? Object.keys(part).every((key) => (
|
|
27
|
+
key === 'type' || key === 'mime' || key === 'attachmentID' || key === 'filename'
|
|
28
|
+
|| key === 'sha256' || key === 'size' || key === 'url'
|
|
29
|
+
))
|
|
30
|
+
: Object.keys(part).every((key) => key === 'type' || key === 'mime' || key === 'url' || key === 'filename');
|
|
31
|
+
const refOk = allowAttachmentRefs
|
|
32
|
+
&& typeof part.attachmentID === 'string'
|
|
33
|
+
&& part.attachmentID.length > 0
|
|
34
|
+
&& part.attachmentID.length <= MAX_STRING_LENGTH
|
|
35
|
+
&& (part.url === undefined || (typeof part.url === 'string' && part.url.length > 0 && part.url.length <= MAX_FILE_URL_LENGTH));
|
|
36
|
+
const urlOk = typeof part.url === 'string' && part.url.length > 0 && part.url.length <= MAX_FILE_URL_LENGTH;
|
|
37
|
+
return part.type === 'file'
|
|
38
|
+
&& typeof part.mime === 'string'
|
|
39
|
+
&& part.mime.length > 0
|
|
40
|
+
&& part.mime.length <= MAX_STRING_LENGTH
|
|
41
|
+
&& filenameOk
|
|
42
|
+
&& fileKeysOk
|
|
43
|
+
&& (refOk || urlOk);
|
|
26
44
|
});
|
|
@@ -40,6 +40,7 @@ and keep their existing error result handling.
|
|
|
40
40
|
- Worker sessions stamp `metadata.openchamber.assigned` (`from: 'contact'`, `assistantID`, `name`). They must **not** use `openchamber.assistant.assistantID` — that marker hides archived Assistant bindings from Chat.
|
|
41
41
|
- `AssistantDTO.assignedSessionIDs` lists in-flight (`busy`/`question`) watches for assigned worker sessions. Session-card busy stays on the card; it does **not** drive the list green dot.
|
|
42
42
|
- **Contact active turn (server authoritative):** process-local metadata tracks admission → `queued` → `running` → settled (removed). `AssistantDTO.working` is true only while that assistant has an unsettled contact turn. `AssistantDTO.activeContactTurn` is `{ turnID, messageID, status: 'queued'|'running', admittedAt }` or `null` so APP restart / reconnect can rehydrate list green dots and the contact 3-dot row from the snapshot HTTP GET — local optimistic and SSE preview are temporary only. A server process restart clears in-memory activity (no permanent green; tools are not auto-rerun). Per-assistant lanes isolate turns across assistants/runtimes. Stale `contact-turn-end` for an older `turnID` must not clear a newer active turn.
|
|
43
|
+
- **List latest-message preview (server authoritative):** every `AssistantDTO` path (`snapshot` / `create` / `update` / other `output` rows) carries `latestMessagePreview: { messageID, ordinal, role: 'user'|'assistant', text, fallbackKind: 'image'|'file'|'session'|'assistant'|'schedule'|null } | null`. Source is the contact transcript only (not `defaultPrompt` / `updatedAt`). Order is the same keyset as contact pages: newest `(ordinal DESC, message_id DESC)`. Visible roles are `user`, `assistant`, and `peer` (peer maps to `role: 'user'` because inbound DMs are user-visible). Internal assigned-session settle markers (`oc.settle.*`) are excluded in the SQL candidate probe (and again in `buildContactMessagePreview`). Durable error bubbles keep their real body text. Plain text is sanitized and capped at `CONTACT_PREVIEW_MAX_CHARS` (500) with no data-URL/base64 bodies. File-only rows set `fallbackKind` `image`/`file`; pure cards set `session`/`assistant`/`schedule`. Empty transcript → `null`. **Snapshot cost:** one prepared statement reused per assistant (`assistant_id` + indexed `ORDER BY ordinal DESC, message_id DESC LIMIT candidateLimit`, catalog ≤100) collecting only those bounded candidates, then **one** parts `IN` query — not a window/`ROW_NUMBER` over full multi-assistant history and not HTTP N+1. SQL already drops pure settle tails so they cannot exhaust the LIMIT and hide an older real bubble; remaining non-preview empty rows may still consume a candidate slot within that same LIMIT. Admission, assistant completion, peer DM, card insert, wipe, and clear-memory already bump domain revision / `openchamber:assistants-changed`; clients re-GET snapshot for the new preview. Clear-memory keeps transcript rows so the preview still reflects the last bubble; clear-history / reset remove rows so the preview becomes the wipe confirm (or `null` after a full unbounded wipe with no remaining user).
|
|
43
44
|
- No registered project → clear `project_required` (ask the user to configure a project). Never fall back to managed assistant-workspaces.
|
|
44
45
|
- Assign must not go through the peer DM channel.
|
|
45
46
|
- `assignWork` (service) resolves the worker model via the connected catalog (`capabilities.input.image` preferred), forwards tool `variant` (cross-model drops contact variant), passes AbortSignal into create/prompt/delete/catalog, and supplies `lookupMessage` over real SDK exact lookup (`v2.session.message` → `session.message` → bounded `session.messages`). Ambiguous prompt admission returns `prompt_ambiguous` with `sessionID`/`messageID` and does **not** delete the worker; the contact-turn assign gate retains that identity so a same-args retry reuses the session and cannot blind-create another worker this turn.
|
|
@@ -63,12 +64,12 @@ and keep their existing error result handling.
|
|
|
63
64
|
**Clear memory vs clear chat history (this PR)**
|
|
64
65
|
|
|
65
66
|
- `new_conversation` clears **LLM memory only**. It advances the durable per-assistant context boundary in `assistant_contact_context_boundary` (`after_ordinal` watermark). `GET /:id/contact/messages` keeps the full transcript. Later `contactHistoryForLlm` returns only messages with `ordinal > after_ordinal`. Confirms with `NEW_CONVERSATION_CONFIRM_BUBBLE`. Natural language default (safe): 开新对话 / new conversation / 清除记忆 / clear memory / clear chat / start over.
|
|
66
|
-
- `clear_chat_history` **deletes** this assistant's contact transcript via `deleteContactMessages` (messages, parts, watches) and clears the boundary. Confirms with `CLEAR_CHAT_HISTORY_CONFIRM_BUBBLE`. Natural
|
|
67
|
-
-
|
|
67
|
+
- `clear_chat_history` **deletes** this assistant's contact transcript via `deleteContactMessages` (messages, parts, watches) and clears the boundary. Confirms with `CLEAR_CHAT_HISTORY_CONFIRM_BUBBLE`. Natural-language tool-selection hint (missed-fence retry): 清空/清除/删除聊天记录 / clear chat history / delete chat history. Negation (不要清除聊天记录) is not a wipe request hint. When the model calls the tool, the wipe **executes** — there is no separate user-text authorization gate and no silent/denied bubble protocol. Real storage failures still surface as tool errors.
|
|
68
|
+
- Tool wipe (`upToOrdinal` = current turn's user ordinal) **keeps only** `role=user` rows with `ordinal >= ceiling` (the wipe request itself + later-admitted queued users) and their parts/`messageID`s. It **deletes all other roles at any ordinal** (prior users, assistant/peer/error/cards) — including late writes from an earlier still-running lane whose ordinal landed after the wipe user — so leftover A replies/cards cannot pollute the transcript or later LLM history. Watches and the context boundary always clear. Keeping the wipe user avoids delete+re-admit reordering queued users before it. Direct `POST /api/openchamber/assistants/:id/contact/reset` → `resetContact` without a ceiling deletes **every** transcript row (existing contract; concurrent in-flight admissions are not preserved on that path).
|
|
68
69
|
- Service also exposes `clearContactMemory` for the watermark path (`new_conversation`). Neither path calls OpenCode `session/new` / `createNew`.
|
|
69
|
-
- Both tools terminate the contact turn. Persist only the matching confirm bubble. Discard leftover assistant text and cards from the same pre-reset generation.
|
|
70
|
+
- Both tools terminate the contact turn (`terminate: true`). Persist only the matching confirm bubble. Discard leftover assistant text and cards from the same pre-reset generation. Application tool result text is preferred for the visible confirm — never paint a denial body.
|
|
70
71
|
- Failed boundary/transcript writes roll back and keep the previous state.
|
|
71
|
-
- Contact send loads `contactHistoryForLlm` when the per-assistant turn lane starts (not at admit-time snapshot), so a prior clear-memory cannot leave a queued turn with stale history. The admitted user row is excluded from that window; `userText` / parts still go to the prompt. The current turn's user `ordinal` is the **upper bound for later-admitted user rows** (`beforeOrdinal`): queued user messages already in SQLite must not be injected into this turn's history. Assistant rows written by a prior completed lane turn after that ordinal still enter the window. Clear-memory watermark
|
|
72
|
+
- Contact send loads `contactHistoryForLlm` when the per-assistant turn lane starts (not at admit-time snapshot), so a prior clear-memory cannot leave a queued turn with stale history. The admitted user row is excluded from that window; `userText` / parts still go to the prompt. The current turn's user `ordinal` is the **upper bound for later-admitted user rows** (`beforeOrdinal`): queued user messages already in SQLite must not be injected into this turn's history. Assistant rows written by a prior completed lane turn after that ordinal still enter the window. Clear-memory watermark and tool wipe both use the **clearing turn's user ordinal** (`upToOrdinal`), not global MAX — otherwise later-admitted queued user rows would be permanently excluded (or deleted). Direct API `clearContactMemory` / `resetContact` without a turn ceiling still advance/delete through the current full set.
|
|
72
73
|
|
|
73
74
|
**Contact LLM window (this PR)**
|
|
74
75
|
|
|
@@ -76,9 +77,22 @@ and keep their existing error result handling.
|
|
|
76
77
|
|
|
77
78
|
**Contact attachments (this PR)**
|
|
78
79
|
|
|
79
|
-
- Attach is required on the contact composer: images and non-image files via picker, paste, and drag-drop.
|
|
80
|
-
-
|
|
81
|
-
-
|
|
80
|
+
- Attach is required on the contact composer: images and non-image files via picker, paste, and drag-drop.
|
|
81
|
+
- **Upload (frozen):** `PUT /api/openchamber/assistants/:id/contact/attachments/:uploadID` raw bytes with headers
|
|
82
|
+
`X-Content-SHA256`, `X-Content-Size`, `Content-Type`, optional `X-Attachment-Filename` (encodeURIComponent).
|
|
83
|
+
Returns `{ type:'file', attachmentID, sha256, size, mime, filename? }` — never a filesystem path.
|
|
84
|
+
Same uploadID + same content is idempotent; different content → `idempotency_conflict` (409).
|
|
85
|
+
- **Download (frozen):** `GET …/contact/attachments/:attachmentID` runtime-auth, opaque ID scoped to
|
|
86
|
+
assistant + live `generation`. Body is raw bytes with `Content-Type`, `Content-Length`, `ETag`,
|
|
87
|
+
`X-Content-Type-Options: nosniff`. Stale generation after clear-chat → 404.
|
|
88
|
+
- Bytes are content-addressed under `dataDir/prompt-attachments` (shared with Chat prompt uploads).
|
|
89
|
+
DB metadata stores only controlled `relative_path` + descriptor; client paths/urls are never authority.
|
|
90
|
+
- New uploads capped at **25 MiB**; image magic-byte checks for PNG/JPEG/GIF/WEBP/BMP.
|
|
91
|
+
- Admission accepts `attachmentID` refs (validated ownership) or legacy data URLs (landed to disk then stored as descriptors).
|
|
92
|
+
- Harness + assign materialize descriptors to data URLs **only at execution time**; DB/UI keep descriptors.
|
|
93
|
+
- Clear-memory keeps attachment rows; clear-chat bumps generation so external GETs fail while in-flight
|
|
94
|
+
materialize (owned read) may still complete for the running turn.
|
|
95
|
+
- Legacy data-URL migration: batch 20 / 50 MiB, write disk first, CAS-replace `part_json`; failure keeps old JSON.
|
|
82
96
|
|
|
83
97
|
**Inter-assistant DM (this PR, read-only)**
|
|
84
98
|
|
|
@@ -90,6 +104,24 @@ and keep their existing error result handling.
|
|
|
90
104
|
|
|
91
105
|
`GET /api/openchamber/assistants/capability` remains the navigation gate.
|
|
92
106
|
|
|
107
|
+
**Contact messages page (frozen UI contract)**
|
|
108
|
+
|
|
109
|
+
- `GET /api/openchamber/assistants/:id/contact/messages?limit=20[&before=opaque][&messageID=…]`
|
|
110
|
+
returns `{ messages, nextCursor, complete, generation, revision }`.
|
|
111
|
+
- Default `limit` is **20**, max **100**. The first page is the **newest**
|
|
112
|
+
window (chat tail); each page's `messages` array is ascending by
|
|
113
|
+
`(ordinal, messageID)`. Older pages use keyset `before` encoded as base64url
|
|
114
|
+
JSON `{ v:1, assistantID, generation, ordinal, messageID }`.
|
|
115
|
+
- `generation` starts at **0** and increments **only** on transcript wipe
|
|
116
|
+
(`clear_chat_history` / `POST …/contact/reset`). `new_conversation` /
|
|
117
|
+
clear-memory does **not** bump it. A cursor whose generation does not match
|
|
118
|
+
returns `contact_generation_conflict` (HTTP **409**); clients must refetch
|
|
119
|
+
from the start. Invalid cursor encoding is `validation_error` (400).
|
|
120
|
+
- `messageID` exact admission is mutually exclusive with `before`. Same page
|
|
121
|
+
envelope: at most one message for this assistant, `nextCursor: null`,
|
|
122
|
+
`complete: true`. Missing or other-assistant IDs yield `messages: []`.
|
|
123
|
+
- `revision` is the assistants domain tip (same counter as snapshot).
|
|
124
|
+
|
|
93
125
|
## History coverage
|
|
94
126
|
|
|
95
127
|
Snapshots expose the latest 50 `historySessionIDs` in chronological order and `historySessionCount` for the full count. The messages pagination endpoint owns complete history, including the current binding. A successful direct, shared, or queued OpenCode admission writes its user message and provisional parts to the Assistant SQLite mirror before the HTTP operation settles; this covered admission row survives binding replacement, restart, and an unavailable OpenCode history endpoint. Matching live parts replace provisional parts by message ID. Other event mirrors retain raw JSON as uncovered (`covered=0`) provisional fallback rows: they remain visible in archived history until an explicit shrink signal. Authoritative OpenCode backfill upserts covered rows and reconciles authoritative parts, rejects entries whose embedded session ID belongs to another session, and never deletes provisional mirrors merely because a successful page omitted them. Pagination `complete` only records that the OpenCode cursor was exhausted; it does not authorize deleting uncovered event mirrors. The only shrink whitelist is explicit `message.removed`, an authoritative `session.messages` 404 (`session-missing`), or assistant deletion. Late archived `message.updated` / `message.part.updated` and session lifecycle events (`session.idle`, `session.error`, `session.status` busy/retry/idle) call `invalidateBackfill` to reopen that session's cursor/complete without clearing covered flags. `history-state.js` owns the pure backfill reducer (`invalidate` → preserve; `page` → complete iff next cursor empty, always preserve; `session-missing` → discard provisional). Backfill persists the OpenCode `x-next-cursor` header verbatim and derives completion from its presence. A demand request commits up to three upstream pages and returns committed archived mirror rows (covered and provisional) with a stable scan-boundary cursor when more work remains. Startup begins one non-blocking current-binding backfill page. Archived rows preserve their stored directory; a legacy null directory triggers an authoritative session lookup of `data.directory` and `data.project.worktree`, with containment validation before persistence. Unresolved legacy directories remain `null` in persisted and historical response data. Ordinary mirror upserts preserve covered rows and never blanket-invalidate a session; explicit authoritative upserts elevate coverage; session-wide `invalidateCoverage` preserves every already-covered user row, including admitted rows whose local marker was replaced by live OpenCode info, while resetting other coverage on archive/re-archive; message-scoped coverage invalidation runs only after structural part deletes that require re-backfill. Removing an assistant tombstones the row and deletes its session history, message/part mirrors, and backfill state in one transaction. Schema v11 adds the mirror coverage marker.
|
|
@@ -74,9 +74,23 @@ export function parseContactCard(value) {
|
|
|
74
74
|
function parseContactFilePart(value) {
|
|
75
75
|
if (!isRecord(value) || value.type !== 'file') return null;
|
|
76
76
|
const mime = string(value.mime);
|
|
77
|
-
|
|
78
|
-
if (!mime || !url) return null;
|
|
77
|
+
if (!mime) return null;
|
|
79
78
|
const filename = string(value.filename);
|
|
79
|
+
const attachmentID = string(value.attachmentID);
|
|
80
|
+
const sha256 = string(value.sha256);
|
|
81
|
+
const size = typeof value.size === 'number' && Number.isSafeInteger(value.size) && value.size >= 0
|
|
82
|
+
? value.size
|
|
83
|
+
: null;
|
|
84
|
+
// Preferred durable form: opaque attachmentID (no client path/url authority).
|
|
85
|
+
if (attachmentID) {
|
|
86
|
+
const next = { type: 'file', mime, attachmentID };
|
|
87
|
+
if (filename) next.filename = filename;
|
|
88
|
+
if (sha256) next.sha256 = sha256;
|
|
89
|
+
if (size != null) next.size = size;
|
|
90
|
+
return next;
|
|
91
|
+
}
|
|
92
|
+
const url = typeof value.url === 'string' && value.url.trim() ? value.url.trim() : '';
|
|
93
|
+
if (!url) return null;
|
|
80
94
|
return filename ? { type: 'file', mime, url, filename } : { type: 'file', mime, url };
|
|
81
95
|
}
|
|
82
96
|
|
|
@@ -68,7 +68,7 @@ describe('contact cards', () => {
|
|
|
68
68
|
})).toBeNull()
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
-
it('parses contact file parts with optional filename', () => {
|
|
71
|
+
it('parses contact file parts with optional filename and attachmentID refs', () => {
|
|
72
72
|
expect(parseContactPart({
|
|
73
73
|
type: 'file',
|
|
74
74
|
mime: 'image/png',
|
|
@@ -89,6 +89,21 @@ describe('contact cards', () => {
|
|
|
89
89
|
mime: 'text/plain',
|
|
90
90
|
url: 'data:text/plain;base64,eA==',
|
|
91
91
|
})
|
|
92
|
+
expect(parseContactPart({
|
|
93
|
+
type: 'file',
|
|
94
|
+
mime: 'image/png',
|
|
95
|
+
attachmentID: 'att_abc',
|
|
96
|
+
sha256: 'a'.repeat(64),
|
|
97
|
+
size: 12,
|
|
98
|
+
filename: 'shot.png',
|
|
99
|
+
})).toEqual({
|
|
100
|
+
type: 'file',
|
|
101
|
+
mime: 'image/png',
|
|
102
|
+
attachmentID: 'att_abc',
|
|
103
|
+
sha256: 'a'.repeat(64),
|
|
104
|
+
size: 12,
|
|
105
|
+
filename: 'shot.png',
|
|
106
|
+
})
|
|
92
107
|
expect(parseContactPart({ type: 'file', mime: 'image/png' })).toBeNull()
|
|
93
108
|
})
|
|
94
109
|
|