@molecule/app-ide-react 1.14.0 → 1.16.0

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.
@@ -44,7 +44,7 @@ import { SettingsCard } from './SettingsCard.js';
44
44
  import { ShareModal } from './ShareModal.js';
45
45
  import { SkillsCard } from './SkillsCard.js';
46
46
  import { StreamingIndicator } from './StreamingIndicator.js';
47
- import { applyTestRunEvent, EMPTY_RUN_STATE, failRun, parseTestCommand, } from './tests-card-utilities.js';
47
+ import { applyTestRunEvent, buildTestFixMessage, EMPTY_RUN_STATE, failRun, markSkipUnavailable, parseTestCommand, requestSkip, } from './tests-card-utilities.js';
48
48
  import { TestsCard } from './TestsCard.js';
49
49
  import { TipCard } from './TipCard.js';
50
50
  import { ToolCallCard } from './ToolCallCard.js';
@@ -973,7 +973,7 @@ AuthorNameButton.displayName = 'AuthorNameButton';
973
973
  * @returns The rendered message item.
974
974
  */
975
975
  const MessageItem = memo(function MessageItem(props) {
976
- const { msg, sendMessage, handleAskUserResponse, isLoading, streamingStatus, onNavigatePreview, undoneTcIds, handleUndoToggle, onFileOpen, onFileDoubleClick, onFileDiff, handleFileRevert, setInputAndCursorEnd, setModelPicker, chatMode, userAvatar, onProfileClick, currentUserId, discovery, buildUpgradeCta, agentName, canEdit, showTimestamp, } = props;
976
+ const { msg, sendMessage, handleAskUserResponse, isLoading, streamingStatus, onNavigatePreview, undoneTcIds, handleUndoToggle, onFileOpen, onFileDoubleClick, onFileDiff, handleFileRevert, setInputAndCursorEnd, setModelPicker, chatMode, userAvatar, onProfileClick, currentUserId, discovery, buildUpgradeCta, agentName, canEdit, onSkipToolCall, skipToolCallReason, showTimestamp, } = props;
977
977
  const cm = getClassMap();
978
978
  const themeMode = useThemeMode();
979
979
  const isLight = themeMode === 'light';
@@ -1176,7 +1176,7 @@ const MessageItem = memo(function MessageItem(props) {
1176
1176
  const tc = msg.toolCalls?.find((c) => c.id === block.id);
1177
1177
  if (!tc)
1178
1178
  return null;
1179
- return (_jsx("div", { style: { marginTop: '4px' }, children: _jsx(ToolCallCard, { id: tc.id, name: tc.name, input: tc.input, output: tc.output, status: tc.status, fileDiff: tc.fileDiff, isUndone: undoneTcIds.has(tc.id), onUndoToggle: handleUndoToggle, onFileOpen: onFileOpen, onFileDoubleClick: onFileDoubleClick, onFileDiff: onFileDiff, onFileRevert: canEdit === false ? undefined : handleFileRevert, onAskUserResponse: canEdit === false ? undefined : handleAskUserResponse }) }, tc.id));
1179
+ return (_jsx("div", { style: { marginTop: '4px' }, children: _jsx(ToolCallCard, { id: tc.id, name: tc.name, input: tc.input, output: tc.output, status: tc.status, fileDiff: tc.fileDiff, isUndone: undoneTcIds.has(tc.id), onUndoToggle: handleUndoToggle, onFileOpen: onFileOpen, onFileDoubleClick: onFileDoubleClick, onFileDiff: onFileDiff, onFileRevert: canEdit === false ? undefined : handleFileRevert, onAskUserResponse: canEdit === false ? undefined : handleAskUserResponse, onSkip: onSkipToolCall, skipDisabledReason: skipToolCallReason ?? null }) }, tc.id));
1180
1180
  })) : msg.content ? (_jsx(MarkdownContent, { text: msg.content, isStreaming: msg.isStreaming, statusLabel: msg.isStreaming ? streamingStatus : undefined, statusStartedAt: typeof msg.timestamp === 'number' ? msg.timestamp : undefined, onNavigatePreview: onNavigatePreview, hideStreamingIndicator: true })) : null, msg.toolCalls &&
1181
1181
  msg.blocks &&
1182
1182
  msg.blocks.length > 0 &&
@@ -1187,10 +1187,10 @@ const MessageItem = memo(function MessageItem(props) {
1187
1187
  tc.output.status === 'awaiting_response' &&
1188
1188
  !msg.blocks.some((b) => b.type === 'tool_call' &&
1189
1189
  b.id === tc.id))
1190
- .map((tc) => (_jsx(ToolCallCard, { id: tc.id, name: tc.name, input: tc.input, output: tc.output, status: tc.status, fileDiff: tc.fileDiff, isUndone: undoneTcIds.has(tc.id), onUndoToggle: handleUndoToggle, onFileOpen: onFileOpen, onFileDoubleClick: onFileDoubleClick, onFileDiff: onFileDiff, onFileRevert: canEdit === false ? undefined : handleFileRevert, onAskUserResponse: canEdit === false ? undefined : handleAskUserResponse }, `orphan-ask-${tc.id}`))), msg.toolCalls &&
1190
+ .map((tc) => (_jsx(ToolCallCard, { id: tc.id, name: tc.name, input: tc.input, output: tc.output, status: tc.status, fileDiff: tc.fileDiff, isUndone: undoneTcIds.has(tc.id), onUndoToggle: handleUndoToggle, onFileOpen: onFileOpen, onFileDoubleClick: onFileDoubleClick, onFileDiff: onFileDiff, onFileRevert: canEdit === false ? undefined : handleFileRevert, onAskUserResponse: canEdit === false ? undefined : handleAskUserResponse, onSkip: onSkipToolCall, skipDisabledReason: skipToolCallReason ?? null }, `orphan-ask-${tc.id}`))), msg.toolCalls &&
1191
1191
  msg.toolCalls.length > 0 &&
1192
1192
  (!msg.blocks || msg.blocks.length === 0) &&
1193
- msg.toolCalls.map((tc) => (_jsx(ToolCallCard, { id: tc.id, name: tc.name, input: tc.input, output: tc.output, status: tc.status, fileDiff: tc.fileDiff, isUndone: undoneTcIds.has(tc.id), onUndoToggle: handleUndoToggle, onFileOpen: onFileOpen, onFileDoubleClick: onFileDoubleClick, onFileDiff: onFileDiff, onFileRevert: canEdit === false ? undefined : handleFileRevert, onAskUserResponse: canEdit === false ? undefined : handleAskUserResponse }, tc.id))), msg.aborted && (_jsx("span", { className: cm.cn(cm.textMuted, cm.textSize('xs')), style: { display: 'block', marginTop: 4, fontStyle: 'italic' }, children: t('ide.chat.responseStopped', undefined, {
1193
+ msg.toolCalls.map((tc) => (_jsx(ToolCallCard, { id: tc.id, name: tc.name, input: tc.input, output: tc.output, status: tc.status, fileDiff: tc.fileDiff, isUndone: undoneTcIds.has(tc.id), onUndoToggle: handleUndoToggle, onFileOpen: onFileOpen, onFileDoubleClick: onFileDoubleClick, onFileDiff: onFileDiff, onFileRevert: canEdit === false ? undefined : handleFileRevert, onAskUserResponse: canEdit === false ? undefined : handleAskUserResponse, onSkip: onSkipToolCall, skipDisabledReason: skipToolCallReason ?? null }, tc.id))), msg.aborted && (_jsx("span", { className: cm.cn(cm.textMuted, cm.textSize('xs')), style: { display: 'block', marginTop: 4, fontStyle: 'italic' }, children: t('ide.chat.responseStopped', undefined, {
1194
1194
  defaultValue: 'Response stopped',
1195
1195
  }) })), msg.loopLimitReached &&
1196
1196
  !msg.isStreaming &&
@@ -1281,7 +1281,7 @@ const MessageItem = memo(function MessageItem(props) {
1281
1281
  * @param props - Component props (see {@link MessageItemProps}).
1282
1282
  * @returns The rendered chat inner component.
1283
1283
  */
1284
- function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent, isPro, isAnonymous, canEdit, canShare, buildUpgradeCta, buildHelpUpgradeSection, activeFile, openTabs, onFileOpen, onFileDoubleClick, onFileDiff, onFileRevert, onFileChange, onFileDeleted, onCommit, onConversationId, onActivityClick, onRenderError, onProfileClick, currentUserId, onReadyToBuild, awaitingSandboxBoot, onClientAction, onTurnComplete, onLoadingChange, onNavigatePreview, onRegisterPushHandler, onRegisterHistoryReconcile, autoSubmitSignal, openSettingsSignal, onManageCustomModels, modelSelectionSignal, openReportSignal, openShareSignal, initialInputValue, pendingMessage, pendingMessageKey, pendingMessageSuppressUser, pendingMessageUserInitiated, userEditedFile, userEditedFileKey, gitStatusTick: externalGitStatusTick, discovery, userAvatar, agentName = DEFAULT_AGENT_NAME, productName = DEFAULT_PRODUCT_NAME, version, extraCommands, listTests, runTests, canRunTests, testsAvailable,
1284
+ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent, isPro, isAnonymous, canEdit, canShare, buildUpgradeCta, buildHelpUpgradeSection, activeFile, openTabs, onFileOpen, onFileDoubleClick, onFileDiff, onFileRevert, onFileChange, onFileDeleted, onCommit, onConversationId, onActivityClick, onRenderError, onProfileClick, currentUserId, onReadyToBuild, awaitingSandboxBoot, onClientAction, onTurnComplete, onLoadingChange, onNavigatePreview, onRegisterPushHandler, onRegisterHistoryReconcile, autoSubmitSignal, openSettingsSignal, onManageCustomModels, modelSelectionSignal, openReportSignal, openShareSignal, initialInputValue, pendingMessage, pendingMessageKey, pendingMessageSuppressUser, pendingMessageUserInitiated, userEditedFile, userEditedFileKey, gitStatusTick: externalGitStatusTick, discovery, userAvatar, agentName = DEFAULT_AGENT_NAME, productName = DEFAULT_PRODUCT_NAME, version, extraCommands, listTests, runTests, canRunTests, testsAvailable, skipToolCall,
1285
1285
  // feedbackUrl: prop kept for back-compat (callers still pass it), but no longer
1286
1286
  // consumed here — its only use was the command-menu footer link removed in P3-21.
1287
1287
  }) {
@@ -2641,6 +2641,8 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
2641
2641
  // would eventually capture stale.
2642
2642
  const testsRunningRef = useRef(false);
2643
2643
  testsRunningRef.current = testsRun.running;
2644
+ // Whether a TURN is in flight — a fix is a real message, so it waits its turn.
2645
+ const testsBusyRef = useRef(false);
2644
2646
  // Live for the async callbacks, so a list resolving after an unmount, or a
2645
2647
  // run event arriving then, never sets state on a dead tree.
2646
2648
  const testsMountedRef = useRef(true);
@@ -2700,7 +2702,7 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
2700
2702
  durationMs: null,
2701
2703
  }));
2702
2704
  try {
2703
- testsRunHandleRef.current = runTests(selection, (event) => {
2705
+ const handle = runTests(selection, (event) => {
2704
2706
  if (!testsMountedRef.current)
2705
2707
  return;
2706
2708
  setTestsRun((prev) => applyTestRunEvent(prev, event));
@@ -2711,6 +2713,12 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
2711
2713
  void refreshTests();
2712
2714
  }
2713
2715
  });
2716
+ testsRunHandleRef.current = handle;
2717
+ // Whether a Skip control belongs on screen is decided HERE, by whether
2718
+ // this host's handle serves one — not by the card guessing, and not by
2719
+ // a button that would do nothing when clicked.
2720
+ const skips = typeof handle.skipCurrent === 'function';
2721
+ setTestsRun((prev) => ({ ...prev, skipPending: false, skipUnavailable: !skips }));
2714
2722
  }
2715
2723
  catch (error) {
2716
2724
  logger.warn('Failed to start a test run', { error });
@@ -2721,11 +2729,82 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
2721
2729
  })));
2722
2730
  }
2723
2731
  }, [runTests, canRunTests, canEdit, testsAvailable, refreshTests]);
