sparkecoder 0.1.52 → 0.1.54
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/agent/index.d.ts +2 -2
- package/dist/{index-dJv_dqUq.d.ts → index-BYOHniN4.d.ts} +5 -5
- package/dist/index.d.ts +3 -3
- package/dist/{search-DrztQ_iP.d.ts → search-DALwmPRX.d.ts} +5 -5
- package/dist/tools/index.d.ts +2 -2
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/(main)/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/api/config/route.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/api/health/route.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/embed/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/embed/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_40c1da73._.js → 2374f_06a5ea48._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_ec658806._.js → 2374f_2572135b._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_c8f8a326._.js → 2374f_273991ba._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_13da7b2a._.js → 2374f_460c0d78._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_1de2f628._.js → 2374f_5ee28d4c._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_9f2fae06._.js → 2374f_65b86b54._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_f3c65774._.js → 2374f_7b421f78._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_41d07cce._.js → 2374f_88cbeb7b._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_2bfcd3a2._.js → 2374f_8d018190._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_e5142825._.js → 2374f_a7457131._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_dd21a4e9._.js → 2374f_c9e3cd7b._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_88aa1671._.js → 2374f_de035f79._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_ac79ddf4._.js → 2374f_df3c414e._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_6d8e5e94._.js → 2374f_ec997752._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__a87e1c27._.js +3 -3
- package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__43405ad6._.js → [root-of-the-server]__c94aac98._.js} +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/{web_273500a6._.js → web_9c9f0e3b._.js} +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/{web_329773d1._.js → web_b85931da._.js} +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/{web_8305f089._.js → web_d08270f7._.js} +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_src_components_sessions-sidebar_tsx_92510070._.js +1 -1
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/standalone/web/.next/static/chunks/3f295b6960943c38.js +1 -0
- package/web/.next/standalone/web/.next/static/chunks/{e69c4473f80e8752.js → 9b4c4424a720586b.js} +6 -6
- package/web/.next/standalone/web/.next/static/chunks/a2b4737b190d1b54.js +5 -0
- package/web/.next/{static/chunks/b7d722dab2a7ecc0.js → standalone/web/.next/static/chunks/e97212fcc8221479.js} +2 -2
- package/web/.next/standalone/web/.next/static/chunks/f6e47c8a9766ce91.js +7 -0
- package/web/.next/standalone/web/.next/static/static/chunks/3f295b6960943c38.js +1 -0
- package/web/.next/standalone/web/.next/static/static/chunks/{e69c4473f80e8752.js → 9b4c4424a720586b.js} +6 -6
- package/web/.next/standalone/web/.next/static/static/chunks/a2b4737b190d1b54.js +5 -0
- package/web/.next/standalone/web/.next/static/static/chunks/{b7d722dab2a7ecc0.js → e97212fcc8221479.js} +2 -2
- package/web/.next/standalone/web/.next/static/static/chunks/f6e47c8a9766ce91.js +7 -0
- package/web/.next/standalone/web/src/components/ai-elements/search-tool.tsx +26 -3
- package/web/.next/standalone/web/src/components/ai-elements/subagent-modal.tsx +13 -1
- package/web/.next/standalone/web/src/components/chat-interface.tsx +79 -74
- package/web/.next/standalone/web/src/components/sessions-sidebar.tsx +23 -1
- package/web/.next/standalone/web/src/hooks/use-notification-sound.ts +78 -0
- package/web/.next/static/chunks/3f295b6960943c38.js +1 -0
- package/web/.next/static/chunks/{e69c4473f80e8752.js → 9b4c4424a720586b.js} +6 -6
- package/web/.next/static/chunks/a2b4737b190d1b54.js +5 -0
- package/web/.next/{standalone/web/.next/static/chunks/b7d722dab2a7ecc0.js → static/chunks/e97212fcc8221479.js} +2 -2
- package/web/.next/static/chunks/f6e47c8a9766ce91.js +7 -0
- package/web/.next/standalone/web/.next/static/chunks/96ec96279ada0efe.js +0 -1
- package/web/.next/standalone/web/.next/static/chunks/cc6d43f798bbe415.js +0 -5
- package/web/.next/standalone/web/.next/static/chunks/de71e63276f488bb.js +0 -7
- package/web/.next/standalone/web/.next/static/static/chunks/96ec96279ada0efe.js +0 -1
- package/web/.next/standalone/web/.next/static/static/chunks/cc6d43f798bbe415.js +0 -5
- package/web/.next/standalone/web/.next/static/static/chunks/de71e63276f488bb.js +0 -7
- package/web/.next/static/chunks/96ec96279ada0efe.js +0 -1
- package/web/.next/static/chunks/cc6d43f798bbe415.js +0 -5
- package/web/.next/static/chunks/de71e63276f488bb.js +0 -7
- /package/web/.next/standalone/web/.next/static/{TLPvH3fh2g6xnXoqOVcq8 → 7rKMR1VNC_1_vH6S9H5aS}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{TLPvH3fh2g6xnXoqOVcq8 → 7rKMR1VNC_1_vH6S9H5aS}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{TLPvH3fh2g6xnXoqOVcq8 → 7rKMR1VNC_1_vH6S9H5aS}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{TLPvH3fh2g6xnXoqOVcq8 → 7rKMR1VNC_1_vH6S9H5aS}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{TLPvH3fh2g6xnXoqOVcq8 → 7rKMR1VNC_1_vH6S9H5aS}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{TLPvH3fh2g6xnXoqOVcq8 → 7rKMR1VNC_1_vH6S9H5aS}/_ssgManifest.js +0 -0
- /package/web/.next/static/{TLPvH3fh2g6xnXoqOVcq8 → 7rKMR1VNC_1_vH6S9H5aS}/_buildManifest.js +0 -0
- /package/web/.next/static/{TLPvH3fh2g6xnXoqOVcq8 → 7rKMR1VNC_1_vH6S9H5aS}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{TLPvH3fh2g6xnXoqOVcq8 → 7rKMR1VNC_1_vH6S9H5aS}/_ssgManifest.js +0 -0
|
@@ -116,6 +116,7 @@ import {
|
|
|
116
116
|
import { TodoPanel } from '@/components/ai-elements/todo-panel';
|
|
117
117
|
import { getConfig, type AppConfig } from '@/lib/config';
|
|
118
118
|
import { mutateSessions } from '@/hooks/use-sessions';
|
|
119
|
+
import { useNotificationSound } from '@/hooks/use-notification-sound';
|
|
119
120
|
import {
|
|
120
121
|
Select,
|
|
121
122
|
SelectContent,
|
|
@@ -368,6 +369,10 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
|
|
|
368
369
|
const [pendingSelectedElements, setPendingSelectedElements] = useState<string | null>(null);
|
|
369
370
|
const [isRunning, setIsRunning] = useState(false);
|
|
370
371
|
const [messageQueue, setMessageQueue] = useState<QueuedMessage[]>([]);
|
|
372
|
+
// Ref mirror of messageQueue so SSE event handlers can read the latest queue
|
|
373
|
+
// without stale closures. Updated on every render.
|
|
374
|
+
const messageQueueRef = useRef<QueuedMessage[]>([]);
|
|
375
|
+
messageQueueRef.current = messageQueue;
|
|
371
376
|
const [editingQueueId, setEditingQueueId] = useState<string | null>(null);
|
|
372
377
|
const [editingQueueText, setEditingQueueText] = useState('');
|
|
373
378
|
const [queueExpanded, setQueueExpanded] = useState(true);
|
|
@@ -409,6 +414,9 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
|
|
|
409
414
|
const sessionIdRef = useRef(session.id);
|
|
410
415
|
sessionIdRef.current = session.id;
|
|
411
416
|
|
|
417
|
+
// Notification sound
|
|
418
|
+
const { playDing } = useNotificationSound();
|
|
419
|
+
|
|
412
420
|
// Version check state
|
|
413
421
|
const [versionInfo, setVersionInfo] = useState<VersionInfo | null>(null);
|
|
414
422
|
const [updateBannerDismissed, setUpdateBannerDismissed] = useState(false);
|
|
@@ -1051,15 +1059,40 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
|
|
|
1051
1059
|
setCurrentText('');
|
|
1052
1060
|
}
|
|
1053
1061
|
|
|
1054
|
-
//
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1062
|
+
// Check if there's already a placeholder for this tool type
|
|
1063
|
+
// (created from early tool-progress events before this SSE arrives)
|
|
1064
|
+
{
|
|
1065
|
+
const placeholderPrefix = `${event.toolName}_pending_`;
|
|
1066
|
+
const existingPlaceholder = toolCallsRef.current.find(
|
|
1067
|
+
tc => tc.toolName === event.toolName && tc.toolCallId.startsWith(placeholderPrefix)
|
|
1068
|
+
);
|
|
1069
|
+
const alreadyExists = toolCallsRef.current.some(tc => tc.toolCallId === event.toolCallId);
|
|
1070
|
+
|
|
1071
|
+
if (existingPlaceholder) {
|
|
1072
|
+
// Replace placeholder with real tool call, preserving accumulated data
|
|
1073
|
+
toolCallsRef.current = toolCallsRef.current.map((tc) => {
|
|
1074
|
+
if (tc.toolCallId !== existingPlaceholder.toolCallId) return tc;
|
|
1075
|
+
return {
|
|
1076
|
+
...tc,
|
|
1077
|
+
toolCallId: event.toolCallId,
|
|
1078
|
+
toolName: event.toolName,
|
|
1079
|
+
status: 'streaming' as const,
|
|
1080
|
+
streamingArgsText: '',
|
|
1081
|
+
};
|
|
1082
|
+
});
|
|
1083
|
+
} else if (!alreadyExists) {
|
|
1084
|
+
// Create a new streaming tool call
|
|
1085
|
+
const streamingToolCall: ToolCallInfo = {
|
|
1086
|
+
toolCallId: event.toolCallId,
|
|
1087
|
+
toolName: event.toolName,
|
|
1088
|
+
input: {},
|
|
1089
|
+
status: 'streaming' as const,
|
|
1090
|
+
streamingArgsText: '',
|
|
1091
|
+
};
|
|
1092
|
+
toolCallsRef.current = [...toolCallsRef.current, streamingToolCall];
|
|
1093
|
+
}
|
|
1094
|
+
// If alreadyExists, do nothing - tool-input-available will update it
|
|
1095
|
+
}
|
|
1063
1096
|
setCurrentToolCalls([...toolCallsRef.current]);
|
|
1064
1097
|
break;
|
|
1065
1098
|
|
|
@@ -1110,19 +1143,20 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
|
|
|
1110
1143
|
setCurrentText('');
|
|
1111
1144
|
}
|
|
1112
1145
|
|
|
1113
|
-
// Create/update the tool call info, preserving live content from
|
|
1146
|
+
// Create/update the tool call info, preserving live content from any source
|
|
1147
|
+
// (placeholder, existing streaming entry, or tool-input-start entry)
|
|
1114
1148
|
const toolCallInfo: ToolCallInfo = {
|
|
1115
1149
|
toolCallId: event.toolCallId,
|
|
1116
1150
|
toolName: event.toolName,
|
|
1117
1151
|
input: event.input,
|
|
1118
1152
|
status: 'running' as const,
|
|
1119
1153
|
streamingArgsText: existingToolCall?.streamingArgsText,
|
|
1120
|
-
// Preserve live content from
|
|
1121
|
-
liveContent: placeholderWriteFile?.liveContent,
|
|
1122
|
-
liveOldString: placeholderWriteFile?.liveOldString,
|
|
1123
|
-
liveNewString: placeholderWriteFile?.liveNewString,
|
|
1124
|
-
// Preserve explore steps from
|
|
1125
|
-
exploreSteps: placeholderExplore?.exploreSteps,
|
|
1154
|
+
// Preserve live content from whatever source has it
|
|
1155
|
+
liveContent: placeholderWriteFile?.liveContent || existingToolCall?.liveContent,
|
|
1156
|
+
liveOldString: placeholderWriteFile?.liveOldString || existingToolCall?.liveOldString,
|
|
1157
|
+
liveNewString: placeholderWriteFile?.liveNewString || existingToolCall?.liveNewString,
|
|
1158
|
+
// Preserve explore steps from whatever source has them
|
|
1159
|
+
exploreSteps: placeholderExplore?.exploreSteps || existingToolCall?.exploreSteps,
|
|
1126
1160
|
};
|
|
1127
1161
|
|
|
1128
1162
|
// Update toolCallsRef
|
|
@@ -1287,26 +1321,33 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
|
|
|
1287
1321
|
// Don't reset lastKnownStreamIdRef here - it helps prevent reconnecting to same stream
|
|
1288
1322
|
setIsRunning(false);
|
|
1289
1323
|
setIsWatching(false);
|
|
1324
|
+
playDing();
|
|
1290
1325
|
|
|
1291
|
-
//
|
|
1292
|
-
// This ensures messages have proper messageSequence for the revert button.
|
|
1293
|
-
// We DON'T clear chatItems first - the current items stay visible until
|
|
1294
|
-
// the API response arrives, preventing the "flash" where everything disappears.
|
|
1326
|
+
// Only refresh checkpoints (for revert buttons) - NOT chatItems.
|
|
1295
1327
|
{
|
|
1296
1328
|
const finishSessionId = session.id;
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1329
|
+
getSessionCheckpoints(finishSessionId)
|
|
1330
|
+
.then((checkpointsData) => {
|
|
1331
|
+
if (sessionIdRef.current !== finishSessionId) return;
|
|
1332
|
+
setCheckpoints(checkpointsData.checkpoints || []);
|
|
1333
|
+
})
|
|
1334
|
+
.catch(() => {});
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
// Send next queued message directly from the finish event.
|
|
1338
|
+
// This is the correct place to do it: one event → one send.
|
|
1339
|
+
// No useEffect, no timers, no race conditions.
|
|
1340
|
+
{
|
|
1341
|
+
const queue = messageQueueRef.current;
|
|
1342
|
+
if (queue.length > 0) {
|
|
1343
|
+
const next = queue[0];
|
|
1344
|
+
setMessageQueue((prev) => prev.slice(1));
|
|
1345
|
+
// Small delay so React can commit the state reset above first,
|
|
1346
|
+
// then start the new stream in a fresh render cycle
|
|
1347
|
+
setTimeout(() => {
|
|
1348
|
+
executeSubmitRef.current(next.text, next.attachments, next.selectedElements);
|
|
1349
|
+
}, 50);
|
|
1350
|
+
}
|
|
1310
1351
|
}
|
|
1311
1352
|
break;
|
|
1312
1353
|
|
|
@@ -1848,46 +1889,12 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
|
|
|
1848
1889
|
setIsWatching(false);
|
|
1849
1890
|
};
|
|
1850
1891
|
|
|
1851
|
-
//
|
|
1852
|
-
// latest version (avoids stale closure capturing old handleSSEEvent, etc.)
|
|
1892
|
+
// Ref to executeSubmit so SSE handlers and sendNow can always call the latest version
|
|
1853
1893
|
const executeSubmitRef = useRef(executeSubmit);
|
|
1854
1894
|
executeSubmitRef.current = executeSubmit;
|
|
1855
|
-
|
|
1856
|
-
//
|
|
1857
|
-
|
|
1858
|
-
const skipAutoSendRef = useRef(false); // Set by sendNow to prevent double-send
|
|
1859
|
-
useEffect(() => {
|
|
1860
|
-
const wasRunning = prevIsRunningRef.current;
|
|
1861
|
-
prevIsRunningRef.current = isRunning;
|
|
1862
|
-
|
|
1863
|
-
// Auto-send whenever we're idle and there are queued messages.
|
|
1864
|
-
// This covers both:
|
|
1865
|
-
// 1. Agent just finished (wasRunning=true → isRunning=false) with a queue
|
|
1866
|
-
// 2. Queue got a new item while already idle (e.g., agent finished BEFORE
|
|
1867
|
-
// the user queued a message, so the running→stopped transition was missed)
|
|
1868
|
-
// Safe because executeSubmit sets isRunning=true, preventing re-entry
|
|
1869
|
-
// until the next agent response finishes.
|
|
1870
|
-
const shouldAutoSend = !isRunning && messageQueue.length > 0;
|
|
1871
|
-
|
|
1872
|
-
if (shouldAutoSend) {
|
|
1873
|
-
// If sendNow triggered the stop, skip auto-send (it handles its own send)
|
|
1874
|
-
if (skipAutoSendRef.current) {
|
|
1875
|
-
skipAutoSendRef.current = false;
|
|
1876
|
-
return;
|
|
1877
|
-
}
|
|
1878
|
-
// Small delay to let UI settle
|
|
1879
|
-
const timer = setTimeout(() => {
|
|
1880
|
-
setMessageQueue((prev) => {
|
|
1881
|
-
if (prev.length === 0) return prev;
|
|
1882
|
-
const [next, ...rest] = prev;
|
|
1883
|
-
// Use ref to always call the latest executeSubmit (not a stale closure)
|
|
1884
|
-
executeSubmitRef.current(next.text, next.attachments, next.selectedElements);
|
|
1885
|
-
return rest;
|
|
1886
|
-
});
|
|
1887
|
-
}, 300);
|
|
1888
|
-
return () => clearTimeout(timer);
|
|
1889
|
-
}
|
|
1890
|
-
}, [isRunning, messageQueue.length]);
|
|
1895
|
+
|
|
1896
|
+
// Note: Queue auto-send is handled directly in the 'finish' SSE event handler,
|
|
1897
|
+
// not via useEffect. This avoids timers, stale closures, and double-fires.
|
|
1891
1898
|
|
|
1892
1899
|
// Queue management helpers
|
|
1893
1900
|
const removeFromQueue = (id: string) => {
|
|
@@ -1924,11 +1931,9 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
|
|
|
1924
1931
|
// Remove from queue
|
|
1925
1932
|
setMessageQueue((prev) => prev.filter((m) => m.id !== id));
|
|
1926
1933
|
|
|
1927
|
-
// Stop current if running
|
|
1934
|
+
// Stop current if running, then send after it settles
|
|
1928
1935
|
if (isRunning) {
|
|
1929
|
-
skipAutoSendRef.current = true; // Prevent auto-send from firing
|
|
1930
1936
|
await handleStop();
|
|
1931
|
-
// Wait for stop to settle, then send using ref for fresh closure
|
|
1932
1937
|
setTimeout(() => {
|
|
1933
1938
|
executeSubmitRef.current(item.text, item.attachments, item.selectedElements);
|
|
1934
1939
|
}, 500);
|
|
@@ -4,7 +4,7 @@ import { useState, useEffect, useRef } from 'react';
|
|
|
4
4
|
import { useRouter, usePathname } from 'next/navigation';
|
|
5
5
|
import Link from 'next/link';
|
|
6
6
|
import Image from 'next/image';
|
|
7
|
-
import { Plus, MessageSquare, Trash2, Loader2, Settings, PanelLeftClose, PanelLeft, Key, Check, X, Eye, EyeOff } from 'lucide-react';
|
|
7
|
+
import { Plus, MessageSquare, Trash2, Loader2, Settings, PanelLeftClose, PanelLeft, Key, Check, X, Eye, EyeOff, Volume2 } from 'lucide-react';
|
|
8
8
|
import {
|
|
9
9
|
Sidebar,
|
|
10
10
|
SidebarContent,
|
|
@@ -45,6 +45,7 @@ import { createSession, deleteSession, getApiKeys, setApiKey, type ApiKeyStatus
|
|
|
45
45
|
import { getConfig, type AppConfig } from '@/lib/config';
|
|
46
46
|
import { cn } from '@/lib/utils';
|
|
47
47
|
import { useSessions, mutateSessions } from '@/hooks/use-sessions';
|
|
48
|
+
import { useNotificationSound } from '@/hooks/use-notification-sound';
|
|
48
49
|
|
|
49
50
|
// Format relative time like "2m", "1h", "3d"
|
|
50
51
|
function formatRelativeTime(dateString: string): string {
|
|
@@ -87,6 +88,9 @@ export function SessionsSidebar() {
|
|
|
87
88
|
const [showApiKey, setShowApiKey] = useState(false);
|
|
88
89
|
const [savingApiKey, setSavingApiKey] = useState(false);
|
|
89
90
|
|
|
91
|
+
// Notification sound setting
|
|
92
|
+
const { enabled: soundEnabled, setEnabled: setSoundEnabled } = useNotificationSound();
|
|
93
|
+
|
|
90
94
|
// Detect if we're in embed mode
|
|
91
95
|
const isEmbedMode = pathname.startsWith('/embed/');
|
|
92
96
|
|
|
@@ -828,6 +832,24 @@ export function SessionsSidebar() {
|
|
|
828
832
|
</div>
|
|
829
833
|
</div>
|
|
830
834
|
|
|
835
|
+
{/* Notification Sound */}
|
|
836
|
+
<div className="space-y-1.5">
|
|
837
|
+
<Label className="flex items-center gap-2 text-sm font-medium">
|
|
838
|
+
<Volume2 className="size-4" />
|
|
839
|
+
Notification Sound
|
|
840
|
+
</Label>
|
|
841
|
+
<div className="flex items-center justify-between rounded-lg border p-2.5 bg-muted/30">
|
|
842
|
+
<div className="space-y-0">
|
|
843
|
+
<span className="text-sm font-medium">Play sound when done</span>
|
|
844
|
+
<p className="text-[11px] text-muted-foreground">Ding when the assistant finishes responding</p>
|
|
845
|
+
</div>
|
|
846
|
+
<Switch
|
|
847
|
+
checked={soundEnabled}
|
|
848
|
+
onCheckedChange={setSoundEnabled}
|
|
849
|
+
/>
|
|
850
|
+
</div>
|
|
851
|
+
</div>
|
|
852
|
+
|
|
831
853
|
<p className="text-xs text-muted-foreground">
|
|
832
854
|
These settings apply to new sessions. You can also change the model per-session in the chat header.
|
|
833
855
|
</p>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useCallback, useRef, useEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
const STORAGE_KEY = 'sparkecoder_notification_sound';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Synthesize a pleasant two-tone "ding" using the Web Audio API.
|
|
9
|
+
* No audio file needed – it generates the tones on the fly.
|
|
10
|
+
*/
|
|
11
|
+
function playDingSound() {
|
|
12
|
+
try {
|
|
13
|
+
const ctx = new (window.AudioContext || (window as any).webkitAudioContext)();
|
|
14
|
+
|
|
15
|
+
// --- first tone (higher, shorter) ---
|
|
16
|
+
const osc1 = ctx.createOscillator();
|
|
17
|
+
const gain1 = ctx.createGain();
|
|
18
|
+
osc1.type = 'sine';
|
|
19
|
+
osc1.frequency.setValueAtTime(880, ctx.currentTime); // A5
|
|
20
|
+
gain1.gain.setValueAtTime(0.3, ctx.currentTime);
|
|
21
|
+
gain1.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.3);
|
|
22
|
+
osc1.connect(gain1);
|
|
23
|
+
gain1.connect(ctx.destination);
|
|
24
|
+
osc1.start(ctx.currentTime);
|
|
25
|
+
osc1.stop(ctx.currentTime + 0.3);
|
|
26
|
+
|
|
27
|
+
// --- second tone (slightly higher, slightly delayed) ---
|
|
28
|
+
const osc2 = ctx.createOscillator();
|
|
29
|
+
const gain2 = ctx.createGain();
|
|
30
|
+
osc2.type = 'sine';
|
|
31
|
+
osc2.frequency.setValueAtTime(1174.66, ctx.currentTime + 0.15); // D6
|
|
32
|
+
gain2.gain.setValueAtTime(0.0001, ctx.currentTime);
|
|
33
|
+
gain2.gain.setValueAtTime(0.25, ctx.currentTime + 0.15);
|
|
34
|
+
gain2.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.5);
|
|
35
|
+
osc2.connect(gain2);
|
|
36
|
+
gain2.connect(ctx.destination);
|
|
37
|
+
osc2.start(ctx.currentTime + 0.15);
|
|
38
|
+
osc2.stop(ctx.currentTime + 0.5);
|
|
39
|
+
|
|
40
|
+
// Clean up context after the sound finishes
|
|
41
|
+
setTimeout(() => ctx.close(), 600);
|
|
42
|
+
} catch {
|
|
43
|
+
// Silently ignore – e.g. if AudioContext isn't available
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Hook to manage the notification sound setting and playback.
|
|
49
|
+
*
|
|
50
|
+
* - `enabled` / `setEnabled` – toggle stored in localStorage
|
|
51
|
+
* - `playDing()` – plays the ding only when enabled
|
|
52
|
+
*/
|
|
53
|
+
export function useNotificationSound() {
|
|
54
|
+
const [enabled, setEnabledState] = useState(() => {
|
|
55
|
+
if (typeof window === 'undefined') return true;
|
|
56
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
57
|
+
return stored === null ? true : stored === 'true'; // default ON
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Keep a ref so callbacks that capture stale closures still see the latest value
|
|
61
|
+
const enabledRef = useRef(enabled);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
enabledRef.current = enabled;
|
|
64
|
+
}, [enabled]);
|
|
65
|
+
|
|
66
|
+
const setEnabled = useCallback((value: boolean) => {
|
|
67
|
+
setEnabledState(value);
|
|
68
|
+
localStorage.setItem(STORAGE_KEY, String(value));
|
|
69
|
+
}, []);
|
|
70
|
+
|
|
71
|
+
const playDing = useCallback(() => {
|
|
72
|
+
if (enabledRef.current) {
|
|
73
|
+
playDingSound();
|
|
74
|
+
}
|
|
75
|
+
}, []);
|
|
76
|
+
|
|
77
|
+
return { enabled, setEnabled, playDing } as const;
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,819609,(e,t,s)=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0}),Object.defineProperty(s,"warnOnce",{enumerable:!0,get:function(){return r}});let r=e=>{}},215232,(e,t,s)=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0}),Object.defineProperty(s,"useMergedRef",{enumerable:!0,get:function(){return n}});let r=e.r(430878);function n(e,t){let s=(0,r.useRef)(null),n=(0,r.useRef)(null);return(0,r.useCallback)(r=>{if(null===r){let e=s.current;e&&(s.current=null,e());let t=n.current;t&&(n.current=null,t())}else e&&(s.current=a(e,r)),t&&(n.current=a(t,r))},[e,t])}function a(e,t){if("function"!=typeof e)return e.current=t,()=>{e.current=null};{let s=e(t);return"function"==typeof s?s:()=>e(null)}}("function"==typeof s.default||"object"==typeof s.default&&null!==s.default)&&void 0===s.default.__esModule&&(Object.defineProperty(s.default,"__esModule",{value:!0}),Object.assign(s.default,s),t.exports=s.default)},325203,(e,t,s)=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0});var r={assign:function(){return o},searchParamsToUrlQuery:function(){return a},urlQueryToSearchParams:function(){return l}};for(var n in r)Object.defineProperty(s,n,{enumerable:!0,get:r[n]});function a(e){let t={};for(let[s,r]of e.entries()){let e=t[s];void 0===e?t[s]=r:Array.isArray(e)?e.push(r):t[s]=[e,r]}return t}function i(e){return"string"==typeof e?e:("number"!=typeof e||isNaN(e))&&"boolean"!=typeof e?"":String(e)}function l(e){let t=new URLSearchParams;for(let[s,r]of Object.entries(e))if(Array.isArray(r))for(let e of r)t.append(s,i(e));else t.set(s,i(r));return t}function o(e,...t){for(let s of t){for(let t of s.keys())e.delete(t);for(let[t,r]of s.entries())e.append(t,r)}return e}},971746,(e,t,s)=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0});var r={formatUrl:function(){return l},formatWithValidation:function(){return c},urlObjectKeys:function(){return o}};for(var n in r)Object.defineProperty(s,n,{enumerable:!0,get:r[n]});let a=e.r(279510)._(e.r(325203)),i=/https?|ftp|gopher|file/;function l(e){let{auth:t,hostname:s}=e,r=e.protocol||"",n=e.pathname||"",l=e.hash||"",o=e.query||"",c=!1;t=t?encodeURIComponent(t).replace(/%3A/i,":")+"@":"",e.host?c=t+e.host:s&&(c=t+(~s.indexOf(":")?`[${s}]`:s),e.port&&(c+=":"+e.port)),o&&"object"==typeof o&&(o=String(a.urlQueryToSearchParams(o)));let d=e.search||o&&`?${o}`||"";return r&&!r.endsWith(":")&&(r+=":"),e.slashes||(!r||i.test(r))&&!1!==c?(c="//"+(c||""),n&&"/"!==n[0]&&(n="/"+n)):c||(c=""),l&&"#"!==l[0]&&(l="#"+l),d&&"?"!==d[0]&&(d="?"+d),n=n.replace(/[?#]/g,encodeURIComponent),d=d.replace("#","%23"),`${r}${c}${n}${d}${l}`}let o=["auth","hash","host","hostname","href","path","pathname","port","protocol","query","search","slashes"];function c(e){return l(e)}},309008,(e,t,s)=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0});var r={DecodeError:function(){return g},MiddlewareNotFoundError:function(){return b},MissingStaticPage:function(){return v},NormalizeError:function(){return j},PageNotFoundError:function(){return y},SP:function(){return x},ST:function(){return f},WEB_VITALS:function(){return a},execOnce:function(){return i},getDisplayName:function(){return u},getLocationOrigin:function(){return c},getURL:function(){return d},isAbsoluteUrl:function(){return o},isResSent:function(){return m},loadGetInitialProps:function(){return h},normalizeRepeatedSlashes:function(){return p},stringifyError:function(){return N}};for(var n in r)Object.defineProperty(s,n,{enumerable:!0,get:r[n]});let a=["CLS","FCP","FID","INP","LCP","TTFB"];function i(e){let t,s=!1;return(...r)=>(s||(s=!0,t=e(...r)),t)}let l=/^[a-zA-Z][a-zA-Z\d+\-.]*?:/,o=e=>l.test(e);function c(){let{protocol:e,hostname:t,port:s}=window.location;return`${e}//${t}${s?":"+s:""}`}function d(){let{href:e}=window.location,t=c();return e.substring(t.length)}function u(e){return"string"==typeof e?e:e.displayName||e.name||"Unknown"}function m(e){return e.finished||e.headersSent}function p(e){let t=e.split("?");return t[0].replace(/\\/g,"/").replace(/\/\/+/g,"/")+(t[1]?`?${t.slice(1).join("?")}`:"")}async function h(e,t){let s=t.res||t.ctx&&t.ctx.res;if(!e.getInitialProps)return t.ctx&&t.Component?{pageProps:await h(t.Component,t.ctx)}:{};let r=await e.getInitialProps(t);if(s&&m(s))return r;if(!r)throw Object.defineProperty(Error(`"${u(e)}.getInitialProps()" should resolve to an object. But found "${r}" instead.`),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});return r}let x="u">typeof performance,f=x&&["mark","measure","getEntriesByName"].every(e=>"function"==typeof performance[e]);class g extends Error{}class j extends Error{}class y extends Error{constructor(e){super(),this.code="ENOENT",this.name="PageNotFoundError",this.message=`Cannot find module for page: ${e}`}}class v extends Error{constructor(e,t){super(),this.message=`Failed to load static file for page: ${e} ${t}`}}class b extends Error{constructor(){super(),this.code="ENOENT",this.message="Cannot find the middleware module"}}function N(e){return JSON.stringify({message:e.message,stack:e.stack})}},868988,(e,t,s)=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0}),Object.defineProperty(s,"isLocalURL",{enumerable:!0,get:function(){return a}});let r=e.r(309008),n=e.r(698018);function a(e){if(!(0,r.isAbsoluteUrl)(e))return!0;try{let t=(0,r.getLocationOrigin)(),s=new URL(e,t);return s.origin===t&&(0,n.hasBasePath)(s.pathname)}catch(e){return!1}}},312491,(e,t,s)=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0}),Object.defineProperty(s,"errorOnce",{enumerable:!0,get:function(){return r}});let r=e=>{}},504561,(e,t,s)=>{"use strict";Object.defineProperty(s,"__esModule",{value:!0});var r={default:function(){return g},useLinkStatus:function(){return y}};for(var n in r)Object.defineProperty(s,n,{enumerable:!0,get:r[n]});let a=e.r(279510),i=e.r(414294),l=a._(e.r(430878)),o=e.r(971746),c=e.r(369168),d=e.r(215232),u=e.r(309008),m=e.r(869343);e.r(819609);let p=e.r(93505),h=e.r(868988),x=e.r(291544);function f(e){return"string"==typeof e?e:(0,o.formatUrl)(e)}function g(t){var s;let r,n,a,[o,g]=(0,l.useOptimistic)(p.IDLE_LINK_STATUS),y=(0,l.useRef)(null),{href:v,as:b,children:N,prefetch:S=null,passHref:k,replace:C,shallow:T,scroll:w,onClick:P,onMouseEnter:z,onTouchStart:M,legacyBehavior:E=!1,onNavigate:O,ref:A,unstable_dynamicOnHover:_,...L}=t;r=N,E&&("string"==typeof r||"number"==typeof r)&&(r=(0,i.jsx)("a",{children:r}));let $=l.default.useContext(c.AppRouterContext),I=!1!==S,D=!1!==S?null===(s=S)||"auto"===s?x.FetchStrategy.PPR:x.FetchStrategy.Full:x.FetchStrategy.PPR,{href:R,as:B}=l.default.useMemo(()=>{let e=f(v);return{href:e,as:b?f(b):e}},[v,b]);if(E){if(r?.$$typeof===Symbol.for("react.lazy"))throw Object.defineProperty(Error("`<Link legacyBehavior>` received a direct child that is either a Server Component, or JSX that was loaded with React.lazy(). This is not supported. Either remove legacyBehavior, or make the direct child a Client Component that renders the Link's `<a>` tag."),"__NEXT_ERROR_CODE",{value:"E863",enumerable:!1,configurable:!0});n=l.default.Children.only(r)}let F=E?n&&"object"==typeof n&&n.ref:A,U=l.default.useCallback(e=>(null!==$&&(y.current=(0,p.mountLinkInstance)(e,R,$,D,I,g)),()=>{y.current&&((0,p.unmountLinkForCurrentNavigation)(y.current),y.current=null),(0,p.unmountPrefetchableInstance)(e)}),[I,R,$,D,g]),K={ref:(0,d.useMergedRef)(U,F),onClick(t){E||"function"!=typeof P||P(t),E&&n.props&&"function"==typeof n.props.onClick&&n.props.onClick(t),!$||t.defaultPrevented||function(t,s,r,n,a,i,o){if("u">typeof window){let c,{nodeName:d}=t.currentTarget;if("A"===d.toUpperCase()&&((c=t.currentTarget.getAttribute("target"))&&"_self"!==c||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||t.nativeEvent&&2===t.nativeEvent.which)||t.currentTarget.hasAttribute("download"))return;if(!(0,h.isLocalURL)(s)){a&&(t.preventDefault(),location.replace(s));return}if(t.preventDefault(),o){let e=!1;if(o({preventDefault:()=>{e=!0}}),e)return}let{dispatchNavigateAction:u}=e.r(389867);l.default.startTransition(()=>{u(r||s,a?"replace":"push",i??!0,n.current)})}}(t,R,B,y,C,w,O)},onMouseEnter(e){E||"function"!=typeof z||z(e),E&&n.props&&"function"==typeof n.props.onMouseEnter&&n.props.onMouseEnter(e),$&&I&&(0,p.onNavigationIntent)(e.currentTarget,!0===_)},onTouchStart:function(e){E||"function"!=typeof M||M(e),E&&n.props&&"function"==typeof n.props.onTouchStart&&n.props.onTouchStart(e),$&&I&&(0,p.onNavigationIntent)(e.currentTarget,!0===_)}};return(0,u.isAbsoluteUrl)(B)?K.href=B:E&&!k&&("a"!==n.type||"href"in n.props)||(K.href=(0,m.addBasePath)(B)),a=E?l.default.cloneElement(n,K):(0,i.jsx)("a",{...L,...K,children:r}),(0,i.jsx)(j.Provider,{value:o,children:a})}e.r(312491);let j=(0,l.createContext)(p.IDLE_LINK_STATUS),y=()=>(0,l.useContext)(j);("function"==typeof s.default||"object"==typeof s.default&&null!==s.default)&&void 0===s.default.__esModule&&(Object.defineProperty(s.default,"__esModule",{value:!0}),Object.assign(s.default,s),t.exports=s.default)},996720,e=>{"use strict";var t=e.i(257868);e.s(["Plus",()=>t.default])},667249,e=>{"use strict";let t=(0,e.i(292511).default)("message-square",[["path",{d:"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z",key:"18887p"}]]);e.s(["MessageSquare",()=>t],667249)},846193,e=>{"use strict";let t=(0,e.i(292511).default)("key",[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4",key:"g0fldk"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}]]);e.s(["Key",()=>t],846193)},421722,e=>{"use strict";var t=e.i(414294),s=e.i(430878),r=e.i(353913),n=e.i(504561),a=e.i(292623),i=e.i(996720),l=e.i(667249),o=e.i(904781),c=e.i(461957),d=e.i(816187),u=e.i(292511);let m=(0,u.default)("panel-left-close",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"m16 15-3-3 3-3",key:"14y99z"}]]);var p=e.i(220563),h=e.i(846193),x=e.i(719583),f=e.i(707387),g=e.i(481298),g=g;let j=(0,u.default)("eye-off",[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]),y=(0,u.default)("volume-2",[["path",{d:"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z",key:"uqj9uw"}],["path",{d:"M16 9a5 5 0 0 1 0 6",key:"1q6k2b"}],["path",{d:"M19.364 18.364a9 9 0 0 0 0-12.728",key:"ijwkga"}]]);var v=e.i(529757),b=e.i(666904),N=e.i(836191),S=e.i(77982),k=e.i(634066),C=e.i(865259),T=e.i(553880),w=e.i(87614),P=e.i(524741),z=e.i(739963),M=e.i(555552),E=e.i(300739),O=e.i(335130);function A(){let e=(0,r.useRouter)(),u=(0,r.usePathname)(),{state:A,toggleSidebar:_}=(0,v.useSidebar)(),{sessions:L,isLoading:$}=(0,E.useSessions)(),[I,D]=(0,s.useState)(!1),[R,B]=(0,s.useState)(!1),[F,U]=(0,s.useState)(!1),[K,q]=(0,s.useState)(null),[V,W]=(0,s.useState)(null),H=(0,s.useRef)(null),[X,G]=(0,s.useState)(""),[Q,J]=(0,s.useState)(""),[Z,Y]=(0,s.useState)({}),[ee,et]=(0,s.useState)([]),[es,er]=(0,s.useState)(null),[en,ea]=(0,s.useState)(""),[ei,el]=(0,s.useState)(!1),[eo,ec]=(0,s.useState)(!1),{enabled:ed,setEnabled:eu}=(0,O.useNotificationSound)(),em=u.startsWith("/embed/"),ep=u.startsWith("/session/")?u.split("/session/")[1]:u.startsWith("/embed/")?u.split("/embed/")[1]:null,eh=em?"/embed":"/session",ex=L.some(e=>e.isStreaming),ef=async()=>{let e=await (0,z.getConfig)();q(e),J(e.defaultModel),Y(e.defaultToolApprovals)},eg=async()=>{try{let e=await (0,P.getApiKeys)();et(e.providers)}catch(e){console.error("Failed to load API keys:",e)}};(0,s.useEffect)(()=>{ef(),eg()},[]),(0,s.useEffect)(()=>{F&&eg()},[F]);let ej=async e=>{if(en.trim()){ec(!0);try{await (0,P.setApiKey)(e,en),await eg(),er(null),ea(""),el(!1)}catch(e){console.error("Failed to save API key:",e)}finally{ec(!1)}}},ey=()=>{er(null),ea(""),el(!1)};(0,s.useEffect)(()=>{H.current&&(ex?H.current.play().catch(()=>{}):(H.current.pause(),H.current.currentTime=0))},[ex]);let ev=async()=>{if(!I){D(!0);try{let t=await (0,P.createSession)({name:`Session ${L.length+1}`,model:K?.defaultModel||"anthropic/claude-opus-4-6",toolApprovals:Z});(0,E.mutateSessions)(),e.push(`${eh}/${t.id}`)}catch(e){console.error("Failed to create session:",e)}finally{D(!1)}}},eb=async()=>{D(!0);try{let t=await (0,P.createSession)({name:X||`Session ${L.length+1}`,model:Q,toolApprovals:Z});(0,E.mutateSessions)(),eN(),B(!1),e.push(`${eh}/${t.id}`)}catch(e){console.error("Failed to create session:",e)}finally{D(!1)}},eN=()=>{G(""),K&&(J(K.defaultModel),Y(K.defaultToolApprovals))},eS=async(t,s)=>{t.preventDefault(),t.stopPropagation();try{await (0,P.deleteSession)(s),(0,E.mutateSessions)(),ep===s&&e.push("/")}catch(e){console.error("Failed to delete session:",e)}},ek=e=>{Y(t=>({...t,[e]:!t[e]}))},eC="collapsed"===A;return(0,t.jsxs)(v.Sidebar,{collapsible:em?"offcanvas":"icon",className:"border-r border-border/50",children:[(0,t.jsxs)(v.SidebarHeader,{className:(0,M.cn)(eC?"p-2 space-y-2":"p-3 space-y-3"),children:[!eC&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(0,t.jsxs)("div",{className:"relative shrink-0 overflow-hidden rounded-xl size-10 shadow-md ring-1 ring-white/10",children:[(0,t.jsx)(a.default,{src:"/sparke-coder.png",alt:"Sparke",width:40,height:40,className:"absolute inset-0 size-full object-cover",priority:!0}),(0,t.jsx)("video",{ref:H,src:"/sparkecode.mp4",muted:!0,loop:!0,playsInline:!0,className:(0,M.cn)("absolute inset-0 size-full object-cover transition-opacity duration-300",ex?"opacity-100":"opacity-0")})]}),(0,t.jsxs)("div",{className:"flex flex-1 items-center justify-between min-w-0",children:[(0,t.jsx)("h1",{className:"text-lg font-bold text-foreground",children:"SparkECoder"}),(0,t.jsx)(w.TooltipProvider,{children:(0,t.jsxs)(w.Tooltip,{children:[(0,t.jsx)(w.TooltipTrigger,{asChild:!0,children:(0,t.jsx)(b.Button,{size:"icon",variant:"ghost",className:"size-7 hover:bg-accent transition-colors",onClick:_,children:(0,t.jsx)(m,{className:"size-4"})})}),(0,t.jsxs)(w.TooltipContent,{side:"bottom",children:["Collapse ",(0,t.jsx)("kbd",{className:"ml-1 text-[10px] opacity-60",children:"⌘B"})]})]})})]})]}),(0,t.jsxs)(b.Button,{onClick:ev,disabled:I,className:"w-full justify-center gap-2 h-9",children:[I?(0,t.jsx)(c.Loader2,{className:"size-4 animate-spin"}):(0,t.jsx)(i.Plus,{className:"size-4"}),"New Agent"]})]}),eC&&(0,t.jsxs)("div",{className:"flex flex-col items-center gap-2 w-full",children:[(0,t.jsx)(w.TooltipProvider,{children:(0,t.jsxs)(w.Tooltip,{children:[(0,t.jsx)(w.TooltipTrigger,{asChild:!0,children:(0,t.jsx)(b.Button,{size:"icon",variant:"ghost",onClick:_,className:"size-8 mx-auto",children:(0,t.jsx)(p.PanelLeft,{className:"size-4"})})}),(0,t.jsxs)(w.TooltipContent,{side:"right",children:["Expand ",(0,t.jsx)("kbd",{className:"ml-1 text-[10px] opacity-60",children:"⌘B"})]})]})}),(0,t.jsxs)("div",{className:"relative overflow-hidden rounded-xl size-8 shadow-md ring-1 ring-white/10 mx-auto",children:[(0,t.jsx)(a.default,{src:"/sparke-coder.png",alt:"SparkECoder",width:32,height:32,className:"absolute inset-0 size-full object-cover",priority:!0}),(0,t.jsx)("video",{ref:H,src:"/sparkecode.mp4",muted:!0,loop:!0,playsInline:!0,className:(0,M.cn)("absolute inset-0 size-full object-cover transition-opacity duration-300",ex?"opacity-100":"opacity-0")})]}),(0,t.jsx)(w.TooltipProvider,{children:(0,t.jsxs)(w.Tooltip,{children:[(0,t.jsx)(w.TooltipTrigger,{asChild:!0,children:(0,t.jsx)(b.Button,{size:"icon",onClick:ev,disabled:I,className:"size-8 mx-auto",children:I?(0,t.jsx)(c.Loader2,{className:"size-4 animate-spin"}):(0,t.jsx)(i.Plus,{className:"size-4"})})}),(0,t.jsx)(w.TooltipContent,{side:"right",children:"New Agent"})]})})]})]}),(0,t.jsx)(N.Dialog,{open:R,onOpenChange:e=>{B(e),e&&eN()},children:(0,t.jsxs)(N.DialogContent,{className:"sm:max-w-md",children:[(0,t.jsx)(N.DialogHeader,{children:(0,t.jsxs)(N.DialogTitle,{className:"flex items-center gap-2",children:[(0,t.jsx)("div",{className:"size-8 rounded-lg bg-primary flex items-center justify-center",children:(0,t.jsx)(d.Settings,{className:"size-4 text-primary-foreground"})}),"New Agent"]})}),(0,t.jsxs)("div",{className:"space-y-4 pt-2",children:[(0,t.jsxs)("div",{className:"space-y-1.5",children:[(0,t.jsx)(k.Label,{htmlFor:"name",className:"text-sm font-medium",children:"Session Name"}),(0,t.jsx)(S.Input,{id:"name",placeholder:"My Coding Project (optional)",value:X,onChange:e=>G(e.target.value),className:"transition-all focus:ring-2 focus:ring-primary/20"})]}),(0,t.jsxs)("div",{className:"space-y-1.5",children:[(0,t.jsx)(k.Label,{className:"text-sm font-medium",children:"Model"}),(0,t.jsxs)(T.Select,{value:Q,onValueChange:J,children:[(0,t.jsx)(T.SelectTrigger,{className:"transition-all hover:border-primary/50",children:(0,t.jsx)(T.SelectValue,{placeholder:"Select a model"})}),(0,t.jsx)(T.SelectContent,{children:K?.availableModels.map(e=>(0,t.jsx)(T.SelectItem,{value:e.id,children:(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{children:e.name}),(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:e.provider})]})},e.id))})]})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(k.Label,{className:"flex items-center gap-2 text-sm font-medium",children:"Tool Approvals"}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground -mt-0.5",children:"Toggle on to require approval before tool executes"}),(0,t.jsx)("div",{className:"space-y-1 rounded-lg border p-2.5 bg-muted/30",children:K?.availableTools.map(e=>(0,t.jsxs)("div",{className:"flex items-center justify-between py-1.5 hover:bg-muted/50 rounded px-2 -mx-1 transition-colors",children:[(0,t.jsxs)("div",{className:"space-y-0",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{className:"text-sm font-medium",children:e.name}),e.dangerous&&(0,t.jsx)("span",{className:"text-[10px] bg-amber-500/20 text-amber-600 dark:text-amber-400 px-1.5 py-0.5 rounded font-medium",children:"risky"})]}),(0,t.jsx)("p",{className:"text-[11px] text-muted-foreground",children:e.description})]}),(0,t.jsx)(C.Switch,{checked:Z[e.id]??!1,onCheckedChange:()=>ek(e.id)})]},e.id))})]}),(0,t.jsxs)(b.Button,{onClick:eb,disabled:I,className:"w-full",children:[I?(0,t.jsx)(c.Loader2,{className:"size-4 animate-spin mr-2"}):(0,t.jsx)(i.Plus,{className:"size-4 mr-2"}),"Create Session"]})]})]})}),(0,t.jsx)(v.SidebarContent,{className:"px-2",children:(0,t.jsx)(v.SidebarGroup,{className:"p-0",children:(0,t.jsx)(v.SidebarGroupContent,{children:(0,t.jsx)(v.SidebarMenu,{className:"gap-1",children:$?(0,t.jsx)("div",{className:"flex justify-center py-8",children:(0,t.jsx)(c.Loader2,{className:"size-5 animate-spin text-muted-foreground"})}):0===L.length?!eC&&(0,t.jsxs)("div",{className:"text-center py-8 px-4",children:[(0,t.jsxs)("div",{className:"relative overflow-hidden rounded-xl size-12 mx-auto mb-3 shadow-md ring-1 ring-white/10",children:[(0,t.jsx)(a.default,{src:"/sparke-coder.png",alt:"SparkECoder",width:48,height:48,className:"absolute inset-0 size-full object-cover"}),ex&&(0,t.jsx)("video",{src:"/sparkecode.mp4",autoPlay:!0,muted:!0,loop:!0,playsInline:!0,className:"absolute inset-0 size-full object-cover"})]}),(0,t.jsx)("p",{className:"text-sm text-foreground",children:"No sessions yet"}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground mt-1",children:"Click New Agent above"})]}):L.map(e=>{let s,r,a,i,c=e.id===ep,d=V===e.id,u=!0===e.isStreaming,m=!eC&&(d||c);return(0,t.jsx)(v.SidebarMenuItem,{onMouseEnter:()=>W(e.id),onMouseLeave:()=>W(null),children:eC?(0,t.jsx)(w.TooltipProvider,{children:(0,t.jsxs)(w.Tooltip,{children:[(0,t.jsx)(w.TooltipTrigger,{asChild:!0,children:(0,t.jsx)(n.default,{href:`${eh}/${e.id}`,className:(0,M.cn)("flex items-center justify-center size-8 rounded-lg transition-colors mx-auto",c?"bg-accent":"hover:bg-accent/60",u&&!c&&"bg-emerald-500/10"),children:u?(0,t.jsx)("span",{className:"size-2 rounded-full bg-emerald-500 animate-pulse"}):(0,t.jsx)(l.MessageSquare,{className:(0,M.cn)("size-4",c?"text-primary":"text-muted-foreground")})})}),(0,t.jsxs)(w.TooltipContent,{side:"right",children:[e.name||"Untitled",u&&" (Running)"]})]})}):(0,t.jsx)(v.SidebarMenuButton,{asChild:!0,isActive:c,className:(0,M.cn)("h-9 transition-all duration-150","hover:bg-accent/60",c&&"bg-accent",u&&!c&&"bg-emerald-500/5"),children:(0,t.jsxs)(n.default,{href:`${eh}/${e.id}`,className:"flex items-center gap-2.5 px-2",children:[u?(0,t.jsx)("span",{className:"size-2 rounded-full bg-emerald-500 animate-pulse shrink-0"}):(0,t.jsx)(l.MessageSquare,{className:(0,M.cn)("size-4 shrink-0",c?"text-primary":"text-muted-foreground")}),(0,t.jsx)("span",{className:(0,M.cn)("truncate flex-1 text-sm",u&&"text-emerald-600 dark:text-emerald-400"),children:e.name||"Untitled"}),m?(0,t.jsx)(w.TooltipProvider,{children:(0,t.jsxs)(w.Tooltip,{children:[(0,t.jsx)(w.TooltipTrigger,{asChild:!0,children:(0,t.jsx)(b.Button,{size:"icon",variant:"ghost",className:"size-6 shrink-0 hover:bg-destructive/10 hover:text-destructive transition-colors",onClick:t=>eS(t,e.id),children:(0,t.jsx)(o.Trash2,{className:"size-3.5"})})}),(0,t.jsx)(w.TooltipContent,{side:"right",children:"Delete session"})]})}):u?(0,t.jsx)("span",{className:"inline-flex items-center gap-1 text-[10px] text-emerald-600 dark:text-emerald-400 shrink-0 font-medium",children:"Active"}):"waiting"===e.status?(0,t.jsx)("span",{className:"text-[10px] text-amber-600 dark:text-amber-400 shrink-0 font-medium",children:"Waiting"}):"error"===e.status?(0,t.jsx)("span",{className:"text-[10px] text-red-600 dark:text-red-400 shrink-0 font-medium",children:"Error"}):(0,t.jsx)("span",{className:"text-[11px] text-muted-foreground shrink-0 tabular-nums",children:(s=new Date(e.createdAt),i=Math.floor((a=Math.floor((r=Math.floor(Math.floor((new Date().getTime()-s.getTime())/1e3)/60))/60))/24),r<1?"now":r<60?`${r}m`:a<24?`${a}h`:i<7?`${i}d`:`${Math.floor(i/7)}w`)})]})})},e.id)})})})})}),(0,t.jsx)(v.SidebarFooter,{className:(0,M.cn)("border-t border-border/50",eC?"p-2":"p-3"),children:(0,t.jsx)("div",{className:"flex items-center justify-between",children:eC?(0,t.jsxs)("div",{className:"flex flex-col items-center gap-2 w-full",children:[(0,t.jsx)(w.TooltipProvider,{children:(0,t.jsxs)(w.Tooltip,{children:[(0,t.jsx)(w.TooltipTrigger,{asChild:!0,children:(0,t.jsx)("div",{className:"flex items-center justify-center",children:(0,t.jsx)("span",{className:(0,M.cn)("size-2 rounded-full",K?.serverConnected?"bg-emerald-500 animate-pulse":"bg-red-500")})})}),(0,t.jsx)(w.TooltipContent,{side:"right",children:K?.serverConnected?"Connected":"Disconnected"})]})}),(0,t.jsx)(N.Dialog,{open:F,onOpenChange:U,children:(0,t.jsx)(w.TooltipProvider,{children:(0,t.jsxs)(w.Tooltip,{children:[(0,t.jsx)(w.TooltipTrigger,{asChild:!0,children:(0,t.jsx)(N.DialogTrigger,{asChild:!0,children:(0,t.jsx)(b.Button,{size:"icon",variant:"ghost",className:"size-8",children:(0,t.jsx)(d.Settings,{className:"size-4"})})})}),(0,t.jsx)(w.TooltipContent,{side:"right",children:"Settings"})]})})})]}):(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 text-xs",children:[K?.serverConnected?(0,t.jsxs)("div",{className:"flex items-center gap-1.5 text-emerald-600 dark:text-emerald-400",children:[(0,t.jsx)("span",{className:"size-1.5 rounded-full bg-current animate-pulse"}),(0,t.jsx)("span",{children:"Connected"})]}):(0,t.jsxs)("div",{className:"flex items-center gap-1.5 text-red-500",children:[(0,t.jsx)("span",{className:"size-1.5 rounded-full bg-current"}),(0,t.jsx)("span",{children:"Disconnected"})]}),(0,t.jsx)("span",{className:"text-muted-foreground",children:"·"}),(0,t.jsx)("span",{className:"text-muted-foreground",children:L.length})]}),(0,t.jsxs)(N.Dialog,{open:F,onOpenChange:U,children:[(0,t.jsx)(w.TooltipProvider,{children:(0,t.jsxs)(w.Tooltip,{children:[(0,t.jsx)(w.TooltipTrigger,{asChild:!0,children:(0,t.jsx)(N.DialogTrigger,{asChild:!0,children:(0,t.jsx)(b.Button,{size:"icon",variant:"ghost",className:"size-7 hover:bg-accent transition-colors",children:(0,t.jsx)(d.Settings,{className:"size-4"})})})}),(0,t.jsx)(w.TooltipContent,{side:"top",children:"Settings"})]})}),(0,t.jsxs)(N.DialogContent,{className:"sm:max-w-md",children:[(0,t.jsx)(N.DialogHeader,{children:(0,t.jsxs)(N.DialogTitle,{className:"flex items-center gap-2",children:[(0,t.jsx)("div",{className:"size-8 rounded-lg bg-muted flex items-center justify-center",children:(0,t.jsx)(d.Settings,{className:"size-4"})}),"Settings"]})}),(0,t.jsxs)("div",{className:"space-y-4 pt-2",children:[(0,t.jsxs)("div",{className:"space-y-1.5",children:[(0,t.jsx)(k.Label,{className:"text-sm font-medium",children:"Default Model"}),(0,t.jsxs)(T.Select,{value:Q,onValueChange:J,children:[(0,t.jsx)(T.SelectTrigger,{className:"transition-all hover:border-primary/50",children:(0,t.jsx)(T.SelectValue,{placeholder:"Select a model"})}),(0,t.jsx)(T.SelectContent,{children:K?.availableModels.map(e=>(0,t.jsx)(T.SelectItem,{value:e.id,children:(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{children:e.name}),(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:e.provider})]})},e.id))})]})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(k.Label,{className:"flex items-center gap-2 text-sm font-medium",children:"Tool Approvals"}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground -mt-0.5",children:"Toggle on to require approval before tool executes"}),(0,t.jsx)("div",{className:"space-y-1 rounded-lg border p-2.5 bg-muted/30",children:K?.availableTools.map(e=>(0,t.jsxs)("div",{className:"flex items-center justify-between py-1.5 hover:bg-muted/50 rounded px-2 -mx-1 transition-colors",children:[(0,t.jsxs)("div",{className:"space-y-0",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{className:"text-sm font-medium",children:e.name}),e.dangerous&&(0,t.jsx)("span",{className:"text-[10px] bg-amber-500/20 text-amber-600 dark:text-amber-400 px-1.5 py-0.5 rounded font-medium",children:"risky"})]}),(0,t.jsx)("p",{className:"text-[11px] text-muted-foreground",children:e.description})]}),(0,t.jsx)(C.Switch,{checked:Z[e.id]??!1,onCheckedChange:()=>ek(e.id)})]},e.id))})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)(k.Label,{className:"flex items-center gap-2 text-sm font-medium",children:[(0,t.jsx)(h.Key,{className:"size-4"}),"API Keys"]}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground -mt-0.5",children:"Configure API keys for different providers. Keys are stored securely on your machine."}),(0,t.jsx)("div",{className:"space-y-1 rounded-lg border p-2.5 bg-muted/30",children:ee.map(e=>(0,t.jsx)("div",{className:"py-1.5 hover:bg-muted/50 rounded px-2 -mx-1 transition-colors",children:es===e.provider?(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between",children:[(0,t.jsx)("span",{className:"text-sm font-medium capitalize",children:e.provider}),(0,t.jsx)("span",{className:"text-[10px] text-muted-foreground font-mono",children:e.envVar})]}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsxs)("div",{className:"relative flex-1",children:[(0,t.jsx)(S.Input,{type:ei?"text":"password",value:en,onChange:e=>ea(e.target.value),placeholder:"Paste your API key...",className:"pr-8 text-sm font-mono",autoFocus:!0}),(0,t.jsx)(b.Button,{type:"button",variant:"ghost",size:"icon",className:"absolute right-0 top-0 h-full px-2 hover:bg-transparent",onClick:()=>el(!ei),children:ei?(0,t.jsx)(j,{className:"size-4"}):(0,t.jsx)(g.default,{className:"size-4"})})]}),(0,t.jsx)(b.Button,{size:"icon",variant:"ghost",className:"shrink-0",onClick:()=>ej(e.provider),disabled:eo||!en.trim(),children:eo?(0,t.jsx)(c.Loader2,{className:"size-4 animate-spin"}):(0,t.jsx)(x.Check,{className:"size-4 text-green-500"})}),(0,t.jsx)(b.Button,{size:"icon",variant:"ghost",className:"shrink-0",onClick:ey,children:(0,t.jsx)(f.X,{className:"size-4 text-muted-foreground"})})]})]}):(0,t.jsxs)("div",{className:"flex items-center justify-between",children:[(0,t.jsxs)("div",{className:"space-y-0",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{className:"text-sm font-medium capitalize",children:e.provider}),e.configured&&(0,t.jsx)("span",{className:(0,M.cn)("text-[10px] px-1.5 py-0.5 rounded font-medium","env"===e.source?"bg-blue-500/20 text-blue-600 dark:text-blue-400":"bg-green-500/20 text-green-600 dark:text-green-400"),children:"env"===e.source?"from env":"saved"})]}),(0,t.jsx)("p",{className:"text-[11px] text-muted-foreground font-mono",children:e.configured?e.maskedKey:"Not configured"})]}),(0,t.jsx)(b.Button,{size:"sm",variant:"ghost",className:"h-7 text-xs",onClick:()=>er(e.provider),children:e.configured?"Update":"Add"})]})},e.provider))})]}),(0,t.jsxs)("div",{className:"space-y-1.5",children:[(0,t.jsxs)(k.Label,{className:"flex items-center gap-2 text-sm font-medium",children:[(0,t.jsx)(y,{className:"size-4"}),"Notification Sound"]}),(0,t.jsxs)("div",{className:"flex items-center justify-between rounded-lg border p-2.5 bg-muted/30",children:[(0,t.jsxs)("div",{className:"space-y-0",children:[(0,t.jsx)("span",{className:"text-sm font-medium",children:"Play sound when done"}),(0,t.jsx)("p",{className:"text-[11px] text-muted-foreground",children:"Ding when the assistant finishes responding"})]}),(0,t.jsx)(C.Switch,{checked:ed,onCheckedChange:eu})]})]}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground",children:"These settings apply to new sessions. You can also change the model per-session in the chat header."})]})]})]})]})})})]})}e.s(["SessionsSidebar",()=>A],421722)},138134,e=>{"use strict";var t=e.i(414294),s=e.i(529757),r=e.i(421722);function n({children:e}){return(0,t.jsxs)(s.SidebarProvider,{defaultOpen:!0,children:[(0,t.jsx)(r.SessionsSidebar,{}),(0,t.jsx)(s.SidebarInset,{className:"h-screen flex flex-col bg-background min-w-0",children:(0,t.jsx)("div",{className:"flex-1 overflow-hidden min-w-0",children:e})})]})}e.s(["default",()=>n])}]);
|