@alpaca-editor/core 1.0.4037 → 1.0.4039
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/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/textarea.js +7 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/editor/Terminal.js +20 -0
- package/dist/editor/Terminal.js.map +1 -1
- package/dist/editor/ai/Agents.js +14 -0
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiPromptPopover.js +26 -26
- package/dist/editor/ai/AiPromptPopover.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.js +8 -6
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/AiTerminal.d.ts +2 -0
- package/dist/editor/ai/AiTerminal.js +179 -38
- package/dist/editor/ai/AiTerminal.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js +5 -2
- package/dist/editor/field-types/SingleLineText.js.map +1 -1
- package/dist/editor/services/agentService.js +54 -9
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/styles.css +9 -5
- package/package.json +1 -1
- package/src/components/ui/textarea.tsx +18 -0
- package/src/editor/Terminal.tsx +21 -0
- package/src/editor/ai/Agents.tsx +20 -0
- package/src/editor/ai/AiPromptPopover.tsx +29 -32
- package/src/editor/ai/AiResponseMessage.tsx +22 -6
- package/src/editor/ai/AiTerminal.tsx +250 -50
- package/src/editor/field-types/SingleLineText.tsx +18 -1
- package/src/editor/services/agentService.ts +86 -11
- package/src/revision.ts +2 -2
|
@@ -72,6 +72,8 @@ export type ToolCall = {
|
|
|
72
72
|
function: {
|
|
73
73
|
name: string;
|
|
74
74
|
arguments: string;
|
|
75
|
+
result?: string;
|
|
76
|
+
error?: string;
|
|
75
77
|
};
|
|
76
78
|
};
|
|
77
79
|
|
|
@@ -202,17 +204,35 @@ export function AiTerminal({
|
|
|
202
204
|
// Agent reconnection logic
|
|
203
205
|
useEffect(() => {
|
|
204
206
|
async function checkAndReconnectAgent() {
|
|
205
|
-
if (!editContext || !agentId)
|
|
207
|
+
if (!editContext || !editContext.sessionId || !agentId) {
|
|
208
|
+
console.log(
|
|
209
|
+
"RECONNECT: Skipping reconnection - missing editContext or agentId",
|
|
210
|
+
{
|
|
211
|
+
editContext: !!editContext,
|
|
212
|
+
sessionId: editContext?.sessionId,
|
|
213
|
+
agentId,
|
|
214
|
+
},
|
|
215
|
+
);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
206
218
|
|
|
207
219
|
const context = createAiContext({ editContext });
|
|
208
220
|
|
|
209
221
|
try {
|
|
210
|
-
console.log(
|
|
222
|
+
console.log(
|
|
223
|
+
"RECONNECT: Checking agent state for reconnection:",
|
|
224
|
+
agentId,
|
|
225
|
+
);
|
|
211
226
|
const agentState = await checkAgentState(agentId, context);
|
|
227
|
+
console.log("RECONNECT: Agent state check result:", {
|
|
228
|
+
exists: agentState.exists,
|
|
229
|
+
isRunning: agentState.isRunning,
|
|
230
|
+
status: agentState.agent?.status,
|
|
231
|
+
});
|
|
212
232
|
|
|
213
233
|
if (agentState.exists && agentState.agent) {
|
|
214
234
|
console.log(
|
|
215
|
-
"Found existing agent, restoring state:",
|
|
235
|
+
"RECONNECT: Found existing agent, restoring state:",
|
|
216
236
|
agentState.agent,
|
|
217
237
|
);
|
|
218
238
|
|
|
@@ -226,13 +246,32 @@ export function AiTerminal({
|
|
|
226
246
|
const terminalMessages = convertAgentMessagesToTerminalFormat(
|
|
227
247
|
agent.messages,
|
|
228
248
|
);
|
|
229
|
-
console.log(
|
|
249
|
+
console.log(
|
|
250
|
+
"RECONNECT: Restoring messages:",
|
|
251
|
+
terminalMessages.length,
|
|
252
|
+
"messages",
|
|
253
|
+
);
|
|
230
254
|
setMessages(terminalMessages);
|
|
231
255
|
setResponseMessages(terminalMessages);
|
|
256
|
+
} else {
|
|
257
|
+
console.log(
|
|
258
|
+
"RECONNECT: Skipping message restoration - no messages or already initialized",
|
|
259
|
+
{
|
|
260
|
+
hasAgentMessages: !!agent.messages,
|
|
261
|
+
agentMessageCount: agent.messages?.length || 0,
|
|
262
|
+
hasInitialMessages: !!options?.initialMessages,
|
|
263
|
+
initialMessageCount: options?.initialMessages?.length || 0,
|
|
264
|
+
},
|
|
265
|
+
);
|
|
232
266
|
}
|
|
233
267
|
|
|
234
268
|
// Set cost information if available
|
|
235
269
|
if (agent.totalCost !== undefined) {
|
|
270
|
+
console.log("RECONNECT: Setting cost information:", {
|
|
271
|
+
totalCost: agent.totalCost,
|
|
272
|
+
totalInputTokens: agent.totalInputTokens,
|
|
273
|
+
totalOutputTokens: agent.totalOutputTokens,
|
|
274
|
+
});
|
|
236
275
|
setResponse(
|
|
237
276
|
(prev) =>
|
|
238
277
|
({
|
|
@@ -250,30 +289,52 @@ export function AiTerminal({
|
|
|
250
289
|
|
|
251
290
|
// If agent is still running, reconnect to the stream
|
|
252
291
|
if (agentState.isRunning) {
|
|
253
|
-
console.log(
|
|
292
|
+
console.log(
|
|
293
|
+
"RECONNECT: Agent is still running, attempting to reconnect to stream",
|
|
294
|
+
);
|
|
295
|
+
setIsRunning(true);
|
|
254
296
|
await reconnectToRunningAgent(agentId, context);
|
|
255
297
|
} else {
|
|
256
298
|
console.log(
|
|
257
|
-
"Agent completed while disconnected, showing final state",
|
|
299
|
+
"RECONNECT: Agent completed while disconnected, showing final state",
|
|
258
300
|
);
|
|
259
301
|
}
|
|
260
302
|
} else {
|
|
261
|
-
console.log(
|
|
303
|
+
console.log(
|
|
304
|
+
"RECONNECT: No existing agent found or agent doesn't exist",
|
|
305
|
+
);
|
|
262
306
|
}
|
|
263
307
|
} catch (error) {
|
|
264
|
-
console.error("Failed to check agent state:", error);
|
|
265
|
-
|
|
308
|
+
console.error("RECONNECT: Failed to check agent state:", error);
|
|
309
|
+
setTerminalError(
|
|
310
|
+
`Reconnection failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
311
|
+
);
|
|
266
312
|
}
|
|
267
313
|
}
|
|
268
314
|
|
|
269
|
-
// Only try to reconnect if we have an agentId and
|
|
270
|
-
if (agentId && editContext) {
|
|
315
|
+
// Only try to reconnect if we have an agentId and edit context
|
|
316
|
+
if (agentId && editContext && editContext.sessionId) {
|
|
317
|
+
console.log("RECONNECT: Starting reconnection check for agent:", agentId);
|
|
271
318
|
checkAndReconnectAgent();
|
|
319
|
+
} else {
|
|
320
|
+
console.log(
|
|
321
|
+
"RECONNECT: Skipping reconnection check - conditions not met",
|
|
322
|
+
{
|
|
323
|
+
hasAgentId: !!agentId,
|
|
324
|
+
hasEditContext: !!editContext,
|
|
325
|
+
hasSessionId: !!editContext?.sessionId,
|
|
326
|
+
},
|
|
327
|
+
);
|
|
272
328
|
}
|
|
273
|
-
}, [agentId]); //
|
|
329
|
+
}, [agentId, editContext?.sessionId]); // Run when agentId or session becomes available
|
|
274
330
|
|
|
275
331
|
// Function to reconnect to a running agent stream
|
|
276
332
|
async function reconnectToRunningAgent(agentId: string, context: AiContext) {
|
|
333
|
+
console.log(
|
|
334
|
+
"RECONNECT: Starting reconnectToRunningAgent for agent:",
|
|
335
|
+
agentId,
|
|
336
|
+
);
|
|
337
|
+
|
|
277
338
|
try {
|
|
278
339
|
const abortController = new AbortController();
|
|
279
340
|
abortControllerRef.current = abortController;
|
|
@@ -289,34 +350,84 @@ export function AiTerminal({
|
|
|
289
350
|
};
|
|
290
351
|
let completionProcessed = false;
|
|
291
352
|
|
|
292
|
-
console.log("
|
|
353
|
+
console.log("RECONNECT: Attempting to connect to agent stream:", agentId);
|
|
354
|
+
console.log(
|
|
355
|
+
"RECONNECT: Current messages state:",
|
|
356
|
+
messages.length,
|
|
357
|
+
"messages",
|
|
358
|
+
);
|
|
359
|
+
|
|
293
360
|
await connectToAgentStream(
|
|
294
361
|
agentId,
|
|
295
362
|
context,
|
|
296
363
|
(streamMessage) => {
|
|
297
364
|
console.log(
|
|
298
|
-
"
|
|
365
|
+
"RECONNECT: Received stream message:",
|
|
299
366
|
streamMessage.type,
|
|
300
367
|
streamMessage,
|
|
301
368
|
);
|
|
302
369
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
370
|
+
if (!streamMessage || !streamMessage.type) {
|
|
371
|
+
console.error(
|
|
372
|
+
"RECONNECT: Invalid stream message received:",
|
|
373
|
+
streamMessage,
|
|
374
|
+
);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Reuse stream message handling, but pipe updates into Terminal via TerminalService
|
|
379
|
+
try {
|
|
380
|
+
const terminalCallback = (
|
|
381
|
+
text: React.ReactNode,
|
|
382
|
+
finished: boolean,
|
|
383
|
+
) => {
|
|
384
|
+
TerminalService.emit("response", { text, finished });
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const result = handleStreamMessage(
|
|
388
|
+
streamMessage,
|
|
389
|
+
accumulatedResponse,
|
|
390
|
+
completionProcessed,
|
|
391
|
+
context,
|
|
392
|
+
terminalCallback,
|
|
393
|
+
);
|
|
394
|
+
if (result) {
|
|
395
|
+
accumulatedResponse = result.accumulatedResponse;
|
|
396
|
+
completionProcessed = result.completionProcessed;
|
|
397
|
+
}
|
|
398
|
+
} catch (error) {
|
|
399
|
+
console.error(
|
|
400
|
+
"RECONNECT: Error handling stream message:",
|
|
401
|
+
error,
|
|
402
|
+
streamMessage,
|
|
403
|
+
);
|
|
404
|
+
}
|
|
311
405
|
},
|
|
312
406
|
abortController.signal,
|
|
313
407
|
);
|
|
408
|
+
|
|
409
|
+
console.log(
|
|
410
|
+
"RECONNECT: Successfully completed reconnection to agent stream:",
|
|
411
|
+
agentId,
|
|
412
|
+
);
|
|
413
|
+
setIsRunning(false);
|
|
314
414
|
} catch (error) {
|
|
315
|
-
console.error("Failed to reconnect to agent stream:", error);
|
|
415
|
+
console.error("RECONNECT: Failed to reconnect to agent stream:", error);
|
|
316
416
|
setIsRunning(false);
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
417
|
+
|
|
418
|
+
// Check if it's an abort error (user cancelled)
|
|
419
|
+
const isAbortError =
|
|
420
|
+
error instanceof Error &&
|
|
421
|
+
(error.name === "AbortError" ||
|
|
422
|
+
error.message.toLowerCase().includes("abort"));
|
|
423
|
+
|
|
424
|
+
if (!isAbortError) {
|
|
425
|
+
const errorMessage = `Failed to reconnect to agent: ${error instanceof Error ? error.message : "Unknown error"}`;
|
|
426
|
+
console.error("RECONNECT: Setting terminal error:", errorMessage);
|
|
427
|
+
setTerminalError(errorMessage);
|
|
428
|
+
} else {
|
|
429
|
+
console.log("RECONNECT: Connection was aborted (user cancelled)");
|
|
430
|
+
}
|
|
320
431
|
}
|
|
321
432
|
}
|
|
322
433
|
|
|
@@ -326,7 +437,8 @@ export function AiTerminal({
|
|
|
326
437
|
accumulatedResponse: any,
|
|
327
438
|
completionProcessed: boolean,
|
|
328
439
|
context: AiContext,
|
|
329
|
-
|
|
440
|
+
terminalCallback: (text: React.ReactNode, finished: boolean) => void,
|
|
441
|
+
): { accumulatedResponse: any; completionProcessed: boolean } | void {
|
|
330
442
|
// Safety check for valid stream message
|
|
331
443
|
if (!streamMessage || !streamMessage.type) {
|
|
332
444
|
console.error("Invalid stream message received:", streamMessage);
|
|
@@ -392,7 +504,7 @@ export function AiTerminal({
|
|
|
392
504
|
};
|
|
393
505
|
|
|
394
506
|
// Update accumulated response with incremental content
|
|
395
|
-
|
|
507
|
+
const newAccumulated = {
|
|
396
508
|
...accumulatedResponse,
|
|
397
509
|
...streamMessage.data,
|
|
398
510
|
messages: updatedMessages,
|
|
@@ -400,45 +512,132 @@ export function AiTerminal({
|
|
|
400
512
|
streamMessage.data.editOperations ||
|
|
401
513
|
accumulatedResponse.editOperations,
|
|
402
514
|
};
|
|
515
|
+
accumulatedResponse = newAccumulated;
|
|
403
516
|
} else {
|
|
404
517
|
// Non-incremental update - use as provided
|
|
405
|
-
|
|
518
|
+
const newAccumulated = {
|
|
406
519
|
...accumulatedResponse,
|
|
407
520
|
...streamMessage.data,
|
|
408
521
|
editOperations:
|
|
409
522
|
streamMessage.data.editOperations ||
|
|
410
523
|
accumulatedResponse.editOperations,
|
|
411
524
|
};
|
|
525
|
+
accumulatedResponse = newAccumulated;
|
|
412
526
|
}
|
|
413
527
|
|
|
414
528
|
// Always trigger UI update for content chunks
|
|
415
|
-
handleResponse(accumulatedResponse,
|
|
529
|
+
handleResponse(accumulatedResponse, terminalCallback, false);
|
|
416
530
|
}
|
|
417
|
-
|
|
531
|
+
return { accumulatedResponse, completionProcessed };
|
|
418
532
|
|
|
419
533
|
case AgentStreamMessageType.ToolCall:
|
|
420
|
-
// Handle tool calls - simplified for reconnection
|
|
421
534
|
if (streamMessage.data && typeof streamMessage.data === "object") {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
535
|
+
// Find or create the assistant message that contains this tool call
|
|
536
|
+
const updatedMessages = [...(accumulatedResponse.messages || [])];
|
|
537
|
+
let lastAssistantMessage = null;
|
|
538
|
+
let lastAssistantIndex = -1;
|
|
539
|
+
|
|
540
|
+
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
541
|
+
if (updatedMessages[i].role === "assistant") {
|
|
542
|
+
lastAssistantMessage = updatedMessages[i];
|
|
543
|
+
lastAssistantIndex = i;
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// If no assistant message exists, create one
|
|
549
|
+
if (!lastAssistantMessage) {
|
|
550
|
+
lastAssistantMessage = {
|
|
551
|
+
id: crypto.randomUUID(),
|
|
552
|
+
role: "assistant",
|
|
553
|
+
name: "assistant",
|
|
554
|
+
content: "",
|
|
555
|
+
tool_calls: [],
|
|
556
|
+
} as Message;
|
|
557
|
+
updatedMessages.push(lastAssistantMessage);
|
|
558
|
+
lastAssistantIndex = updatedMessages.length - 1;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const toolCall = {
|
|
562
|
+
id: streamMessage.data.id,
|
|
563
|
+
displayName: streamMessage.data.displayName,
|
|
564
|
+
function: {
|
|
565
|
+
name:
|
|
566
|
+
streamMessage.data.function?.name || streamMessage.data.name,
|
|
567
|
+
arguments:
|
|
568
|
+
streamMessage.data.function?.arguments ||
|
|
569
|
+
streamMessage.data.arguments,
|
|
570
|
+
},
|
|
571
|
+
} as any;
|
|
572
|
+
|
|
573
|
+
const existingToolCalls = lastAssistantMessage.tool_calls || [];
|
|
574
|
+
const existingIndex = existingToolCalls.findIndex(
|
|
575
|
+
(tc: any) => tc.id === toolCall.id,
|
|
425
576
|
);
|
|
426
|
-
|
|
427
|
-
|
|
577
|
+
let updatedToolCalls;
|
|
578
|
+
if (existingIndex >= 0) {
|
|
579
|
+
updatedToolCalls = [...existingToolCalls];
|
|
580
|
+
updatedToolCalls[existingIndex] = toolCall;
|
|
581
|
+
} else {
|
|
582
|
+
updatedToolCalls = [...existingToolCalls, toolCall];
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
updatedMessages[lastAssistantIndex] = {
|
|
586
|
+
...lastAssistantMessage,
|
|
587
|
+
tool_calls: updatedToolCalls,
|
|
588
|
+
} as Message;
|
|
589
|
+
|
|
590
|
+
const newAccumulated = {
|
|
591
|
+
...accumulatedResponse,
|
|
592
|
+
messages: updatedMessages,
|
|
593
|
+
};
|
|
594
|
+
accumulatedResponse = newAccumulated;
|
|
595
|
+
|
|
596
|
+
handleResponse(accumulatedResponse, terminalCallback, false);
|
|
428
597
|
}
|
|
429
|
-
|
|
598
|
+
return { accumulatedResponse, completionProcessed };
|
|
430
599
|
|
|
431
600
|
case AgentStreamMessageType.ToolResult:
|
|
432
|
-
// Handle tool results - simplified for reconnection
|
|
433
601
|
if (streamMessage.data && typeof streamMessage.data === "object") {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
602
|
+
const updatedMessages = [...(accumulatedResponse.messages || [])];
|
|
603
|
+
// Find the assistant message with the matching tool call ID
|
|
604
|
+
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
605
|
+
if (
|
|
606
|
+
updatedMessages[i].role === "assistant" &&
|
|
607
|
+
updatedMessages[i].tool_calls
|
|
608
|
+
) {
|
|
609
|
+
const toolCalls = updatedMessages[i].tool_calls || [];
|
|
610
|
+
const toolCallIndex = toolCalls.findIndex(
|
|
611
|
+
(tc: any) => tc.id === streamMessage.data.toolCallId,
|
|
612
|
+
);
|
|
613
|
+
if (toolCallIndex >= 0) {
|
|
614
|
+
const updatedToolCalls = [...toolCalls];
|
|
615
|
+
updatedToolCalls[toolCallIndex] = {
|
|
616
|
+
...updatedToolCalls[toolCallIndex],
|
|
617
|
+
function: {
|
|
618
|
+
...updatedToolCalls[toolCallIndex].function,
|
|
619
|
+
result: streamMessage.data.result,
|
|
620
|
+
error: streamMessage.data.error,
|
|
621
|
+
},
|
|
622
|
+
};
|
|
623
|
+
updatedMessages[i] = {
|
|
624
|
+
...updatedMessages[i],
|
|
625
|
+
tool_calls: updatedToolCalls,
|
|
626
|
+
} as Message;
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
const newAccumulated = {
|
|
633
|
+
...accumulatedResponse,
|
|
634
|
+
messages: updatedMessages,
|
|
635
|
+
};
|
|
636
|
+
accumulatedResponse = newAccumulated;
|
|
637
|
+
|
|
638
|
+
handleResponse(accumulatedResponse, terminalCallback, false);
|
|
440
639
|
}
|
|
441
|
-
|
|
640
|
+
return { accumulatedResponse, completionProcessed };
|
|
442
641
|
|
|
443
642
|
case AgentStreamMessageType.Completed:
|
|
444
643
|
if (!completionProcessed) {
|
|
@@ -446,16 +645,16 @@ export function AiTerminal({
|
|
|
446
645
|
console.log("Agent execution completed");
|
|
447
646
|
setIsRunning(false);
|
|
448
647
|
if (streamMessage.data) {
|
|
449
|
-
handleResponse(streamMessage.data,
|
|
648
|
+
handleResponse(streamMessage.data, terminalCallback, true);
|
|
450
649
|
}
|
|
451
650
|
}
|
|
452
|
-
|
|
651
|
+
return { accumulatedResponse, completionProcessed };
|
|
453
652
|
|
|
454
653
|
case AgentStreamMessageType.Error:
|
|
455
654
|
console.error("Agent execution error:", streamMessage);
|
|
456
655
|
setIsRunning(false);
|
|
457
656
|
setTerminalError(streamMessage.error || "Agent execution failed");
|
|
458
|
-
|
|
657
|
+
return { accumulatedResponse, completionProcessed };
|
|
459
658
|
|
|
460
659
|
default:
|
|
461
660
|
console.warn("Unknown stream message type:", streamMessage.type);
|
|
@@ -967,13 +1166,14 @@ export function AiTerminal({
|
|
|
967
1166
|
);
|
|
968
1167
|
|
|
969
1168
|
if (toolCallIndex >= 0) {
|
|
970
|
-
// Update the tool call with the result
|
|
1169
|
+
// Update the tool call with the result or error
|
|
971
1170
|
const updatedToolCalls = [...toolCalls];
|
|
972
1171
|
updatedToolCalls[toolCallIndex] = {
|
|
973
1172
|
...updatedToolCalls[toolCallIndex],
|
|
974
1173
|
function: {
|
|
975
1174
|
...updatedToolCalls[toolCallIndex].function,
|
|
976
1175
|
result: streamMessage.data.result,
|
|
1176
|
+
error: streamMessage.data.error,
|
|
977
1177
|
},
|
|
978
1178
|
};
|
|
979
1179
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { useFieldModification } from "../client/fieldModificationStore";
|
|
11
11
|
|
|
12
12
|
import { useEffect, useRef, useState, useMemo } from "react";
|
|
13
|
+
import { RefreshCw } from "lucide-react";
|
|
13
14
|
|
|
14
15
|
import { Field } from "../pageModel";
|
|
15
16
|
|
|
@@ -152,6 +153,12 @@ export function SingleLineText({
|
|
|
152
153
|
}, 500);
|
|
153
154
|
}, [editContext?.focusedField]);
|
|
154
155
|
|
|
156
|
+
const customSource = (field as any)?.customProperties?.source as
|
|
157
|
+
| string
|
|
158
|
+
| undefined;
|
|
159
|
+
const isManualRefreshEnabled =
|
|
160
|
+
typeof customSource === "string" && customSource.includes("manual-refresh");
|
|
161
|
+
|
|
155
162
|
return (
|
|
156
163
|
<div className="relative">
|
|
157
164
|
{/* <div
|
|
@@ -168,12 +175,22 @@ export function SingleLineText({
|
|
|
168
175
|
key={fieldItem.id + field.id + fieldItem.language + fieldItem.version}
|
|
169
176
|
value={value || ""}
|
|
170
177
|
disabled={readOnly}
|
|
171
|
-
className="focus-shadow bg-gray-5 p-1.5 text-xs"
|
|
178
|
+
className="focus-shadow bg-gray-5 p-1.5 pr-7 text-xs"
|
|
172
179
|
style={{ width: "100%" }}
|
|
173
180
|
onChange={handleChange}
|
|
174
181
|
onSelect={handleSelect}
|
|
175
182
|
onBlur={editContextRef.current?.operations.onFieldBlur}
|
|
176
183
|
/>
|
|
184
|
+
{isManualRefreshEnabled && (
|
|
185
|
+
<button
|
|
186
|
+
type="button"
|
|
187
|
+
title="Re-render"
|
|
188
|
+
className="absolute right-1 top-1/2 -translate-y-1/2 rounded p-1 text-gray-600 hover:text-gray-900"
|
|
189
|
+
onClick={() => editContext?.requestRefresh("immediate")}
|
|
190
|
+
>
|
|
191
|
+
<RefreshCw className="h-4 w-4" strokeWidth={1} />
|
|
192
|
+
</button>
|
|
193
|
+
)}
|
|
177
194
|
</div>
|
|
178
195
|
);
|
|
179
196
|
}
|