@agent-native/core 0.58.3 → 0.58.5
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/production-agent.d.ts +9 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +80 -4
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/plan-local.d.ts +34 -0
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +205 -1
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +5 -0
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +19 -2
- package/dist/cli/recap.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +6 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +5 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +141 -39
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +44 -31
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/blocks/library/diagram.d.ts.map +1 -1
- package/dist/client/blocks/library/diagram.js +85 -20
- package/dist/client/blocks/library/diagram.js.map +1 -1
- package/dist/client/blocks/library/tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/tabs.js +5 -5
- package/dist/client/blocks/library/tabs.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +13 -10
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +3 -3
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +0 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +5 -2
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat/widgets/DataChartRenderer.d.ts.map +1 -1
- package/dist/client/chat/widgets/DataChartRenderer.js +98 -21
- package/dist/client/chat/widgets/DataChartRenderer.js.map +1 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.d.ts +4 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.js +30 -4
- package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
- package/dist/client/composer/AgentComposerFrame.js +1 -1
- package/dist/client/composer/AgentComposerFrame.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +17 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +6 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +13 -0
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +25 -11
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
- package/dist/styles/agent-native.css +115 -2
- package/dist/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +100 -0
- package/docs/content/pr-visual-recap.md +2 -2
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +100 -0
|
@@ -6,6 +6,7 @@ import { type AgentChatContextItem } from "./agent-chat.js";
|
|
|
6
6
|
import { type AgentDynamicSuggestionsOption } from "./dynamic-suggestions.js";
|
|
7
7
|
import type { ReasoningEffort } from "../shared/reasoning-effort.js";
|
|
8
8
|
import type { ChatThreadScope, ChatThreadSnapshot } from "./use-chat-threads.js";
|
|
9
|
+
import { type ComposerSubmitIntent } from "./composer/TiptapComposer.js";
|
|
9
10
|
import type { AgentComposerLayoutVariant } from "./composer/types.js";
|
|
10
11
|
export { AssistantMessageListErrorBoundary, AssistantUiStaleIndexErrorBoundary, assistantUiRecoverableRenderErrorKind, isAssistantUiRecoverableRenderError, isAssistantUiStaleIndexError, } from "./assistant-ui-recovery.js";
|
|
11
12
|
export { displayableUserMessageText } from "./chat/message-components.js";
|
|
@@ -16,6 +17,10 @@ export interface AssistantChatSendOptions {
|
|
|
16
17
|
requestMode?: AgentRequestMode;
|
|
17
18
|
}
|
|
18
19
|
export declare function latestNonRecoveryUserMessageText(messages: readonly unknown[]): string;
|
|
20
|
+
export declare function resolveAssistantChatSubmitIntent({ isRunning, requestedIntent, }: {
|
|
21
|
+
isRunning: boolean;
|
|
22
|
+
requestedIntent?: ComposerSubmitIntent;
|
|
23
|
+
}): ComposerSubmitIntent;
|
|
19
24
|
export interface AssistantChatHandle {
|
|
20
25
|
/** Programmatically send a message into this chat */
|
|
21
26
|
sendMessage(text: string, images?: string[], options?: AssistantChatSendOptions): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KASN,MAAM,OAAO,CAAC;AAWf,OAAO,KAAK,EAEV,gBAAgB,EAChB,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAML,KAAK,oBAAoB,EAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,KAAK,6BAA6B,EACnC,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"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"}
|
|
@@ -24,7 +24,7 @@ import { AgentComposerFrame } from "./composer/AgentComposerFrame.js";
|
|
|
24
24
|
import { isPastedTextAttachmentName } from "./composer/pasted-text.js";
|
|
25
25
|
import { PastedTextChip } from "./composer/PastedTextChip.js";
|
|
26
26
|
import { ContextMeter } from "./context-xray/ContextMeter.js";
|
|
27
|
-
import { IconMessage, IconX, IconPlayerStop, IconChevronDown, IconTerminal,
|
|
27
|
+
import { IconMessage, IconX, IconPlayerStop, IconChevronDown, IconTerminal, IconAlertTriangle, IconRefresh, } from "@tabler/icons-react";
|
|
28
28
|
// ─── chat/ module imports ─────────────────────────────────────────────────────
|
|
29
29
|
import { DownscalingImageAttachmentAdapter, BinaryDocumentAttachmentAdapter, MAX_ESTIMATED_BODY_BYTES, AGGRESSIVE_MAX_IMAGE_DIMENSION, AGGRESSIVE_JPEG_QUALITY, transcodeImageToDataURL, createAgentImageAttachments, serializeQueuedAttachments, estimateAttachmentBodyBytes, } from "./chat/attachment-adapters.js";
|
|
30
30
|
import { TextStreamingContext } from "./chat/markdown-renderer.js";
|
|
@@ -256,6 +256,11 @@ export function latestNonRecoveryUserMessageText(messages) {
|
|
|
256
256
|
}
|
|
257
257
|
return "";
|
|
258
258
|
}
|
|
259
|
+
export function resolveAssistantChatSubmitIntent({ isRunning, requestedIntent, }) {
|
|
260
|
+
if (isRunning)
|
|
261
|
+
return "queued";
|
|
262
|
+
return requestedIntent ?? "immediate";
|
|
263
|
+
}
|
|
259
264
|
export const CHAT_STORAGE_PREFIX = "agent-chat:";
|
|
260
265
|
const THREAD_SNAPSHOT_CACHE_PREFIX = `${CHAT_STORAGE_PREFIX}thread-snapshot:`;
|
|
261
266
|
function threadSnapshotCacheKey(apiUrl, threadId) {
|
|
@@ -535,6 +540,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
535
540
|
const [authError, setAuthError] = useState(null);
|
|
536
541
|
const [authSessionAvailable, setAuthSessionAvailable] = useState(false);
|
|
537
542
|
const [queuedMessages, setQueuedMessages] = useState([]);
|
|
543
|
+
const queuedMessagesRef = useRef([]);
|
|
544
|
+
const queueDirtyRef = useRef(false);
|
|
545
|
+
const queueMutationVersionRef = useRef(0);
|
|
546
|
+
const dequeueInFlightRef = useRef(false);
|
|
538
547
|
const [composerContextItems, setComposerContextItems] = useState([]);
|
|
539
548
|
const composerContextItemsRef = useRef([]);
|
|
540
549
|
const isActiveComposerRef = useRef(isActiveComposer);
|
|
@@ -575,6 +584,18 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
575
584
|
includesContext: true,
|
|
576
585
|
};
|
|
577
586
|
}, []);
|
|
587
|
+
useEffect(() => {
|
|
588
|
+
queuedMessagesRef.current = queuedMessages;
|
|
589
|
+
}, [queuedMessages]);
|
|
590
|
+
const applyLocalQueuedMessages = useCallback((updater) => {
|
|
591
|
+
setQueuedMessages((previous) => {
|
|
592
|
+
const next = updater(previous);
|
|
593
|
+
queuedMessagesRef.current = next;
|
|
594
|
+
queueDirtyRef.current = true;
|
|
595
|
+
queueMutationVersionRef.current += 1;
|
|
596
|
+
return next;
|
|
597
|
+
});
|
|
598
|
+
}, []);
|
|
578
599
|
useEffect(() => {
|
|
579
600
|
if (!isActiveComposer)
|
|
580
601
|
return;
|
|
@@ -634,7 +655,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
634
655
|
const textStreaming = isRunning || externalStreaming;
|
|
635
656
|
// UI-only running state — drives the stop button and thinking indicator.
|
|
636
657
|
const showRunningInUI = isRunning;
|
|
637
|
-
const wasRunningRef = useRef(false);
|
|
638
658
|
const lastBroadcastRunningRef = useRef(isRunning);
|
|
639
659
|
const tiptapRef = useRef(null);
|
|
640
660
|
// Stable ref to the "stop active run" action so addToQueue can abort
|
|
@@ -712,8 +732,16 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
712
732
|
}
|
|
713
733
|
}
|
|
714
734
|
if (Array.isArray(repo?.queuedMessages)) {
|
|
715
|
-
|
|
716
|
-
|
|
735
|
+
const incomingQueue = repo.queuedMessages;
|
|
736
|
+
const incomingSerialized = JSON.stringify(incomingQueue);
|
|
737
|
+
const currentSerialized = JSON.stringify(queuedMessagesRef.current);
|
|
738
|
+
if (!queueDirtyRef.current ||
|
|
739
|
+
incomingSerialized === currentSerialized) {
|
|
740
|
+
queuedMessagesRef.current = incomingQueue;
|
|
741
|
+
setQueuedMessages(incomingQueue);
|
|
742
|
+
lastPersistedQueueRef.current = incomingSerialized;
|
|
743
|
+
queueDirtyRef.current = false;
|
|
744
|
+
}
|
|
717
745
|
}
|
|
718
746
|
if (settled && signature !== null) {
|
|
719
747
|
lastImportedSignatureRef.current = signature;
|
|
@@ -961,6 +989,14 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
961
989
|
return false;
|
|
962
990
|
}
|
|
963
991
|
}, [apiUrl, refreshThreadFromServer, startReconnectToRun, threadId]);
|
|
992
|
+
useEffect(() => {
|
|
993
|
+
if (!threadId || !isNewThread)
|
|
994
|
+
return;
|
|
995
|
+
// A restored tab can be reclassified as client-only after the thread list
|
|
996
|
+
// loads. Once that happens, there is no server row to restore, so show the
|
|
997
|
+
// empty composer instead of leaving the per-thread restore skeleton up.
|
|
998
|
+
setIsRestoring(false);
|
|
999
|
+
}, [isNewThread, threadId]);
|
|
964
1000
|
// Restore messages from server on mount (when threadId is set). The
|
|
965
1001
|
// server is the single source of truth — we don't hydrate from localStorage
|
|
966
1002
|
// first, so what the user sees in the chat panel always matches what the
|
|
@@ -1242,6 +1278,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1242
1278
|
const serialized = JSON.stringify(queuedMessages);
|
|
1243
1279
|
if (serialized === lastPersistedQueueRef.current)
|
|
1244
1280
|
return;
|
|
1281
|
+
const queueVersion = queueMutationVersionRef.current;
|
|
1245
1282
|
const timer = setTimeout(() => {
|
|
1246
1283
|
(async () => {
|
|
1247
1284
|
try {
|
|
@@ -1252,6 +1289,9 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1252
1289
|
});
|
|
1253
1290
|
if (res.ok) {
|
|
1254
1291
|
lastPersistedQueueRef.current = serialized;
|
|
1292
|
+
if (queueMutationVersionRef.current === queueVersion) {
|
|
1293
|
+
queueDirtyRef.current = false;
|
|
1294
|
+
}
|
|
1255
1295
|
}
|
|
1256
1296
|
}
|
|
1257
1297
|
catch {
|
|
@@ -1457,19 +1497,43 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1457
1497
|
setIsAutoResuming(false);
|
|
1458
1498
|
}
|
|
1459
1499
|
}, [isRunning]);
|
|
1460
|
-
// Auto-dequeue: when agent
|
|
1500
|
+
// Auto-dequeue: when the agent is idle, send the next queued message. This
|
|
1501
|
+
// intentionally does not depend on observing the running -> idle transition:
|
|
1502
|
+
// restored queues can exist after a reload where this component never saw the
|
|
1503
|
+
// previous run as active.
|
|
1461
1504
|
useEffect(() => {
|
|
1462
|
-
if (
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1505
|
+
if (isRestoring || isRunning || queuedMessages.length === 0) {
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
if (dequeueInFlightRef.current)
|
|
1509
|
+
return;
|
|
1510
|
+
const next = queuedMessages[0];
|
|
1511
|
+
if (!next)
|
|
1512
|
+
return;
|
|
1513
|
+
dequeueInFlightRef.current = true;
|
|
1514
|
+
let cancelled = false;
|
|
1515
|
+
let started = false;
|
|
1516
|
+
const timer = window.setTimeout(() => {
|
|
1517
|
+
started = true;
|
|
1518
|
+
void (async () => {
|
|
1519
|
+
let removedForAppend = false;
|
|
1520
|
+
let appended = false;
|
|
1521
|
+
try {
|
|
1468
1522
|
// In serverless/cross-isolate deployments the client can receive the
|
|
1469
1523
|
// terminal SSE event a beat before SQL has marked the previous run
|
|
1470
1524
|
// complete. Starting the queued turn during that window can reconnect
|
|
1471
1525
|
// to the old run and replay the old answer under the new prompt.
|
|
1472
1526
|
await waitForThreadRunToClear(apiUrl, threadId);
|
|
1527
|
+
if (cancelled)
|
|
1528
|
+
return;
|
|
1529
|
+
if (queuedMessagesRef.current[0]?.id !== next.id) {
|
|
1530
|
+
return;
|
|
1531
|
+
}
|
|
1532
|
+
// Keep the placeholder visible while waiting. Remove it only when the
|
|
1533
|
+
// append is about to begin, so queue stalls don't look like the chat
|
|
1534
|
+
// silently ate the next message.
|
|
1535
|
+
applyLocalQueuedMessages((prev) => prev.filter((message) => message.id !== next.id));
|
|
1536
|
+
removedForAppend = true;
|
|
1473
1537
|
const imageAttachments = createAgentImageAttachments(next.images);
|
|
1474
1538
|
const messageAttachments = next.attachments && next.attachments.length > 0
|
|
1475
1539
|
? next.attachments
|
|
@@ -1482,11 +1546,52 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1482
1546
|
: {}),
|
|
1483
1547
|
...createUserMessageRunConfig(next.references, next.requestMode, next.recoveryAction, next.trackInRunsTray),
|
|
1484
1548
|
});
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1549
|
+
appended = true;
|
|
1550
|
+
}
|
|
1551
|
+
catch (err) {
|
|
1552
|
+
if (removedForAppend &&
|
|
1553
|
+
!queuedMessagesRef.current.some((message) => message.id === next.id)) {
|
|
1554
|
+
applyLocalQueuedMessages((prev) => [next, ...prev]);
|
|
1555
|
+
}
|
|
1556
|
+
captureError(err, {
|
|
1557
|
+
tags: {
|
|
1558
|
+
source: "agent-chat-client",
|
|
1559
|
+
phase: "dequeue-message",
|
|
1560
|
+
},
|
|
1561
|
+
extra: {
|
|
1562
|
+
threadId: threadId ?? null,
|
|
1563
|
+
queuedMessageId: next.id,
|
|
1564
|
+
},
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
finally {
|
|
1568
|
+
if (appended) {
|
|
1569
|
+
window.setTimeout(() => {
|
|
1570
|
+
dequeueInFlightRef.current = false;
|
|
1571
|
+
}, 500);
|
|
1572
|
+
}
|
|
1573
|
+
else {
|
|
1574
|
+
dequeueInFlightRef.current = false;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
})();
|
|
1578
|
+
}, 100);
|
|
1579
|
+
return () => {
|
|
1580
|
+
cancelled = true;
|
|
1581
|
+
window.clearTimeout(timer);
|
|
1582
|
+
if (!started) {
|
|
1583
|
+
dequeueInFlightRef.current = false;
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
}, [
|
|
1587
|
+
apiUrl,
|
|
1588
|
+
applyLocalQueuedMessages,
|
|
1589
|
+
isRestoring,
|
|
1590
|
+
isRunning,
|
|
1591
|
+
queuedMessages,
|
|
1592
|
+
threadId,
|
|
1593
|
+
threadRuntime,
|
|
1594
|
+
]);
|
|
1490
1595
|
// Clear frozen reconnect content + forceStopped only on the false→true
|
|
1491
1596
|
// transition of isRuntimeRunning (i.e. a NEW run is actually starting).
|
|
1492
1597
|
// Reacting to "isRuntimeRunning is currently true" would clear the
|
|
@@ -1738,13 +1843,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1738
1843
|
? "act"
|
|
1739
1844
|
: undefined);
|
|
1740
1845
|
if (isRunning && intent === "immediate") {
|
|
1741
|
-
//
|
|
1742
|
-
//
|
|
1743
|
-
//
|
|
1744
|
-
|
|
1745
|
-
// going; the new POST would then 409, reconnect to the OLD run, and
|
|
1746
|
-
// replay the old answer under the new prompt.
|
|
1747
|
-
setQueuedMessages((prev) => [
|
|
1846
|
+
// Explicit interrupt path: abort the active server run, then let the
|
|
1847
|
+
// auto-dequeue path append this message once the run is clear. Normal
|
|
1848
|
+
// composer sends while running resolve to "queued" before reaching here.
|
|
1849
|
+
applyLocalQueuedMessages((prev) => [
|
|
1748
1850
|
...prev,
|
|
1749
1851
|
{
|
|
1750
1852
|
id: typeof crypto !== "undefined" && crypto.randomUUID
|
|
@@ -1759,14 +1861,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1759
1861
|
trackInRunsTray,
|
|
1760
1862
|
},
|
|
1761
1863
|
]);
|
|
1762
|
-
// Abort the server run (same as Stop button). This flips forceStopped
|
|
1763
|
-
// → isRunning=false → auto-dequeue fires → waitForThreadRunToClear →
|
|
1764
|
-
// append. The abort is fire-and-forget; waitForThreadRunToClear does
|
|
1765
|
-
// the actual wait.
|
|
1766
1864
|
stopActiveRunRef.current();
|
|
1767
1865
|
}
|
|
1768
1866
|
else if (isRunning && intent === "queued") {
|
|
1769
|
-
|
|
1867
|
+
applyLocalQueuedMessages((prev) => [
|
|
1770
1868
|
...prev,
|
|
1771
1869
|
{
|
|
1772
1870
|
id: typeof crypto !== "undefined" && crypto.randomUUID
|
|
@@ -1796,6 +1894,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1796
1894
|
updateComposerContextItems(() => []);
|
|
1797
1895
|
}
|
|
1798
1896
|
}, [
|
|
1897
|
+
applyLocalQueuedMessages,
|
|
1799
1898
|
buildComposerContextSubmission,
|
|
1800
1899
|
execMode,
|
|
1801
1900
|
isRunning,
|
|
@@ -2047,11 +2146,18 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2047
2146
|
}
|
|
2048
2147
|
setRunErrorInfo(null);
|
|
2049
2148
|
} })), (isReconnecting || reconnectFrozen) &&
|
|
2050
|
-
reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })),
|
|
2149
|
+
reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), showRunningInUI && (_jsx(RunningActivityStatus, { label: isReconnecting
|
|
2150
|
+
? "Reconnecting"
|
|
2151
|
+
: isAutoResuming
|
|
2152
|
+
? "Resuming"
|
|
2153
|
+
: // Keep a steady "Thinking" while the model works —
|
|
2154
|
+
// never flip through transient activity labels
|
|
2155
|
+
// (e.g. "Contacting model", "Preparing X action").
|
|
2156
|
+
"Thinking" })), queuedMessages.map((msg) => {
|
|
2051
2157
|
const displayText = msg.text
|
|
2052
2158
|
.replace(/<context>[\s\S]*?<\/context>\n?/g, "")
|
|
2053
2159
|
.trim();
|
|
2054
|
-
return (
|
|
2160
|
+
return (_jsxs("div", { className: "group flex items-start justify-end gap-1.5", children: [_jsx("button", { type: "button", onClick: () => applyLocalQueuedMessages((prev) => prev.filter((m) => m.id !== msg.id)), "aria-label": "Remove from queue", className: "mt-1.5 flex h-5 w-5 items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 shadow-sm transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100", children: _jsx(IconX, { className: "h-3 w-3" }) }), _jsxs("div", { className: "max-w-[85%] rounded-lg bg-accent/50 px-3 py-2 text-sm leading-relaxed text-foreground/60 whitespace-pre-wrap break-words", children: [displayText, msg.images && msg.images.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5 mt-1.5", children: msg.images.map((img, j) => (_jsx("img", { src: img, alt: "", className: "h-12 w-12 rounded object-cover border border-border/50" }, j))) }))] })] }, msg.id));
|
|
2055
2161
|
})] })) }), showScrollToBottom && (_jsx("div", { className: "shrink-0 flex justify-center -mb-1", children: _jsx("button", { type: "button", onClick: scrollToBottom, className: "flex h-7 w-7 items-center justify-center rounded-full border border-border bg-background shadow-sm hover:bg-accent", "aria-label": "Scroll to bottom", children: _jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" }) }) })), showComposerSlot ? composerSlot : null, guidedQuestions && guidedQuestions.length > 0 && (_jsx("div", { className: "shrink-0 px-3 pb-2 pt-1", children: _jsx("div", { className: "rounded-lg border border-border bg-card/60 shadow-sm", children: _jsx(GuidedQuestionFlow, { questions: guidedQuestions, onSubmit: handleGuidedQuestionsSubmit, onSkip: handleGuidedQuestionsSkip, ...(guidedQuestionsTitle
|
|
2056
2162
|
? { title: guidedQuestionsTitle }
|
|
2057
2163
|
: {}), ...(guidedQuestionsDescription
|
|
@@ -2060,14 +2166,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2060
2166
|
? { skipLabel: guidedQuestionsSkipLabel }
|
|
2061
2167
|
: {}), ...(guidedQuestionsSubmitLabel
|
|
2062
2168
|
? { submitLabel: guidedQuestionsSubmitLabel }
|
|
2063
|
-
: {}), className: "h-auto items-stretch justify-stretch bg-transparent" }) }) })), showPlanModeCallout && (_jsx(PlanModeCallout, { canImplementPlan: canImplementPlan, onImplementPlan: handleImplementPlan, onSwitchToAct: handleSwitchToAct })), _jsx(SelectionAttachedPill, {}),
|
|
2064
|
-
? "Reconnecting"
|
|
2065
|
-
: isAutoResuming
|
|
2066
|
-
? "Resuming"
|
|
2067
|
-
: // Keep a steady "Thinking" while the model works —
|
|
2068
|
-
// never flip through transient activity labels
|
|
2069
|
-
// (e.g. "Contacting model", "Preparing X action").
|
|
2070
|
-
"Thinking" })), composerError && (_jsxs("div", { role: "alert", className: "shrink-0 mx-3 mb-1.5 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [_jsx(IconAlertTriangle, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), _jsx("span", { className: "flex-1 leading-snug", children: composerError }), _jsx("button", { type: "button", "aria-label": "Dismiss error", onClick: () => setComposerError(null), className: "shrink-0 opacity-70 hover:opacity-100", children: _jsx(IconX, { className: "h-3 w-3" }) })] })), _jsxs(AgentComposerFrame, { layoutVariant: composerLayoutVariant, className: cn(composerAreaClassName, missingApiKey && "cursor-pointer", isComposerDisabled && "opacity-70"), onClick: missingApiKey
|
|
2169
|
+
: {}), className: "h-auto items-stretch justify-stretch bg-transparent" }) }) })), showPlanModeCallout && (_jsx(PlanModeCallout, { canImplementPlan: canImplementPlan, onImplementPlan: handleImplementPlan, onSwitchToAct: handleSwitchToAct })), _jsx(SelectionAttachedPill, {}), composerError && (_jsxs("div", { role: "alert", className: "shrink-0 mx-3 mb-1.5 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [_jsx(IconAlertTriangle, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), _jsx("span", { className: "flex-1 leading-snug", children: composerError }), _jsx("button", { type: "button", "aria-label": "Dismiss error", onClick: () => setComposerError(null), className: "shrink-0 opacity-70 hover:opacity-100", children: _jsx(IconX, { className: "h-3 w-3" }) })] })), _jsxs(AgentComposerFrame, { layoutVariant: composerLayoutVariant, className: cn(composerAreaClassName, missingApiKey && "cursor-pointer", isComposerDisabled && "opacity-70"), onClick: missingApiKey
|
|
2071
2170
|
? () => setMissingKeyBouncePulse((p) => p + 1)
|
|
2072
2171
|
: undefined, children: [_jsx(ComposerAttachmentPreviewStrip, {}), _jsx(TiptapComposer, { focusRef: tiptapRef, disabled: isComposerDisabled, placeholder: missingApiKey
|
|
2073
2172
|
? "Connect AI below to start chatting..."
|
|
@@ -2079,7 +2178,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2079
2178
|
? `${queuedMessages.length} queued — send a follow-up...`
|
|
2080
2179
|
: "Send a follow-up..."
|
|
2081
2180
|
: composerPlaceholder, onSubmit: isRunning || composerContextItems.length > 0
|
|
2082
|
-
? (text, references, attachments, options) => void addToQueue(text, undefined, references.length > 0 ? references : undefined, attachments, undefined,
|
|
2181
|
+
? (text, references, attachments, options) => void addToQueue(text, undefined, references.length > 0 ? references : undefined, attachments, undefined, resolveAssistantChatSubmitIntent({
|
|
2182
|
+
isRunning,
|
|
2183
|
+
requestedIntent: options?.intent,
|
|
2184
|
+
}), undefined, true)
|
|
2083
2185
|
: undefined, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, planModeDisabled: planModeDisabled, planModeDisabledReason: planModeDisabledReason, selectedModel: selectedModel ?? defaultModel, selectedEffort: selectedEffort, availableModels: availableModels, onModelChange: onModelChange, onEffortChange: onEffortChange, onConnectProvider: onConnectProvider, toolbarSlot: composerToolbarSlot, contextItems: composerContextItems, onRemoveContextItem: removeComposerContextItem, plusMenuMode: plusMenuMode, layoutVariant: composerLayoutVariant, providerConnectStatusEnabled: providerStatusChecksEnabled, draftScope: threadId || tabId, interceptBuildRequestsForBuilder: true, onAttachmentError: setComposerError, extraActionButton: contextXRayEnabled ||
|
|
2084
2186
|
composerExtraActionButton ||
|
|
2085
2187
|
showRunningInUI ? (_jsxs(_Fragment, { children: [contextXRayEnabled && (_jsx(ContextMeter, { threadId: threadId })), composerExtraActionButton, showRunningInUI && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: stopActiveRun, className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-muted text-foreground hover:bg-muted/80", children: _jsx(IconPlayerStop, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Stop generating" })] }))] })) : undefined })] }), missingApiKey && !authError ? (_jsx(BuilderSetupCard, { onConnected: handleBuilderConnected, bouncePulse: missingKeyBouncePulse })) : null] }) }) }) }) }) }));
|