@openchambery/web 1.19.7-beta.24 → 1.19.7-beta.26

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.
Files changed (101) hide show
  1. package/dist/assets/{AgentAvatar-DI2zs2WH.js → AgentAvatar-CX0a1rKE.js} +1 -1
  2. package/dist/assets/AssistantView-BYHD7Fcy.js +2 -0
  3. package/dist/assets/{DiagramView-DZhC-gPw.js → DiagramView-BUucK4Mn.js} +1 -1
  4. package/dist/assets/{FadeInOnReveal-BWJcUp5P.js → FadeInOnReveal-CK4asqVR.js} +1 -1
  5. package/dist/assets/{Icon-4My8YZwt.js → Icon-BYM02QyU.js} +1 -1
  6. package/dist/assets/{MarkdownLoadingSkeleton-Vezjvk9B.js → MarkdownLoadingSkeleton-DWs4Jg7b.js} +1 -1
  7. package/dist/assets/{MarkdownRenderer-Dd7nPtW4.js → MarkdownRenderer-uiTtRexW.js} +2 -2
  8. package/dist/assets/{MarkdownRendererImpl-CuGusb9c.js → MarkdownRendererImpl-DszSA6px.js} +1 -1
  9. package/dist/assets/MarkstreamRendererImpl-CsNwy1T5.css +1 -0
  10. package/dist/assets/MarkstreamRendererImpl-DkjZ7QYA.js +1 -0
  11. package/dist/assets/{MobileDetailNavigation-DXLN8AfE.js → MobileDetailNavigation-BElZdvTL.js} +1 -1
  12. package/dist/assets/MobileShareBridge-DiXOck30.js +4 -0
  13. package/dist/assets/{MobileSurface-DZys0gQW.js → MobileSurface-BCIZyDOc.js} +1 -1
  14. package/dist/assets/{MultiRunWindow-DNSCvp1n.js → MultiRunWindow-XXWgGd6d.js} +1 -1
  15. package/dist/assets/{OnboardingScreen-BNEtPmvw.js → OnboardingScreen-C3-wzeSX.js} +1 -1
  16. package/dist/assets/{OverlayScrollbar-BZB21Yp_.js → OverlayScrollbar-KUpvYHdv.js} +1 -1
  17. package/dist/assets/{SettingsView-CW0sP1G5.js → SettingsView-CdYIJh0f.js} +5 -5
  18. package/dist/assets/{SettingsWindow-BbY8rAaP.js → SettingsWindow-CLr0dXVg.js} +1 -1
  19. package/dist/assets/{TerminalView-Blou_qZo.js → TerminalView-BdtasXsi.js} +1 -1
  20. package/dist/assets/{ToolOutputDialog-D69bhD7_.js → ToolOutputDialog-D22RYqMI.js} +1 -1
  21. package/dist/assets/{appThemeRegistry-DTf7Ymvj.js → appThemeRegistry-D1wTvHoc.js} +1 -1
  22. package/dist/assets/{button-Or0daT9o.js → button-C0cth9tl.js} +1 -1
  23. package/dist/assets/{clipboard-BXxLshVq.js → clipboard-DJ4nQEuY.js} +1 -1
  24. package/dist/assets/{collapsible-C-kzSGkq.js → collapsible-DFT9cE80.js} +1 -1
  25. package/dist/assets/{context-menu-Dpjla5p4.js → context-menu-CAp74NfV.js} +1 -1
  26. package/dist/assets/desktopHosts-CWxex1c3.js +1 -0
  27. package/dist/assets/{desktopRelayRestore-BaKjk1kQ.js → desktopRelayRestore-9EbBYQ9s.js} +1 -1
  28. package/dist/assets/{diagram-D0mT3mo1.js → diagram-BryzMuta.js} +1 -1
  29. package/dist/assets/{dialog-BkhHBTd4.js → dialog-CgbV5ljg.js} +1 -1
  30. package/dist/assets/{fileQueries-DFY6Kiy1.js → fileQueries-BY-9OWzp.js} +1 -1
  31. package/dist/assets/{fileReferenceActions-Di_DoDex.js → fileReferenceActions-BJJtX_S5.js} +1 -1
  32. package/dist/assets/{gitApi-s3lJ_NUC.js → gitApi-RhwRTt2X.js} +1 -1
  33. package/dist/assets/{input-BUsGnzwe.js → input-DFLpqjGR.js} +1 -1
  34. package/dist/assets/{insertionBoundaries-BXIh3qwN.js → insertionBoundaries-D-UUqego.js} +1 -1
  35. package/dist/assets/{main-CbWB2MxW.js → main-BRB8Kly8.js} +2 -2
  36. package/dist/assets/{main-6h4AIMd7.js → main-BaSeqhTm.js} +11 -11
  37. package/dist/assets/{markdownTheme-CVS01wHf.js → markdownTheme-CzZm3riB.js} +1 -1
  38. package/dist/assets/{miniChat-DuYRiHjj.js → miniChat-CDZ48aEf.js} +2 -2
  39. package/dist/assets/{mobile-DKja4fFV.js → mobile-B2Hpp_5U.js} +2 -2
  40. package/dist/assets/{multirun-CWbdKSsT.js → multirun-CfvHH_3s.js} +1 -1
  41. package/dist/assets/{outsideFileGrants-BB4GPvCq.js → outsideFileGrants-DnplRxr-.js} +1 -1
  42. package/dist/assets/persistence-DdUac14I.js +3 -0
  43. package/dist/assets/platform-B4KKLnZ5.js +2 -0
  44. package/dist/assets/{projectMeta-BjeUc8MG.js → projectMeta-vCCip4-G.js} +1 -1
  45. package/dist/assets/{renderElectronMiniChatApp-Cv1F39fu.js → renderElectronMiniChatApp-D9RarEOS.js} +2 -2
  46. package/dist/assets/{renderMobileApp-C4zDY0CW.js → renderMobileApp-DOiQLCcY.js} +7 -7
  47. package/dist/assets/{runtimeConfig-D0G_wzhg.js → runtimeConfig-CkWKMmAR.js} +1 -1
  48. package/dist/assets/{runtimeEndpointReset-Cx37ZLh4.js → runtimeEndpointReset-aW8qogl0.js} +1 -1
  49. package/dist/assets/{sessionChangeSummary-CX2MJIkc.js → sessionChangeSummary-DOq8EN_H.js} +1 -1
  50. package/dist/assets/{sessionLookup-B56D_zE1.js → sessionLookup-BNO4Ta46.js} +1 -1
  51. package/dist/assets/{sortable-tabs-strip-C5gGnikj.js → sortable-tabs-strip-C8_9kHqu.js} +1 -1
  52. package/dist/assets/src-DasvfkEg.css +2 -0
  53. package/dist/assets/{terminalApi-CIIs9vFx.js → terminalApi-947l7Ra3.js} +1 -1
  54. package/dist/assets/{textarea-CIO34TZz.js → textarea-Cgo_nWUU.js} +1 -1
  55. package/dist/assets/{tooltip-BSrJYYYc.js → tooltip-BifLJ8o0.js} +1 -1
  56. package/dist/assets/{url-CE_gAfNa.js → url-Pk6tQ1EZ.js} +1 -1
  57. package/dist/assets/{useAppFontEffects-i1QzgXKU.js → useAppFontEffects-BqBeuVr8.js} +6 -6
  58. package/dist/assets/{useAssistantUIStore-BHacrxe_.js → useAssistantUIStore-me6s63b2.js} +1 -1
  59. package/dist/assets/{useDesktopWindowControlsLayout-BqT0VDLV.js → useDesktopWindowControlsLayout-CnX7JJa1.js} +1 -1
  60. package/dist/assets/{useEffectiveDirectory-CUSBKiSi.js → useEffectiveDirectory-F2fNcQ22.js} +1 -1
  61. package/dist/assets/{useFontPreferences-BxOHKuVw.js → useFontPreferences-BCOBlaAd.js} +1 -1
  62. package/dist/assets/useMobileNavigationStore-CBfSvE2P.js +413 -0
  63. package/dist/assets/{useSessionAutoCleanup-mitMfzXN.js → useSessionAutoCleanup-BVJKWCtK.js} +1 -1
  64. package/dist/assets/useUIStore-CuaA8-Hp.js +1 -0
  65. package/dist/assets/{useWorkerHighlightedLines-BZHDVxzL.js → useWorkerHighlightedLines-WYqpkPyP.js} +1 -1
  66. package/dist/assets/{utils-B0mQXN9L.js → utils-BiK3tBGM.js} +1 -1
  67. package/dist/index.html +9 -9
  68. package/dist/mini-chat.html +9 -9
  69. package/dist/mobile.html +9 -9
  70. package/package.json +1 -1
  71. package/server/lib/assistants/contact-tools.test.js +6 -6
  72. package/server/lib/assistants/harness.test.js +3 -3
  73. package/server/lib/assistants/service.test.js +1 -1
  74. package/server/lib/event-stream/DOCUMENTATION.md +12 -1
  75. package/server/lib/event-stream/directory-ws-bridge.js +11 -2
  76. package/server/lib/event-stream/global-ws-bridge.js +19 -3
  77. package/server/lib/event-stream/protocol.js +11 -1
  78. package/server/lib/event-stream/reasoning-projection.js +425 -0
  79. package/server/lib/event-stream/reasoning-projection.test.js +300 -0
  80. package/server/lib/event-stream/runtime.js +10 -0
  81. package/server/lib/event-stream/runtime.test.js +53 -0
  82. package/server/lib/opencode/DOCUMENTATION.md +2 -1
  83. package/server/lib/opencode/proxy.js +103 -9
  84. package/server/lib/opencode/proxy.test.js +177 -1
  85. package/server/lib/relay/reasoning-projection.e2e.test.ts +529 -0
  86. package/server/lib/session-turn-pages/DOCUMENTATION.md +2 -1
  87. package/server/lib/session-turn-pages/routes.js +22 -3
  88. package/server/lib/session-turn-pages/routes.test.js +43 -0
  89. package/server/lib/transcript-cache/DOCUMENTATION.md +2 -2
  90. package/server/lib/transcript-cache/routes.js +9 -2
  91. package/server/lib/transcript-cache/routes.test.js +32 -0
  92. package/dist/assets/AssistantView-DDIVh1W4.js +0 -2
  93. package/dist/assets/MarkstreamRendererImpl-Ca7RATbs.css +0 -1
  94. package/dist/assets/MarkstreamRendererImpl-DANegq9r.js +0 -1
  95. package/dist/assets/MobileShareBridge-BVHXNDqj.js +0 -4
  96. package/dist/assets/desktopHosts-BzSE0sK7.js +0 -1
  97. package/dist/assets/persistence-CSZp1CNB.js +0 -3
  98. package/dist/assets/platform-CenlWqxu.js +0 -2
  99. package/dist/assets/src-Cs2WiOMc.css +0 -2
  100. package/dist/assets/useMobileNavigationStore-C-EBQ7Zt.js +0 -412
  101. package/dist/assets/useUIStore-CqqO11ZI.js +0 -1