2732
+ // Hand the failing tests to the agent as ONE ordinary user message — the same
2733
+ // move as the editor’s "Fix with AI" and the auto-fix loop: compose the
2734
+ // problem, send it through the normal path, let the turn answer. The overlay
2735
+ // closes so the person watches the turn they just started.
2736
+ const fixTests = useCallback((failures) => {
2737
+ if (canEdit === false || failures.length === 0)
2738
+ return;
2739
+ if (testsBusyRef.current)
2740
+ return;
2741
+ const message = buildTestFixMessage(failures);
2742
+ if (!message)
2743
+ return;
2744
+ setPanelOverlay(null);
2745
+ sendMessageRef.current(message);
2746
+ }, [canEdit]);
2724
2747
  const cancelTestsRun = useCallback(() => {
2725
2748
  testsRunHandleRef.current?.cancel();
2726
2749
  testsRunHandleRef.current = null;
2727
- setTestsRun((prev) => ({ ...prev, running: false, currentId: null, outcome: 'cancelled' }));
2750
+ setTestsRun((prev) => ({
2751
+ ...prev,
2752
+ running: false,
2753
+ currentId: null,
2754
+ cases: {},
2755
+ skipPending: false,
2756
+ skipUnavailable: true,
2757
+ outcome: 'cancelled',
2758
+ }));
2728
2759
  }, []);
