@agent-native/core 0.80.10 → 0.80.11
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +108 -15
- package/corpus/core/src/client/AssistantChat.tsx +123 -26
- package/corpus/core/src/client/sse-event-processor.ts +9 -0
- package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +9 -2
- package/corpus/templates/assets/AGENTS.md +4 -0
- package/corpus/templates/assets/actions/_tool-activity.ts +46 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +26 -5
- package/corpus/templates/assets/actions/generate-image.ts +118 -67
- package/corpus/templates/assets/actions/list-draft-assets.ts +50 -0
- package/corpus/templates/assets/actions/rerun-generation-run.ts +52 -31
- package/corpus/templates/assets/app/components/create/RecentDraftsSection.tsx +100 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +7 -0
- package/corpus/templates/assets/app/i18n-data.ts +61 -0
- package/corpus/templates/assets/app/routes/_index.tsx +4 -0
- package/corpus/templates/assets/app/routes/library.tsx +145 -38
- package/corpus/templates/assets/changelog/2026-06-29-image-generation-can-now-render-requested-text-and-respect-b.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-30-image-generation-no-longer-looks-stuck-while-the-provider-is-still-working.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-30-tagged-presets-now-control-the-image-aspect-ratio.md +6 -0
- package/corpus/templates/assets/server/lib/generation.ts +135 -11
- package/corpus/templates/assets/shared/api.ts +4 -0
- package/corpus/templates/clips/actions/list-ai-requests.ts +60 -0
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +24 -25
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +13 -5
- package/corpus/templates/design/actions/apply-design-state.ts +17 -4
- package/corpus/templates/design/actions/apply-motion-edit.ts +9 -46
- package/corpus/templates/design/actions/delete-design.ts +20 -0
- package/corpus/templates/design/actions/get-component-details.ts +16 -7
- package/corpus/templates/design/actions/index-design-tokens.ts +8 -4
- package/corpus/templates/design/actions/list-design-states.ts +19 -1
- package/corpus/templates/design/actions/open-component-source.ts +7 -2
- package/corpus/templates/design/actions/preview-component-prop-edit.ts +32 -26
- package/corpus/templates/design/actions/preview-shader-fill.ts +9 -11
- package/corpus/templates/design/actions/run-design-audit.ts +21 -6
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +139 -14
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +20 -3
- package/corpus/templates/design/app/components/design/EditPanel.tsx +428 -31
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +110 -30
- package/corpus/templates/design/app/components/design/MotionDock.tsx +9 -0
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1 -1
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +12 -5
- package/corpus/templates/design/app/components/design/StatesPanel.tsx +4 -2
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +13 -8
- package/corpus/templates/design/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/design/app/i18n-data.ts +11 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +684 -179
- package/corpus/templates/design/changelog/2026-06-30-design-token-edits-now-stay-visible-in-previews-and-token-li.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +94 -2
- package/corpus/templates/design/shared/component-model.ts +35 -0
- package/corpus/templates/design/shared/motion-compiler.ts +79 -8
- package/corpus/templates/design/shared/resolve-tweaks.ts +32 -9
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +94 -10
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +14 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +115 -22
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +10 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/package.json +1 -1
|
@@ -17,6 +17,20 @@ export interface AssistantChatSendOptions {
|
|
|
17
17
|
trackInRunsTray?: boolean;
|
|
18
18
|
requestMode?: AgentRequestMode;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Decide whether a reconnect should give up with "no progress". The signal is
|
|
22
|
+
* *time since the last streamed event*, NOT total reconnect duration: a healthy
|
|
23
|
+
* long-running tool (e.g. image generation, which emits `activity` heartbeats
|
|
24
|
+
* every few seconds) makes continuous progress and must never be aborted just
|
|
25
|
+
* for running longer than the threshold. Only genuine silence for the full
|
|
26
|
+
* stuck threshold counts as stuck. Pure + exported so the decision is unit
|
|
27
|
+
* testable without driving the whole reconnect lifecycle.
|
|
28
|
+
*/
|
|
29
|
+
export declare function reconnectProgressTimedOut(args: {
|
|
30
|
+
lastProgressAt: number;
|
|
31
|
+
now: number;
|
|
32
|
+
thresholdMs?: number;
|
|
33
|
+
}): boolean;
|
|
20
34
|
export declare function latestNonRecoveryUserMessageText(messages: readonly unknown[]): string;
|
|
21
35
|
export declare function resolveAssistantChatSubmitIntent({ isRunning, requestedIntent, }: {
|
|
22
36
|
isRunning: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,gBAAgB,EAChB,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;AAW7B,OAAO,KASN,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAOrE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAQL,KAAK,oBAAoB,EAC1B,MAAM,iBAAiB,CAAC;AAqCzB,OAAO,EAQL,KAAK,sBAAsB,EAG5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAiB3B,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAE5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,0BAA0B,EAE3B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAEL,KAAK,6BAA6B,EACnC,MAAM,0BAA0B,CAAC;AAelC,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EACL,iCAAiC,EACjC,kCAAkC,EAClC,qCAAqC,EACrC,mCAAmC,EACnC,4BAA4B,GAC7B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAK1E,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,MAAM,CAAC;AAC9C,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,OAAO,CAAC;AACvD,MAAM,WAAW,wBAAwB;IACvC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;
|
|
1
|
+
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"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"}
|
|
@@ -68,6 +68,12 @@ const PENDING_SELECTION_KEY = "pending-selection-context";
|
|
|
68
68
|
const ACTIVE_RUN_CLEAR_TIMEOUT_MS = 5_000;
|
|
69
69
|
const ACTIVE_RUN_STUCK_THRESHOLD_MS = 90_000;
|
|
70
70
|
const ACTIVE_RUN_POLL_INTERVAL_MS = 150;
|
|
71
|
+
// How long a single activity (model call, tool prep, long tool) must stay
|
|
72
|
+
// in-flight before its label is surfaced in the running indicator. Below this
|
|
73
|
+
// the indicator stays a steady "Thinking" so normal fast turns don't flicker
|
|
74
|
+
// through transient labels ("Contacting model", "Preparing X action"); past it
|
|
75
|
+
// the live label appears so a genuinely slow step reads as working, not hung.
|
|
76
|
+
const ACTIVITY_LABEL_REVEAL_DELAY_MS = 6_000;
|
|
71
77
|
const SUBMIT_ENGINE_STATUS_TIMEOUT_MS = 1000;
|
|
72
78
|
function activeRunLooksStale(runInfo) {
|
|
73
79
|
const lastProgressAt = typeof runInfo.lastProgressAt === "number" ? runInfo.lastProgressAt : null;
|
|
@@ -76,6 +82,19 @@ function activeRunLooksStale(runInfo) {
|
|
|
76
82
|
lastProgressAt != null &&
|
|
77
83
|
nowMs - lastProgressAt > ACTIVE_RUN_STUCK_THRESHOLD_MS);
|
|
78
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Decide whether a reconnect should give up with "no progress". The signal is
|
|
87
|
+
* *time since the last streamed event*, NOT total reconnect duration: a healthy
|
|
88
|
+
* long-running tool (e.g. image generation, which emits `activity` heartbeats
|
|
89
|
+
* every few seconds) makes continuous progress and must never be aborted just
|
|
90
|
+
* for running longer than the threshold. Only genuine silence for the full
|
|
91
|
+
* stuck threshold counts as stuck. Pure + exported so the decision is unit
|
|
92
|
+
* testable without driving the whole reconnect lifecycle.
|
|
93
|
+
*/
|
|
94
|
+
export function reconnectProgressTimedOut(args) {
|
|
95
|
+
const threshold = args.thresholdMs ?? ACTIVE_RUN_STUCK_THRESHOLD_MS;
|
|
96
|
+
return args.now - args.lastProgressAt >= threshold;
|
|
97
|
+
}
|
|
79
98
|
function isAssistantUiDuplicateMessageIdError(error) {
|
|
80
99
|
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
81
100
|
return (message.includes("MessageRepository") &&
|
|
@@ -690,6 +709,22 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
690
709
|
// True during the 250ms continuation window and startup of the next chunk
|
|
691
710
|
// (adapter's auto-continue delay before POSTing the next chunk).
|
|
692
711
|
const [isAutoResuming, setIsAutoResuming] = useState(false);
|
|
712
|
+
const [runningActivityLabel, setRunningActivityLabel] = useState(null);
|
|
713
|
+
// Delayed-reveal state for the activity label (see ACTIVITY_LABEL_REVEAL_DELAY_MS).
|
|
714
|
+
// `latest` holds the most recent activity label; `surfaced` flips true once the
|
|
715
|
+
// reveal timer fires; `timer` is the pending one-shot reveal.
|
|
716
|
+
const activityLabelTimerRef = useRef(null);
|
|
717
|
+
const latestActivityLabelRef = useRef(null);
|
|
718
|
+
const activityLabelSurfacedRef = useRef(false);
|
|
719
|
+
const resetRunningActivity = useCallback(() => {
|
|
720
|
+
if (activityLabelTimerRef.current !== null) {
|
|
721
|
+
window.clearTimeout(activityLabelTimerRef.current);
|
|
722
|
+
activityLabelTimerRef.current = null;
|
|
723
|
+
}
|
|
724
|
+
latestActivityLabelRef.current = null;
|
|
725
|
+
activityLabelSurfacedRef.current = false;
|
|
726
|
+
setRunningActivityLabel(null);
|
|
727
|
+
}, []);
|
|
693
728
|
const [reconnectContent, setReconnectContent] = useState([]);
|
|
694
729
|
// When stop is clicked during reconnect, keep content visible (don't wipe it)
|
|
695
730
|
const [reconnectFrozen, setReconnectFrozen] = useState(false);
|
|
@@ -708,6 +743,19 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
708
743
|
const textStreaming = isRunning || externalStreaming;
|
|
709
744
|
// UI-only running state — drives the stop button and thinking indicator.
|
|
710
745
|
const showRunningInUI = isRunning;
|
|
746
|
+
// A revealed activity label wins; otherwise stay a steady "Thinking" by
|
|
747
|
+
// default. We only surface "Reconnecting" while we are actively replaying
|
|
748
|
+
// recovered content (reconnectContent populated). A bare reconnect with no
|
|
749
|
+
// replayed content — e.g. a tail-resume after the serverless wall, where
|
|
750
|
+
// `scheduleUpdate` intentionally leaves reconnectContent empty — is normal
|
|
751
|
+
// ongoing work, so it must read as "Thinking", never a perpetual "Working".
|
|
752
|
+
const runningStatusLabel = runningActivityLabel
|
|
753
|
+
? runningActivityLabel
|
|
754
|
+
: isAutoResuming
|
|
755
|
+
? "Resuming"
|
|
756
|
+
: isReconnecting && reconnectContent.length > 0
|
|
757
|
+
? "Reconnecting"
|
|
758
|
+
: "Thinking";
|
|
711
759
|
const lastBroadcastRunningRef = useRef(isRunning);
|
|
712
760
|
const tiptapRef = useRef(null);
|
|
713
761
|
// Stable ref to the "stop active run" action so addToQueue can abort
|
|
@@ -938,11 +986,30 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
938
986
|
}
|
|
939
987
|
}, 1000);
|
|
940
988
|
let reconnectTimedOut = false;
|
|
941
|
-
|
|
989
|
+
// Idle deadline, NOT a total-duration cap. A long-but-healthy run (image
|
|
990
|
+
// generation emits `activity` heartbeats every few seconds) keeps
|
|
991
|
+
// advancing `lastReconnectProgressAt`, so it is never aborted for simply
|
|
992
|
+
// taking longer than the threshold. Only true silence for the full stuck
|
|
993
|
+
// threshold trips it — the same semantics as `activeRunLooksStale` and the
|
|
994
|
+
// SSE-level no-progress timeout. `markReconnectProgress` resets it on every
|
|
995
|
+
// streamed event (see the `onSeq` callback below, which fires for every
|
|
996
|
+
// event including activity, for both fresh and tail-resume reconnects).
|
|
997
|
+
let lastReconnectProgressAt = Date.now();
|
|
998
|
+
const markReconnectProgress = () => {
|
|
999
|
+
lastReconnectProgressAt = Date.now();
|
|
1000
|
+
};
|
|
1001
|
+
const idleCheck = setInterval(() => {
|
|
1002
|
+
if (!reconnectProgressTimedOut({
|
|
1003
|
+
lastProgressAt: lastReconnectProgressAt,
|
|
1004
|
+
now: Date.now(),
|
|
1005
|
+
})) {
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
942
1008
|
reconnectTimedOut = true;
|
|
943
1009
|
abortCtrl.abort();
|
|
944
1010
|
clearInterval(watchdog);
|
|
945
|
-
|
|
1011
|
+
clearInterval(idleCheck);
|
|
1012
|
+
}, 1000);
|
|
946
1013
|
const streamReconnect = async () => {
|
|
947
1014
|
let noProgressDuringReconnect = false;
|
|
948
1015
|
let latestContent = [];
|
|
@@ -973,7 +1040,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
973
1040
|
setReconnectContent(latestSnapshot);
|
|
974
1041
|
});
|
|
975
1042
|
};
|
|
976
|
-
await readSSEStreamRaw(sseRes.body, content, toolCallCounter, tabId, scheduleUpdate, (seq) =>
|
|
1043
|
+
await readSSEStreamRaw(sseRes.body, content, toolCallCounter, tabId, scheduleUpdate, (seq) => {
|
|
1044
|
+
markReconnectProgress();
|
|
1045
|
+
updateActiveRunSeq(seq);
|
|
1046
|
+
});
|
|
977
1047
|
if (afterSeq === 0) {
|
|
978
1048
|
setReconnectContent([...content]);
|
|
979
1049
|
}
|
|
@@ -995,7 +1065,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
995
1065
|
window.clearInterval(threadPollInterval);
|
|
996
1066
|
}
|
|
997
1067
|
clearInterval(watchdog);
|
|
998
|
-
|
|
1068
|
+
clearInterval(idleCheck);
|
|
999
1069
|
}
|
|
1000
1070
|
if (noProgressDuringReconnect && reconnectRunIdRef.current === runId) {
|
|
1001
1071
|
captureError(new Error("agent-chat:reconnect_no_progress"), {
|
|
@@ -1530,23 +1600,52 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1530
1600
|
window.addEventListener("agent-chat:run-error", handler);
|
|
1531
1601
|
return () => window.removeEventListener("agent-chat:run-error", handler);
|
|
1532
1602
|
}, [tabId]);
|
|
1533
|
-
// Real activity means the next chunk has started
|
|
1534
|
-
//
|
|
1535
|
-
//
|
|
1536
|
-
// indicator stays a steady "Thinking" rather than flipping through
|
|
1537
|
-
// transient step labels.
|
|
1603
|
+
// Real activity means the next chunk has started. Surface longer-lived
|
|
1604
|
+
// activity such as "Still generating image" so active-run reconnects do not
|
|
1605
|
+
// look like failures while the server is still making progress.
|
|
1538
1606
|
useEffect(() => {
|
|
1539
1607
|
const handler = (e) => {
|
|
1540
1608
|
const detail = e.detail;
|
|
1541
1609
|
if (tabId && detail?.tabId && detail.tabId !== tabId)
|
|
1542
1610
|
return;
|
|
1543
|
-
|
|
1544
|
-
|
|
1611
|
+
const label = typeof detail?.label === "string" ? detail.label.trim() : "";
|
|
1612
|
+
if (!label)
|
|
1613
|
+
return;
|
|
1614
|
+
setIsAutoResuming(false);
|
|
1615
|
+
latestActivityLabelRef.current = label;
|
|
1616
|
+
// Already past the delay → keep the visible label current.
|
|
1617
|
+
if (activityLabelSurfacedRef.current) {
|
|
1618
|
+
setRunningActivityLabel(label);
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
// Not yet surfaced → arm a single reveal timer on the FIRST activity of
|
|
1622
|
+
// this in-flight period. A burst of quick steps that all finish (clear)
|
|
1623
|
+
// before the timer fires never surfaces anything, so normal fast turns
|
|
1624
|
+
// stay a steady "Thinking". A step still in-flight at the deadline reveals
|
|
1625
|
+
// the latest label so a slow operation reads as working, not hung.
|
|
1626
|
+
if (activityLabelTimerRef.current === null) {
|
|
1627
|
+
activityLabelTimerRef.current = window.setTimeout(() => {
|
|
1628
|
+
activityLabelTimerRef.current = null;
|
|
1629
|
+
activityLabelSurfacedRef.current = true;
|
|
1630
|
+
if (latestActivityLabelRef.current) {
|
|
1631
|
+
setRunningActivityLabel(latestActivityLabelRef.current);
|
|
1632
|
+
}
|
|
1633
|
+
}, ACTIVITY_LABEL_REVEAL_DELAY_MS);
|
|
1545
1634
|
}
|
|
1546
1635
|
};
|
|
1636
|
+
const clear = (e) => {
|
|
1637
|
+
const detail = e.detail;
|
|
1638
|
+
if (tabId && detail?.tabId && detail.tabId !== tabId)
|
|
1639
|
+
return;
|
|
1640
|
+
resetRunningActivity();
|
|
1641
|
+
};
|
|
1547
1642
|
window.addEventListener("agent-chat:activity", handler);
|
|
1548
|
-
|
|
1549
|
-
|
|
1643
|
+
window.addEventListener("agent-chat:activity-clear", clear);
|
|
1644
|
+
return () => {
|
|
1645
|
+
window.removeEventListener("agent-chat:activity", handler);
|
|
1646
|
+
window.removeEventListener("agent-chat:activity-clear", clear);
|
|
1647
|
+
};
|
|
1648
|
+
}, [resetRunningActivity, tabId]);
|
|
1550
1649
|
// Show "Resuming…" during the adapter's auto-continuation window (the
|
|
1551
1650
|
// ~250ms gap between the end of one serverless chunk and the POST for the
|
|
1552
1651
|
// next). The adapter dispatches `agent-chat:auto-continue` at that moment.
|
|
@@ -1564,8 +1663,9 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1564
1663
|
useEffect(() => {
|
|
1565
1664
|
if (!isRunning) {
|
|
1566
1665
|
setIsAutoResuming(false);
|
|
1666
|
+
resetRunningActivity();
|
|
1567
1667
|
}
|
|
1568
|
-
}, [isRunning]);
|
|
1668
|
+
}, [isRunning, resetRunningActivity]);
|
|
1569
1669
|
// Auto-dequeue: when the agent is idle, send the next queued message. This
|
|
1570
1670
|
// intentionally does not depend on observing the running -> idle transition:
|
|
1571
1671
|
// restored queues can exist after a reload where this component never saw the
|
|
@@ -2245,14 +2345,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2245
2345
|
setRunErrorInfo(null);
|
|
2246
2346
|
} })), (isReconnecting || reconnectFrozen) &&
|
|
2247
2347
|
reconnectAfterSeq === 0 &&
|
|
2248
|
-
reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), showRunningInUI && (_jsx(RunningActivityStatus, { label:
|
|
2249
|
-
? "Reconnecting"
|
|
2250
|
-
: isAutoResuming
|
|
2251
|
-
? "Resuming"
|
|
2252
|
-
: // Keep a steady "Thinking" while the model works —
|
|
2253
|
-
// never flip through transient activity labels
|
|
2254
|
-
// (e.g. "Contacting model", "Preparing X action").
|
|
2255
|
-
"Thinking" })), queuedMessages.map((msg) => {
|
|
2348
|
+
reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), showRunningInUI && (_jsx(RunningActivityStatus, { label: runningStatusLabel })), queuedMessages.map((msg) => {
|
|
2256
2349
|
const displayText = msg.text
|
|
2257
2350
|
.replace(/<context>[\s\S]*?<\/context>\n?/g, "")
|
|
2258
2351
|
.trim();
|