@@ -1,12 +1,69 @@
1
- import { describe, expect, it } from 'vitest';
1
+ import express from 'express';
2
+ import request from 'supertest';
3
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
4
 
3
5
  import {
4
6
  createDirectoryQueryCanonicalizer,
5
7
  isInteractiveSessionRequest,
6
8
  normalizeForwardedDirectoryHeaders,
9
+ registerOpenCodeProxy,
7
10
  resolveSessionTurnAdmissionRequest,
8
11
  } from './proxy.js';
9
12
 
13
+ const originalFetch = globalThis.fetch;
14
+
15
+ afterEach(() => {
16
+ globalThis.fetch = originalFetch;
17
+ vi.restoreAllMocks();
18
+ });
19
+
20
+ const readyRuntime = () => ({
21
+ isOpenCodeReady: true,
22
+ openCodeNotReadySince: 0,
23
+ isRestartingOpenCode: false,
24
+ openCodePort: 4096,
25
+ openCodeBaseUrl: 'http://127.0.0.1:4096',
26
+ });
27
+
28
+ const mountProxy = () => {
29
+ const app = express();
30
+ // Fresh app each time — registerOpenCodeProxy guards on app setting.
31
+ registerOpenCodeProxy(app, {
32
+ fs: { promises: { realpath: async (v) => v } },
33
+ os: {},
34
+ path: {},
35
+ OPEN_CODE_READY_GRACE_MS: 1000,
36
+ LONG_REQUEST_TIMEOUT_MS: 60_000,
37
+ SSE_UPSTREAM_CONNECT_TIMEOUT_MS: 5_000,
38
+ SSE_UPSTREAM_STALL_TIMEOUT_MS: 5_000,
39
+ getRuntime: readyRuntime,
40
+ getOpenCodeAuthHeaders: () => ({}),
41
+ buildOpenCodeUrl: (path) => `http://127.0.0.1:4096${path}`,
42
+ ensureOpenCodeApiPrefix: () => {},
43
+ });
44
+ return app;
45
+ };
46
+
47
+ const sseBody = (blocks) => {
48
+ const encoder = new TextEncoder();
49
+ const text = blocks.join('');
50
+ let sent = false;
51
+ return {
52
+ getReader() {
53
+ return {
54
+ async read() {
55
+ if (sent) return { done: true, value: undefined };
56
+ sent = true;
57
+ return { done: false, value: encoder.encode(text) };
58
+ },
59
+ async cancel() {},
60
+ releaseLock() {},
61
+ };
62
+ },
63
+ async cancel() {},
64
+ };
65
+ };
66
+
10
67
  describe('createDirectoryQueryCanonicalizer', () => {
11
68
  it('canonicalizes directory query params and preserves other params', async () => {
12
69
  const canonicalize = createDirectoryQueryCanonicalizer({
@@ -124,3 +181,122 @@ describe('resolveSessionTurnAdmissionRequest', () => {
124
181
  expect(resolveSessionTurnAdmissionRequest({ method: 'POST', url: '/api/session/ses_1/message' })).toBeNull();
125
182
  });
126
183
  });
184
+
185
+ describe('registerOpenCodeProxy reasoning projection routes', () => {
186
+ it('strips includeReasoning from SSE upstream and drops reasoning events when false', async () => {
187
+ const upstreamUrls = [];
188
+ globalThis.fetch = vi.fn(async (url) => {
189
+ upstreamUrls.push(String(url));
190
+ return {
191
+ ok: true,
192
+ status: 200,
193
+ headers: new Headers({ 'content-type': 'text/event-stream' }),
194
+ body: sseBody([
195
+ 'id: 1\ndata: {"type":"message.part.updated","properties":{"part":{"id":"t","messageID":"m","type":"text","text":"hi"}}}\n\n',
196
+ 'id: 2\ndata: {"type":"session.next.reasoning.delta.1","properties":{"delta":"secret"}}\n\n',
197
+ 'id: 3\ndata: {"type":"message.part.delta","properties":{"messageID":"m","partID":"t","field":"text","delta":"!"}}\n\n',
198
+ ]),
199
+ };
200
+ });
201
+
202
+ const app = mountProxy();
203
+ const res = await request(app)
204
+ .get('/api/event?directory=%2Ftmp&includeReasoning=false')
205
+ .buffer(true)
206
+ .parse((response, callback) => {
207
+ const chunks = [];
208
+ response.on('data', (c) => chunks.push(Buffer.from(c)));
209
+ response.on('end', () => callback(null, Buffer.concat(chunks).toString('utf8')));
210
+ });
211
+
212
+ expect(res.status).toBe(200);
213
+ expect(upstreamUrls).toHaveLength(1);
214
+ expect(upstreamUrls[0]).not.toContain('includeReasoning');
215
+ expect(upstreamUrls[0]).toContain('directory=');
216
+ expect(res.body).toContain('"type":"message.part.updated"');
217
+ expect(res.body).toContain('"type":"message.part.delta"');
218
+ expect(res.body).not.toContain('reasoning');
219
+ expect(res.body).not.toContain('secret');
220
+ });
221
+
222
+ it('byte-passthrough SSE when includeReasoning is omitted', async () => {
223
+ const raw =
224
+ 'id: 1\ndata: {"type":"session.next.reasoning.delta","properties":{"delta":"keep"}}\n\n';
225
+ globalThis.fetch = vi.fn(async () => ({
226
+ ok: true,
227
+ status: 200,
228
+ headers: new Headers({ 'content-type': 'text/event-stream' }),
229
+ body: sseBody([raw]),
230
+ }));
231
+
232
+ const app = mountProxy();
233
+ const res = await request(app)
234
+ .get('/api/global/event')
235
+ .buffer(true)
236
+ .parse((response, callback) => {
237
+ const chunks = [];
238
+ response.on('data', (c) => chunks.push(Buffer.from(c)));
239
+ response.on('end', () => callback(null, Buffer.concat(chunks).toString('utf8')));
240
+ });
241
+
242
+ expect(res.status).toBe(200);
243
+ expect(res.body).toContain('session.next.reasoning.delta');
244
+ expect(res.body).toContain('keep');
245
+ });
246
+
247
+ it('filters session.messages list JSON and strips includeReasoning upstream', async () => {
248
+ const upstreamUrls = [];
249
+ globalThis.fetch = vi.fn(async (url) => {
250
+ upstreamUrls.push(String(url));
251
+ return {
252
+ ok: true,
253
+ status: 200,
254
+ headers: new Headers({ 'content-type': 'application/json' }),
255
+ async text() {
256
+ return JSON.stringify([
257
+ {
258
+ info: { id: 'msg_1', tokens: { reasoning: 12 } },
259
+ parts: [
260
+ { id: 'r', type: 'reasoning', text: 'hidden' },
261
+ { id: 't', type: 'text', text: 'visible' },
262
+ ],
263
+ },
264
+ ]);
265
+ },
266
+ };
267
+ });
268
+
269
+ const app = mountProxy();
270
+ const res = await request(app)
271
+ .get('/api/session/ses_1/message?limit=30&includeReasoning=false&directory=%2Frepo');
272
+
273
+ expect(res.status).toBe(200);
274
+ expect(upstreamUrls[0]).not.toContain('includeReasoning');
275
+ expect(upstreamUrls[0]).toContain('/session/ses_1/message');
276
+ expect(res.body[0].parts).toEqual([{ id: 't', type: 'text', text: 'visible' }]);
277
+ expect(res.body[0].info.tokens.reasoning).toBe(12);
278
+ expect(JSON.stringify(res.body)).not.toContain('hidden');
279
+ });
280
+
281
+ it('keeps reasoning parts on session.messages list when includeReasoning is omitted', async () => {
282
+ globalThis.fetch = vi.fn(async () => ({
283
+ ok: true,
284
+ status: 200,
285
+ headers: new Headers({ 'content-type': 'application/json' }),
286
+ async text() {
287
+ return JSON.stringify([
288
+ {
289
+ info: { id: 'msg_1' },
290
+ parts: [{ id: 'r', type: 'reasoning', text: 'keep-me' }],
291
+ },
292
+ ]);
293
+ },
294
+ }));
295
+
296
+ const app = mountProxy();
297
+ const res = await request(app).get('/api/session/ses_1/message');
298
+ expect(res.status).toBe(200);
299
+ expect(res.body[0].parts[0].type).toBe('reasoning');
300
+ expect(res.body[0].parts[0].text).toBe('keep-me');
301
+ });
302
+ });