2760
+ // Skip the executor's in-flight tool call WITHOUT ending the turn — the
2761
+ // model is told the command did not run and carries on. The card owns its own
2762
+ // pressed state, so this just forwards the host's answer: `false` means the
2763
+ // call had already finished (a race the person did not cause), which the card
2764
+ // answers by returning the button to rest rather than reporting anything.
2765
+ const handleSkipToolCall = useCallback(async (toolCallId) => {
2766
+ if (canEdit === false || !skipToolCall)
2767
+ return false;
2768
+ try {
2769
+ return await skipToolCall(toolCallId);
2770
+ }
2771
+ catch (error) {
2772
+ logger.warn('Failed to skip the running tool call', { error });
2773
+ return false;
2774
+ }
2775
+ }, [canEdit, skipToolCall]);
2776
+ // Skip the command the run is ON, leaving the run itself alive. The state
2777
+ // only records that the request went out — the run's own `result` for that
2778
+ // file is what moves the row, so a skip can never paint itself as a pass. A
2779
+ // host answering "there was nothing to skip" is a race the person did not
2780
+ // cause: the control goes away, no error line.
2781
+ const skipCurrentTest = useCallback(() => {
2782
+ if (canEdit === false || canRunTests === false)
2783
+ return;
2784
+ const skip = testsRunHandleRef.current?.skipCurrent;
2785
+ if (!skip) {
2786
+ setTestsRun((prev) => markSkipUnavailable(prev));
2787
+ return;
2788
+ }
2789
+ setTestsRun((prev) => requestSkip(prev));
2790
+ const unavailable = () => {
2791
+ if (testsMountedRef.current)
2792
+ setTestsRun((prev) => markSkipUnavailable(prev));
2793
+ };
2794
+ try {
2795
+ const outcome = skip.call(testsRunHandleRef.current);
2796
+ if (outcome) {
2797
+ void outcome.then((accepted) => {
2798
+ if (accepted === false)
2799
+ unavailable();
2800
+ }, unavailable);
2801
+ }
2802
+ }
2803
+ catch (error) {
2804
+ logger.warn('Failed to skip the running test', { error });
2805
+ unavailable();
2806
+ }
2807
+ }, [canEdit, canRunTests]);
2729
2808
  /** Open the tests browser, re-listing so a spec just written shows up. */
