@openchambery/web 1.19.7-beta.13 → 1.19.7-beta.15
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-Dp_hbVcD.js → AgentAvatar-BsU82CEP.js} +1 -1
- package/dist/assets/AssistantView-CxC9FX9C.js +2 -0
- package/dist/assets/{DiagramView-iX3nhWaN.js → DiagramView-yMUQZB0N.js} +1 -1
- package/dist/assets/{MarkdownRendererImpl-tDry9J76.js → MarkdownRendererImpl-DHLlx_NY.js} +1 -1
- package/dist/assets/{MarkstreamRendererImpl-BDVGi72n.js → MarkstreamRendererImpl-npYzOsgz.js} +1 -1
- package/dist/assets/MobileDetailNavigation-CQjttwAO.js +1 -0
- package/dist/assets/{MobileShareBridge-BQ79cuPX.js → MobileShareBridge-BVq0juvZ.js} +3 -3
- package/dist/assets/MobileSurface-CNvc2sAe.js +2 -0
- package/dist/assets/{MultiRunWindow-CzMbzYD3.js → MultiRunWindow-BaPCe5H6.js} +1 -1
- package/dist/assets/{OnboardingScreen-CuvjeXSo.js → OnboardingScreen-BNEtPmvw.js} +1 -1
- package/dist/assets/SettingsView-lvmcERgb.js +25 -0
- package/dist/assets/{SettingsWindow-DqwoBYvU.js → SettingsWindow-4M8nitNm.js} +1 -1
- package/dist/assets/{TerminalView-4pFqXfvj.js → TerminalView-B-grl1Sg.js} +1 -1
- package/dist/assets/{ToolOutputDialog-GmD4kIoH.js → ToolOutputDialog-DB7tlLR-.js} +1 -1
- package/dist/assets/{appThemeRegistry-BlEYFhXM.js → appThemeRegistry-aEqhY6Jd.js} +2 -2
- package/dist/assets/{clipboard-Bu0lpyX1.js → clipboard-BXxLshVq.js} +1 -1
- package/dist/assets/context-menu-Dpjla5p4.js +1 -0
- package/dist/assets/{dialog-D21YndEx.js → dialog-BkhHBTd4.js} +1 -1
- package/dist/assets/dropdown-menu.styles-Bzo6L3FH.js +1 -0
- package/dist/assets/{es-C8Sqjsia.js → es-BHqnSjoZ.js} +1 -1
- package/dist/assets/{fr-p-Zwm_j2.js → fr-BfrlJY9i.js} +1 -1
- package/dist/assets/{gitApi-CciB055B.js → gitApi-iKSVqWGT.js} +3 -3
- package/dist/assets/insertionBoundaries-XFIbRzxa.js +4 -0
- package/dist/assets/{ja-B6REu1qP.js → ja-DP-7qt-x.js} +1 -1
- package/dist/assets/{ko-CJBNH9IZ.js → ko-E2B5vGQP.js} +1 -1
- package/dist/assets/{main-DYFky6Uj.js → main-CAh-fkHv.js} +2 -2
- package/dist/assets/main-DiVOSucH.js +169 -0
- package/dist/assets/{markdownTheme-E_Ina01F.js → markdownTheme-CVS01wHf.js} +1 -1
- package/dist/assets/miniChat-D-KGjCnF.js +2 -0
- package/dist/assets/mobile-Cd1e4fBX.js +2 -0
- package/dist/assets/multirun-iFn8TY6T.js +4 -0
- package/dist/assets/{pl-B2cBI_7K.js → pl-r8X5gRM5.js} +1 -1
- package/dist/assets/projectMeta-DpHkpJw_.js +3 -0
- package/dist/assets/{pt-BR-CrCc9hmt.js → pt-BR-DcpdXCf5.js} +1 -1
- package/dist/assets/renderElectronMiniChatApp-VzrrMvJ1.js +2 -0
- package/dist/assets/renderMobileApp-Dko2HpCa.js +28 -0
- package/dist/assets/{runtimeConfig-DNsnUkyp.js → runtimeConfig-ni8yyqoa.js} +1 -1
- package/dist/assets/runtimeEndpointReset-aBxjZ2PR.js +147 -0
- package/dist/assets/sessionChangeSummary-CX2MJIkc.js +1 -0
- package/dist/assets/sessionLookup-z52pghDe.js +1 -0
- package/dist/assets/{sortable-tabs-strip-Biow4Fqu.js → sortable-tabs-strip-C5gGnikj.js} +1 -1
- package/dist/assets/src-BgLw5Nu2.css +2 -0
- package/dist/assets/{store-CL3WP48T.js → store-BDFdnk6l.js} +2 -2
- package/dist/assets/textarea-CIO34TZz.js +1 -0
- package/dist/assets/{uk-C8YKAz0x.js → uk-Di0vl9V-.js} +1 -1
- package/dist/assets/{ChatContainer-C04WuLo8.js → useAppFontEffects-DCVqvGQe.js} +46 -41
- package/dist/assets/useDesktopWindowControlsLayout-9IP1JKnB.js +1 -0
- package/dist/assets/useEffectiveDirectory-j1hFzIcz.js +1 -0
- package/dist/assets/useMobileNavigationStore-CL-8n4jx.js +412 -0
- package/dist/assets/useSessionAutoCleanup-Dfhza4uy.js +1 -0
- package/dist/assets/{useWorkerHighlightedLines-BaNK-wuY.js → useWorkerHighlightedLines-D49Ie_e4.js} +1 -1
- package/dist/assets/{zh-CN-CCYwUnmB.js → zh-CN-coFCfeQE.js} +1 -1
- package/dist/assets/{zh-TW-D8Y6py08.js → zh-TW-oDRZ1-yb.js} +1 -1
- package/dist/index.html +3 -3
- package/dist/mini-chat.html +3 -3
- package/dist/mobile.html +9 -9
- package/package.json +2 -1
- package/server/index.js +2 -0
- package/server/lib/assistant-delivery-parts.js +3 -1
- package/server/lib/assistant-delivery-parts.test.js +11 -0
- package/server/lib/assistants/DOCUMENTATION.md +76 -3
- package/server/lib/assistants/assign.js +225 -0
- package/server/lib/assistants/assign.test.js +118 -0
- package/server/lib/assistants/bubbles.js +45 -0
- package/server/lib/assistants/bubbles.test.js +36 -0
- package/server/lib/assistants/cards.js +148 -0
- package/server/lib/assistants/cards.test.js +116 -0
- package/server/lib/assistants/contact-store.js +284 -0
- package/server/lib/assistants/contact-store.test.js +131 -0
- package/server/lib/assistants/contact-tools.js +761 -0
- package/server/lib/assistants/contact-tools.test.js +328 -0
- package/server/lib/assistants/contracts.js +20 -1
- package/server/lib/assistants/harness.js +551 -0
- package/server/lib/assistants/harness.test.js +607 -0
- package/server/lib/assistants/routes.js +44 -4
- package/server/lib/assistants/service.js +930 -17
- package/server/lib/assistants/service.test.js +1163 -45
- package/server/lib/llm/DOCUMENTATION.md +84 -0
- package/server/lib/llm/catalog.js +100 -0
- package/server/lib/llm/catalog.test.js +78 -0
- package/server/lib/llm/completions.js +151 -0
- package/server/lib/llm/completions.test.js +127 -0
- package/server/lib/llm/generate.js +570 -0
- package/server/lib/llm/generate.test.js +459 -0
- package/server/lib/llm/routes.js +47 -0
- package/server/lib/llm/temp-directory.js +37 -0
- package/server/lib/notifications/runtime.js +52 -0
- package/server/lib/notifications/runtime.test.js +39 -0
- package/server/lib/opencode/feature-routes-runtime.js +30 -0
- package/server/lib/opencode/feature-routes-runtime.test.js +20 -0
- package/server/lib/opencode/settings-runtime.js +2 -2
- package/server/lib/session-goal/DOCUMENTATION.md +8 -1
- package/server/lib/session-goal/runtime.js +20 -0
- package/server/lib/session-index/DOCUMENTATION.md +3 -1
- package/server/lib/session-index/service.js +10 -4
- package/server/lib/session-index/service.test.js +37 -0
- package/server/lib/session-title/runtime.js +1 -0
- package/server/lib/session-title/runtime.test.js +11 -0
- package/dist/assets/AssistantView-CQHey6je.js +0 -1
- package/dist/assets/ContextPanel-BJEFzgz7.js +0 -285
- package/dist/assets/MobileDetailNavigation-Dcl7Upvc.js +0 -1
- package/dist/assets/MobileSurface-CpAbBAQ5.js +0 -2
- package/dist/assets/SettingsView-DRiEDi23.js +0 -25
- package/dist/assets/insertionBoundaries-DcS10A9Q.js +0 -4
- package/dist/assets/main-Coj1Z4LN.js +0 -29
- package/dist/assets/miniChat-DK-d_3-7.js +0 -2
- package/dist/assets/mobile-8QzXy5wz.js +0 -2
- package/dist/assets/multirun-BFHWrDOR.js +0 -4
- package/dist/assets/projectMeta-CEGa4Czs.js +0 -3
- package/dist/assets/radio-Bw11T40N.js +0 -1
- package/dist/assets/renderElectronMiniChatApp-_fchgm-8.js +0 -2
- package/dist/assets/renderMobileApp-B1j1BUXB.js +0 -28
- package/dist/assets/runtimeEndpointReset-C-Sm4wpj.js +0 -4
- package/dist/assets/shikiHighlight-GaNLBDUk.js +0 -1
- package/dist/assets/src-BGao3JmJ.css +0 -2
- package/dist/assets/useAppFontEffects-D0UWTJui.js +0 -7
- package/dist/assets/useDesktopWindowControlsLayout-_5M7NHJ8.js +0 -1
- package/dist/assets/useEffectiveDirectory-DqOLKISv.js +0 -1
- package/dist/assets/useMobileNavigationStore-DxH1DjU-.js +0 -412
- package/dist/assets/useSessionAutoCleanup-Dpp0-zw2.js +0 -1
|
@@ -15,6 +15,7 @@ import { registerScheduledTaskToolRoute } from '../scheduled-tasks/managed-tool-
|
|
|
15
15
|
import { registerConversationRoutes } from '../conversations/routes.js';
|
|
16
16
|
import { registerSessionTurnPageRoutes } from '../session-turn-pages/routes.js';
|
|
17
17
|
import { registerAssistantRoutes } from '../assistants/routes.js';
|
|
18
|
+
import { registerLlmRoutes } from '../llm/routes.js';
|
|
18
19
|
import { registerMessageQueueRoutes } from '../message-queue/routes.js';
|
|
19
20
|
import { registerSkillRoutes } from './skill-routes.js';
|
|
20
21
|
import { registerPluginRoutes } from './plugin-routes.js';
|
|
@@ -126,6 +127,8 @@ export const createFeatureRoutesRuntime = (dependencies) => {
|
|
|
126
127
|
broadcastGlobalUiEvent,
|
|
127
128
|
globalMessageStreamHub,
|
|
128
129
|
getServerId,
|
|
130
|
+
sessionIndexService,
|
|
131
|
+
notifyContactTurnComplete,
|
|
129
132
|
} = routeDependencies;
|
|
130
133
|
|
|
131
134
|
registerSettingsUtilityRoutes(app, {
|
|
@@ -215,6 +218,15 @@ export const createFeatureRoutesRuntime = (dependencies) => {
|
|
|
215
218
|
getOpenChamberEventClients,
|
|
216
219
|
writeSseEvent,
|
|
217
220
|
});
|
|
221
|
+
// Contact turn lifecycle / bubble deltas — same SSE bus, not revision watermark.
|
|
222
|
+
const broadcastContactTurnEvent = createOpenChamberEventBroadcaster({
|
|
223
|
+
getOpenChamberEventClients,
|
|
224
|
+
writeSseEvent,
|
|
225
|
+
});
|
|
226
|
+
registerLlmRoutes(app, {
|
|
227
|
+
buildOpenCodeUrl,
|
|
228
|
+
getOpenCodeAuthHeaders,
|
|
229
|
+
});
|
|
218
230
|
assistantRoutesRuntime = registerAssistantRoutes(app, {
|
|
219
231
|
openchamberDataDir,
|
|
220
232
|
dbPath: path.join(openchamberDataDir, 'assistants.sqlite'),
|
|
@@ -222,12 +234,30 @@ export const createFeatureRoutesRuntime = (dependencies) => {
|
|
|
222
234
|
getOpenCodeAuthHeaders,
|
|
223
235
|
getServerId,
|
|
224
236
|
getAllowedRoots: () => assistantAllowedRoots,
|
|
237
|
+
listProjects: async () => {
|
|
238
|
+
const settings = await readSettingsFromDiskMigrated();
|
|
239
|
+
return sanitizeProjects(settings?.projects ?? [])
|
|
240
|
+
.filter((project) => project && typeof project.id === 'string' && typeof project.path === 'string')
|
|
241
|
+
.map((project) => ({
|
|
242
|
+
id: project.id,
|
|
243
|
+
path: project.path,
|
|
244
|
+
...(typeof project.label === 'string' && project.label.trim()
|
|
245
|
+
? { label: project.label.trim() }
|
|
246
|
+
: {}),
|
|
247
|
+
}));
|
|
248
|
+
},
|
|
249
|
+
listScheduledTasks: (projectID) => projectConfigRuntime.listScheduledTasks(projectID),
|
|
250
|
+
sessionIndexService,
|
|
251
|
+
upsertScheduledTask: (projectID, task) => projectConfigRuntime.upsertScheduledTask(projectID, task),
|
|
252
|
+
syncScheduledTaskProject: (projectID) => scheduledTasksRuntime.syncProject(projectID),
|
|
225
253
|
refreshAllowedRoots: refreshAssistantAllowedRoots,
|
|
226
254
|
globalEventHub: globalMessageStreamHub,
|
|
227
255
|
onRevisionTip: (tip) => broadcastAssistantRevisionTip({
|
|
228
256
|
type: 'openchamber:assistants-changed',
|
|
229
257
|
properties: tip,
|
|
230
258
|
}),
|
|
259
|
+
onContactTurnEvent: (event) => broadcastContactTurnEvent(event),
|
|
260
|
+
onContactTurnComplete: (event) => notifyContactTurnComplete?.(event),
|
|
231
261
|
});
|
|
232
262
|
messageQueueRuntime?.setAssistantDeliveryService?.(assistantRoutesRuntime.service);
|
|
233
263
|
|
|
@@ -3,6 +3,26 @@ import { describe, expect, it, vi } from 'vitest';
|
|
|
3
3
|
import { createWorktreeTopologyBroadcaster } from './feature-routes-runtime.js';
|
|
4
4
|
|
|
5
5
|
describe('feature routes runtime composition', () => {
|
|
6
|
+
it('wires scheduled-task upsert into assistant contact tools', async () => {
|
|
7
|
+
const source = await fs.readFile(new URL('./feature-routes-runtime.js', import.meta.url), 'utf8');
|
|
8
|
+
expect(source).toMatch(/registerAssistantRoutes\(app, \{[\s\S]*upsertScheduledTask:[\s\S]*projectConfigRuntime\.upsertScheduledTask/);
|
|
9
|
+
expect(source).toMatch(/registerAssistantRoutes\(app, \{[\s\S]*syncScheduledTaskProject:[\s\S]*scheduledTasksRuntime\.syncProject/);
|
|
10
|
+
expect(source).toMatch(/registerAssistantRoutes\(app, \{[\s\S]*listProjects:/);
|
|
11
|
+
expect(source).toMatch(/registerAssistantRoutes\(app, \{[\s\S]*listScheduledTasks:[\s\S]*projectConfigRuntime\.listScheduledTasks/);
|
|
12
|
+
expect(source).toMatch(/registerAssistantRoutes\(app, \{[\s\S]*sessionIndexService/);
|
|
13
|
+
expect(source).toMatch(/label: project\.label\.trim\(\)/);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('fans contact turn events out on the OpenChamber SSE bus separately from revision tips', async () => {
|
|
17
|
+
const source = await fs.readFile(new URL('./feature-routes-runtime.js', import.meta.url), 'utf8');
|
|
18
|
+
expect(source).toMatch(/const broadcastContactTurnEvent = createOpenChamberEventBroadcaster\(/);
|
|
19
|
+
expect(source).toMatch(/onContactTurnEvent: \(event\) => broadcastContactTurnEvent\(event\)/);
|
|
20
|
+
expect(source).toMatch(/onContactTurnComplete: \(event\) => notifyContactTurnComplete\?\.\(event\)/);
|
|
21
|
+
expect(source).toMatch(/onRevisionTip: \(tip\) => broadcastAssistantRevisionTip\(\{\s*type: 'openchamber:assistants-changed'/);
|
|
22
|
+
// Contact turn envelopes stay off the assistants-changed revision watermark path.
|
|
23
|
+
expect(source).not.toMatch(/onRevisionTip:[\s\S]*contact-turn/);
|
|
24
|
+
});
|
|
25
|
+
|
|
6
26
|
it('registers the managed scheduled-task tool route with its required dependencies', async () => {
|
|
7
27
|
const source = await fs.readFile(new URL('./feature-routes-runtime.js', import.meta.url), 'utf8');
|
|
8
28
|
expect(source).toContain("import { registerScheduledTaskToolRoute } from '../scheduled-tasks/managed-tool-route.js';");
|
|
@@ -666,8 +666,8 @@ export const createSettingsRuntime = (deps) => {
|
|
|
666
666
|
return { settings, changed: false };
|
|
667
667
|
}
|
|
668
668
|
|
|
669
|
-
const defaultLight = '
|
|
670
|
-
const defaultDark = '
|
|
669
|
+
const defaultLight = 'carbonfox-light';
|
|
670
|
+
const defaultDark = 'vitesse-dark-dark';
|
|
671
671
|
|
|
672
672
|
let nextLightThemeId = hasLight ? settings.lightThemeId : undefined;
|
|
673
673
|
let nextDarkThemeId = hasDark ? settings.darkThemeId : undefined;
|
|
@@ -135,7 +135,10 @@ before touching the filesystem). Rationale: metadata rides every
|
|
|
135
135
|
continuation prompt using the last assistant message's
|
|
136
136
|
provider/model/agent — the goal spends the session's own subscription.
|
|
137
137
|
4. Settling (`complete`/`blocked`/`budgetLimited`) fires the injected
|
|
138
|
-
`emitGoalNotification` so the user hears about it even with the UI closed
|
|
138
|
+
`emitGoalNotification` so the user hears about it even with the UI closed.
|
|
139
|
+
The same settle also notifies a registered Assistant contact reporter
|
|
140
|
+
(`setAssignedSessionSettleHandler`) so an assigned/watched session updates
|
|
141
|
+
its contact card — read-only, no second scheduler:
|
|
139
142
|
desktop + UI broadcast + the standard push fanout (web-push with full
|
|
140
143
|
text; APNs with a generic per-type title and the session name as body).
|
|
141
144
|
It obeys the notify-on-completion setting. Conversely, while a goal is
|
|
@@ -180,6 +183,10 @@ The loop here picks it up from session events like any other goal.
|
|
|
180
183
|
|
|
181
184
|
## Limitations
|
|
182
185
|
|
|
186
|
+
- TODO(watch): Assistant contact assign skipped a watch tool this slice.
|
|
187
|
+
Goal settle already notifies. Do not invent a second scheduler. A later
|
|
188
|
+
thin contact tool can post a read-only session status card when
|
|
189
|
+
`metadata.openchamber.goal` settles.
|
|
183
190
|
- Web-server feature: VS Code (extension-only) renders goal state via
|
|
184
191
|
`session.updated` but does not run the loop.
|
|
185
192
|
- A goal on a session with no assistant reply yet starts after the first
|
|
@@ -286,6 +286,18 @@ export const accountGoalTokenSpend = ({ messages, goal }) => {
|
|
|
286
286
|
return { tokensUsed, lastAccountedMessageID };
|
|
287
287
|
};
|
|
288
288
|
|
|
289
|
+
let assignedSessionSettle = null;
|
|
290
|
+
|
|
291
|
+
export const setAssignedSessionSettleHandler = (handler) => {
|
|
292
|
+
assignedSessionSettle = typeof handler === 'function' ? handler : null;
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const contactStatusFromGoal = (status) => {
|
|
296
|
+
if (status === 'complete' || status === 'budgetLimited') return 'complete';
|
|
297
|
+
if (status === 'blocked') return 'error';
|
|
298
|
+
return null;
|
|
299
|
+
};
|
|
300
|
+
|
|
289
301
|
export const createSessionGoalRuntime = ({
|
|
290
302
|
buildOpenCodeUrl,
|
|
291
303
|
getOpenCodeAuthHeaders,
|
|
@@ -401,6 +413,14 @@ export const createSessionGoalRuntime = ({
|
|
|
401
413
|
console.warn('[session-goal] notification failed:', error?.message || error);
|
|
402
414
|
}
|
|
403
415
|
}
|
|
416
|
+
const contactStatus = contactStatusFromGoal(status);
|
|
417
|
+
if (contactStatus && typeof assignedSessionSettle === 'function') {
|
|
418
|
+
try {
|
|
419
|
+
assignedSessionSettle({ sessionId, directory, status: contactStatus });
|
|
420
|
+
} catch (error) {
|
|
421
|
+
console.warn('[session-goal] assigned session settle failed:', error?.message || error);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
404
424
|
};
|
|
405
425
|
|
|
406
426
|
const runAudit = async ({ goal, assistantText, directory, lastAssistantInfo }) => {
|
|
@@ -15,7 +15,9 @@ Sessions titled `smartfetch-secondary` are temporary SmartFetch model calls;
|
|
|
15
15
|
the index excludes them from every snapshot and clears prior summaries when a
|
|
16
16
|
matching session update arrives. System-owned sessions are excluded by
|
|
17
17
|
authoritative metadata only: a non-empty
|
|
18
|
-
`metadata.openchamber.assistant.assistantID
|
|
18
|
+
`metadata.openchamber.assistant.assistantID` (unless
|
|
19
|
+
`metadata.openchamber.assigned.from === 'contact'` — those are visible
|
|
20
|
+
coding workers the Assistant subscribed to),
|
|
19
21
|
`metadata.openchamber.scheduledTask.taskID`, or
|
|
20
22
|
`metadata.openchamber.smallModel.purpose`. Title prefixes are human labels and
|
|
21
23
|
never participate in this filter. Metadata is the ownership/isolation signal;
|
|
@@ -10,10 +10,14 @@ const HIDDEN_SESSION_TITLES = new Set(['smartfetch-secondary']);
|
|
|
10
10
|
const nonEmptySystemID = (value) => typeof value === 'string' && value.length > 0;
|
|
11
11
|
|
|
12
12
|
/** System sessions are isolated by authoritative metadata only — never by title prefix. */
|
|
13
|
+
const isContactAssignedSession = (openchamber) => openchamber?.assigned?.from === 'contact';
|
|
14
|
+
|
|
13
15
|
const isSystemSession = (session) => {
|
|
14
16
|
const openchamber = session?.metadata?.openchamber;
|
|
15
17
|
if (!openchamber || typeof openchamber !== 'object') return false;
|
|
16
|
-
|
|
18
|
+
// Contact-assigned workers stay visible in Chat. Only archived Assistant
|
|
19
|
+
// bindings use `openchamber.assistant` as a hide marker.
|
|
20
|
+
if (nonEmptySystemID(openchamber.assistant?.assistantID) && !isContactAssignedSession(openchamber)) return true;
|
|
17
21
|
if (nonEmptySystemID(openchamber.scheduledTask?.taskID)) return true;
|
|
18
22
|
if (nonEmptySystemID(openchamber.smallModel?.purpose)) return true;
|
|
19
23
|
return false;
|
|
@@ -52,7 +56,9 @@ const toSummary = (session, fallbackDirectory) => {
|
|
|
52
56
|
if (!session || !isVisibleSession(session) || typeof session.id !== 'string' || !session.id) return null;
|
|
53
57
|
const directory = normalizeDirectory(session.directory ?? session.project?.worktree ?? fallbackDirectory);
|
|
54
58
|
if (!directory) return null;
|
|
55
|
-
const
|
|
59
|
+
const openchamber = session.metadata?.openchamber;
|
|
60
|
+
const assistant = openchamber?.assistant;
|
|
61
|
+
const hideAssistantMarker = isContactAssignedSession(openchamber);
|
|
56
62
|
return {
|
|
57
63
|
id: session.id,
|
|
58
64
|
directory,
|
|
@@ -63,8 +69,8 @@ const toSummary = (session, fallbackDirectory) => {
|
|
|
63
69
|
archivedAt: toTimestamp(session.time?.archived),
|
|
64
70
|
parentID: typeof session.parentID === 'string' ? session.parentID : null,
|
|
65
71
|
hasChildren: typeof session.hasChildren === 'boolean' ? session.hasChildren : null,
|
|
66
|
-
assistantID: typeof assistant?.assistantID
|
|
67
|
-
assistantName: typeof assistant?.name
|
|
72
|
+
assistantID: hideAssistantMarker || typeof assistant?.assistantID !== 'string' ? null : assistant.assistantID,
|
|
73
|
+
assistantName: hideAssistantMarker || typeof assistant?.name !== 'string' ? null : assistant.name,
|
|
68
74
|
};
|
|
69
75
|
};
|
|
70
76
|
|
|
@@ -100,6 +100,43 @@ describe('Electron session index', () => {
|
|
|
100
100
|
service.close();
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
+
it('keeps contact-assigned worker sessions visible in ordinary sidebar summaries', () => {
|
|
104
|
+
const runtimeRef = { value: 'http://runtime-a.test' };
|
|
105
|
+
const service = createService(runtimeRef);
|
|
106
|
+
const worker = {
|
|
107
|
+
...session('ses_worker', 100),
|
|
108
|
+
metadata: {
|
|
109
|
+
openchamber: {
|
|
110
|
+
assigned: { from: 'contact', assistantID: 'assistant_1', name: 'A' },
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
const legacyWorker = {
|
|
115
|
+
...session('ses_legacy_worker', 99),
|
|
116
|
+
metadata: {
|
|
117
|
+
openchamber: {
|
|
118
|
+
assistant: { assistantID: 'assistant_1', name: 'A' },
|
|
119
|
+
assigned: { from: 'contact' },
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
const hiddenBinding = {
|
|
124
|
+
...session('ses_binding', 98),
|
|
125
|
+
metadata: { openchamber: { assistant: { assistantID: 'assistant_1', name: 'A' } } },
|
|
126
|
+
};
|
|
127
|
+
service.replaceDirectory({
|
|
128
|
+
directory: '/repo',
|
|
129
|
+
sessions: [worker, legacyWorker, hiddenBinding],
|
|
130
|
+
cursor: null,
|
|
131
|
+
hasMore: false,
|
|
132
|
+
});
|
|
133
|
+
expect(service.snapshot().directories[0].sessions.map((item) => item.id)).toEqual([
|
|
134
|
+
'ses_worker',
|
|
135
|
+
'ses_legacy_worker',
|
|
136
|
+
]);
|
|
137
|
+
service.close();
|
|
138
|
+
});
|
|
139
|
+
|
|
103
140
|
it('keeps runtime targets isolated in one Electron database', () => {
|
|
104
141
|
const runtimeRef = { value: 'http://runtime-a.test' };
|
|
105
142
|
const service = createService(runtimeRef);
|
|
@@ -163,6 +163,7 @@ const extractSessionStatus = (payload) => {
|
|
|
163
163
|
export const isSystemOwnedSession = (sessionOrInfo) => {
|
|
164
164
|
const openchamber = sessionOrInfo?.metadata?.openchamber;
|
|
165
165
|
if (!openchamber || typeof openchamber !== 'object') return false;
|
|
166
|
+
if (openchamber.assigned?.from === 'contact') return false;
|
|
166
167
|
if (typeof openchamber.assistant?.assistantID === 'string' && openchamber.assistant.assistantID) return true;
|
|
167
168
|
if (typeof openchamber.scheduledTask?.taskID === 'string' && openchamber.scheduledTask.taskID) return true;
|
|
168
169
|
if (typeof openchamber.smallModel?.purpose === 'string' && openchamber.smallModel.purpose) return true;
|
|
@@ -243,6 +243,17 @@ describe('session-title helpers', () => {
|
|
|
243
243
|
metadata: { openchamber: { smallModel: { purpose: '' } } },
|
|
244
244
|
})).toBe(false);
|
|
245
245
|
expect(isSystemOwnedSession({ title: 'Ordinary' })).toBe(false);
|
|
246
|
+
expect(isSystemOwnedSession({
|
|
247
|
+
metadata: { openchamber: { assigned: { from: 'contact', assistantID: 'assistant_1' } } },
|
|
248
|
+
})).toBe(false);
|
|
249
|
+
expect(isSystemOwnedSession({
|
|
250
|
+
metadata: {
|
|
251
|
+
openchamber: {
|
|
252
|
+
assistant: { assistantID: 'assistant_1' },
|
|
253
|
+
assigned: { from: 'contact' },
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
})).toBe(false);
|
|
246
257
|
});
|
|
247
258
|
|
|
248
259
|
it('skips title generation and patch for system-owned sessions', async () => {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e,r as t}from"./rolldown-runtime-C0FnF6B9.js";import{A as n,E as r,t as i,w as a}from"./useUIStore-CqqO11ZI.js";import{$t as o,Ot as s,et as c,rt as l,yt as u}from"./persistence-CSZp1CNB.js";import{nt as d,rt as f}from"./vendor-base-ui-CnHfUmDN.js";import{r as p}from"./platform-CenlWqxu.js";import{n as m}from"./vendor-react-DLPElpoQ.js";import{r as h}from"./vendor-sonner-DVzioF3d.js";import{n as g}from"./vendor-reactuses-core-DDoDDyM9.js";import{n as _}from"./clipboard-Bu0lpyX1.js";import{a as v,n as y,s as b}from"./MobileShareBridge-BQ79cuPX.js";import{Ga as x,Ha as S,Pi as C,Ur as ee,_n as w,aa as T,an as E,hi as D,ho as O,ko as k,mo as A,o as j,qr as M,un as N,vn as P,yn as F}from"./useMobileNavigationStore-DxH1DjU-.js";import{_ as I,a as L,c as R,d as z,f as B,g as te,l as ne,n as re,o as ie,p as ae,r as oe,t as V,v as H,x as U,y as se}from"./MobileDetailNavigation-Dcl7Upvc.js";import{i as ce,r as le}from"./useAssistantUIStore-BHacrxe_.js";import{a as ue,i as de,n as W,o as G,r as K,t as q}from"./dialog-D21YndEx.js";import{t as fe}from"./utils-B0mQXN9L.js";import{t as pe}from"./AgentAvatar-Dp_hbVcD.js";import{n as me}from"./Icon-4My8YZwt.js";import{t as he}from"./button-Or0daT9o.js";import{i as ge}from"./OverlayScrollbar-BZB21Yp_.js";import{B as _e,F as ve,I as J,Y as ye,t as be,z as xe}from"./ChatContainer-C04WuLo8.js";import{t as Se}from"./ContextPanel-BJEFzgz7.js";import{a as Ce,c as we,l as Te,o as Ee,s as De}from"./shikiHighlight-GaNLBDUk.js";var Y=e(f(),1),Oe=m(),X=e=>e.isVSCode||e.isPhoneShell||e.isMobile&&!e.isIPad?`session`:`context-panel`,Z=d(),ke=e=>{let t=(0,Oe.c)(56),{assistant:n,sessionID:r,warning:a,surface:s,onRevertMessage:c,onEditMessage:l,pendingUserMessages:u,onPendingUserMessagesMaterialized:d}=e,{t:f}=_(),{isMobile:m}=ge(),h=n.effectiveWorkspacePath,v;t[0]!==n.sessionGeneration||t[1]!==r?(v={sessionID:r,sessionGeneration:n.sessionGeneration},t[0]=n.sessionGeneration,t[1]=r,t[2]=v):v=t[2];let y=H(n.id,v,s.active);y.data?.pages;let b;t[3]===y.data?.pages?b=t[4]:(b=y.data?.pages??[],t[3]=y.data?.pages,t[4]=b);let x;t[5]===b?x=t[6]:(x=D(b),t[5]=b,t[6]=x);let S=x,C;if(t[7]!==S){C=new Map;for(let e of S){let t=C.get(e.sessionID);C.set(e.sessionID,t===void 0||t===e.directory?e.directory:null)}t[7]=S,t[8]=C}else C=t[8];let ee=C,w;t[9]===y?w=t[10]:(w=async()=>{(y.hasNextPage||y.isFetchNextPageError)&&await y.fetchNextPage()},t[9]=y,t[10]=w);let T=g(w),E=n.mode===`continuous`,O=ve(),k;t[11]===O?k=t[12]:(k=O&&!p(),t[11]=O,t[12]=k);let A=!!k,j;t[13]===A?j=t[14]:(j=(e,t)=>{F(e,t,{phoneShell:A,switchToChat:!0})},t[13]=A,t[14]=j);let M=g(j),N;t[15]!==h||t[16]!==ee||t[17]!==M||t[18]!==r?(N=(e,t)=>{let n=e===r?h:ee.get(e);if(!n||n!==t){P(e,`missing-directory`);return}M(e,t)},t[15]=h,t[16]=ee,t[17]=M,t[18]=r,t[19]=N):N=t[19];let I=g(N),L;t[20]!==m||t[21]!==A||t[22]!==M||t[23]!==f?(L=(e,t)=>{let n=e.trim(),r=t.trim();if(!n){P(e,`missing-session-id`);return}if(!r){P(n,`missing-directory`);return}if(X({isPhoneShell:A,isMobile:m,isIPad:p(),isVSCode:o()})===`session`){M(n,r);return}i.getState().openContextPanelTab(r,{mode:`chat`,dedupeKey:`session:${n}`,label:f(`contextPanel.mode.chat`),readOnly:!0})},t[20]=m,t[21]=A,t[22]=M,t[23]=f,t[24]=L):L=t[24];let R=g(L),z;t[25]===E?z=t[26]:(z={...J,forkSession:!1,mutateSession:E},t[25]=E,t[26]=z);let B;t[27]===l?B=t[28]:(B=l?{onEditMessage:l}:{},t[27]=l,t[28]=B);let te;t[29]!==h||t[30]!==R||t[31]!==c||t[32]!==I||t[33]!==r||t[34]!==s.active||t[35]!==s.surfaceID||t[36]!==B||t[37]!==z?(te={kind:`embedded`,surfaceId:s.surfaceID,sessionId:r,directory:h,active:s.active,capabilities:z,navigateSession:R,onRevertMessage:c,...B,openSourceSession:I},t[29]=h,t[30]=R,t[31]=c,t[32]=I,t[33]=r,t[34]=s.active,t[35]=s.surfaceID,t[36]=B,t[37]=z,t[38]=te):te=t[38];let ne=te,re=y.isError||y.isSuccess&&!y.hasNextPage,ie=y.isLoading||y.isFetchingNextPage,ae;t[39]!==T||t[40]!==re||t[41]!==S||t[42]!==ie?(ae={entries:S,complete:re,loading:ie,fetchPrevious:T},t[39]=T,t[40]=re,t[41]=S,t[42]=ie,t[43]=ae):ae=t[43];let oe;t[44]!==h||t[45]!==d||t[46]!==c||t[47]!==u||t[48]!==r||t[49]!==ne||t[50]!==s||t[51]!==ae||t[52]!==a?(oe={sessionId:r,directory:h,composerSurface:s,sessionSurface:ne,warning:a,pendingUserMessages:u,onPendingUserMessagesMaterialized:d,assistantHistory:ae,onRevertMessage:c},t[44]=h,t[45]=d,t[46]=c,t[47]=u,t[48]=r,t[49]=ne,t[50]=s,t[51]=ae,t[52]=a,t[53]=oe):oe=t[53];let V=oe,U;return t[54]===V?U=t[55]:(U=(0,Z.jsx)(be,{autoOpenDraft:!1,host:V}),t[54]=V,t[55]=U),U},Ae=class extends Error{constructor(){super(`assistant_selection_stale`)}},Q=(e,t)=>e.assistantID===t.assistantID&&e.transportIdentity===t.transportIdentity&&e.runtimeGeneration===t.runtimeGeneration,je=class{onBusyChange;onError;flight=null;authoritativeIdentity=null;constructor(e,t){this.onBusyChange=e,this.onError=t}activate(e){this.authoritativeIdentity&&!Q(this.authoritativeIdentity,e)&&this.flight&&this.retire(this.flight),this.authoritativeIdentity=e}enqueue(e,t,n){if(!this.isAuthoritative(e))return Promise.reject(new Ae);let r=this.flight;r||(r={identity:e,controller:new AbortController,running:!1,desired:null,waiters:[],activeWaiters:[],idleWaiters:[],retired:!1},this.flight=r),r.desired=t;let i=new Promise((e,t)=>{r.waiters.push({resolve:e,reject:t})});return r.running||(r.running=!0,this.onBusyChange(!0),this.run(r,n)),i}async flush(e){if(!this.isAuthoritative(e))throw new Ae;let t=this.flight;t?.running&&await new Promise((e,n)=>t.idleWaiters.push({resolve:e,reject:n}))}assertAuthoritative(e){if(!this.isAuthoritative(e))throw new Ae}dispose(){this.flight&&this.retire(this.flight),this.authoritativeIdentity=null}async run(e,t){for(;!e.retired&&e.desired;){let n=e.desired;e.desired=null;let r=e.waiters.splice(0);e.activeWaiters=r;try{if(await t({identity:e.identity,selection:n,signal:e.controller.signal}),!e.retired)for(let e of r)e.resolve()}catch(t){if(!e.retired){this.onError(t);for(let e of r)e.reject(t)}}e.activeWaiters=[]}e.running=!1;for(let t of e.idleWaiters.splice(0))t.resolve();this.flight===e&&this.onBusyChange(!1)}retire(e){e.retired=!0,e.controller.abort();let t=new Ae;for(let n of e.activeWaiters.splice(0))n.reject(t);for(let n of e.waiters.splice(0))n.reject(t);for(let n of e.idleWaiters.splice(0))n.reject(t);this.flight===e&&(this.flight=null,this.onBusyChange(!1))}isAuthoritative(e){return this.authoritativeIdentity!==null&&Q(this.authoritativeIdentity,e)}},Me=(e,t)=>{let n=t.providerID??e.providerID,r=t.modelID??e.modelID,i=n!==e.providerID||r!==e.modelID;return{enabled:e.enabled,name:e.name,defaultPrompt:e.defaultPrompt,workspacePath:e.workspacePath,providerID:n,modelID:r,agent:t.agent??null,variant:i?null:t.variant??null,mode:e.mode}},Ne=async(e,t,n)=>{n.assertAuthoritative();let r=n.readSnapshot()?.assistants.find(t=>t.id===e.assistantID);if(!r)throw Error(`assistant_unavailable`);try{n.assertAuthoritative(),await n.updateAssistant(r,Me(r,t)),n.assertAuthoritative()}catch(i){if(n.assertAuthoritative(),n.signal.aborted)throw new Ae;if(!(i instanceof U)||i.code!==`revision_conflict`)throw i;if(n.assertAuthoritative(),r=(await n.ensureSnapshot(n.signal)).assistants.find(t=>t.id===e.assistantID),n.assertAuthoritative(),!r)throw new U(`revision_conflict`,409);n.assertAuthoritative(),await n.updateAssistant(r,Me(r,t)),n.assertAuthoritative()}};async function Pe(e){await L(e);let t=ce.getState().defaultShareAssistant;if(t?.assistantID!==e.id)return;let n=await R();n.serverInstanceID&&t.serverInstanceID===n.serverInstanceID&&ce.getState().setDefaultShareAssistant(null)}function Fe({assistant:e,open:t,onOpenChange:n,onDeleted:r}){let{t:i}=_(),[a,o]=Y.useState(!1),s=e?v(e.name).displayName||e.name:``,c=g(e=>{a&&!e||n(e)}),l=g(()=>{a||n(!1)}),u=g(async()=>{if(!(!e||a)){o(!0);try{await Pe(e),r?.(e.id),n(!1),h.success(i(`assistants.settings.toast.deleted`))}catch{h.error(i(`assistants.settings.toast.deleteFailed`))}finally{o(!1)}}});return(0,Z.jsx)(q,{open:t&&e!==null,onOpenChange:c,children:(0,Z.jsxs)(W,{className:`max-w-md`,children:[(0,Z.jsxs)(ue,{children:[(0,Z.jsx)(G,{children:i(`assistants.settings.delete`)}),(0,Z.jsx)(K,{children:i(`assistants.settings.deleteConfirm`,{name:s})})]}),(0,Z.jsxs)(de,{children:[(0,Z.jsx)(he,{size:`sm`,variant:`ghost`,onClick:l,disabled:a,children:i(`settings.common.actions.cancel`)}),(0,Z.jsx)(he,{size:`sm`,variant:`destructive`,onClick:u,disabled:a,children:i(`settings.common.actions.delete`)})]})]})})}var Ie=[0,500,1500,4e3],Le=(e,t,n)=>{let r=!1,i=e.map(e=>e.info.id!==t||e.info.sessionID===n?e:(r=!0,{...e,info:{...e.info,sessionID:n}}));return r?i:e},Re=e=>{let t=e.refreshDelaysMs??Ie,n=e.sleep??(e=>new Promise(t=>setTimeout(t,e)));(async()=>{for(let r of t){if(r>0&&await n(r),!e.isCurrent())return;try{await e.refresh(e.binding);break}catch{}}})()},ze=e=>`${e.transport}\u0000${e.assistantID}`,Be=e=>({transport:e.transport,assistantID:e.assistantID}),Ve=(e,t)=>e.assistantID===t.assistantID&&e.sessionID===t.sessionID&&e.directory===t.directory&&e.sessionGeneration===t.sessionGeneration&&e.transport===t.transport&&e.runtimeGeneration===t.runtimeGeneration,He=(e,t)=>e.assistantID===t.assistantID&&e.sessionID===t.sessionID&&e.directory===t.directory&&e.sessionGeneration===t.sessionGeneration&&e.messageID===t.messageID&&e.transport===t.transport&&e.runtimeGeneration===t.runtimeGeneration,Ue=()=>{let e=new Map,t=new Map,n=1,r=e=>ze(e),i=async(e,n)=>{let i=r(e),a=t.get(i)??Promise.resolve(),o,s=new Promise(e=>{o=e}),c=a.catch(()=>void 0).then(()=>s);t.set(i,c),await a.catch(()=>void 0);try{return await n()}finally{o(),t.get(i)===c&&t.delete(i)}},a=(t,i)=>{let a=r(Be(t)),o=n++;return e.set(a,{identity:t,rollback:i,token:o}),o},o=t=>e.get(r(t))?.identity,s=t=>e.delete(r(t)),c=async e=>i(e,()=>s(e)),l=async t=>{let n=r(t),i=e.get(n);if(!i)return{kind:`none`};let a=i.token,o=i.identity,s;try{s=await i.rollback()}catch{return{kind:`blocked`,status:`failed`}}let c=e.get(n);return!c||c.token!==a||!He(c.identity,o)?{kind:`superseded`}:s.status===`rolled-back`||s.status===`conflict`?(e.delete(n),{kind:`cleared`,status:s.status}):{kind:`blocked`,status:s.status}},u=async(t,n)=>{let i=r(t),a=e.get(i);if(!a)return{kind:`none`};if(Ve(a.identity,n))return{kind:`match`};let o=a.token,s=a.identity,c=await a.rollback(),l=e.get(i);return!l||l.token!==o||!He(l.identity,s)?{kind:`superseded`}:c.status===`rolled-back`||c.status===`conflict`?(e.delete(i),{kind:`cleared`,status:c.status}):{kind:`rollback_failed`,retained:!0,status:c.status}};return{register:a,read:o,clear:s,clearExclusive:c,retireCurrent:l,rollbackAndClearIfBindingMismatch:async(e,t)=>i(e,()=>u(e,t)),rollbackAllBestEffort:async t=>{let n=[...e.entries()];await Promise.all(n.map(async([,n])=>{if(t?.excludeTransport!==void 0&&n.identity.transport===t.excludeTransport)return;let a=Be(n.identity);await i(a,async()=>{let t=r(a),i=e.get(t);if(!i||i.token!==n.token)return;let o=i.token,s=i.identity;try{let n=await i.rollback(),r=e.get(t);if(!r||r.token!==o||!He(r.identity,s))return;(n.status===`rolled-back`||n.status===`conflict`)&&e.delete(t)}catch{}})}))},stageExclusive:async(e,t)=>i(e,async()=>{let n=await l(e);if(n.kind===`blocked`)return{kind:`blocked`,status:n.status};let r=await t();if(!r)return{kind:`skipped`};let i=a(r.identity,r.rollback);return r.protectOnStale?{kind:`stale_protected`,token:i,identity:r.identity}:{kind:`registered`,token:i,identity:r.identity}})}},We=(e,t)=>!e?.attachments?.length||!t?[]:e.attachments.flatMap(e=>{let n=t[e.attachmentRefID];return n?[n]:[]}),Ge=(e,t)=>{let n=t??{};return e.map(e=>({partID:e.partID,text:e.text,...e.synthetic===!0?{synthetic:!0}:{},attachments:e.attachments.flatMap(e=>n[e.attachmentRefID]?[n[e.attachmentRefID]]:[])}))},Ke=(e,t)=>{if(t.length===0)return[...e];let n=new Map;for(let t of e)n.set(t.partID,t);for(let e of t)n.set(e.partID,e);let r=new Set,i=[];for(let t of e){let e=n.get(t.partID);e&&(i.push(e),r.add(t.partID))}for(let e of t)r.has(e.partID)||(i.push(e),r.add(e.partID));return i},qe=t({AssistantView:()=>et}),Je={},Ye=[],Xe=[],Ze=(e,t,n)=>[...e===void 0?[]:[{type:`text`,text:e}],...(t??[]).flatMap(e=>[{type:`text`,text:e.text,...e.synthetic===!0?{synthetic:!0}:{}},...(e.attachments??[]).map(e=>({type:`file`,mime:e.mimeType,url:e.dataUrl}))]),...(n??[]).map(e=>({type:`file`,mime:e.mimeType,url:e.dataUrl}))],Qe=e=>{let t=(0,Oe.c)(11),{assistant:n,onBack:r}=e,{t:i}=_(),a;t[0]===n?a=t[1]:(a=n?v(n.name):null,t[0]=n,t[1]=a);let o=a,s=n&&o?o.displayName||n.name:``,c;t[2]!==s||t[3]!==i?(c=s||i(`assistants.title`),t[2]=s,t[3]=i,t[4]=c):c=t[4];let l;t[5]===i?l=t[6]:(l=i(`assistants.actions.backToChat`),t[5]=i,t[6]=l);let u;return t[7]!==r||t[8]!==c||t[9]!==l?(u=(0,Z.jsx)(V,{title:c,backAriaLabel:l,onBack:r,overlay:!0}),t[7]=r,t[8]=c,t[9]=l,t[10]=u):u=t[10],u},$e=e=>{let t=(0,Oe.c)(45),{assistantID:n,displayName:r,avatarEmoji:i,modeLabel:a,selected:o,enabled:s,editLabel:c,deleteLabel:l,onSelect:u,onEdit:d,onDelete:f}=e,[p,m]=Y.useState(!1),h;t[0]===u?h=t[1]:(h=()=>u(),t[0]=u,t[1]=h);let _=g(h),v;t[2]===d?v=t[3]:(v=()=>{m(!1),d()},t[2]=d,t[3]=v);let y=g(v),b;t[4]===f?b=t[5]:(b=()=>{m(!1),f()},t[4]=f,t[5]=b);let x=g(b),S;t[6]===Symbol.for(`react.memo_cache_sentinel`)?(S=e=>{e.preventDefault(),m(!0)},t[6]=S):S=t[6];let C=o?`border-border/50 bg-[var(--surface-elevated)]`:`border-transparent hover:bg-interactive-hover`,ee=!s&&`opacity-65`,w;t[7]!==C||t[8]!==ee?(w=fe(`flex w-full min-h-11 items-center gap-3 rounded-xl border px-3 py-3 text-left outline-none transition-[background-color,border-color,opacity] duration-150 ease-out active:bg-interactive-active focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)] motion-reduce:transition-none`,C,ee),t[7]=C,t[8]=ee,t[9]=w):w=t[9];let T;t[10]!==_||t[11]!==o||t[12]!==w?(T=(0,Z.jsx)(`button`,{type:`button`,role:`option`,"aria-selected":o,onClick:_,onContextMenu:S,className:w}),t[10]=_,t[11]=o,t[12]=w,t[13]=T):T=t[13];let E;t[14]!==n||t[15]!==i||t[16]!==r?(E=(0,Z.jsx)(pe,{name:n,emoji:i,size:24,label:r}),t[14]=n,t[15]=i,t[16]=r,t[17]=E):E=t[17];let D;t[18]===r?D=t[19]:(D=(0,Z.jsx)(`span`,{className:`block truncate typography-ui-label font-medium`,children:r}),t[18]=r,t[19]=D);let O;t[20]===a?O=t[21]:(O=(0,Z.jsx)(`span`,{className:`mt-0.5 block truncate typography-micro text-muted-foreground`,children:a}),t[20]=a,t[21]=O);let k;t[22]!==D||t[23]!==O?(k=(0,Z.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[D,O]}),t[22]=D,t[23]=O,t[24]=k):k=t[24];let A;t[25]!==k||t[26]!==T||t[27]!==E?(A=(0,Z.jsxs)(Te,{render:T,children:[E,k]}),t[25]=k,t[26]=T,t[27]=E,t[28]=A):A=t[28];let j;t[29]===Symbol.for(`react.memo_cache_sentinel`)?(j=(0,Z.jsx)(me,{name:`edit`,className:`size-4`}),t[29]=j):j=t[29];let M;t[30]!==c||t[31]!==y?(M=(0,Z.jsxs)(De,{onClick:y,children:[j,c]}),t[30]=c,t[31]=y,t[32]=M):M=t[32];let N;t[33]===Symbol.for(`react.memo_cache_sentinel`)?(N=(0,Z.jsx)(we,{}),t[33]=N):N=t[33];let P;t[34]===Symbol.for(`react.memo_cache_sentinel`)?(P=(0,Z.jsx)(me,{name:`delete-bin`,className:`size-4`}),t[34]=P):P=t[34];let F;t[35]!==l||t[36]!==x?(F=(0,Z.jsxs)(De,{onClick:x,className:`text-[var(--status-error)] focus:text-[var(--status-error)] data-[highlighted]:text-[var(--status-error)] [&_svg]:text-[var(--status-error)]`,children:[P,l]}),t[35]=l,t[36]=x,t[37]=F):F=t[37];let I;t[38]!==M||t[39]!==F?(I=(0,Z.jsxs)(Ee,{className:`min-w-[10rem]`,children:[M,N,F]}),t[38]=M,t[39]=F,t[40]=I):I=t[40];let L;return t[41]!==p||t[42]!==A||t[43]!==I?(L=(0,Z.jsxs)(Ce,{open:p,onOpenChange:m,children:[A,I]}),t[41]=p,t[42]=A,t[43]=I,t[44]=L):L=t[44],L},et=({activeOverride:e,onMobileBack:t})=>{let{t:o}=_(),{isMobile:d}=ge(),f=ve(),p=Y.useSyncExternalStore(n,r,r),m=a(),D=i(e=>e.activeMainTab===`assistant`),P=e??D,F=i(e=>e.isMobile),L=d||F,R=I(),V=se(),H=V.data,U=ce(e=>e.assistantByTransport[p]??null),ue=ce(e=>e.selectAssistant),de=ce(e=>e.requestCreate),W=H?.assistants.find(e=>e.id===U)??null,G=W?.id??``,K=W?.sessionID??``,q=W?.effectiveWorkspacePath??``,J=Y.useMemo(()=>s({transportIdentity:p},`assistant:${G}`),[G,p]),be=u(J),Ce=k(e=>e.draftAttachmentViews[be]??Je),we=k(e=>e.drafts[be]),Te=Y.useMemo(()=>{let e=We(we,Ce);return e.length===0?Ye:e},[Ce,we]),Ee=we?.attachments,De=we?.syntheticParts,Oe=Y.useMemo(()=>!Ee||!De?``:`${Ee.map(e=>e.attachmentRefID).join(``)}\u0004${De.map(e=>`${e.partID}\u0002${e.attachments.map(e=>e.attachmentRefID).join(``)}`).join(``)}`,[Ee,De]);Y.useEffect(()=>{G&&k.getState().hydrateDraftAttachments(J)},[G,J,Oe]);let X=O(q||null,{enabled:!!q&&P}),Q=A(q||null,{enabled:!!q&&P}),Me=E(K,q||void 0),Pe=N(K,q||void 0),Ie=w(K),ze=ye(),[Ve,He]=Y.useState(()=>new Map),qe=Y.useRef(0),et=Y.useRef(Ue()),tt=Ve.get(G)??Xe,[,nt]=Y.useState(!1),rt=Y.useRef(()=>{});rt.current=()=>{h.error(o(`assistants.composer.selectionSaveFailed`))};let it=Y.useRef(null);it.current||=new je(nt,e=>rt.current(e));let at=Y.useMemo(()=>({assistantID:G,transportIdentity:p,runtimeGeneration:m}),[G,m,p]),$=it.current,ot=Y.useMemo(()=>({transport:p,assistantID:G}),[G,p]),st=g(async(e,t=p)=>{await et.current.clearExclusive({transport:t,assistantID:e})}),ct=g(e=>{et.current.rollbackAllBestEffort(e).catch(()=>void 0)});Y.useEffect(()=>{!U&&H?.assistants[0]&&ue(H.assistants[0].id)},[ue,U,H?.assistants]),Y.useEffect(()=>{V.isSuccess&&U&&!W&&ue(H?.assistants[0]?.id??null)},[W,ue,U,H?.assistants,V.isSuccess]),Y.useEffect(()=>{P&&G&&!K&&ie(G)},[P,G,K]),Y.useEffect(()=>{qe.current++,He(new Map),ct({excludeTransport:p})},[p,m,ct]),Y.useEffect(()=>()=>{qe.current++,ct()},[ct]),Y.useEffect(()=>{$.activate(at)},[$,at]),Y.useEffect(()=>()=>{$.dispose()},[$]),Y.useEffect(()=>{G&&et.current.rollbackAndClearIfBindingMismatch(ot,{assistantID:G,sessionID:K,directory:q,sessionGeneration:W?.sessionGeneration??-1,transport:p,runtimeGeneration:m}).catch(()=>void 0)},[W?.sessionGeneration,G,q,m,K,ot,p]);let lt=g(e=>at.assistantID?$.enqueue(at,e,async({identity:e,selection:t,signal:n})=>{await Ne(e,t,{readSnapshot:()=>B(void 0,e.transportIdentity),ensureSnapshot:e=>ne(e),updateAssistant:te,signal:n,assertAuthoritative:()=>{if($.assertAuthoritative(e),r()!==e.transportIdentity||a()!==e.runtimeGeneration)throw new Ae}})}):Promise.reject(Error(`assistant_unavailable`))),ut=Y.useMemo(()=>_e(Q.data),[Q.data]),dt=g(e=>{if(!W)return;let t=S(ut,W.agent??void 0,e);if(t){let e=x({providerID:W.providerID,modelID:W.modelID,agent:W.agent},t,ut,X.data??[]),n=e.providerID===W.providerID&&e.modelID===W.modelID;lt({...e,agent:e.agent??void 0,variant:n?W.variant??void 0:void 0})}}),ft=g(async(e,t)=>{e.sessionID&&await ze.ensureSessionRenderable(e.sessionID,{directory:e.directory,...t?.force?{force:!0}:{}})}),pt=W?.sessionGeneration;Y.useEffect(()=>{!P||!G||!K||!q||pt===void 0||ft({sessionID:K,directory:q,sessionGeneration:pt},{force:!0})},[P,G,q,ft,pt,K]);let mt=g((e,t)=>{if(t.length===0)return;let n=new Set(t);He(t=>{let r=t.get(e);if(!r?.some(e=>n.has(e.info.id)))return t;let i=new Map(t),a=r.filter(e=>!n.has(e.info.id));return a.length>0?i.set(e,a):i.delete(e),i})}),ht=g((e,t,n)=>{He(r=>{let i=r.get(e);if(!i)return r;let a=Le(i,t,n);if(a===i)return r;let o=new Map(r);return o.set(e,a),o})}),gt=g(e=>{mt(G,e)}),_t=g(async e=>{if(!K||!q)throw Error(`assistant_unavailable`);T(K,q).some(t=>t?.id===e)&&(await ee(K,e,{directory:q,draftKey:J,restorePrimaryInput:!1}),await st(G))}),vt=g(async(e,t)=>{if(!W||W.mode!==`continuous`)return;if(!K||!q)throw Error(`assistant_unavailable`);if(!T(K,q).some(t=>t?.id===e))return;if(t.info.id!==e||t.info.sessionID!==K||t.info.role!==`user`)throw Error(`The selected user message is unavailable`);let n={assistantID:W.id,sessionID:K,directory:q,sessionGeneration:W.sessionGeneration,messageID:e,transport:p,runtimeGeneration:m},i=Be(n),o=await et.current.stageExclusive(i,async()=>{let i=await M(K,e,t,{directory:q,draftKey:J}),o=r()===n.transport&&a()===n.runtimeGeneration,s=o?B(void 0,n.transport)?.assistants.find(e=>e.id===n.assistantID):void 0,c=!!(s&&s.mode===`continuous`&&s.sessionID===n.sessionID&&s.sessionGeneration===n.sessionGeneration&&(s.effectiveWorkspacePath??``)===n.directory);if(o&&c)return{identity:n,rollback:()=>i.rollback()};let l=await i.rollback();return l.status===`failed`||l.status===`skipped`?{identity:n,rollback:()=>i.rollback(),protectOnStale:!0}:null});if(o.kind===`blocked`)throw Error(`assistant_stage_message_edit_prior_blocked`);if(o.kind===`stale_protected`)throw Error(`assistant_stage_message_edit_rollback_failed`)}),yt=Y.useMemo(()=>{let e=C(J,()=>k.getState());return{busy:!1,attachments:Te,addAttachment:t=>e.addLocal(t),removeAttachment:t=>e.removeByAttachmentID(t),clearAttachments:()=>e.clearRootAttachments(),restoreAttachments:t=>e.restoreRootAttachments(t),pendingInput:null,consumePendingInput:()=>null,pendingPreset:null,consumePendingPreset:()=>null,consumeSyntheticParts:()=>{let e=k.getState(),t=e.draftAttachmentViews[u(J)]??Je,n=e.consumeDraftSyntheticParts(J,b);return n?Ge(n,t):null},restoreSyntheticParts:e=>{(async()=>{let t=k.getState(),n=e.map(e=>({partID:e.partID??c(),text:e.text,attachments:[],...e.synthetic===!0?{synthetic:!0}:{}})),r=Ke(t.getDraft(J)?.syntheticParts??[],n);t.setDraftSyntheticParts(J,r);for(let r=0;r<n.length;r++){let i=n[r].partID;for(let n of e[r]?.attachments??[])n.source===`server`&&n.dataUrl?t.addDraftDurableAttachment(J,{attachmentID:n.id,filename:n.filename,mimeType:n.mimeType,size:n.size,source:`server`,url:n.dataUrl,serverPath:n.serverPath,partID:i}):await t.addDraftLocalAttachment(J,n.file,{attachmentID:n.id,filename:n.filename,source:n.source===`vscode`?`vscode`:`local`,vscodePath:n.vscodePath,vscodeSource:n.vscodeSource===`selection`?`selection`:void 0,partID:i})}})()},inlineDrafts:[],removeInlineDraft:()=>{},restoreInlineDrafts:()=>{},history:Ie,captureRuntime:()=>k.getState().captureDraftRuntime(),getDraft:e=>k.getState().getDraft(e),abortPrompt:{sessionID:null,clear:()=>{}}}},[Te,J,Ie]),bt=Y.useMemo(()=>{let e=(X.data??[]).find(e=>e.id===W?.providerID)?.models?.find(e=>e.id===W?.modelID);return xe(e)},[W?.modelID,W?.providerID,X.data]),xt=Me.length>0,St=Y.useMemo(()=>{if(!W||!K||!q)return null;let e={sessionID:K,directory:q,sessionGeneration:W.sessionGeneration};return{kind:`secondary`,surfaceID:`assistant:${W.id}`,active:P,sessionID:K,directory:q,draftKey:J,transportIdentity:p,runtimeGeneration:m,deliveryTarget:{kind:`assistant`,assistantID:W.id},resources:yt,...W.mode===`stateless`?{queueSessionID:`assistant:${W.id}`}:{},selection:{value:{providerID:W.providerID,modelID:W.modelID,agent:W.agent??void 0,variant:W.variant??void 0},catalog:{providers:X.data??[],agents:ut,variants:bt,variantsReady:X.isSuccess,ready:X.isSuccess&&Q.isSuccess,loading:X.isPending||Q.isPending,error:X.isError||Q.isError},change:lt,flush:()=>$.flush(at)},activity:{phase:Pe?.type===`busy`?`busy`:Pe?.type===`retry`?`retry`:`idle`,canAbort:Pe?.type===`busy`||Pe?.type===`retry`},commands:{sessionID:K,hasMessages:xt,hasNewDraft:!1},commandPolicy:e=>e.name!==`fork`&&e.name!==`thread`,backend:{send:async t=>{let n;for(let t of T(e.sessionID,e.directory)){let e=typeof t?.id==`string`?t.id:``;/^msg_[0-9a-f]{12}[0-9A-Za-z]{14}$/.test(e)&&(!n||e>n)&&(n=e)}let r=l(`msg`,n);t.options?.commitStagedMessageEdit&&et.current.clear({transport:p,assistantID:W.id});let i=j({messageID:r,sessionID:e.sessionID,providerID:t.providerID??W.providerID,modelID:t.modelID??W.modelID,agent:t.agent??W.agent??void 0,text:t.text,attachments:t.attachments,additionalParts:t.parts});He(e=>{let t=new Map(e);return t.set(W.id,[...e.get(W.id)??[],i]),t});let a;try{a=await ae(W.id,e,r,Ze(t.text,t.parts,t.attachments))}catch(e){throw mt(W.id,[r]),e}if(R.data?.serverInstanceID){let e=v(W.name);y({serverInstanceID:R.data.serverInstanceID,assistantID:W.id,name:e.displayName||W.name,avatarSeed:W.id,...e.avatarEmoji?{avatarEmoji:e.avatarEmoji}:{}}).catch(()=>void 0)}a.binding.sessionID&&ht(W.id,r,a.binding.sessionID);let o=qe.current;Re({binding:a.binding,refresh:t=>ft(t,{force:t.sessionID!==e.sessionID||t.sessionGeneration!==e.sessionGeneration}),isCurrent:()=>qe.current===o})},sendQueued:async()=>{throw Error(`assistant-server-queue-required`)},create:async()=>{let e=await z(W.id);await st(W.id),await ft(e,{force:!0})},compact:async()=>{let t=await oe(W.id,e);await st(W.id),await ft(t.binding,{force:!0})},abort:async()=>{await re(W.id,e)}},shortcuts:{cycle:dt,new:async()=>{let e=await z(W.id);await st(W.id),await ft(e,{force:!0})},abort:async()=>{await re(W.id,e)},submit:()=>{}}}},[P,W,R.data?.serverInstanceID,lt,st,dt,q,J,xt,X.data,X.isError,X.isPending,X.isSuccess,Q.isError,Q.isPending,Q.isSuccess,ft,ht,mt,yt,m,$,at,K,Pe,p,bt,ut]),Ct=g(()=>{if(de(),f){f.openSettings();return}let e=i.getState();e.setSettingsPage(`assistants`),e.setSettingsDialogOpen(!0)}),wt=g(e=>{le(e,f?{openMobileSettings:f.openSettings}:void 0)}),[Tt,Et]=Y.useState(null),Dt=g(e=>{Et(e)}),Ot=g(e=>{e||Et(null)}),kt=g(()=>{i.getState().setActiveMainTab(`chat`)}),At=g(()=>{if(t){t();return}kt()}),jt=(e,t,n,r)=>(0,Z.jsxs)(`div`,{className:`relative flex h-full min-h-0 flex-col`,children:[L?(0,Z.jsx)(Qe,{assistant:W,onBack:At}):null,(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col items-center justify-center px-6 pt-[calc(max(0.25rem,var(--oc-safe-area-top,0px))+var(--oc-mobile-detail-navigation-height,3.5rem))] text-center`,children:[(0,Z.jsx)(me,{name:e,className:`size-6 text-muted-foreground`}),(0,Z.jsx)(`h1`,{className:`mt-4 typography-ui-header font-semibold`,children:t}),n?(0,Z.jsx)(`p`,{className:`mt-2 max-w-md typography-ui text-muted-foreground`,children:n}):null,r?(0,Z.jsx)(`div`,{className:`mt-5`,children:r}):null]})]});if(R.isPending||V.isPending)return jt(`ai-agent`,o(`assistants.state.unavailable`));if(R.isError||!R.data?.supported||!R.data.enabled||!H?.enabled)return jt(`cloud-off`,o(`assistants.state.unavailable`));if(!H.assistants.length)return jt(`ai-agent`,o(`assistants.onboarding.title`),o(`assistants.onboarding.description`),(0,Z.jsx)(he,{onClick:Ct,children:o(`assistants.onboarding.action`)}));if(!W)return jt(`ai-agent`,o(`assistants.state.unavailable`));if(!St)return(0,Z.jsxs)(`div`,{className:`relative flex h-full min-h-0 flex-col bg-background`,children:[L?(0,Z.jsx)(Qe,{assistant:W,onBack:At}):null,(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col items-center justify-center gap-3 px-6 pt-[calc(max(0.25rem,var(--oc-safe-area-top,0px))+var(--oc-mobile-detail-navigation-height,3.5rem))]`,"aria-busy":`true`,"aria-label":o(`assistants.state.unavailable`),children:[(0,Z.jsx)(`div`,{className:`size-10 animate-pulse rounded-xl bg-[var(--surface-muted)] motion-reduce:animate-none`}),(0,Z.jsx)(`div`,{className:`h-3.5 w-36 animate-pulse rounded-md bg-[var(--surface-muted)] motion-reduce:animate-none`})]})]});let Mt=v(W.name),Nt=W.enabled?V.isError?o(`assistants.state.staleSnapshot`):null:o(`assistants.state.assistantDisabled`);return(0,Z.jsxs)(`div`,{className:`relative flex h-full min-h-0 overflow-hidden bg-background`,"data-presentation":`workspace`,children:[L?null:(0,Z.jsxs)(`section`,{className:`flex h-full min-h-0 w-[clamp(16rem,22vw,20rem)] shrink-0 flex-col overflow-hidden`,children:[(0,Z.jsx)(`header`,{className:`shrink-0 px-4 pb-3 pt-4 sm:px-5`,children:(0,Z.jsx)(`h1`,{className:`truncate typography-ui-label font-semibold text-foreground`,children:o(`assistants.title`)})}),(0,Z.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-3 pb-4 sm:px-4`,role:`listbox`,"aria-label":o(`assistants.listAria`),children:(0,Z.jsx)(`div`,{className:`flex flex-col gap-1 border-t border-border/40 pt-3`,children:H.assistants.map(e=>{let t=e.id===U,n=v(e.name);return(0,Z.jsx)($e,{assistantID:e.id,displayName:n.displayName,avatarEmoji:n.avatarEmoji??void 0,modeLabel:e.mode===`stateless`?o(`assistants.mode.stateless`):o(`assistants.mode.continuous`),selected:t,enabled:e.enabled,editLabel:o(`assistants.menu.edit`),deleteLabel:o(`assistants.settings.delete`),onSelect:()=>ue(e.id),onEdit:()=>wt(e.id),onDelete:()=>Dt(e)},e.id)})})})]}),(0,Z.jsx)(Fe,{assistant:Tt,open:Tt!==null,onOpenChange:Ot}),(0,Z.jsxs)(`div`,{className:fe(`relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background`,!L&&`border-l border-border/60`),children:[L?(0,Z.jsx)(Qe,{assistant:W,onBack:At}):(0,Z.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-3 border-b border-border/40 px-4 sm:px-5`,children:[(0,Z.jsx)(pe,{name:W.id,emoji:Mt.avatarEmoji,size:24,label:Mt.displayName||W.name}),(0,Z.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Z.jsx)(`div`,{className:`truncate typography-ui-label font-medium`,children:Mt.displayName}),(0,Z.jsx)(`div`,{className:`mt-0.5 truncate typography-micro leading-none text-muted-foreground/70`,children:W.mode===`stateless`?o(`assistants.conversation.statelessHint`):o(`assistants.conversation.continuousHint`)})]})]}),(0,Z.jsx)(ke,{onRevertMessage:_t,onEditMessage:W.mode===`continuous`?vt:void 0,assistant:W,sessionID:K,warning:Nt,surface:St,pendingUserMessages:tt,onPendingUserMessagesMaterialized:gt})]}),L?null:(0,Z.jsx)(Se,{directory:q||null})]})};export{qe as n,Fe as r,et as t};
|