@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.
- package/README.md +261 -7
- package/dist/components/ChatPanel.d.ts +10 -1
- package/dist/components/ChatPanel.d.ts.map +1 -1
- package/dist/components/ChatPanel.js +114 -13
- package/dist/components/ChatPanel.js.map +1 -1
- package/dist/components/TestsCard.d.ts +27 -3
- package/dist/components/TestsCard.d.ts.map +1 -1
- package/dist/components/TestsCard.js +116 -21
- package/dist/components/TestsCard.js.map +1 -1
- package/dist/components/ToolCallCard.d.ts +7 -1
- package/dist/components/ToolCallCard.d.ts.map +1 -1
- package/dist/components/ToolCallCard.js +133 -94
- package/dist/components/ToolCallCard.js.map +1 -1
- package/dist/components/tests-card-utilities.d.ts +108 -2
- package/dist/components/tests-card-utilities.d.ts.map +1 -1
- package/dist/components/tests-card-utilities.js +205 -6
- package/dist/components/tests-card-utilities.js.map +1 -1
- package/dist/components/tool-call-utilities.d.ts +13 -0
- package/dist/components/tool-call-utilities.d.ts.map +1 -1
- package/dist/components/tool-call-utilities.js +22 -0
- package/dist/components/tool-call-utilities.js.map +1 -1
- package/dist/types.d.ts +60 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -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
|
-
|
|
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) => ({
|
|
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,
|
|
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
|
|
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,
|
|
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
|