2730
2809
  const openTestsBrowser = useCallback((query = '', runAll = false) => {
2731
2810
  openPanelOverlay('tests', query);
@@ -3144,6 +3223,8 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
3144
3223
  // last file change and the turn's end, never mid-turn.
3145
3224
  const autoCommitArmed = isAutoCommitArmed(autoCommit);
3146
3225
  const autoCommitHeld = isLoading || isRemoteStreaming || autoFixCountdown !== null;
3226
+ // Keep the tests-card fix gate live (declared above, where the run state is).
3227
+ testsBusyRef.current = isLoading || isRemoteStreaming;
3147
3228
  useEffect(() => {
3148
3229
  if (!autoCommitArmed || autoCommitHeld)
3149
3230
  return;
@@ -5823,7 +5904,15 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
5823
5904
  return (_jsx(ScriptsCard, { projectId: projectId, initialQuery: item.card.query ?? '', isLight: isLight, agentName: agentName }, item.card.id));
5824
5905
  }
5825
5906
  if (item.card.variant === 'tests') {
5826
- return (_jsx(TestsCard, { tests: testsList, status: testsStatus, run: testsRun, initialQuery: item.card.query ?? '', canRun: (canRunTests ?? canEdit !== false) && canEdit !== false, onRun: startTestsRun, onCancel: cancelTestsRun, isLight: isLight }, item.card.id));
5907
+ return (_jsx(TestsCard, { tests: testsList, status: testsStatus, run: testsRun, initialQuery: item.card.query ?? '', canRun: (canRunTests ?? canEdit !== false) && canEdit !== false, onRun: startTestsRun, onCancel: cancelTestsRun, onSkipCurrent: skipCurrentTest, onFix: fixTests, fixDisabledReason: canEdit === false
5908
+ ? t('ide.tests.viewerCannotRun', undefined, {
5909
+ defaultValue: 'Only editors can run this project’s tests.',
5910
+ })
5911
+ : isLoading || isRemoteStreaming
5912
+ ? t('ide.tests.fixBusy', undefined, {
5913
+ defaultValue: 'Wait for the current turn to finish.',
5914
+ })
5915
+ : null, isLight: isLight }, item.card.id));
5827
5916
  }
5828
5917
  if (item.card.variant === 'help') {
5829
5918
  // The plan/upgrade blurb is app-specific (pricing, plan names), so the
@@ -5916,7 +6005,11 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
5916
6005
  // MessageItem builds the identity from the message's own
5917
6006
  // author (teammates included), so the host shows their
5918
6007
  // view-only profile and the viewer's editable own.
5919
- onProfileClick: onProfileClick, currentUserId: currentUserId, showTimestamp: shownTimestampIds.has(msg.id), discovery: discovery, buildUpgradeCta: buildUpgradeCta, agentName: agentName, canEdit: canEdit }, msg.id));
6008
+ onProfileClick: onProfileClick, currentUserId: currentUserId, showTimestamp: shownTimestampIds.has(msg.id), discovery: discovery, buildUpgradeCta: buildUpgradeCta, agentName: agentName, canEdit: canEdit, onSkipToolCall: skipToolCall ? handleSkipToolCall : undefined, skipToolCallReason: canEdit === false
6009
+ ? t('ide.chat.skipToolCallViewer', undefined, {
6010
+ defaultValue: 'Only editors can skip this.',
6011
+ })
6012
+ : null }, msg.id));
5920
6013
  })()) }, item.kind === 'message' ? item.msg.id : item.card.id))), error &&
