@openchambery/web 1.19.7-beta.20 → 1.19.7-beta.21
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/AssistantView-sV1PVQiM.js +2 -0
- package/dist/assets/{DiagramView-CSXRZQ5S.js → DiagramView-D2hqP5VV.js} +1 -1
- package/dist/assets/MarkdownLoadingSkeleton-Vezjvk9B.js +3 -0
- package/dist/assets/MarkdownRenderer-x091Z--3.js +2 -0
- package/dist/assets/MarkdownRendererImpl-DML8BSro.js +7 -0
- package/dist/assets/{MarkstreamRendererImpl-CowOCU5W.js → MarkstreamRendererImpl-BK-HM2k3.js} +1 -1
- package/dist/assets/{MobileDetailNavigation-ACMbLTqb.js → MobileDetailNavigation-DcxkWiks.js} +1 -1
- package/dist/assets/{MobileShareBridge-CXR-B1xW.js → MobileShareBridge-TAGcOiyb.js} +1 -1
- package/dist/assets/{MobileSurface-CKBSKqUH.js → MobileSurface-zqlZzEFQ.js} +1 -1
- package/dist/assets/{MultiRunWindow-el9_nl25.js → MultiRunWindow-iH1d9S14.js} +1 -1
- package/dist/assets/{SettingsView-CVSiIRia.js → SettingsView-CzW23DZA.js} +3 -3
- package/dist/assets/{SettingsWindow-BXYswtp5.js → SettingsWindow-DZXCWZid.js} +1 -1
- package/dist/assets/{TerminalView-Bh0IQwa5.js → TerminalView-pU0wpD8s.js} +1 -1
- package/dist/assets/{ToolOutputDialog-XeIJ2etT.js → ToolOutputDialog-Bt7JChFG.js} +2 -2
- package/dist/assets/appThemeRegistry-BI7WR2Wo.js +1 -0
- package/dist/assets/fileReferenceActions-Di_DoDex.js +1 -0
- package/dist/assets/{gitApi-Uvb9w70Y.js → gitApi-CeFszLvk.js} +1 -1
- package/dist/assets/{insertionBoundaries-Bgec5nsP.js → insertionBoundaries-DDJNusn2.js} +1 -1
- package/dist/assets/{main-COfQt8Sj.js → main-CjnOsKDL.js} +8 -8
- package/dist/assets/{main-PPlpRj1-.js → main-j-Ij13jc.js} +2 -2
- package/dist/assets/markdown-worker-BuveaH3O.js +1 -0
- package/dist/assets/markdownHeightCache-CvUyZT4q.js +1 -0
- package/dist/assets/{miniChat-EZGRqQZr.js → miniChat-DgxavREE.js} +2 -2
- package/dist/assets/{mobile-DQNqMo5J.js → mobile-C0rwPMPM.js} +2 -2
- package/dist/assets/{multirun-EViX73vm.js → multirun-ot7-bKg7.js} +1 -1
- package/dist/assets/{projectMeta-Bv1L_nEb.js → projectMeta-3yOEc0oI.js} +1 -1
- package/dist/assets/{renderElectronMiniChatApp-Nsq4Wc4s.js → renderElectronMiniChatApp-BPNvFA_N.js} +2 -2
- package/dist/assets/renderMobileApp-CNog29Xy.js +28 -0
- package/dist/assets/{runtimeConfig-DKUQS4iY.js → runtimeConfig-D28kNEYO.js} +1 -1
- package/dist/assets/{runtimeEndpointReset-BMeu9Hqj.js → runtimeEndpointReset-CorvFIRk.js} +1 -1
- package/dist/assets/{sessionLookup-Sb2HN3G2.js → sessionLookup-CbatbQf7.js} +1 -1
- package/dist/assets/{markdownHeightCache-Bj707yG-.js → toolHelpers-DEvVP9U0.js} +1 -1
- package/dist/assets/{useAppFontEffects-B_6vc0u3.js → useAppFontEffects-CDpeZWK4.js} +32 -32
- package/dist/assets/{useDesktopWindowControlsLayout-B2L5PWHW.js → useDesktopWindowControlsLayout-D-xPByG0.js} +1 -1
- package/dist/assets/{useEffectiveDirectory-CBd5vt8N.js → useEffectiveDirectory-Dp-tez_r.js} +1 -1
- package/dist/assets/{useMobileNavigationStore-CUGaydRW.js → useMobileNavigationStore-DE1Pe9A9.js} +2 -2
- package/dist/assets/{useSessionAutoCleanup-Clhzc1wn.js → useSessionAutoCleanup-jNJ_WC38.js} +1 -1
- package/dist/assets/useWorkerHighlightedLines-MDnGj3yv.js +7 -0
- package/dist/index.html +2 -2
- package/dist/mini-chat.html +2 -2
- package/dist/mobile.html +2 -2
- package/package.json +1 -1
- package/server/lib/notifications/APNS.md +19 -13
- package/server/lib/notifications/DOCUMENTATION.md +4 -3
- package/server/lib/notifications/runtime.js +101 -42
- package/server/lib/notifications/runtime.test.js +65 -4
- package/dist/assets/AssistantView-C0p-8f2B.js +0 -2
- package/dist/assets/MarkdownRendererImpl-C6rkoZYH.js +0 -7
- package/dist/assets/appThemeRegistry-rSdmh4sW.js +0 -2
- package/dist/assets/fileReferenceActions-3pPDAJSl.js +0 -1
- package/dist/assets/markdown-worker-wEFz5Hm_.js +0 -3
- package/dist/assets/renderMobileApp-5WJDYaMR.js +0 -28
- package/dist/assets/useWorkerHighlightedLines-C4iQlbPQ.js +0 -7
package/dist/mini-chat.html
CHANGED
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
}
|
|
75
75
|
</style>
|
|
76
76
|
|
|
77
|
-
<script type="module" crossorigin src="/assets/miniChat-
|
|
77
|
+
<script type="module" crossorigin src="/assets/miniChat-DgxavREE.js"></script>
|
|
78
78
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
|
|
79
79
|
<link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
|
|
80
80
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
<link rel="modulepreload" crossorigin href="/assets/terminalApi-CIIs9vFx.js">
|
|
92
92
|
<link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
|
|
93
93
|
<link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
|
|
94
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
94
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-D28kNEYO.js">
|
|
95
95
|
<link rel="stylesheet" crossorigin href="/assets/src-Af9cMFKF.css">
|
|
96
96
|
</head>
|
|
97
97
|
<body class="h-full bg-background text-foreground">
|
package/dist/mobile.html
CHANGED
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
})();
|
|
64
64
|
</script>
|
|
65
65
|
|
|
66
|
-
<script type="module" crossorigin src="/assets/mobile-
|
|
66
|
+
<script type="module" crossorigin src="/assets/mobile-C0rwPMPM.js"></script>
|
|
67
67
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
|
|
68
68
|
<link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
|
|
69
69
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
<link rel="modulepreload" crossorigin href="/assets/terminalApi-CIIs9vFx.js">
|
|
81
81
|
<link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
|
|
82
82
|
<link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
|
|
83
|
-
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-
|
|
83
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-D28kNEYO.js">
|
|
84
84
|
<link rel="stylesheet" crossorigin href="/assets/src-Af9cMFKF.css">
|
|
85
85
|
</head>
|
|
86
86
|
<body class="h-full bg-background text-foreground">
|
package/package.json
CHANGED
|
@@ -16,18 +16,22 @@ registered them — so a leaked device token alone can't be used to push.
|
|
|
16
16
|
3. On a trigger (ready/error/question/permission/goal_*), the server composes **generic,
|
|
17
17
|
content-free** text — a **locale-specific** scenario title (from `apns-titles.js`, keyed off
|
|
18
18
|
the locale stored with each device token at `POST /api/push/apns-token`) + the **session name**
|
|
19
|
-
as the body, no model/project/message content — plus a **`badge`** count (see below).
|
|
20
|
-
are
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
as the body, no model/project/message content — plus a **`badge`** count (see below).
|
|
20
|
+
**Contact turns are the exception:** APNs keeps the assistant nickname as the title and the
|
|
21
|
+
spoken message as the body (`preserveAlert`), and forwards `assistantID` so a tap opens that
|
|
22
|
+
conversation. Tokens are grouped by locale (relay signatures cover `title`, so mixed locales
|
|
23
|
+
cannot share one batch) and each group POSTs `{ tokens, title, body, badge, env,
|
|
24
|
+
data:{sessionId|assistantID}, publicKeyJwk, ts, sig }` to `POST /v1/push/send`
|
|
25
|
+
(`apns-runtime.js` → `sendViaRelay`). It does **not** gate on UI visibility (see below).
|
|
26
|
+
Legacy tokens without a locale fall back to English.
|
|
24
27
|
4. The **Push Relay** (`packages/relay-server/src/push/`, process `openchamber-push-relay`)
|
|
25
28
|
verifies the signature + `ts` freshness, derives `serverId`, and only delivers to tokens bound
|
|
26
29
|
to that server. It holds the project APNs `.p8` key, signs an ES256 JWT with Node crypto, and
|
|
27
30
|
sends each token to APNs over HTTP/2, returning per-token results; the server drops tokens
|
|
28
31
|
flagged `drop` (410 / BadDeviceToken). The Push database stores `token → serverId` bindings,
|
|
29
32
|
not application plaintext. Layer 1 (`openchamber-relay`) never sees these secrets.
|
|
30
|
-
5. Tapping a push deep-links
|
|
33
|
+
5. Tapping a session push deep-links via the forwarded `sessionId`. Tapping a contact push
|
|
34
|
+
opens that assistant via `assistantID` / `openchamber://assistant/<id>`.
|
|
31
35
|
|
|
32
36
|
## Live Activity (update / end)
|
|
33
37
|
|
|
@@ -167,13 +171,15 @@ Who can read the alert text:
|
|
|
167
171
|
- **Apple APNs:** the alert text too — APNs always reads the alert payload of an `alert` push.
|
|
168
172
|
- **The device:** displays it.
|
|
169
173
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
Ordinary session triggers stay **content-free**: a fixed scenario title (localized per device) +
|
|
175
|
+
the session name only — no model, project, or message content (`runtime.js` →
|
|
176
|
+
`toApnsGenericPayload` → `localizeApnsPayload`). The session name is the single semi-personal
|
|
177
|
+
field that crosses the relay/Apple on that path.
|
|
178
|
+
|
|
179
|
+
Contact-turn alerts are an intentional exception: nickname + spoken message cross the relay so
|
|
180
|
+
the banner reads like a normal contact. To hide even that from Apple would require an end-to-end
|
|
181
|
+
**encrypted payload** (`mutable-content` + a Notification Service Extension that decrypts
|
|
182
|
+
on-device with a key never sent to the relay) — not implemented.
|
|
177
183
|
|
|
178
184
|
## Android (FCM) note
|
|
179
185
|
|
|
@@ -47,9 +47,10 @@ This module provides notification message preparation utilities for the web serv
|
|
|
47
47
|
- Returned API:
|
|
48
48
|
- `maybeSendPushForTrigger(payload)`
|
|
49
49
|
- Owns:
|
|
50
|
-
- top-level completion/question/permission trigger routing; completion is the sole task-status notification
|
|
51
|
-
-
|
|
52
|
-
-
|
|
50
|
+
- top-level completion/question/permission trigger routing; completion is the sole task-status notification. Ordinary push is limited to sidebar-visible root sessions. Child/subagent sessions, Assistant bindings (`openchamber.assistant.assistantID` unless `assigned.from === 'contact'`), scheduled-task sessions, small-model system sessions (`metadata.openchamber.smallModel.purpose`), and `smartfetch-secondary` titles are suppressed. Contact-assigned workers stay visible and still notify.
|
|
51
|
+
- contact-turn notifications (`sendContactTurnNotification`) are a separate SMS-style path: title is the assistant nickname, body is the spoken message text, on desktop / UI SSE / web-push / APNs. APNs does **not** rewrite these into the generic "Task completed" scenario title.
|
|
52
|
+
- top-level completion/error Live Activity `end` (`sendLiveActivityEnd`), independent of ordinary push settings and UI visibility, with the same hidden-session suppression; duplicate terminal events are idempotent at the token store
|
|
53
|
+
- session meta cache for sidebar-visibility suppression
|
|
53
54
|
- template resolution and fallback behavior
|
|
54
55
|
- native notification fanout and web push payload fanout
|
|
55
56
|
- push always fans out to every subscribed surface; another client's visibility never suppresses delivery
|
|
@@ -47,9 +47,20 @@ export const createNotificationTriggerRuntime = (deps) => {
|
|
|
47
47
|
return pendingPushTags.size;
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
+
const stringifyApnsData = (data) => {
|
|
51
|
+
if (!data || typeof data !== 'object') return undefined;
|
|
52
|
+
const next = {};
|
|
53
|
+
for (const [key, value] of Object.entries(data)) {
|
|
54
|
+
if (typeof value !== 'string' || value.length === 0) continue;
|
|
55
|
+
next[key] = value;
|
|
56
|
+
}
|
|
57
|
+
return Object.keys(next).length > 0 ? next : undefined;
|
|
58
|
+
};
|
|
59
|
+
|
|
50
60
|
// Generic notification for native push (per the mobile design): a fixed, scenario-based
|
|
51
61
|
// title + the session name as the body. No model/project/message content crosses the relay.
|
|
52
62
|
// Title strings are localized per device token locale inside sendApnsToAllUiSessions.
|
|
63
|
+
// Contact turns opt out via preserveAlert — those keep nickname + spoken text.
|
|
53
64
|
const toApnsGenericPayload = (payload) => {
|
|
54
65
|
const data = payload?.data && typeof payload.data === 'object' ? payload.data : {};
|
|
55
66
|
const sessionName = typeof data.sessionName === 'string' && data.sessionName.trim().length > 0
|
|
@@ -66,15 +77,39 @@ export const createNotificationTriggerRuntime = (deps) => {
|
|
|
66
77
|
};
|
|
67
78
|
};
|
|
68
79
|
|
|
80
|
+
const toApnsContactPayload = (payload) => {
|
|
81
|
+
const data = payload?.data && typeof payload.data === 'object' ? payload.data : {};
|
|
82
|
+
const title = typeof payload?.title === 'string' && payload.title.trim()
|
|
83
|
+
? payload.title.trim()
|
|
84
|
+
: 'Assistant';
|
|
85
|
+
const body = typeof payload?.body === 'string' ? payload.body : '';
|
|
86
|
+
return {
|
|
87
|
+
title,
|
|
88
|
+
body,
|
|
89
|
+
badge: trackPushAndCountBadge(typeof payload?.tag === 'string' ? payload.tag : undefined),
|
|
90
|
+
tag: payload?.tag,
|
|
91
|
+
data: stringifyApnsData({
|
|
92
|
+
assistantID: data.assistantID,
|
|
93
|
+
url: typeof data.assistantID === 'string' && data.assistantID.trim()
|
|
94
|
+
? `openchamber://assistant/${encodeURIComponent(data.assistantID.trim())}`
|
|
95
|
+
: (typeof data.url === 'string' ? data.url : undefined),
|
|
96
|
+
}),
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
|
|
69
100
|
// Fan a notification out to every delivery channel: browser web-push (full templated
|
|
70
|
-
// payload) and native iOS APNs (generic model-based text).
|
|
71
|
-
// a failure in one channel must not block the other.
|
|
72
|
-
// never suppresses delivery — every subscribed
|
|
73
|
-
|
|
101
|
+
// payload) and native iOS APNs (generic model-based text, unless preserveAlert).
|
|
102
|
+
// Both share the dedup tag; a failure in one channel must not block the other.
|
|
103
|
+
// Visibility on any other client never suppresses delivery — every subscribed
|
|
104
|
+
// surface gets the push.
|
|
105
|
+
const fanoutPush = (payload, options = {}) => Promise.all([
|
|
74
106
|
Promise.resolve(sendPushToAllUiSessions?.(payload, options)).catch((error) => {
|
|
75
107
|
console.warn('[Push] web-push fanout failed:', error?.message ?? error);
|
|
76
108
|
}),
|
|
77
|
-
Promise.resolve(sendApnsToAllUiSessions?.(
|
|
109
|
+
Promise.resolve(sendApnsToAllUiSessions?.(
|
|
110
|
+
options.preserveAlert === true ? toApnsContactPayload(payload) : toApnsGenericPayload(payload),
|
|
111
|
+
options,
|
|
112
|
+
)).catch((error) => {
|
|
78
113
|
console.warn('[APNs] fanout failed:', error?.message ?? error);
|
|
79
114
|
}),
|
|
80
115
|
]);
|
|
@@ -97,6 +132,8 @@ export const createNotificationTriggerRuntime = (deps) => {
|
|
|
97
132
|
|
|
98
133
|
const sessionMetaCache = new Map();
|
|
99
134
|
const SESSION_META_CACHE_TTL_MS = 60 * 1000;
|
|
135
|
+
const HIDDEN_SESSION_TITLES = new Set(['smartfetch-secondary']);
|
|
136
|
+
const nonEmptySystemID = (value) => typeof value === 'string' && value.length > 0;
|
|
100
137
|
|
|
101
138
|
// Sessions where the client has enabled Permission Auto-Accept. Mirrored
|
|
102
139
|
// from the client-side permissionStore via POST /api/notifications/auto-accept
|
|
@@ -148,32 +185,47 @@ export const createNotificationTriggerRuntime = (deps) => {
|
|
|
148
185
|
smallModelPurpose: meta.smallModelPurpose !== undefined
|
|
149
186
|
? meta.smallModelPurpose
|
|
150
187
|
: (previous?.smallModelPurpose ?? null),
|
|
188
|
+
assistantID: meta.assistantID !== undefined ? meta.assistantID : (previous?.assistantID ?? null),
|
|
189
|
+
assignedFrom: meta.assignedFrom !== undefined ? meta.assignedFrom : (previous?.assignedFrom ?? null),
|
|
190
|
+
scheduledTaskID: meta.scheduledTaskID !== undefined
|
|
191
|
+
? meta.scheduledTaskID
|
|
192
|
+
: (previous?.scheduledTaskID ?? null),
|
|
193
|
+
title: meta.title !== undefined ? meta.title : (previous?.title ?? null),
|
|
194
|
+
complete: meta.complete === true || previous?.complete === true,
|
|
151
195
|
at: Date.now(),
|
|
152
196
|
});
|
|
153
197
|
};
|
|
154
198
|
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
199
|
+
const metaFromOpenchamber = (openchamber, extras = {}) => {
|
|
200
|
+
const assignedFrom = typeof openchamber?.assigned?.from === 'string'
|
|
201
|
+
? openchamber.assigned.from
|
|
202
|
+
: null;
|
|
203
|
+
return {
|
|
204
|
+
smallModelPurpose: normalizeSmallModelPurpose(openchamber?.smallModel?.purpose),
|
|
205
|
+
assistantID: nonEmptySystemID(openchamber?.assistant?.assistantID)
|
|
206
|
+
? openchamber.assistant.assistantID
|
|
207
|
+
: null,
|
|
208
|
+
assignedFrom,
|
|
209
|
+
scheduledTaskID: nonEmptySystemID(openchamber?.scheduledTask?.taskID)
|
|
210
|
+
? openchamber.scheduledTask.taskID
|
|
211
|
+
: null,
|
|
212
|
+
...extras,
|
|
213
|
+
};
|
|
165
214
|
};
|
|
166
215
|
|
|
167
216
|
const maybeCacheSessionMetaFromPayload = (payload) => {
|
|
217
|
+
if (!payload || typeof payload !== 'object') return;
|
|
218
|
+
if (payload.type !== 'session.created' && payload.type !== 'session.updated') return;
|
|
219
|
+
const info = payload.properties?.info;
|
|
220
|
+
if (!info || typeof info !== 'object') return;
|
|
168
221
|
const sessionId = extractSessionIdFromPayload(payload);
|
|
169
222
|
if (typeof sessionId !== 'string' || sessionId.length === 0) return;
|
|
170
223
|
const directory = extractDirectoryFromPayload(payload);
|
|
171
|
-
const parentID = getParentIdFromPayload(payload);
|
|
172
|
-
const smallModelPurpose = getSmallModelPurposeFromPayload(payload);
|
|
173
|
-
if (parentID === undefined && smallModelPurpose === undefined) return;
|
|
174
224
|
setCachedSessionMeta(sessionId, directory, {
|
|
175
|
-
|
|
176
|
-
|
|
225
|
+
parentID: normalizeParentID(info.parentID),
|
|
226
|
+
title: typeof info.title === 'string' ? info.title : null,
|
|
227
|
+
complete: true,
|
|
228
|
+
...metaFromOpenchamber(info.metadata?.openchamber),
|
|
177
229
|
});
|
|
178
230
|
};
|
|
179
231
|
|
|
@@ -181,7 +233,7 @@ export const createNotificationTriggerRuntime = (deps) => {
|
|
|
181
233
|
if (!sessionId) return undefined;
|
|
182
234
|
|
|
183
235
|
const cached = getCachedSessionMeta(sessionId, directory);
|
|
184
|
-
if (cached
|
|
236
|
+
if (cached?.complete) return cached;
|
|
185
237
|
|
|
186
238
|
try {
|
|
187
239
|
const base = buildOpenCodeUrl(`/session/${encodeURIComponent(sessionId)}`, '');
|
|
@@ -195,21 +247,23 @@ export const createNotificationTriggerRuntime = (deps) => {
|
|
|
195
247
|
signal: AbortSignal.timeout(2000),
|
|
196
248
|
});
|
|
197
249
|
if (!response.ok) {
|
|
198
|
-
return
|
|
250
|
+
return cached;
|
|
199
251
|
}
|
|
200
252
|
const session = await response.json().catch(() => null);
|
|
201
253
|
if (!session || typeof session !== 'object') {
|
|
202
|
-
return
|
|
254
|
+
return cached;
|
|
203
255
|
}
|
|
204
256
|
|
|
205
257
|
const meta = {
|
|
206
258
|
parentID: normalizeParentID(session.parentID),
|
|
207
|
-
|
|
259
|
+
title: typeof session.title === 'string' ? session.title : null,
|
|
260
|
+
complete: true,
|
|
261
|
+
...metaFromOpenchamber(session.metadata?.openchamber),
|
|
208
262
|
};
|
|
209
263
|
setCachedSessionMeta(sessionId, directory, meta);
|
|
210
|
-
return meta;
|
|
264
|
+
return getCachedSessionMeta(sessionId, directory) ?? meta;
|
|
211
265
|
} catch {
|
|
212
|
-
return
|
|
266
|
+
return cached;
|
|
213
267
|
}
|
|
214
268
|
};
|
|
215
269
|
|
|
@@ -234,20 +288,25 @@ export const createNotificationTriggerRuntime = (deps) => {
|
|
|
234
288
|
return false;
|
|
235
289
|
};
|
|
236
290
|
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
291
|
+
const isHiddenFromNavSession = (meta) => {
|
|
292
|
+
if (!meta) return false;
|
|
293
|
+
if (typeof meta.parentID === 'string' && meta.parentID.length > 0) return true;
|
|
294
|
+
if (typeof meta.smallModelPurpose === 'string' && meta.smallModelPurpose.length > 0) return true;
|
|
295
|
+
if (typeof meta.assistantID === 'string' && meta.assistantID.length > 0 && meta.assignedFrom !== 'contact') {
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
if (typeof meta.scheduledTaskID === 'string' && meta.scheduledTaskID.length > 0) return true;
|
|
299
|
+
if (typeof meta.title === 'string' && HIDDEN_SESSION_TITLES.has(meta.title)) return true;
|
|
300
|
+
return false;
|
|
245
301
|
};
|
|
246
302
|
|
|
303
|
+
// Only sessions that can appear as sidebar roots get ordinary push. Child /
|
|
304
|
+
// subagent sessions, archived Assistant bindings, scheduled-task sessions,
|
|
305
|
+
// small-model system sessions, and SmartFetch secondaries are excluded.
|
|
306
|
+
// Contact-assigned worker sessions stay visible and still notify.
|
|
247
307
|
const shouldSkipSystemSessionNotification = async (sessionId, directory) => {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
return false;
|
|
308
|
+
const meta = await fetchSessionMeta(sessionId, directory);
|
|
309
|
+
return isHiddenFromNavSession(meta);
|
|
251
310
|
};
|
|
252
311
|
|
|
253
312
|
const extractSessionIdFromPayload = (payload) => {
|
|
@@ -720,7 +779,7 @@ export const createNotificationTriggerRuntime = (deps) => {
|
|
|
720
779
|
title,
|
|
721
780
|
body: text,
|
|
722
781
|
tag,
|
|
723
|
-
kind: '
|
|
782
|
+
kind: 'contact',
|
|
724
783
|
assistantID: assistantID.trim(),
|
|
725
784
|
requireHidden: false,
|
|
726
785
|
};
|
|
@@ -728,19 +787,19 @@ export const createNotificationTriggerRuntime = (deps) => {
|
|
|
728
787
|
broadcastUiNotification(notificationPayload, { desktopNotificationDelivered });
|
|
729
788
|
}
|
|
730
789
|
|
|
790
|
+
const assistantPath = `/assistant/${encodeURIComponent(assistantID.trim())}`;
|
|
731
791
|
await fanoutPush(
|
|
732
792
|
{
|
|
733
793
|
title,
|
|
734
794
|
body: text,
|
|
735
795
|
tag,
|
|
736
796
|
data: {
|
|
737
|
-
url:
|
|
797
|
+
url: assistantPath,
|
|
738
798
|
assistantID: assistantID.trim(),
|
|
739
|
-
|
|
740
|
-
type: 'ready',
|
|
799
|
+
type: 'contact',
|
|
741
800
|
},
|
|
742
801
|
},
|
|
743
|
-
{ requireNoSse: true },
|
|
802
|
+
{ requireNoSse: true, preserveAlert: true },
|
|
744
803
|
);
|
|
745
804
|
};
|
|
746
805
|
|
|
@@ -175,6 +175,58 @@ describe('notification trigger runtime smallModel suppression', () => {
|
|
|
175
175
|
expect(emitDesktopNotification).toHaveBeenCalledTimes(1);
|
|
176
176
|
expect(sendPushToAllUiSessions).toHaveBeenCalledTimes(1);
|
|
177
177
|
});
|
|
178
|
+
|
|
179
|
+
it('skips ready notifications for child sessions', async () => {
|
|
180
|
+
vi.stubGlobal('fetch', vi.fn(async () => jsonResponse({
|
|
181
|
+
id: 'ses_child',
|
|
182
|
+
parentID: 'ses_parent',
|
|
183
|
+
title: 'Fixer',
|
|
184
|
+
metadata: {},
|
|
185
|
+
})));
|
|
186
|
+
const { runtime, emitDesktopNotification, sendPushToAllUiSessions } = createRuntime();
|
|
187
|
+
await runtime.maybeSendPushForTrigger(completionPayload('ses_child'));
|
|
188
|
+
expect(emitDesktopNotification).not.toHaveBeenCalled();
|
|
189
|
+
expect(sendPushToAllUiSessions).not.toHaveBeenCalled();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('skips ready notifications for Assistant binding sessions', async () => {
|
|
193
|
+
vi.stubGlobal('fetch', vi.fn(async () => jsonResponse({
|
|
194
|
+
id: 'ses_binding',
|
|
195
|
+
parentID: null,
|
|
196
|
+
title: '大小白',
|
|
197
|
+
metadata: { openchamber: { assistant: { assistantID: 'asst_1', name: '大小白' } } },
|
|
198
|
+
})));
|
|
199
|
+
const { runtime, emitDesktopNotification, sendPushToAllUiSessions } = createRuntime();
|
|
200
|
+
await runtime.maybeSendPushForTrigger(completionPayload('ses_binding'));
|
|
201
|
+
expect(emitDesktopNotification).not.toHaveBeenCalled();
|
|
202
|
+
expect(sendPushToAllUiSessions).not.toHaveBeenCalled();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('skips ready notifications for scheduled-task sessions', async () => {
|
|
206
|
+
vi.stubGlobal('fetch', vi.fn(async () => jsonResponse({
|
|
207
|
+
id: 'ses_sched',
|
|
208
|
+
parentID: null,
|
|
209
|
+
title: 'Nightly',
|
|
210
|
+
metadata: { openchamber: { scheduledTask: { taskID: 'task_1' } } },
|
|
211
|
+
})));
|
|
212
|
+
const { runtime, emitDesktopNotification, sendPushToAllUiSessions } = createRuntime();
|
|
213
|
+
await runtime.maybeSendPushForTrigger(completionPayload('ses_sched'));
|
|
214
|
+
expect(emitDesktopNotification).not.toHaveBeenCalled();
|
|
215
|
+
expect(sendPushToAllUiSessions).not.toHaveBeenCalled();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('still notifies contact-assigned worker sessions that appear in the sidebar', async () => {
|
|
219
|
+
vi.stubGlobal('fetch', vi.fn(async () => jsonResponse({
|
|
220
|
+
id: 'ses_worker',
|
|
221
|
+
parentID: null,
|
|
222
|
+
title: 'Assigned work',
|
|
223
|
+
metadata: { openchamber: { assigned: { from: 'contact', assistantID: 'asst_1', name: '大小白' } } },
|
|
224
|
+
})));
|
|
225
|
+
const { runtime, emitDesktopNotification, sendPushToAllUiSessions } = createRuntime();
|
|
226
|
+
await runtime.maybeSendPushForTrigger(completionPayload('ses_worker'));
|
|
227
|
+
expect(emitDesktopNotification).toHaveBeenCalledTimes(1);
|
|
228
|
+
expect(sendPushToAllUiSessions).toHaveBeenCalledTimes(1);
|
|
229
|
+
});
|
|
178
230
|
});
|
|
179
231
|
|
|
180
232
|
const rootSessionResponse = () => jsonResponse({
|
|
@@ -201,7 +253,7 @@ const completionPayload = (sessionId = 'ses_root', finish = 'stop') => ({
|
|
|
201
253
|
|
|
202
254
|
describe('contact turn notifications', () => {
|
|
203
255
|
it('sends an SMS-style title and body when a contact turn completes', async () => {
|
|
204
|
-
const { runtime, emitDesktopNotification, broadcastUiNotification, sendPushToAllUiSessions } = createRuntime();
|
|
256
|
+
const { runtime, emitDesktopNotification, broadcastUiNotification, sendPushToAllUiSessions, sendApnsToAllUiSessions } = createRuntime();
|
|
205
257
|
await runtime.sendContactTurnNotification({
|
|
206
258
|
assistantID: 'asst_1',
|
|
207
259
|
name: '大小白',
|
|
@@ -212,15 +264,24 @@ describe('contact turn notifications', () => {
|
|
|
212
264
|
title: '大小白',
|
|
213
265
|
body: '我去找一下',
|
|
214
266
|
tag: 'contact-asst_1',
|
|
215
|
-
kind: '
|
|
267
|
+
kind: 'contact',
|
|
216
268
|
assistantID: 'asst_1',
|
|
217
269
|
}));
|
|
218
270
|
expect(broadcastUiNotification).toHaveBeenCalled();
|
|
219
271
|
expect(sendPushToAllUiSessions).toHaveBeenCalledWith(expect.objectContaining({
|
|
220
272
|
title: '大小白',
|
|
221
273
|
body: '我去找一下',
|
|
222
|
-
data: expect.objectContaining({ assistantID: 'asst_1', type: '
|
|
223
|
-
}), { requireNoSse: true });
|
|
274
|
+
data: expect.objectContaining({ assistantID: 'asst_1', type: 'contact', url: '/assistant/asst_1' }),
|
|
275
|
+
}), expect.objectContaining({ requireNoSse: true, preserveAlert: true }));
|
|
276
|
+
expect(sendApnsToAllUiSessions).toHaveBeenCalledWith(expect.objectContaining({
|
|
277
|
+
title: '大小白',
|
|
278
|
+
body: '我去找一下',
|
|
279
|
+
data: expect.objectContaining({
|
|
280
|
+
assistantID: 'asst_1',
|
|
281
|
+
url: 'openchamber://assistant/asst_1',
|
|
282
|
+
}),
|
|
283
|
+
}), expect.objectContaining({ preserveAlert: true }));
|
|
284
|
+
expect(sendApnsToAllUiSessions.mock.calls[0][0].type).toBeUndefined();
|
|
224
285
|
});
|
|
225
286
|
|
|
226
287
|
it('skips contact notifications when completion notices are disabled', async () => {
|
|
@@ -1,2 +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}from"./useUIStore-CqqO11ZI.js";import{et as a}from"./persistence-CSZp1CNB.js";import{a as o}from"./vendor-zustand-B4dlGEM2.js";import{nt as s,rt as c}from"./vendor-base-ui-CnHfUmDN.js";import{r as l}from"./platform-CenlWqxu.js";import{n as u}from"./vendor-react-DLPElpoQ.js";import{r as d}from"./vendor-sonner-DVzioF3d.js";import{n as f}from"./vendor-reactuses-core-DDoDDyM9.js";import{n as p}from"./clipboard-BXxLshVq.js";import{a as m,n as h}from"./MobileShareBridge-CXR-B1xW.js";import{Oo as g,dr as _,qt as v,r as y,vn as b}from"./useMobileNavigationStore-CUGaydRW.js";import{a as x,b as S,c as C,f as w,h as ee,p as T,r as E,t as D,v as O}from"./MobileDetailNavigation-ACMbLTqb.js";import{i as k,n as A,r as j}from"./useAssistantUIStore-BHacrxe_.js";import{a as M,i as N,n as P,o as F,r as I,t as L}from"./dialog-BkhHBTd4.js";import{t as R}from"./utils-B0mQXN9L.js";import{t as z}from"./AgentAvatar-DI2zs2WH.js";import{n as B}from"./Icon-4My8YZwt.js";import{t as V}from"./button-Or0daT9o.js";import{i as H}from"./OverlayScrollbar-BZB21Yp_.js";import{a as U,i as te,n as ne,r as re,t as ie,u as W}from"./sessionChangeSummary-CX2MJIkc.js";import{a as G,i as ae,n as K,r as oe,t as se}from"./context-menu-Dpjla5p4.js";import{t as ce}from"./sessionLookup-Sb2HN3G2.js";var q=u(),J=e(c(),1),Y=s(),le=e=>{let t=(0,q.c)(17),{name:n,emoji:r,size:i,label:a,working:o,className:s}=e,c=i===void 0?24:i,l=o!==void 0&&o,{t:u}=p(),d=`calc(${c}px * var(--dpt-n, 1))`,f;t[0]===s?f=t[1]:(f=R(`relative inline-block shrink-0 align-middle leading-none`,s),t[0]=s,t[1]=f);let m;t[2]===d?m=t[3]:(m={width:d,height:d},t[2]=d,t[3]=m);let h;t[4]!==r||t[5]!==a||t[6]!==n||t[7]!==c?(h=(0,Y.jsx)(z,{name:n,emoji:r,size:c,label:a,shape:`circle`}),t[4]=r,t[5]=a,t[6]=n,t[7]=c,t[8]=h):h=t[8];let g;t[9]!==u||t[10]!==l?(g=l?(0,Y.jsx)(`span`,{className:`pointer-events-none absolute right-0 bottom-0 size-2 translate-x-1/4 translate-y-1/4 rounded-full bg-[var(--status-success)] ring-2 ring-background`,"data-assistant-working-dot":``,"aria-label":u(`assistants.contact.working`)}):null,t[9]=u,t[10]=l,t[11]=g):g=t[11];let _;return t[12]!==f||t[13]!==m||t[14]!==h||t[15]!==g?(_=(0,Y.jsxs)(`span`,{className:f,style:m,"data-assistant-working-avatar":``,children:[h,g]}),t[12]=f,t[13]=m,t[14]=h,t[15]=g,t[16]=_):_=t[16],_},X=o(e=>({workingByID:{},setWorking:(t,n)=>e(e=>({workingByID:{...e.workingByID,[t]:n}}))})),ue=({sending:e=!1,processing:t=!1})=>e||t,de=e=>{let t=(0,q.c)(4),n;t[0]===e?n=t[1]:(n=t=>!!t.workingByID[e],t[0]=e,t[1]=n);let r=X(n),i;return t[2]===r?i=t[3]:(i=ue({processing:r}),t[2]=r,t[3]=i),i},Z=[],fe=e=>e.flatMap(e=>e.type===`text`&&e.text.trim()?[e.text]:[]).join(`
|
|
2
|
-
`),pe=(e,t,n,r=Date.now())=>({assistantID:e,messageID:t,parts:n,status:`sending`,createdAt:r}),me=(e,t)=>{let n=e.filter(e=>e.assistantID===t);return n.length===e.length?e:n},he=(e,t)=>{let n=e.filter(e=>e.assistantID===t);return n.length===e.length?e:n},Q=(e,t,n,r)=>({messageID:t?`${e.turnID}:preview:${t.bubbleIndex}`:`${e.turnID}:preview:${r}`,assistantID:e.assistantID,role:`assistant`,turnID:e.turnID,bubbleIndex:t?.bubbleIndex??0,createdAt:t?.occurredAt??e.occurredAt,ordinal:n,status:r,fromAssistantID:null,fromAssistantName:null,parts:t?[{type:`text`,text:t.text}]:[],text:t?.text??``,cards:[]}),ge=(e,t,n)=>{let r=e.bubbles.filter(e=>!t.has(e.bubbleIndex)).map((t,r)=>Q(e,t,n+r,t.done?`complete`:`streaming`));return e.status===`admitted`&&e.bubbles.length===0&&t.size===0?[Q(e,null,n,`admitted`)]:e.status===`failed`?[...r,Q(e,null,n+r.length,`failed`)]:r},_e=(e,t,n,r=[])=>{let i=new Set(e.map(e=>e.messageID)),a=t.flatMap((t,r)=>t.assistantID!==n||i.has(t.messageID)?[]:[{messageID:t.messageID,assistantID:n,role:`user`,turnID:t.messageID,bubbleIndex:0,createdAt:t.createdAt,ordinal:e.length+r,status:t.status,fromAssistantID:null,fromAssistantName:null,parts:[...t.parts],text:fe(t.parts),cards:[]}]),o=a.length===0?e:[...e,...a],s=r.filter(e=>e.assistantID===n);if(s.length===0)return o;let c=new Map,l=new Map;o.forEach((e,t)=>{if(c.set(e.turnID,t),e.role!==`assistant`||e.messageID.includes(`:preview:`))return;let n=l.get(e.turnID)??new Set;n.add(e.bubbleIndex),l.set(e.turnID,n)});let u=new Map,d=[];for(let e of s){let t=ge(e,l.get(e.turnID)??new Set,o.length+d.length);if(t.length===0)continue;let n=c.get(e.turnID);if(n===void 0){d.push(...t);continue}let r=u.get(n)??[];r.push(...t),u.set(n,r)}return u.size===0&&d.length===0?o:o.flatMap((e,t)=>[e,...u.get(t)??[]]).concat(d)},ve=(e,t)=>{let n=new Set(t.map(e=>e.messageID)),r=e.filter(e=>!n.has(e.messageID));return r.length===e.length?e:r},ye=(e,t)=>e.map(e=>e.messageID===t?{...e,status:`admitted`}:e),$=(e,t,n,r=Date.now())=>e.some(e=>e.assistantID===t&&e.turnID===n)?e:[...e,{assistantID:t,turnID:n,status:`admitted`,bubbles:[],occurredAt:r}],be=(e,t)=>$(e,t.assistantID,t.turnID,t.occurredAt).map(e=>{if(e.assistantID!==t.assistantID||e.turnID!==t.turnID||e.status===`failed`||e.status===`complete`)return e;let n=e.bubbles.find(e=>e.bubbleIndex===t.bubbleIndex);if(n?.done)return e;let r=n?{...n,text:`${n.text}${t.delta}`,done:t.done,occurredAt:t.occurredAt}:{bubbleIndex:t.bubbleIndex,text:t.delta,done:t.done,occurredAt:t.occurredAt},i=n?e.bubbles.map(e=>e.bubbleIndex===t.bubbleIndex?r:e):[...e.bubbles,r].sort((e,t)=>e.bubbleIndex-t.bubbleIndex);return{...e,status:`streaming`,bubbles:i}}),xe=(e,t)=>$(e,t.assistantID,t.turnID,t.occurredAt).map(e=>e.assistantID!==t.assistantID||e.turnID!==t.turnID?e:{...e,status:t.status===`error`?`failed`:`complete`,...t.error?{error:t.error}:{}}),Se=(e,t)=>{let n=new Set(t.flatMap(e=>e.role===`assistant`?[e.turnID]:[])),r=e.filter(e=>e.status!==`complete`||!n.has(e.turnID));return r.length===e.length?e:r},Ce=(e,t,n)=>e.map(e=>e.messageID===t?{...e,status:`failed`,error:n}:e),we=(e,t)=>{if(e instanceof O){if(e.code===`no_provider`)return t.noProvider;if(e.code===`admission_timeout`||e.code===`generate_timeout`)return t.timedOut;if(e.message&&e.message!==e.code)return e.message}return S(e)?t.timedOut:t.sendFailed},Te=()=>{let e=!1;return{tryAcquire:()=>!e&&(e=!0,!0),release:()=>{e=!1}}},Ee=e=>{let t=e.text.trim();if(e.sending||!t&&e.attachments.length===0||!e.gate.tryAcquire())return{ok:!1};let n=[...t?[{type:`text`,text:t}]:[],...e.attachments.map(e=>({type:`file`,mime:e.mime,url:e.url,filename:e.name}))],r=e.createMessageID();return{ok:!0,messageID:r,parts:n,turn:pe(e.assistantID,r,n,e.createdAt)}},De=e=>e.some(e=>e.status===`sending`),Oe=e=>e.some(e=>e.status===`admitted`||e.status===`streaming`),ke=[`cursor-pointer rounded-[1.35rem] bg-[var(--surface-elevated)] ring-1 ring-inset ring-[var(--surface-subtle)]`,`px-3.5 py-3 text-left transition-[background-color,box-shadow,transform] duration-200 ease-out motion-reduce:transition-none`,`hover:-translate-y-px hover:bg-interactive-hover/45 hover:shadow-sm active:translate-y-0 motion-reduce:hover:translate-y-0`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]`].join(` `),Ae=`${ke} w-fit max-w-[15rem]`,je=`${ke} w-fit max-w-[20rem]`;function Me(e,t){(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),t())}var Ne=e=>{let t=(0,q.c)(26),{card:n}=e,{t:r}=p(),i=W(),a;t[0]===i?a=t[1]:(a=i&&!l(),t[0]=i,t[1]=a);let o=!!a,s=n.name,c=`${n.providerID}/${n.modelID}`,u;t[2]!==n.mode||t[3]!==c?(u=[c,n.mode].filter(Boolean),t[2]=n.mode,t[3]=c,t[4]=u):u=t[4];let d=u,m;t[5]!==n.assistantID||t[6]!==o?(m=()=>{if(o){y.getState().openAssistant(n.assistantID);return}A(n.assistantID)},t[5]=n.assistantID,t[6]=o,t[7]=m):m=t[7];let h=f(m),g;t[8]===h?g=t[9]:(g=e=>{Me(e,h)},t[8]=h,t[9]=g);let _=f(g),v;t[10]!==r||t[11]!==s?(v=r(`assistants.contact.card.assistant.aria`,{name:s}),t[10]=r,t[11]=s,t[12]=v):v=t[12];let b;t[13]===Symbol.for(`react.memo_cache_sentinel`)?(b=(0,Y.jsx)(`span`,{className:`relative inline-block size-6 shrink-0 leading-none`,children:(0,Y.jsx)(`span`,{className:`flex size-6 items-center justify-center rounded-lg bg-[var(--surface-muted)] text-muted-foreground`,children:(0,Y.jsx)(B,{name:`robot-2`,className:`size-3`})})}),t[13]=b):b=t[13];let x;t[14]===s?x=t[15]:(x=(0,Y.jsx)(`h3`,{className:`min-w-0 truncate typography-ui-label font-medium text-foreground`,children:s}),t[14]=s,t[15]=x);let S;t[16]===d?S=t[17]:(S=d.length>0?(0,Y.jsx)(`p`,{className:`truncate typography-micro text-muted-foreground`,children:d.join(` · `)}):null,t[16]=d,t[17]=S);let C;t[18]!==x||t[19]!==S?(C=(0,Y.jsxs)(`div`,{className:`flex items-center gap-2.5`,children:[b,(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1 space-y-1`,children:[x,S]})]}),t[18]=x,t[19]=S,t[20]=C):C=t[20];let w;return t[21]!==_||t[22]!==h||t[23]!==C||t[24]!==v?(w=(0,Y.jsx)(`article`,{className:Ae,role:`button`,tabIndex:0,"aria-label":v,"data-assistant-contact-card":`assistant`,onClick:h,onKeyDown:_,children:C}),t[21]=_,t[22]=h,t[23]=C,t[24]=v,t[25]=w):w=t[25],w},Pe=e=>{let t=(0,q.c)(25),{card:n}=e,{t:r}=p(),i=n.name,a;t[0]!==n.kind||t[1]!==n.time||t[2]!==n.timezone?(a=[n.kind,n.time,n.timezone].filter(Boolean),t[0]=n.kind,t[1]=n.time,t[2]=n.timezone,t[3]=a):a=t[3];let o=a.join(` `),s;t[4]!==n.prompt||t[5]!==o?(s=o.trim()||(typeof n.prompt==`string`?n.prompt.trim():``),t[4]=n.prompt,t[5]=o,t[6]=s):s=t[6];let c=s,l=f(Fe),u;t[7]===l?u=t[8]:(u=e=>{Me(e,l)},t[7]=l,t[8]=u);let d=f(u),m;t[9]!==r||t[10]!==i?(m=r(`assistants.contact.card.schedule.aria`,{name:i}),t[9]=r,t[10]=i,t[11]=m):m=t[11];let h;t[12]===Symbol.for(`react.memo_cache_sentinel`)?(h=(0,Y.jsx)(`span`,{className:`relative inline-block size-6 shrink-0 leading-none`,children:(0,Y.jsx)(`span`,{className:`flex size-6 items-center justify-center rounded-lg bg-[var(--surface-muted)] text-muted-foreground`,children:(0,Y.jsx)(B,{name:`calendar`,className:`size-3`})})}),t[12]=h):h=t[12];let g;t[13]===i?g=t[14]:(g=(0,Y.jsx)(`h3`,{className:`min-w-0 truncate typography-ui-label font-medium text-foreground`,children:i}),t[13]=i,t[14]=g);let _;t[15]===c?_=t[16]:(_=c?(0,Y.jsx)(`p`,{className:`truncate typography-micro text-muted-foreground`,children:c}):null,t[15]=c,t[16]=_);let v;t[17]!==g||t[18]!==_?(v=(0,Y.jsxs)(`div`,{className:`flex items-center gap-2.5`,children:[h,(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1 space-y-1`,children:[g,_]})]}),t[17]=g,t[18]=_,t[19]=v):v=t[19];let y;return t[20]!==d||t[21]!==l||t[22]!==m||t[23]!==v?(y=(0,Y.jsx)(`article`,{className:Ae,role:`button`,tabIndex:0,"aria-label":m,"data-assistant-contact-card":`schedule`,onClick:l,onKeyDown:d,children:v}),t[20]=d,t[21]=l,t[22]=m,t[23]=v,t[24]=y):y=t[24],y};function Fe(){i.getState().setActiveMainTab(`schedule`),i.getState().setScheduledTasksDialogOpen(!0)}var Ie=(e,t)=>e===`busy`||e===`retry`?e:t===`error`||t===`question`||t===`complete`?t:e===`idle`?`complete`:t===`busy`||t===`retry`||t===`idle`?t:t||`busy`,Le=e=>e===`busy`?`assistants.contact.card.session.status.busy`:e===`retry`?`assistants.contact.card.session.status.retry`:e===`idle`?`assistants.contact.card.session.status.idle`:e===`complete`?`assistants.contact.card.session.status.complete`:e===`error`?`assistants.contact.card.session.status.error`:e===`question`?`assistants.contact.card.session.status.question`:null,Re=e=>e===`busy`?`bg-[var(--status-info)]/10 text-[var(--status-info)]`:e===`retry`||e===`question`?`bg-[var(--status-warning)]/10 text-[var(--status-warning)]`:e===`error`?`bg-[var(--status-error)]/10 text-[var(--status-error)]`:e===`idle`||e===`complete`?`bg-[var(--status-success)]/10 text-[var(--status-success)]`:`bg-[var(--surface-muted)] text-muted-foreground`,ze=e=>e.split(/[/\\]/u).filter(Boolean).at(-1)||e,Be=e=>{let t=(0,q.c)(35),{card:n}=e,{t:r}=p(),a=W(),o;t[0]===a?o=t[1]:(o=a&&!l(),t[0]=a,t[1]=o);let s=!!o,c;t[2]===n.sessionID?c=t[3]:(c=e=>e.activeSessions.find(e=>e.id===n.sessionID)??e.archivedSessions.find(e=>e.id===n.sessionID)??null,t[2]=n.sessionID,t[3]=c);let u=_(c),d=v(n.sessionID),m=(typeof u?.title==`string`&&u.title.trim()?u.title.trim():null)||n.title||r(`assistants.contact.card.session.untitled`),h=Ie(d?.type,n.status),g=Le(h),y=h===`busy`||h===`retry`,x=ze(typeof u?.directory==`string`&&u.directory.trim()?u.directory.trim():n.directory),S=ne(u)||n.branch,C=te(u),w=re(u),ee=ie(w),T=[x,C,S].filter(Ve),E;t[4]!==n.directory||t[5]!==n.sessionID||t[6]!==s?(E=()=>{let e=ce(n.sessionID)?.directory||n.directory;b(n.sessionID,e,{phoneShell:s,switchToChat:!0}),s||i.getState().setActiveMainTab(`chat`)},t[4]=n.directory,t[5]=n.sessionID,t[6]=s,t[7]=E):E=t[7];let D=f(E),O;t[8]===D?O=t[9]:(O=e=>{Me(e,D)},t[8]=D,t[9]=O);let k=f(O),A=je,j=r(`assistants.contact.card.session.aria`,{title:m}),M;t[10]===Symbol.for(`react.memo_cache_sentinel`)?(M=(0,Y.jsx)(`span`,{className:`flex size-6 items-center justify-center rounded-lg bg-[var(--surface-muted)] text-muted-foreground`,children:(0,Y.jsx)(B,{name:`chat-3`,className:`size-3`})}),t[10]=M):M=t[10];let N;t[11]===y?N=t[12]:(N=y?(0,Y.jsx)(`span`,{className:`pointer-events-none absolute right-0 bottom-0 size-2 translate-x-1/4 translate-y-1/4 rounded-full bg-[var(--status-success)] ring-2 ring-[var(--surface-elevated)]`,"data-assistant-working-dot":``,"aria-hidden":!0}):null,t[11]=y,t[12]=N);let P;t[13]===N?P=t[14]:(P=(0,Y.jsxs)(`span`,{className:`relative inline-block size-6 shrink-0 leading-none`,children:[M,N]}),t[13]=N,t[14]=P);let F;t[15]===m?F=t[16]:(F=(0,Y.jsx)(`h3`,{className:`min-w-0 flex-1 truncate typography-ui-label font-medium text-foreground`,children:m}),t[15]=m,t[16]=F);let I=g?(0,Y.jsx)(`span`,{className:R(`shrink-0 rounded-full px-1.5 py-0.5 typography-micro leading-none`,Re(h)),children:r(g)}):null,L;t[17]!==F||t[18]!==I?(L=(0,Y.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[F,I]}),t[17]=F,t[18]=I,t[19]=L):L=t[19];let z;t[20]===T?z=t[21]:(z=T.length>0?(0,Y.jsx)(`p`,{className:`truncate typography-micro text-muted-foreground`,children:T.join(` · `)}):null,t[20]=T,t[21]=z);let V=ee||w?.files!==void 0&&w.files>0?(0,Y.jsxs)(`p`,{className:`flex flex-wrap items-baseline gap-x-1.5 typography-micro tabular-nums`,children:[w?.additions===void 0?null:(0,Y.jsxs)(`span`,{className:`text-[var(--status-success)]`,children:[`+`,w.additions]}),w?.deletions===void 0?null:(0,Y.jsxs)(`span`,{className:`text-[var(--status-error)]`,children:[`−`,w.deletions]}),w?.files===void 0?null:(0,Y.jsx)(`span`,{className:`text-muted-foreground`,children:w.files===1?r(`assistants.contact.card.session.changes.filesSingle`,{count:w.files}):r(`assistants.contact.card.session.changes.filesPlural`,{count:w.files})})]}):null,H;t[22]!==L||t[23]!==z||t[24]!==V?(H=(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1 space-y-1`,children:[L,z,V]}),t[22]=L,t[23]=z,t[24]=V,t[25]=H):H=t[25];let U;t[26]!==P||t[27]!==H?(U=(0,Y.jsxs)(`div`,{className:`flex items-start gap-2.5`,children:[P,H]}),t[26]=P,t[27]=H,t[28]=U):U=t[28];let G;return t[29]!==k||t[30]!==D||t[31]!==U||t[32]!==A||t[33]!==j?(G=(0,Y.jsx)(`article`,{className:A,role:`button`,tabIndex:0,"aria-label":j,"data-assistant-contact-card":`session`,onClick:D,onKeyDown:k,children:U}),t[29]=k,t[30]=D,t[31]=U,t[32]=A,t[33]=j,t[34]=G):G=t[34],G};function Ve(e){return!!(e&&e.trim())}var He=64,Ue=e=>new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{t(typeof r.result==`string`?r.result:``)},r.onerror=()=>{n(r.error??Error(`read_failed`))},r.readAsDataURL(e)}),We=e=>{if(!e)return[];let t=Array.from(e.files||[]);return t.length>0?t:Array.from(e.items||[]).filter(e=>e.kind===`file`).map(e=>e.getAsFile()).filter(e=>e instanceof File)},Ge=e=>Array.from(e?.files||[]),Ke=async(e,t=a)=>{let n=[],r=0;for(let i of Array.from(e||[])){if(!i||i.size<=0)continue;if(i.size>52428800){r+=1;continue}let e=await Ue(i);e.startsWith(`data:`)&&n.push({id:t(),url:e,name:i.name.trim()||`attachment`,mime:i.type.trim()||`application/octet-stream`})}return{attachments:n,skippedTooLarge:r}},qe=(e,t)=>[...e,...t].slice(0,He),Je={"oc.settle.complete":`assistants.contact.settle.complete`,"oc.settle.error":`assistants.contact.settle.error`,"oc.settle.question":`assistants.contact.settle.question`},Ye=({assistant:e,warning:t,active:n,overlayHeader:r=!1})=>{let{t:o}=p(),s=i(e=>e.isMobile),c=w(),l=ee(),u=T(e.id,n),d=m(e.name),_=d.displayName||e.name,v=(e,t)=>{let n=e?l.data?.assistants.find(t=>t.id===e):void 0;return n?m(n.name).displayName||n.name:t||o(`assistants.contact.peer.unknown`)},[y,b]=J.useState(``),[x,S]=J.useState([]),[E,D]=J.useState([]),[O,k]=J.useState([]),[A,j]=J.useState(null),M=J.useMemo(()=>Te(),[]),N=J.useRef(new Set),P=X(e=>e.setWorking),F=J.useRef(null),I=u.data?.messages??Z,L=me(E,e.id),z=he(O,e.id),V=_e(I,L,e.id,z),H=De(L),te=Oe(z),ne=z.reduce((e,t)=>e+t.bubbles.reduce((e,t)=>e+t.text.length,0),0),re=new Map(z.map(e=>[e.turnID,e]));J.useEffect(()=>{j(null),N.current.clear(),D(t=>me(t,e.id)),k(t=>he(t,e.id))},[e.id]),J.useEffect(()=>{D(e=>ve(e,I)),k(e=>Se(e,I))},[I]),J.useEffect(()=>{P(e.id,H||te)},[e.id,te,H,P]),J.useEffect(()=>{let t=e.id;return()=>{P(t,!1)}},[e.id,P]);let ie=f(t=>{if(!(!(`assistantID`in t)||t.assistantID!==e.id)){if(t.type===`contact-turn-start`){if(N.current.has(t.turnID))return;k(e=>$(e,t.assistantID,t.turnID,t.occurredAt));return}if(t.type===`contact-bubble-delta`){if(N.current.has(t.turnID))return;k(e=>be(e,t));return}t.type===`contact-turn-end`&&(N.current.add(t.turnID),k(e=>Se(xe(e,t),I)))}});J.useEffect(()=>{if(n)return g(ie)},[n,e.id]),J.useEffect(()=>{let e=F.current;e&&(e.scrollTop=e.scrollHeight)},[ne,V.length]);let W=f(async e=>{let t=await Ke(e);t.skippedTooLarge>0&&j(o(`assistants.contact.attachment.tooLarge`)),t.attachments.length!==0&&S(e=>qe(e,t.attachments))}),G=f(e=>{let t=We(e.clipboardData);t.length!==0&&(e.preventDefault(),W(t))}),ae=f(e=>{Array.from(e.dataTransfer?.types??[]).includes(`Files`)&&(e.preventDefault(),e.dataTransfer.dropEffect=`copy`)}),K=f(e=>{let t=Ge(e.dataTransfer);t.length!==0&&(e.preventDefault(),W(t))}),oe=f(async()=>{let t=y,n=x,r=e.id,i=Ee({gate:M,sending:De(L),text:t,attachments:n,assistantID:r,createMessageID:()=>`oc_contact_${a()}`});if(i.ok){D(e=>[...e,i.turn]),b(``),S([]),j(null);try{await C(r,i.messageID,{parts:i.parts}),D(e=>ye(e,i.messageID)),N.current.has(i.messageID)||k(e=>$(e,r,i.messageID)),c.data?.serverInstanceID&&h({serverInstanceID:c.data.serverInstanceID,assistantID:r,name:_,avatarSeed:r,...d.avatarEmoji?{avatarEmoji:d.avatarEmoji}:{}}).catch(()=>void 0)}catch(e){let t=we(e,{noProvider:o(`assistants.contact.noProvider`),sendFailed:o(`assistants.contact.sendFailed`),timedOut:o(`assistants.contact.timedOut`)});D(e=>Ce(e,i.messageID,t))}finally{M.release()}}}),se=u.isError&&V.length===0,ce=u.isSuccess&&V.length===0,q=new Map(L.map(e=>[e.messageID,e]));return(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col bg-background`,children:[(0,Y.jsxs)(`div`,{ref:F,className:R(`min-h-0 flex-1 overflow-y-auto px-4 pb-9 sm:px-8 sm:pb-12`,r?`pt-[calc(max(0.625rem,var(--oc-safe-area-top,0px))+var(--oc-mobile-detail-navigation-height)+1.25rem)]`:`pt-5 sm:pt-7`),"data-assistant-contact-transcript":``,children:[t?(0,Y.jsx)(`p`,{className:`mb-3 typography-micro text-[var(--status-warning)]`,children:t}):null,se?(0,Y.jsxs)(`div`,{className:`mx-auto flex h-full min-h-56 max-w-xs flex-col items-center justify-center pb-16 text-center`,"data-assistant-contact-error":``,children:[(0,Y.jsxs)(`div`,{className:`relative`,children:[(0,Y.jsx)(le,{name:e.id,emoji:d.avatarEmoji,size:44,label:_}),(0,Y.jsx)(`span`,{"aria-hidden":!0,className:`absolute -right-1 -bottom-1 flex size-5 items-center justify-center rounded-full bg-[var(--surface-elevated)] text-[var(--status-error)] ring-2 ring-background`,children:(0,Y.jsx)(B,{name:`error-warning`,className:`size-3`})})]}),(0,Y.jsx)(`p`,{className:`mt-4 typography-ui-label font-medium text-foreground`,children:_}),(0,Y.jsx)(`p`,{className:`mt-1.5 typography-ui leading-6 text-muted-foreground`,children:o(`assistants.contact.loadFailed`)})]}):ce?(0,Y.jsxs)(`div`,{className:`mx-auto flex h-full min-h-56 max-w-sm flex-col items-center justify-center pb-16 text-center`,"data-assistant-contact-empty":``,children:[(0,Y.jsx)(le,{name:e.id,emoji:d.avatarEmoji,size:48,label:_,className:`opacity-90`}),(0,Y.jsx)(`p`,{className:`mt-5 typography-ui-header font-medium tracking-[-0.01em] text-foreground`,children:o(`assistants.conversation.emptyTitle`,{name:_})}),(0,Y.jsx)(`p`,{className:`mt-2 max-w-xs typography-ui leading-6 text-muted-foreground/80`,children:o(`assistants.contact.empty`)})]}):(0,Y.jsx)(`div`,{className:`mx-auto flex w-full max-w-[42rem] flex-col`,children:V.map((t,n)=>{let r=n>0?V[n-1]:null,i=t.role===`user`,a=t.role===`peer`,s=t.role===`assistant`&&r?.role===`assistant`&&r.turnID===t.turnID,c=r?.turnID!==t.turnID,u=!i&&(a||!s),d=a?v(t.fromAssistantID,t.fromAssistantName):_,f=a&&t.fromAssistantID?l.data?.assistants.find(e=>e.id===t.fromAssistantID):e,p=f?m(f.name):null,h=q.get(t.messageID),g=re.get(t.turnID),y=t.status===`admitted`&&t.messageID.endsWith(`:preview:admitted`),b=t.status===`failed`&&t.messageID.endsWith(`:preview:failed`);return(0,Y.jsxs)(`div`,{className:R(`flex w-full`,i?`justify-end`:`justify-start`,c?`mt-6 first:mt-0`:s?`mt-1.5`:`mt-3`),"data-assistant-contact-role":t.role,"data-assistant-contact-turn-status":h?.status??t.status,"data-assistant-contact-run-start":t.role===`assistant`&&!s?``:void 0,children:[i?null:(0,Y.jsx)(`div`,{className:`mr-2.5 flex w-8 shrink-0 justify-center pt-0.5`,children:u?(0,Y.jsx)(le,{name:f?.id||t.fromAssistantID||e.id,emoji:p?.avatarEmoji,size:28,label:d}):(0,Y.jsx)(`span`,{className:`size-7`,"aria-hidden":!0})}),(0,Y.jsxs)(`div`,{className:R(`flex min-w-0 flex-col gap-1.5`,i?`max-w-[min(82%,30rem)] items-end`:`max-w-[min(84%,34rem)] items-start`),children:[a?(0,Y.jsx)(`span`,{className:`mb-0.5 px-1 typography-micro text-muted-foreground/75`,children:o(`assistants.contact.peer.from`,{name:d})}):null,y?(0,Y.jsxs)(`div`,{role:`status`,"aria-label":o(`assistants.contact.processing`),className:`inline-flex w-fit items-center gap-1 rounded-full bg-[var(--surface-muted)] px-3.5 py-2.5 text-muted-foreground/70`,"data-assistant-contact-processing":``,children:[(0,Y.jsx)(`span`,{"aria-hidden":!0,className:`size-1.5 animate-pulse rounded-full bg-current [animation-delay:-0.45s] [animation-duration:1.4s] motion-reduce:animate-none`}),(0,Y.jsx)(`span`,{"aria-hidden":!0,className:`size-1.5 animate-pulse rounded-full bg-current [animation-delay:-0.22s] [animation-duration:1.4s] motion-reduce:animate-none`}),(0,Y.jsx)(`span`,{"aria-hidden":!0,className:`size-1.5 animate-pulse rounded-full bg-current [animation-duration:1.4s] motion-reduce:animate-none`})]}):null,t.parts.map((e,n)=>e.type===`card`&&e.cardType===`session`?(0,Y.jsx)(Be,{card:e},`${t.messageID}:card:${n}`):e.type===`card`&&e.cardType===`assistant`?(0,Y.jsx)(Ne,{card:e},`${t.messageID}:card:${n}`):e.type===`card`&&e.cardType===`schedule`?(0,Y.jsx)(Pe,{card:e},`${t.messageID}:card:${n}`):e.type===`file`&&e.mime.startsWith(`image/`)&&e.url?(0,Y.jsx)(`img`,{src:e.url,alt:e.filename||o(`assistants.contact.attachment.image`),className:`max-h-72 max-w-full rounded-[1.35rem] border border-border/40 object-contain`,"data-assistant-contact-image":``},`${t.messageID}:file:${n}`):e.type===`file`?(0,Y.jsxs)(`div`,{className:`flex max-w-full items-center gap-2.5 rounded-[1.25rem] bg-[var(--surface-muted)] px-3.5 py-2.5 ring-1 ring-inset ring-[var(--surface-subtle)]`,"data-assistant-contact-file":``,children:[(0,Y.jsx)(B,{name:`file-text`,className:`size-4 shrink-0 text-muted-foreground`}),(0,Y.jsx)(`span`,{className:`min-w-0 truncate typography-ui`,children:e.filename||o(`assistants.contact.attachment.file`)})]},`${t.messageID}:file:${n}`):e.type===`text`&&(e.text.trim()||t.status===`streaming`)?(0,Y.jsxs)(`div`,{"aria-label":a?o(`assistants.contact.peer.aria`,{name:d}):void 0,className:R(`whitespace-pre-wrap break-words rounded-[1.35rem] px-4 py-2.5 typography-ui leading-6`,i?`rounded-[1.15rem] rounded-br-lg bg-[var(--primary-base)]/90 text-[var(--primary-foreground)]`:a?`rounded-[1.25rem] border border-dashed border-border/50 bg-[var(--surface-muted)]/70 text-foreground`:R(`bg-[var(--surface-muted)] text-foreground`,s&&`rounded-tl-lg`)),children:[Je[e.text]?o(Je[e.text]):e.text,t.status===`streaming`&&n===t.parts.length-1?(0,Y.jsx)(`span`,{"aria-hidden":!0,className:`ml-0.5 inline-block h-[1em] w-px translate-y-[0.12em] animate-pulse bg-current opacity-45 [animation-duration:1.1s] motion-reduce:animate-none`,"data-assistant-contact-streaming-caret":``}):null]},`${t.messageID}:text:${n}`):null),h?.status===`sending`?(0,Y.jsx)(`p`,{className:`px-1 typography-micro text-muted-foreground/75`,children:o(`assistants.contact.sending`)}):null,h?.status===`failed`?(0,Y.jsx)(`p`,{className:`px-1 typography-micro text-[var(--status-error)]`,children:h.error||o(`assistants.contact.sendFailed`)}):null,b?(0,Y.jsx)(`p`,{className:`px-1 typography-micro text-[var(--status-error)]`,children:g?.error||o(`assistants.contact.sendFailed`)}):null]})]},t.messageID)})})]}),(0,Y.jsxs)(`footer`,{className:`relative z-10 shrink-0 bg-background pt-1`,"data-assistant-contact-composer":``,children:[A?(0,Y.jsx)(`p`,{className:`chat-input-column mb-2 typography-micro text-[var(--status-error)]`,children:A}):null,(0,Y.jsx)(`form`,{className:R(`relative w-full pt-1.5 pb-4`,s&&`bottom-safe-area oc-mobile-composer`),onSubmit:e=>{e.preventDefault(),oe()},onDragOver:ae,onDrop:K,children:(0,Y.jsx)(`div`,{className:`chat-input-column relative overflow-visible`,children:(0,Y.jsx)(U,{layout:`inline`,value:y,attachments:x,pending:!1,isMobile:s,placeholder:o(`assistants.contact.placeholder`,{name:_}),sendLabel:o(`assistants.contact.send`),addFilesLabel:o(`assistants.contact.addFiles`),removeAttachmentLabel:o(`assistants.contact.removeAttachment`),fileAccept:`*/*`,onChange:e=>b(e),onSubmit:()=>{oe()},onAddFiles:e=>{W(e)},onRemoveAttachment:e=>{S(t=>t.filter(t=>t.id!==e))},onPaste:G,onDragOver:ae,onDrop:K,className:R(`relative z-10`,s&&`oc-mobile-composer-surface`),style:{borderRadius:`1.5rem`},"data-assistant-contact-composer-surface":``,textareaProps:{"aria-label":o(`assistants.contact.placeholder`,{name:_})}})})})]})]})};async function Xe(e){await E(e);let t=k.getState().defaultShareAssistant;if(t?.assistantID!==e.id)return;let n=await x();n.serverInstanceID&&t.serverInstanceID===n.serverInstanceID&&k.getState().setDefaultShareAssistant(null)}function Ze({assistant:e,open:t,onOpenChange:n,onDeleted:r}){let{t:i}=p(),[a,o]=J.useState(!1),s=e?m(e.name).displayName||e.name:``,c=f(e=>{a&&!e||n(e)}),l=f(()=>{a||n(!1)}),u=f(async()=>{if(!(!e||a)){o(!0);try{await Xe(e),r?.(e.id),n(!1),d.success(i(`assistants.settings.toast.deleted`))}catch{d.error(i(`assistants.settings.toast.deleteFailed`))}finally{o(!1)}}});return(0,Y.jsx)(L,{open:t&&e!==null,onOpenChange:c,children:(0,Y.jsxs)(P,{className:`max-w-md`,children:[(0,Y.jsxs)(M,{children:[(0,Y.jsx)(F,{children:i(`assistants.settings.delete`)}),(0,Y.jsx)(I,{children:i(`assistants.settings.deleteConfirm`,{name:s})})]}),(0,Y.jsxs)(N,{children:[(0,Y.jsx)(V,{size:`sm`,variant:`ghost`,onClick:l,disabled:a,children:i(`settings.common.actions.cancel`)}),(0,Y.jsx)(V,{size:`sm`,variant:`destructive`,onClick:u,disabled:a,children:i(`settings.common.actions.delete`)})]})]})})}var Qe=e=>e.capabilityPending?`loading`:e.capabilityError||e.supported!==!0||e.capabilityEnabled!==!0?`unavailable`:e.snapshotPending?`loading`:e.snapshotEnabled===!0?e.assistantCount===0?`onboarding`:e.hasAssistant?`ready`:e.snapshotSettled?`unavailable`:`loading`:`unavailable`,$e=t({AssistantView:()=>nt}),et=e=>{let t=(0,q.c)(21),{assistant:n,onBack:r}=e,{t:i}=p(),a=W(),o;t[0]===n?o=t[1]:(o=n?m(n.name):null,t[0]=n,t[1]=o);let s=o,c=n&&s?s.displayName||n.name:``,l;t[2]!==n||t[3]!==a?(l=()=>{n&&j(n.id,a?{openMobileSettings:a.openSettings}:void 0)},t[2]=n,t[3]=a,t[4]=l):l=t[4];let u=f(l),d;t[5]!==n||t[6]!==c||t[7]!==s?.avatarEmoji||t[8]!==i?(d=n?(0,Y.jsxs)(`span`,{className:`inline-flex min-w-0 items-center gap-2.5`,children:[(0,Y.jsx)(le,{name:n.id,emoji:s?.avatarEmoji,size:28,label:c}),(0,Y.jsx)(`span`,{className:`truncate font-medium tracking-[-0.01em]`,children:c||i(`assistants.title`)})]}):c||i(`assistants.title`),t[5]=n,t[6]=c,t[7]=s?.avatarEmoji,t[8]=i,t[9]=d):d=t[9];let h;t[10]===i?h=t[11]:(h=i(`assistants.actions.backToChat`),t[10]=i,t[11]=h);let g;t[12]!==n||t[13]!==u||t[14]!==i?(g=n?[{icon:`settings-3`,ariaLabel:i(`assistants.conversation.openSettings`),onClick:u}]:[],t[12]=n,t[13]=u,t[14]=i,t[15]=g):g=t[15];let _;return t[16]!==r||t[17]!==d||t[18]!==h||t[19]!==g?(_=(0,Y.jsx)(D,{title:d,backAriaLabel:h,onBack:r,actions:g,overlay:!0}),t[16]=r,t[17]=d,t[18]=h,t[19]=g,t[20]=_):_=t[20],_},tt=e=>{let t=(0,q.c)(41),{assistantID:n,displayName:r,avatarEmoji:i,selected:a,enabled:o,editLabel:s,deleteLabel:c,onSelect:l,onEdit:u,onDelete:d,assignedSessionIDs:p,serverWorking:m}=e,h=de(n),[g,_]=J.useState(!1),v;t[0]===l?v=t[1]:(v=()=>l(),t[0]=l,t[1]=v);let y=f(v),b;t[2]===u?b=t[3]:(b=()=>{_(!1),u()},t[2]=u,t[3]=b);let x=f(b),S;t[4]===d?S=t[5]:(S=()=>{_(!1),d()},t[4]=d,t[5]=S);let C=f(S),w;t[6]===Symbol.for(`react.memo_cache_sentinel`)?(w=e=>{e.preventDefault(),_(!0)},t[6]=w):w=t[6];let ee=a?`border-border/50 bg-[var(--surface-elevated)]`:`border-transparent hover:bg-interactive-hover`,T=!o&&`opacity-65`,E;t[7]!==ee||t[8]!==T?(E=R(`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`,ee,T),t[7]=ee,t[8]=T,t[9]=E):E=t[9];let D;t[10]!==y||t[11]!==a||t[12]!==E?(D=(0,Y.jsx)(`button`,{type:`button`,role:`option`,"aria-selected":a,onClick:y,onContextMenu:w,className:E}),t[10]=y,t[11]=a,t[12]=E,t[13]=D):D=t[13];let O;t[14]!==n||t[15]!==i||t[16]!==r||t[17]!==h?(O=(0,Y.jsx)(le,{name:n,emoji:i,size:24,label:r,working:h}),t[14]=n,t[15]=i,t[16]=r,t[17]=h,t[18]=O):O=t[18];let k;t[19]===r?k=t[20]:(k=(0,Y.jsx)(`span`,{className:`min-w-0 flex-1`,children:(0,Y.jsx)(`span`,{className:`block truncate typography-ui-label font-medium`,children:r})}),t[19]=r,t[20]=k);let A;t[21]!==D||t[22]!==O||t[23]!==k?(A=(0,Y.jsxs)(G,{render:D,children:[O,k]}),t[21]=D,t[22]=O,t[23]=k,t[24]=A):A=t[24];let j;t[25]===Symbol.for(`react.memo_cache_sentinel`)?(j=(0,Y.jsx)(B,{name:`edit`,className:`size-4`}),t[25]=j):j=t[25];let M;t[26]!==s||t[27]!==x?(M=(0,Y.jsxs)(oe,{onClick:x,children:[j,s]}),t[26]=s,t[27]=x,t[28]=M):M=t[28];let N;t[29]===Symbol.for(`react.memo_cache_sentinel`)?(N=(0,Y.jsx)(ae,{}),t[29]=N):N=t[29];let P;t[30]===Symbol.for(`react.memo_cache_sentinel`)?(P=(0,Y.jsx)(B,{name:`delete-bin`,className:`size-4`}),t[30]=P):P=t[30];let F;t[31]!==c||t[32]!==C?(F=(0,Y.jsxs)(oe,{onClick:C,className:`text-[var(--status-error)] focus:text-[var(--status-error)] data-[highlighted]:text-[var(--status-error)] [&_svg]:text-[var(--status-error)]`,children:[P,c]}),t[31]=c,t[32]=C,t[33]=F):F=t[33];let I;t[34]!==M||t[35]!==F?(I=(0,Y.jsxs)(K,{className:`min-w-[10rem]`,children:[M,N,F]}),t[34]=M,t[35]=F,t[36]=I):I=t[36];let L;return t[37]!==g||t[38]!==A||t[39]!==I?(L=(0,Y.jsxs)(se,{open:g,onOpenChange:_,children:[A,I]}),t[37]=g,t[38]=A,t[39]=I,t[40]=L):L=t[40],L},nt=e=>{let t=(0,q.c)(109),{activeOverride:a,onMobileBack:o}=e,{t:s}=p(),{isMobile:c}=H(),l=W(),u=J.useSyncExternalStore(n,r,r),d=i(rt),h=a??d,g=i(it),_=c||g,v=w(),y=ee(),b=y.data,x;t[0]===u?x=t[1]:(x=e=>e.assistantByTransport[u]??null,t[0]=u,t[1]=x);let S=k(x),C=k(at),T=k(ot),E;t[2]!==S||t[3]!==b?.assistants?(E=b?.assistants.find(e=>e.id===S)??null,t[2]=S,t[3]=b?.assistants,t[4]=E):E=t[4];let D=E,O;t[5]!==C||t[6]!==S||t[7]!==b?(O=()=>{!S&&b?.assistants[0]&&C(b.assistants[0].id)},t[5]=C,t[6]=S,t[7]=b,t[8]=O):O=t[8];let A=b?.assistants,M;t[9]!==C||t[10]!==S||t[11]!==A?(M=[C,S,A],t[9]=C,t[10]=S,t[11]=A,t[12]=M):M=t[12],J.useEffect(O,M);let N;t[13]!==D||t[14]!==C||t[15]!==S||t[16]!==b?.assistants||t[17]!==y.isSuccess?(N=()=>{y.isSuccess&&S&&!D&&C(b?.assistants[0]?.id??null)},t[13]=D,t[14]=C,t[15]=S,t[16]=b?.assistants,t[17]=y.isSuccess,t[18]=N):N=t[18];let P=b?.assistants,F;t[19]!==D||t[20]!==C||t[21]!==S||t[22]!==y.isSuccess||t[23]!==P?(F=[D,C,S,P,y.isSuccess],t[19]=D,t[20]=C,t[21]=S,t[22]=y.isSuccess,t[23]=P,t[24]=F):F=t[24],J.useEffect(N,F);let I;t[25]!==l||t[26]!==T?(I=()=>{if(T(),l){l.openSettings();return}let e=i.getState();e.setSettingsPage(`assistants`),e.setSettingsDialogOpen(!0)},t[25]=l,t[26]=T,t[27]=I):I=t[27];let L=f(I),z;t[28]===l?z=t[29]:(z=e=>{j(e,l?{openMobileSettings:l.openSettings}:void 0)},t[28]=l,t[29]=z);let U=f(z),te;t[30]!==D||t[31]!==l?(te=()=>{D&&j(D.id,l?{openMobileSettings:l.openSettings}:void 0)},t[30]=D,t[31]=l,t[32]=te):te=t[32];let ne=f(te),[re,ie]=J.useState(null),G;t[33]===Symbol.for(`react.memo_cache_sentinel`)?(G=e=>{ie(e)},t[33]=G):G=t[33];let ae=f(G),K;t[34]===Symbol.for(`react.memo_cache_sentinel`)?(K=e=>{e||ie(null)},t[34]=K):K=t[34];let oe=f(K),se=f(st),ce;t[35]!==o||t[36]!==se?(ce=()=>{if(o){o();return}se()},t[35]=o,t[36]=se,t[37]=ce):ce=t[37];let X=f(ce),ue=Qe({capabilityPending:v.isPending,snapshotPending:y.isPending,capabilityError:v.isError,supported:v.data?.supported,capabilityEnabled:v.data?.enabled,snapshotEnabled:b?.enabled,snapshotSettled:y.isSuccess,assistantCount:b?.assistants.length??0,hasAssistant:!!D}),de;t[38]!==D||t[39]!==X||t[40]!==_?(de=(e,t,n,r)=>(0,Y.jsxs)(`div`,{className:`relative flex h-full min-h-0 flex-col`,children:[_?(0,Y.jsx)(et,{assistant:D,onBack:X}):null,(0,Y.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,Y.jsx)(B,{name:e,className:`size-6 text-muted-foreground`}),(0,Y.jsx)(`h1`,{className:`mt-4 typography-ui-header font-semibold`,children:t}),n?(0,Y.jsx)(`p`,{className:`mt-2 max-w-md typography-ui text-muted-foreground`,children:n}):null,r?(0,Y.jsx)(`div`,{className:`mt-5`,children:r}):null]})]}),t[38]=D,t[39]=X,t[40]=_,t[41]=de):de=t[41];let Z=de;if(ue===`loading`){let e;t[42]!==D||t[43]!==X||t[44]!==_?(e=_?(0,Y.jsx)(et,{assistant:D,onBack:X}):null,t[42]=D,t[43]=X,t[44]=_,t[45]=e):e=t[45];let n;t[46]===s?n=t[47]:(n=s(`common.loading`),t[46]=s,t[47]=n);let r;t[48]===Symbol.for(`react.memo_cache_sentinel`)?(r=(0,Y.jsx)(B,{name:`loader-4`,className:`size-6 animate-spin text-muted-foreground`}),t[48]=r):r=t[48];let i;t[49]===n?i=t[50]:(i=(0,Y.jsx)(`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`,"aria-busy":`true`,"aria-label":n,"data-assistant-workspace-loading":``,children:r}),t[49]=n,t[50]=i);let a;return t[51]!==e||t[52]!==i?(a=(0,Y.jsxs)(`div`,{className:`relative flex h-full min-h-0 flex-col`,children:[e,i]}),t[51]=e,t[52]=i,t[53]=a):a=t[53],a}if(ue===`unavailable`){let e;return t[54]!==Z||t[55]!==s?(e=Z(`cloud-off`,s(`assistants.state.unavailable`)),t[54]=Z,t[55]=s,t[56]=e):e=t[56],e}if(ue===`onboarding`){let e;if(t[57]!==L||t[58]!==Z||t[59]!==s){let n=s(`assistants.onboarding.title`),r=s(`assistants.onboarding.description`),i;t[61]===s?i=t[62]:(i=s(`assistants.onboarding.action`),t[61]=s,t[62]=i);let a;t[63]!==L||t[64]!==i?(a=(0,Y.jsx)(V,{onClick:L,children:i}),t[63]=L,t[64]=i,t[65]=a):a=t[65],e=Z(`ai-agent`,n,r,a),t[57]=L,t[58]=Z,t[59]=s,t[60]=e}else e=t[60];return e}if(!b||!D){let e;return t[66]!==Z||t[67]!==s?(e=Z(`cloud-off`,s(`assistants.state.unavailable`)),t[66]=Z,t[67]=s,t[68]=e):e=t[68],e}let fe;t[69]===D.name?fe=t[70]:(fe=m(D.name),t[69]=D.name,t[70]=fe);let pe=fe,me;t[71]!==D.enabled||t[72]!==y.isError||t[73]!==s?(me=D.enabled?y.isError?s(`assistants.state.staleSnapshot`):null:s(`assistants.state.assistantDisabled`),t[71]=D.enabled,t[72]=y.isError,t[73]=s,t[74]=me):me=t[74];let he=me,Q;t[75]!==_||t[76]!==U||t[77]!==ae||t[78]!==C||t[79]!==S||t[80]!==b||t[81]!==s?(Q=_?null:(0,Y.jsxs)(`section`,{className:`flex h-full min-h-0 w-[clamp(16rem,22vw,20rem)] shrink-0 flex-col overflow-hidden`,children:[(0,Y.jsx)(`header`,{className:`shrink-0 px-4 pb-3 pt-4 sm:px-5`,children:(0,Y.jsx)(`h1`,{className:`truncate typography-ui-label font-semibold text-foreground`,children:s(`assistants.title`)})}),(0,Y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-3 pb-4 sm:px-4`,role:`listbox`,"aria-label":s(`assistants.listAria`),children:(0,Y.jsx)(`div`,{className:`flex flex-col gap-1 border-t border-border/40 pt-3`,children:b.assistants.map(e=>{let t=e.id===S,n=m(e.name);return(0,Y.jsx)(tt,{assistantID:e.id,displayName:n.displayName,avatarEmoji:n.avatarEmoji??void 0,selected:t,enabled:e.enabled,editLabel:s(`assistants.menu.edit`),deleteLabel:s(`assistants.settings.delete`),assignedSessionIDs:e.assignedSessionIDs,serverWorking:e.working,onSelect:()=>C(e.id),onEdit:()=>U(e.id),onDelete:()=>ae(e)},e.id)})})})]}),t[75]=_,t[76]=U,t[77]=ae,t[78]=C,t[79]=S,t[80]=b,t[81]=s,t[82]=Q):Q=t[82];let ge=re!==null,_e;t[83]!==re||t[84]!==oe||t[85]!==ge?(_e=(0,Y.jsx)(Ze,{assistant:re,open:ge,onOpenChange:oe}),t[83]=re,t[84]=oe,t[85]=ge,t[86]=_e):_e=t[86];let ve=!_&&`border-l border-[var(--surface-subtle)]`,ye;t[87]===ve?ye=t[88]:(ye=R(`relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background`,ve),t[87]=ve,t[88]=ye);let $;t[89]!==D||t[90]!==X||t[91]!==_||t[92]!==ne||t[93]!==pe||t[94]!==s?($=_?(0,Y.jsx)(et,{assistant:D,onBack:X}):(0,Y.jsxs)(`header`,{className:`flex h-16 shrink-0 items-center gap-3.5 border-b border-[var(--surface-subtle)]/70 px-5 sm:px-7`,children:[(0,Y.jsx)(le,{name:D.id,emoji:pe.avatarEmoji,size:30,label:pe.displayName||D.name}),(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Y.jsx)(`div`,{className:`truncate typography-ui-label font-semibold tracking-[-0.01em] text-foreground`,children:pe.displayName}),(0,Y.jsx)(`div`,{className:`mt-1 truncate typography-micro leading-none text-muted-foreground/55`,children:s(`assistants.conversation.contactHint`)})]}),(0,Y.jsx)(V,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 shrink-0 rounded-full text-muted-foreground/65 transition-colors hover:text-foreground`,onClick:ne,"aria-label":s(`assistants.conversation.openSettings`),children:(0,Y.jsx)(B,{name:`settings-3`,className:`size-4`})})]}),t[89]=D,t[90]=X,t[91]=_,t[92]=ne,t[93]=pe,t[94]=s,t[95]=$):$=t[95];let be;t[96]!==h||t[97]!==D||t[98]!==_||t[99]!==he?(be=(0,Y.jsx)(Ye,{assistant:D,warning:he,active:h,overlayHeader:_}),t[96]=h,t[97]=D,t[98]=_,t[99]=he,t[100]=be):be=t[100];let xe;t[101]!==ye||t[102]!==$||t[103]!==be?(xe=(0,Y.jsxs)(`div`,{className:ye,children:[$,be]}),t[101]=ye,t[102]=$,t[103]=be,t[104]=xe):xe=t[104];let Se;return t[105]!==Q||t[106]!==_e||t[107]!==xe?(Se=(0,Y.jsxs)(`div`,{className:`relative flex h-full min-h-0 overflow-hidden bg-background`,"data-presentation":`workspace`,children:[Q,_e,xe]}),t[105]=Q,t[106]=_e,t[107]=xe,t[108]=Se):Se=t[108],Se};function rt(e){return e.activeMainTab===`assistant`}function it(e){return e.isMobile}function at(e){return e.selectAssistant}function ot(e){return e.requestCreate}function st(){i.getState().setActiveMainTab(`chat`)}export{le as a,de as i,$e as n,Ze as r,nt as t};
|