5921
6014
  !isStaleAnonymousLimit &&
5922
6015
  (errorMeta?.limitType ? (_jsx(ResourceLimitBanner, { message: error, action: buildUpgradeCta?.({
@@ -7061,7 +7154,15 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
7061
7154
  minHeight: 36,
7062
7155
  }
7063
7156
  : {}),
7064
- }, children: '✕' })] }), _jsxs("div", { style: { overflowY: 'auto', flex: 1 }, children: [panelOverlay === 'settings' && (_jsx(SettingsCard, { settings: computeSettingsList(), onRunCommand: (commandId) => void executeCommand(commandId), onPrefillInput: (input) => setInputAndCursorEnd(`${input} `), isLight: isLight, agentName: agentName, embedded: true })), panelOverlay === 'skills' && (_jsx(SkillsCard, { projectId: projectId, initialQuery: panelOverlayQuery, onLoad: loadSkill, onCreate: createSkill, loadedSkillPaths: loadedSkillPaths, defaultSkillPaths: defaultSkillPaths, onToggleDefault: toggleDefaultSkill, onResetDefault: resetDefaultSkills, defaultsExplicit: defaultSkillsExplicitRef.current, isLight: isLight, embedded: true })), panelOverlay === 'scripts' && (_jsx(ScriptsCard, { projectId: projectId, initialQuery: panelOverlayQuery, isLight: isLight, agentName: agentName, embedded: true })), panelOverlay === 'tests' && (_jsx(TestsCard, { tests: testsList, status: testsStatus, run: testsRun, initialQuery: panelOverlayQuery, canRun: (canRunTests ?? canEdit !== false) && canEdit !== false, onRun: startTestsRun, onCancel: cancelTestsRun, isLight: isLight, embedded: true }))] })] })), filePicker &&
7157
+ }, children: '✕' })] }), _jsxs("div", { style: { overflowY: 'auto', flex: 1 }, children: [panelOverlay === 'settings' && (_jsx(SettingsCard, { settings: computeSettingsList(), onRunCommand: (commandId) => void executeCommand(commandId), onPrefillInput: (input) => setInputAndCursorEnd(`${input} `), isLight: isLight, agentName: agentName, embedded: true })), panelOverlay === 'skills' && (_jsx(SkillsCard, { projectId: projectId, initialQuery: panelOverlayQuery, onLoad: loadSkill, onCreate: createSkill, loadedSkillPaths: loadedSkillPaths, defaultSkillPaths: defaultSkillPaths, onToggleDefault: toggleDefaultSkill, onResetDefault: resetDefaultSkills, defaultsExplicit: defaultSkillsExplicitRef.current, isLight: isLight, embedded: true })), panelOverlay === 'scripts' && (_jsx(ScriptsCard, { projectId: projectId, initialQuery: panelOverlayQuery, isLight: isLight, agentName: agentName, embedded: true })), panelOverlay === 'tests' && (_jsx(TestsCard, { tests: testsList, status: testsStatus, run: testsRun, initialQuery: panelOverlayQuery, canRun: (canRunTests ?? canEdit !== false) && canEdit !== false, onRun: startTestsRun, onCancel: cancelTestsRun, onSkipCurrent: skipCurrentTest, onFix: fixTests, fixDisabledReason: canEdit === false
7158
+ ? t('ide.tests.viewerCannotRun', undefined, {
7159
+ defaultValue: 'Only editors can run this project’s tests.',
7160
+ })
7161
+ : isLoading || isRemoteStreaming
7162
+ ? t('ide.tests.fixBusy', undefined, {
7163
+ defaultValue: 'Wait for the current turn to finish.',
7164
+ })
7165
+ : null, isLight: isLight, embedded: true }))] })] })), filePicker &&
7065
7166
  filteredEntries.length > 0 &&
7066
7167
  (() => {
7067
7168
  const normalizeTabPath = (p) => p.startsWith('/workspace/')
@@ -7808,7 +7909,7 @@ function ChatInner({ projectId, endpoint, initialMessage, onInitialMessageSent,
7808
7909
  * @param props - Component props (see {@link MessageItemProps}).
7809
7910
  * @returns The rendered chat panel element.
7810
7911
  */
7811
- export function ChatPanel({ projectId, endpoint, initialMessage, onInitialMessageSent, activeFile, openTabs, onFileOpen, onFileDoubleClick, onFileDiff, onFileRevert, onFileChange, onFileDeleted, onCommit, onActivityClick, onRenderError, onProfileClick, currentUserId, onReadyToBuild, awaitingSandboxBoot, onClientAction, onTurnComplete, onLoadingChange, onNavigatePreview, onRegisterPushHandler, onRegisterHistoryReconcile, autoSubmitSignal, initialInputValue, hideConversationMenu, renderConversationHeader = true, conversationId: controlledConversationId, chatKey: controlledChatKey, onConversationId: controlledOnConversationId, openShareSignal: controlledShareSignal, openReportSignal: controlledReportSignal, openSettingsSignal: controlledSettingsSignal, onManageCustomModels, gitStatusTick, pendingMessage, pendingMessageKey, pendingMessageSuppressUser, pendingMessageUserInitiated, userEditedFile, userEditedFileKey, isPro, isAnonymous, canEdit = true, canShare, buildUpgradeCta, buildHelpUpgradeSection, userAvatar, agentName, productName, version, extraCommands, feedbackUrl, listTests, runTests, canRunTests, testsAvailable, className, }) {
7912
+ export function ChatPanel({ projectId, endpoint, initialMessage, onInitialMessageSent, activeFile, openTabs, onFileOpen, onFileDoubleClick, onFileDiff, onFileRevert, onFileChange, onFileDeleted, onCommit, onActivityClick, onRenderError, onProfileClick, currentUserId, onReadyToBuild, awaitingSandboxBoot, onClientAction, onTurnComplete, onLoadingChange, onNavigatePreview, onRegisterPushHandler, onRegisterHistoryReconcile, autoSubmitSignal, initialInputValue, hideConversationMenu, renderConversationHeader = true, conversationId: controlledConversationId, chatKey: controlledChatKey, onConversationId: controlledOnConversationId, openShareSignal: controlledShareSignal, openReportSignal: controlledReportSignal, openSettingsSignal: controlledSettingsSignal, onManageCustomModels, gitStatusTick, pendingMessage, pendingMessageKey, pendingMessageSuppressUser, pendingMessageUserInitiated, userEditedFile, userEditedFileKey, isPro, isAnonymous, canEdit = true, canShare, buildUpgradeCta, buildHelpUpgradeSection, userAvatar, agentName, productName, version, extraCommands, feedbackUrl, listTests, runTests, canRunTests, testsAvailable, skipToolCall, className, }) {
7812
7913
  const cm = getClassMap();
7813
7914
  // Share management may be gated ABOVE canEdit by the host (see
7814
7915
  // ChatPanelProps.canShare) — gates the built-in header share button here and
@@ -8021,7 +8122,7 @@ export function ChatPanel({ projectId, endpoint, initialMessage, onInitialMessag
8021
8122
  textOverflow: 'ellipsis',
8022
8123
  whiteSpace: 'nowrap',
8023
8124
  width: '100%',
8024
- }, children: conv.preview ?? 'New conversation' }), _jsx("span", { className: cm.cn(cm.textMuted, cm.textSize('xs')), style: { opacity: 0.55 }, children: relativeTime(conv.updatedAt) })] }, conv.id)))] }))] })), _jsx(ChatInner, { projectId: projectId, endpoint: chatEndpoint, initialMessage: initialMessage, onInitialMessageSent: onInitialMessageSent, isPro: isPro, isAnonymous: isAnonymous, canEdit: canEdit, canShare: shareAllowed, buildUpgradeCta: buildUpgradeCta, buildHelpUpgradeSection: buildHelpUpgradeSection, activeFile: activeFile, openTabs: openTabs, onFileOpen: onFileOpen, onFileDoubleClick: onFileDoubleClick, onFileDiff: onFileDiff, onFileRevert: onFileRevert, onFileChange: onFileChange, onFileDeleted: onFileDeleted, onCommit: onCommit, onConversationId: reportConversationId, onActivityClick: onActivityClick, onRenderError: onRenderError, onProfileClick: onProfileClick, currentUserId: currentUserId, onReadyToBuild: onReadyToBuild, awaitingSandboxBoot: awaitingSandboxBoot, onClientAction: onClientAction, onTurnComplete: onTurnComplete, onLoadingChange: onLoadingChange, onNavigatePreview: onNavigatePreview, onRegisterPushHandler: onRegisterPushHandler, onRegisterHistoryReconcile: onRegisterHistoryReconcile, autoSubmitSignal: autoSubmitSignal, openSettingsSignal: effectiveSettingsSignal, onManageCustomModels: onManageCustomModels, openReportSignal: effectiveReportSignal, openShareSignal: effectiveShareSignal, initialInputValue: initialInputValue, pendingMessage: pendingMessage, pendingMessageKey: pendingMessageKey, pendingMessageSuppressUser: pendingMessageSuppressUser, pendingMessageUserInitiated: pendingMessageUserInitiated, userEditedFile: userEditedFile, userEditedFileKey: userEditedFileKey, gitStatusTick: gitStatusTick, discovery: hideConversationMenu, userAvatar: userAvatar, agentName: agentName, productName: productName, version: version, extraCommands: extraCommands, feedbackUrl: feedbackUrl, listTests: listTests, runTests: runTests, canRunTests: canRunTests, testsAvailable: testsAvailable }, chatKey)] }));
8125
+ }, children: conv.preview ?? 'New conversation' }), _jsx("span", { className: cm.cn(cm.textMuted, cm.textSize('xs')), style: { opacity: 0.55 }, children: relativeTime(conv.updatedAt) })] }, conv.id)))] }))] })), _jsx(ChatInner, { projectId: projectId, endpoint: chatEndpoint, initialMessage: initialMessage, onInitialMessageSent: onInitialMessageSent, isPro: isPro, isAnonymous: isAnonymous, canEdit: canEdit, canShare: shareAllowed, buildUpgradeCta: buildUpgradeCta, buildHelpUpgradeSection: buildHelpUpgradeSection, activeFile: activeFile, openTabs: openTabs, onFileOpen: onFileOpen, onFileDoubleClick: onFileDoubleClick, onFileDiff: onFileDiff, onFileRevert: onFileRevert, onFileChange: onFileChange, onFileDeleted: onFileDeleted, onCommit: onCommit, onConversationId: reportConversationId, onActivityClick: onActivityClick, onRenderError: onRenderError, onProfileClick: onProfileClick, currentUserId: currentUserId, onReadyToBuild: onReadyToBuild, awaitingSandboxBoot: awaitingSandboxBoot, onClientAction: onClientAction, onTurnComplete: onTurnComplete, onLoadingChange: onLoadingChange, onNavigatePreview: onNavigatePreview, onRegisterPushHandler: onRegisterPushHandler, onRegisterHistoryReconcile: onRegisterHistoryReconcile, autoSubmitSignal: autoSubmitSignal, openSettingsSignal: effectiveSettingsSignal, onManageCustomModels: onManageCustomModels, openReportSignal: effectiveReportSignal, openShareSignal: effectiveShareSignal, initialInputValue: initialInputValue, pendingMessage: pendingMessage, pendingMessageKey: pendingMessageKey, pendingMessageSuppressUser: pendingMessageSuppressUser, pendingMessageUserInitiated: pendingMessageUserInitiated, userEditedFile: userEditedFile, userEditedFileKey: userEditedFileKey, gitStatusTick: gitStatusTick, discovery: hideConversationMenu, userAvatar: userAvatar, agentName: agentName, productName: productName, version: version, extraCommands: extraCommands, feedbackUrl: feedbackUrl, listTests: listTests, runTests: runTests, canRunTests: canRunTests, testsAvailable: testsAvailable, skipToolCall: skipToolCall }, chatKey)] }));
8025
8126
  }
8026
8127
  ChatPanel.displayName = 'ChatPanel';
8027
8128
  //# sourceMappingURL=ChatPanel.js.map