@agent-native/core 0.95.1 → 0.96.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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +25 -0
- package/corpus/core/package.json +3 -1
- package/corpus/core/src/a2a/client.ts +11 -1
- package/corpus/core/src/agent/production-agent.ts +87 -27
- package/corpus/core/src/agent/thread-data-builder.ts +7 -5
- package/corpus/core/src/chat-threads/store.ts +20 -1
- package/corpus/core/src/cli/code-agent-executor.ts +1 -0
- package/corpus/core/src/cli/code-agent-runs.ts +14 -0
- package/corpus/core/src/client/AgentPanel.tsx +32 -25
- package/corpus/core/src/client/AssistantChat.tsx +36 -20
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +141 -90
- package/corpus/core/src/client/chat/ChatHistoryList.tsx +404 -0
- package/corpus/core/src/client/chat/index.ts +6 -0
- package/corpus/core/src/client/chat/tool-call-display.tsx +37 -3
- package/corpus/core/src/client/code-agent-chat-adapter.ts +72 -4
- package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +52 -11
- package/corpus/core/src/client/composer/TiptapComposer.tsx +157 -20
- package/corpus/core/src/client/composer/VoiceButton.tsx +28 -0
- package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +5 -0
- package/corpus/core/src/client/conversation/code-agent-transcript.ts +4 -5
- package/corpus/core/src/client/guided-questions.tsx +2 -1
- package/corpus/core/src/client/index.ts +11 -0
- package/corpus/core/src/client/use-chat-threads.ts +10 -1
- package/corpus/core/src/client/voice-provider-status.ts +44 -0
- package/corpus/core/src/code-agents/transcript-normalizer.ts +76 -0
- package/corpus/core/src/deploy/build.ts +12 -11
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +35 -5
- package/corpus/core/src/integrations/adapters/slack.ts +74 -21
- package/corpus/core/src/integrations/webhook-handler.ts +14 -0
- package/corpus/core/src/localization/default-messages.ts +6 -0
- package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
- package/corpus/core/src/observability/routes.ts +17 -0
- package/corpus/core/src/observability/store.ts +4 -1
- package/corpus/core/src/observability/traces.ts +41 -2
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +19 -1
- package/corpus/core/src/scripts/call-agent.ts +53 -3
- package/corpus/core/src/scripts/chat/search-chats.ts +11 -8
- package/corpus/core/src/secrets/register-framework-secrets.ts +1 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +41 -6
- package/corpus/core/src/server/core-routes-plugin.ts +15 -0
- package/corpus/core/src/server/realtime-voice.ts +71 -24
- package/corpus/core/src/server/voice-providers-status.ts +4 -3
- package/corpus/core/src/shared/cache-control.ts +2 -8
- package/corpus/core/src/styles/agent-native.css +1 -0
- package/corpus/core/src/styles/chat-history-list.css +313 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
- package/corpus/core/src/vite/client.ts +1 -0
- package/corpus/templates/analytics/AGENTS.md +7 -0
- package/corpus/templates/analytics/actions/bigquery.ts +26 -2
- package/corpus/templates/analytics/actions/data-source-status.ts +18 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +5 -4
- package/corpus/templates/analytics/app/global.css +10 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +25 -2
- package/corpus/templates/analytics/changelog/2026-07-10-analytics-answers-simple-time-bounded-metrics-without-unnece.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-analytics-chat-reliably-uses-connected-data-sources-across-s.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-chat-threads-now-stay-clear-of-top-actions-and-fade-smoothly.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-context-chips-can-now-be-selected-and-removed-one-at-a-time-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-the-ask-composer-no-longer-carries-dashboard-or-panel-contex.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-the-ask-section-stays-highlighted-while-its-chat-history-is-.md +6 -0
- package/corpus/templates/analytics/server/lib/bigquery.ts +90 -14
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +82 -7
- package/dist/a2a/client.d.ts +7 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +2 -1
- package/dist/a2a/client.js.map +1 -1
- package/dist/agent/production-agent.d.ts +6 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +63 -26
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +1 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +6 -5
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/chat-threads/store.d.ts +10 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +6 -0
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/code-agent-executor.d.ts.map +1 -1
- package/dist/cli/code-agent-executor.js +1 -0
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/code-agent-runs.d.ts +12 -0
- package/dist/cli/code-agent-runs.d.ts.map +1 -1
- package/dist/cli/code-agent-runs.js +1 -0
- package/dist/cli/code-agent-runs.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +3 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +11 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +7 -4
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +83 -10
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/chat/ChatHistoryList.d.ts +88 -0
- package/dist/client/chat/ChatHistoryList.d.ts.map +1 -0
- package/dist/client/chat/ChatHistoryList.js +83 -0
- package/dist/client/chat/ChatHistoryList.js.map +1 -0
- package/dist/client/chat/index.d.ts +1 -0
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -0
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +13 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +10 -2
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/code-agent-chat-adapter.d.ts +17 -1
- package/dist/client/code-agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/code-agent-chat-adapter.js +47 -3
- package/dist/client/code-agent-chat-adapter.js.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.d.ts +11 -1
- package/dist/client/composer/RealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.js +5 -3
- package/dist/client/composer/RealtimeVoiceMode.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +25 -2
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +96 -5
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/VoiceButton.d.ts.map +1 -1
- package/dist/client/composer/VoiceButton.js +21 -1
- package/dist/client/composer/VoiceButton.js.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.js +5 -0
- package/dist/client/composer/useRealtimeVoiceMode.js.map +1 -1
- package/dist/client/conversation/code-agent-transcript.d.ts +2 -0
- package/dist/client/conversation/code-agent-transcript.d.ts.map +1 -1
- package/dist/client/conversation/code-agent-transcript.js +3 -5
- package/dist/client/conversation/code-agent-transcript.js.map +1 -1
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +2 -1
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +9 -1
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/voice-provider-status.d.ts +10 -0
- package/dist/client/voice-provider-status.d.ts.map +1 -0
- package/dist/client/voice-provider-status.js +32 -0
- package/dist/client/voice-provider-status.js.map +1 -0
- package/dist/code-agents/transcript-normalizer.d.ts +29 -0
- package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
- package/dist/code-agents/transcript-normalizer.js +55 -0
- package/dist/code-agents/transcript-normalizer.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +13 -11
- package/dist/deploy/build.js.map +1 -1
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +25 -5
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +55 -21
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +11 -0
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/localization/default-messages.d.ts +5 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +5 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/hosted-model-experiment.d.ts +39 -0
- package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
- package/dist/observability/hosted-model-experiment.js +90 -0
- package/dist/observability/hosted-model-experiment.js.map +1 -0
- package/dist/observability/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts.map +1 -1
- package/dist/observability/routes.js +16 -0
- package/dist/observability/routes.js.map +1 -1
- package/dist/observability/store.d.ts.map +1 -1
- package/dist/observability/store.js +4 -1
- package/dist/observability/store.js.map +1 -1
- package/dist/observability/traces.d.ts +6 -0
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +28 -2
- package/dist/observability/traces.js.map +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +19 -1
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +43 -3
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/scripts/chat/search-chats.d.ts +1 -1
- package/dist/scripts/chat/search-chats.d.ts.map +1 -1
- package/dist/scripts/chat/search-chats.js +11 -8
- package/dist/scripts/chat/search-chats.js.map +1 -1
- package/dist/secrets/register-framework-secrets.js +1 -1
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +11 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +27 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts +3 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +13 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/realtime-voice.d.ts.map +1 -1
- package/dist/server/realtime-voice.js +55 -21
- package/dist/server/realtime-voice.js.map +1 -1
- package/dist/server/voice-providers-status.d.ts.map +1 -1
- package/dist/server/voice-providers-status.js +2 -3
- package/dist/server/voice-providers-status.js.map +1 -1
- package/dist/shared/cache-control.d.ts +4 -6
- package/dist/shared/cache-control.d.ts.map +1 -1
- package/dist/shared/cache-control.js +2 -7
- package/dist/shared/cache-control.js.map +1 -1
- package/dist/styles/agent-native.css +1 -0
- package/dist/styles/chat-history-list.css +313 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/package.json +3 -1
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.96.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 270d85f: Use Builder Connect and metered Builder credits automatically for realtime voice, with an OpenAI API key as the secondary fallback.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 270d85f: Run a sticky 80/20 Sonnet 5 versus GPT-5.6 Luna default-model experiment across first-party hosted templates while preserving explicit model choices.
|
|
12
|
+
- 270d85f: Add a shared, presentational `ChatHistoryList` component (`@agent-native/core/client`) for rendering chat/run history lists with optional grouped sections, active-item highlight, search box, loading/empty/error states, and optional pin/rename/delete row actions. Core's `HistoryPopover` now renders through it instead of bespoke row markup, with no behavior change.
|
|
13
|
+
- 270d85f: Allow app final-response guards to grant models additional bounded corrective attempts before emitting a fallback.
|
|
14
|
+
- 270d85f: Improve Slack agent progress and diagnostics, and continue long-running delegated tasks reliably.
|
|
15
|
+
- 270d85f: Keep page-level chat actions clear of conversation content and expose scroll state so hosts can fade older messages beneath header controls.
|
|
16
|
+
- 270d85f: Reduce the public SSR edge-cache freshness window from one hour to ten minutes while retaining long stale-while-revalidate coverage.
|
|
17
|
+
- 270d85f: Attach a pending approval key to the Agent-Native Code tool-call transcript item so the shared inline `ApprovalAffordance` (Approve/Deny) can render directly under the paused bash call, instead of only through a separate host banner. `ApprovalContext` gains optional `onDeny` and `onAlwaysAllow` hooks (both additive; existing consumers keep today's Approve-only, local-Deny behavior when they don't supply them), and `AssistantChat` accepts an optional `approvalActions` prop to wire them. `createCodeAgentChatAdapter` now resolves an approved Code tool call through `controller.control("approve")` instead of treating the approval message as a new prompt.
|
|
18
|
+
- 270d85f: Export `./styles/agent-conversation.css` from the package so consumers outside the monorepo (like the desktop app) can import it by package specifier instead of a fragile source-relative path.
|
|
19
|
+
- 270d85f: Export `./styles/chat-history-list.css` from the package so non-Tailwind hosts (like `@agent-native/code-agents-ui`) can import the shared `ChatHistoryList` stylesheet by package specifier instead of a fragile source-relative path.
|
|
20
|
+
- 270d85f: Export the reasoning hook from browser-only SSR stubs so Cloudflare template builds remain deployable.
|
|
21
|
+
- 270d85f: Archived chat threads are now excluded from thread lists and search by default, so archiving a thread actually removes it from the sidebar/history and the `chat-history` agent tool. Pass `includeArchived: true` (store options, `chat-history` search action, or `search-chats` script) to see archived threads explicitly.
|
|
22
|
+
- 270d85f: Use one primary composer action while a response is running: show stop for an empty draft, restore send when the user types, and keep the microphone immediately to its left.
|
|
23
|
+
- 270d85f: Preserve template and use-case context in Builder waitlist form submissions and lifecycle events.
|
|
24
|
+
- 270d85f: Select composer context chips with the first Backspace at the start of a prompt, then remove the selected chip with the next Backspace.
|
|
25
|
+
- 270d85f: Show compact GPT-5.6 model and reasoning names in the collapsed chat composer control.
|
|
26
|
+
- 270d85f: Add a structured `signal: "credential-gap"` marker to code-agent transcript events and export a shared `isCredentialGapCodeAgentEvent` helper so history builders (`thread-data-builder.ts`, `code-agent-transcript.ts`) detect the "no LLM provider key" condition from the executor's structured field instead of regex-matching the hint text. The regex remains only as a fallback for already-persisted transcripts that predate the field.
|
|
27
|
+
|
|
3
28
|
## 0.95.1
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.96.0",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -219,6 +219,8 @@
|
|
|
219
219
|
"./terminal/server": "./dist/terminal/index.js",
|
|
220
220
|
"./tailwind": "./dist/tailwind.preset.js",
|
|
221
221
|
"./styles/agent-native.css": "./dist/styles/agent-native.css",
|
|
222
|
+
"./styles/agent-conversation.css": "./dist/styles/agent-conversation.css",
|
|
223
|
+
"./styles/chat-history-list.css": "./dist/styles/chat-history-list.css",
|
|
222
224
|
"./agent/engine": "./dist/agent/engine/index.js",
|
|
223
225
|
"./agent/harness": "./dist/agent/harness/index.js",
|
|
224
226
|
"./eval": "./dist/eval/index.js",
|
|
@@ -550,6 +550,13 @@ export async function callAgent(
|
|
|
550
550
|
timeoutMs?: number;
|
|
551
551
|
/** Poll interval for async calls. Primarily useful for tests/retries. */
|
|
552
552
|
pollIntervalMs?: number;
|
|
553
|
+
/**
|
|
554
|
+
* Return receiver-verified artifact text from the last polled task when
|
|
555
|
+
* the call times out. Defaults to true for backwards compatibility.
|
|
556
|
+
* Callers that can continue polling the remote task separately should set
|
|
557
|
+
* this to false so the A2ATaskTimeoutError (and its taskId) is preserved.
|
|
558
|
+
*/
|
|
559
|
+
returnRecoverableArtifactsOnTimeout?: boolean;
|
|
553
560
|
/**
|
|
554
561
|
* Called with each successfully polled task while an async call is still
|
|
555
562
|
* in flight (see `A2AClient.sendAndWait`). Fires once per real poll
|
|
@@ -614,7 +621,10 @@ export async function callAgent(
|
|
|
614
621
|
|
|
615
622
|
return "";
|
|
616
623
|
} catch (err) {
|
|
617
|
-
if (
|
|
624
|
+
if (
|
|
625
|
+
opts?.returnRecoverableArtifactsOnTimeout !== false &&
|
|
626
|
+
err instanceof A2ATaskTimeoutError
|
|
627
|
+
) {
|
|
618
628
|
const recoverableText = extractRecoverableArtifactText(err.lastTask);
|
|
619
629
|
if (recoverableText) return recoverableText;
|
|
620
630
|
}
|
|
@@ -1762,6 +1762,12 @@ export type AgentLoopFinalResponseGuardResult =
|
|
|
1762
1762
|
| {
|
|
1763
1763
|
retryMessage: string;
|
|
1764
1764
|
fallbackMessage?: string;
|
|
1765
|
+
/**
|
|
1766
|
+
* Number of rejected text-only answers the model may correct before the
|
|
1767
|
+
* fallback is emitted. Defaults to one and is capped to keep a broken
|
|
1768
|
+
* guard/model combination from looping indefinitely.
|
|
1769
|
+
*/
|
|
1770
|
+
maxRetries?: number;
|
|
1765
1771
|
};
|
|
1766
1772
|
|
|
1767
1773
|
export type AgentLoopFinalResponseGuard = (
|
|
@@ -3641,7 +3647,11 @@ export async function runAgentLoop(opts: {
|
|
|
3641
3647
|
typeof guard === "string" ? guard : guard.retryMessage;
|
|
3642
3648
|
const fallbackMessage =
|
|
3643
3649
|
typeof guard === "string" ? guard : guard.fallbackMessage;
|
|
3644
|
-
|
|
3650
|
+
const maxGuardRetries =
|
|
3651
|
+
typeof guard === "string"
|
|
3652
|
+
? 1
|
|
3653
|
+
: Math.max(0, Math.min(3, Math.trunc(guard.maxRetries ?? 1)));
|
|
3654
|
+
if (finalGuardRetries < maxGuardRetries) {
|
|
3645
3655
|
finalGuardRetries += 1;
|
|
3646
3656
|
send({ type: "clear" });
|
|
3647
3657
|
messages.push({
|
|
@@ -6160,21 +6170,82 @@ export function createProductionAgentHandler(
|
|
|
6160
6170
|
// DIAGNOSTIC-ONLY: bracket stored-model resolution (getStoredModelForEngine
|
|
6161
6171
|
// settings read).
|
|
6162
6172
|
workerStep("model_start");
|
|
6173
|
+
const storedModel =
|
|
6174
|
+
requestModel == null && configuredModel == null
|
|
6175
|
+
? await getStoredModelForEngine(engine, { appId: options.appId })
|
|
6176
|
+
: undefined;
|
|
6163
6177
|
const modelCandidate =
|
|
6164
|
-
requestModel ??
|
|
6165
|
-
configuredModel ??
|
|
6166
|
-
(await getStoredModelForEngine(engine, { appId: options.appId })) ??
|
|
6167
|
-
engine.defaultModel;
|
|
6178
|
+
requestModel ?? configuredModel ?? storedModel ?? engine.defaultModel;
|
|
6168
6179
|
// DIAGNOSTIC-ONLY: stored-model resolution finished.
|
|
6169
6180
|
workerStep("model_done");
|
|
6170
6181
|
const model = normalizeModelForEngine(engine, modelCandidate);
|
|
6182
|
+
let effectiveModel = model;
|
|
6183
|
+
let modelSelectionSource:
|
|
6184
|
+
| "request"
|
|
6185
|
+
| "configured"
|
|
6186
|
+
| "stored"
|
|
6187
|
+
| "default"
|
|
6188
|
+
| "experiment" =
|
|
6189
|
+
requestModel != null
|
|
6190
|
+
? "request"
|
|
6191
|
+
: configuredModel != null
|
|
6192
|
+
? "configured"
|
|
6193
|
+
: storedModel != null
|
|
6194
|
+
? "stored"
|
|
6195
|
+
: "default";
|
|
6196
|
+
let experimentAssignments: Array<{
|
|
6197
|
+
experimentId: string;
|
|
6198
|
+
variantId: string;
|
|
6199
|
+
}> = [];
|
|
6200
|
+
|
|
6201
|
+
// Database-backed experiments remain available to app operators. A
|
|
6202
|
+
// platform-wide hosted rollout is layered in only when no explicit or
|
|
6203
|
+
// persisted model selection exists, and only on the cross-provider Builder
|
|
6204
|
+
// engine. This preserves the model picker's user intent.
|
|
6205
|
+
try {
|
|
6206
|
+
if (ownerEmail) {
|
|
6207
|
+
const { resolveActiveExperimentConfig } =
|
|
6208
|
+
await import("../observability/experiments.js");
|
|
6209
|
+
const expConfig = await resolveActiveExperimentConfig(ownerEmail);
|
|
6210
|
+
if (expConfig) {
|
|
6211
|
+
experimentAssignments = [...expConfig.assignments];
|
|
6212
|
+
if (typeof expConfig.configs.model === "string") {
|
|
6213
|
+
effectiveModel = normalizeModelForEngine(
|
|
6214
|
+
engine,
|
|
6215
|
+
expConfig.configs.model,
|
|
6216
|
+
);
|
|
6217
|
+
modelSelectionSource = "experiment";
|
|
6218
|
+
}
|
|
6219
|
+
}
|
|
6220
|
+
|
|
6221
|
+
if (modelSelectionSource === "default") {
|
|
6222
|
+
const { resolveHostedDefaultModelExperiment } =
|
|
6223
|
+
await import("../observability/hosted-model-experiment.js");
|
|
6224
|
+
const hostedExperiment = resolveHostedDefaultModelExperiment({
|
|
6225
|
+
userId: ownerEmail,
|
|
6226
|
+
engineName: engine.name,
|
|
6227
|
+
isDefaultModelSelection: true,
|
|
6228
|
+
supportedModels: engine.supportedModels,
|
|
6229
|
+
});
|
|
6230
|
+
if (hostedExperiment) {
|
|
6231
|
+
effectiveModel = hostedExperiment.model;
|
|
6232
|
+
experimentAssignments.push(hostedExperiment.assignment);
|
|
6233
|
+
modelSelectionSource = "experiment";
|
|
6234
|
+
}
|
|
6235
|
+
}
|
|
6236
|
+
}
|
|
6237
|
+
} catch {
|
|
6238
|
+
// Experiments are best-effort. Model resolution must keep working if the
|
|
6239
|
+
// observability tables are unavailable during startup or migration.
|
|
6240
|
+
}
|
|
6241
|
+
|
|
6171
6242
|
const reasoningEffort = resolveAgentRequestReasoningEffort({
|
|
6172
|
-
model,
|
|
6243
|
+
model: effectiveModel,
|
|
6173
6244
|
requestEffort,
|
|
6174
6245
|
configuredEffort: options.reasoningEffort,
|
|
6175
6246
|
});
|
|
6176
6247
|
|
|
6177
|
-
options.onEngineResolved?.(engine,
|
|
6248
|
+
options.onEngineResolved?.(engine, effectiveModel);
|
|
6178
6249
|
|
|
6179
6250
|
// One-line per-turn resolution log so it's obvious in dev which engine
|
|
6180
6251
|
// is actually handling the request. `requestEngine` is what the client
|
|
@@ -6182,7 +6253,7 @@ export function createProductionAgentHandler(
|
|
|
6182
6253
|
// Divergence between them is the usual cause of "status says builder but
|
|
6183
6254
|
// no [builder-engine] log lines appear" confusion.
|
|
6184
6255
|
console.log(
|
|
6185
|
-
`[agent-chat] resolved engine=${engine.name} model=${
|
|
6256
|
+
`[agent-chat] resolved engine=${engine.name} model=${effectiveModel} requestEngine=${requestEngine ?? "(none)"} modelSource=${modelSelectionSource}`,
|
|
6186
6257
|
);
|
|
6187
6258
|
|
|
6188
6259
|
if (
|
|
@@ -7487,25 +7558,6 @@ export function createProductionAgentHandler(
|
|
|
7487
7558
|
}
|
|
7488
7559
|
}
|
|
7489
7560
|
|
|
7490
|
-
// Apply experiment variant overrides (A/B testing)
|
|
7491
|
-
let effectiveModel = model;
|
|
7492
|
-
try {
|
|
7493
|
-
const { resolveActiveExperimentConfig } =
|
|
7494
|
-
await import("../observability/experiments.js");
|
|
7495
|
-
if (!ownerEmail) {
|
|
7496
|
-
// Without an authenticated owner we can't resolve user-scoped experiments.
|
|
7497
|
-
throw new Error("no authenticated user");
|
|
7498
|
-
}
|
|
7499
|
-
const expConfig = await resolveActiveExperimentConfig(ownerEmail);
|
|
7500
|
-
if (expConfig) {
|
|
7501
|
-
if (typeof expConfig.configs.model === "string") {
|
|
7502
|
-
effectiveModel = expConfig.configs.model;
|
|
7503
|
-
}
|
|
7504
|
-
}
|
|
7505
|
-
} catch {
|
|
7506
|
-
// Experiments module unavailable — use default model
|
|
7507
|
-
}
|
|
7508
|
-
|
|
7509
7561
|
// TODO(processor-seam): thread `processors` from ProductionAgentOptions
|
|
7510
7562
|
// through to runAgentLoop here once the handler exposes a way to
|
|
7511
7563
|
// configure them (e.g. a `processors` field on ProductionAgentOptions
|
|
@@ -7592,6 +7644,14 @@ export function createProductionAgentHandler(
|
|
|
7592
7644
|
threadId: threadId ?? null,
|
|
7593
7645
|
userId: ownerEmail,
|
|
7594
7646
|
config: obsConfig,
|
|
7647
|
+
metadata: {
|
|
7648
|
+
modelSelectionSource,
|
|
7649
|
+
...(experimentAssignments.length > 0
|
|
7650
|
+
? { experimentAssignments }
|
|
7651
|
+
: {}),
|
|
7652
|
+
},
|
|
7653
|
+
experimentAssignments,
|
|
7654
|
+
modelSelectionSource,
|
|
7595
7655
|
classifyError: () => {
|
|
7596
7656
|
if (
|
|
7597
7657
|
agentLoopOpts.signal.aborted &&
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ActionChatUIConfig } from "../action-ui.js";
|
|
2
2
|
import {
|
|
3
|
+
isCredentialGapCodeAgentEvent,
|
|
3
4
|
normalizeCodeAgentTranscript,
|
|
4
5
|
type CodeAgentTranscriptEvent as CoreCodeAgentTranscriptEvent,
|
|
5
6
|
type NormalizedCodeAgentStatusEvent,
|
|
@@ -664,6 +665,7 @@ export interface CodeAgentThreadTranscriptEvent {
|
|
|
664
665
|
metadata?: Record<string, unknown>;
|
|
665
666
|
artifactPath?: string;
|
|
666
667
|
artifactUrl?: string;
|
|
668
|
+
signal?: CoreCodeAgentTranscriptEvent["signal"];
|
|
667
669
|
}
|
|
668
670
|
|
|
669
671
|
export interface BuildRepositoryFromCodeAgentTranscriptOptions {
|
|
@@ -1094,6 +1096,7 @@ function toCoreCodeAgentTranscriptEvent(
|
|
|
1094
1096
|
...(event.artifactPath ? { artifactPath: event.artifactPath } : {}),
|
|
1095
1097
|
...(event.artifactUrl ? { artifactUrl: event.artifactUrl } : {}),
|
|
1096
1098
|
},
|
|
1099
|
+
...(event.signal ? { signal: event.signal } : {}),
|
|
1097
1100
|
};
|
|
1098
1101
|
}
|
|
1099
1102
|
|
|
@@ -1137,6 +1140,9 @@ function toolContentPartForCodeAgentTranscriptItem(
|
|
|
1137
1140
|
? { result: previewCodeAgentTranscriptValue(item.result) ?? "" }
|
|
1138
1141
|
: {}),
|
|
1139
1142
|
...(item.structuredMeta ? { structuredMeta: item.structuredMeta } : {}),
|
|
1143
|
+
...(item.pendingApprovalKey
|
|
1144
|
+
? { approval: { approvalKey: item.pendingApprovalKey } }
|
|
1145
|
+
: {}),
|
|
1140
1146
|
};
|
|
1141
1147
|
}
|
|
1142
1148
|
|
|
@@ -1144,7 +1150,7 @@ function statusTextForCodeAgentTranscriptItem(
|
|
|
1144
1150
|
item: NormalizedCodeAgentStatusEvent,
|
|
1145
1151
|
options: BuildRepositoryFromCodeAgentTranscriptOptions,
|
|
1146
1152
|
): string | null {
|
|
1147
|
-
if (options.hideCredentialMessages &&
|
|
1153
|
+
if (options.hideCredentialMessages && isCredentialGapCodeAgentEvent(item)) {
|
|
1148
1154
|
return null;
|
|
1149
1155
|
}
|
|
1150
1156
|
if (item.statusKind === "artifact") {
|
|
@@ -1219,10 +1225,6 @@ function stringRecordValue(
|
|
|
1219
1225
|
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
1220
1226
|
}
|
|
1221
1227
|
|
|
1222
|
-
function isCredentialCodeAgentText(value: string): boolean {
|
|
1223
|
-
return /No LLM provider key was found|Missing credentials/i.test(value);
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
1228
|
export function upsertUserMessage(repo: any, userMsg: UserMessage): any {
|
|
1227
1229
|
const nextRepo = normalizeThreadRepository(repo);
|
|
1228
1230
|
|
|
@@ -639,6 +639,14 @@ export interface ListThreadsOptions {
|
|
|
639
639
|
/** When true, returns only threads with no scope (general chats). */
|
|
640
640
|
unscopedOnly?: boolean;
|
|
641
641
|
orgId?: string | null;
|
|
642
|
+
/**
|
|
643
|
+
* Include archived threads in the results. Defaults to false: archived
|
|
644
|
+
* threads (`archived_at` set via `setThreadArchived`) are hidden from the
|
|
645
|
+
* ordinary chat list/search so archiving actually removes a thread from
|
|
646
|
+
* view. Pass true for surfaces that explicitly need to see archived chats
|
|
647
|
+
* (e.g. an "Archived" filter or restoring one via `setThreadArchived`).
|
|
648
|
+
*/
|
|
649
|
+
includeArchived?: boolean;
|
|
642
650
|
}
|
|
643
651
|
|
|
644
652
|
function chatThreadAccessSql(
|
|
@@ -686,6 +694,9 @@ export async function listThreads(
|
|
|
686
694
|
);
|
|
687
695
|
const filters: string[] = [access.sql, `message_count > 0`];
|
|
688
696
|
const args: (string | number)[] = [...access.args];
|
|
697
|
+
if (!opts.includeArchived) {
|
|
698
|
+
filters.push(`archived_at IS NULL`);
|
|
699
|
+
}
|
|
689
700
|
if (opts.scope) {
|
|
690
701
|
filters.push(`scope_type = ? AND scope_id = ?`);
|
|
691
702
|
args.push(opts.scope.type, opts.scope.id);
|
|
@@ -710,7 +721,12 @@ export async function searchThreads(
|
|
|
710
721
|
ownerEmail: string,
|
|
711
722
|
query: string,
|
|
712
723
|
limit = 50,
|
|
713
|
-
options: {
|
|
724
|
+
options: {
|
|
725
|
+
scope?: { type: string; id: string };
|
|
726
|
+
orgId?: string | null;
|
|
727
|
+
/** See `ListThreadsOptions.includeArchived` — defaults to false. */
|
|
728
|
+
includeArchived?: boolean;
|
|
729
|
+
} = {},
|
|
714
730
|
): Promise<ChatThreadSummary[]> {
|
|
715
731
|
await ensureTable();
|
|
716
732
|
const client = getDbExec();
|
|
@@ -728,6 +744,9 @@ export async function searchThreads(
|
|
|
728
744
|
`(title LIKE ? ESCAPE '!' OR preview LIKE ? ESCAPE '!' OR thread_data LIKE ? ESCAPE '!')`,
|
|
729
745
|
];
|
|
730
746
|
const args: (string | number)[] = [...access.args, pattern, pattern, pattern];
|
|
747
|
+
if (!options.includeArchived) {
|
|
748
|
+
filters.push(`archived_at IS NULL`);
|
|
749
|
+
}
|
|
731
750
|
if (options.scope) {
|
|
732
751
|
filters.push(`scope_type = ? AND scope_id = ?`);
|
|
733
752
|
args.push(options.scope.type, options.scope.id);
|
|
@@ -215,6 +215,7 @@ export async function executeCodeAgentRun(
|
|
|
215
215
|
runId: existing.id,
|
|
216
216
|
kind: "status",
|
|
217
217
|
message,
|
|
218
|
+
signal: "credential-gap",
|
|
218
219
|
metadata: { status: "paused", phase: "missing-credentials" },
|
|
219
220
|
});
|
|
220
221
|
return updateCodeAgentRunRecord(existing.id, {
|
|
@@ -77,6 +77,17 @@ export type CodeAgentTranscriptEventKind =
|
|
|
77
77
|
| "artifact"
|
|
78
78
|
| "status";
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Structured, machine-checkable marker for transcript events that need
|
|
82
|
+
* special handling in the UI beyond free-text matching. `"credential-gap"`
|
|
83
|
+
* marks the status event the executor appends when no LLM provider key (or
|
|
84
|
+
* Codex CLI login) is available; consumers should prefer this field over
|
|
85
|
+
* regex-matching `message` (see `isCredentialGapCodeAgentEvent` in
|
|
86
|
+
* `../code-agents/transcript-normalizer.js`). Optional so older, already
|
|
87
|
+
* persisted JSONL transcripts without the field keep parsing unchanged.
|
|
88
|
+
*/
|
|
89
|
+
export type CodeAgentTranscriptEventSignal = "credential-gap";
|
|
90
|
+
|
|
80
91
|
export interface CodeAgentTranscriptEvent {
|
|
81
92
|
schemaVersion: 1;
|
|
82
93
|
id: string;
|
|
@@ -85,6 +96,7 @@ export interface CodeAgentTranscriptEvent {
|
|
|
85
96
|
message: string;
|
|
86
97
|
createdAt: string;
|
|
87
98
|
metadata?: Record<string, unknown>;
|
|
99
|
+
signal?: CodeAgentTranscriptEventSignal;
|
|
88
100
|
}
|
|
89
101
|
|
|
90
102
|
export interface CreateCodeAgentRunInput {
|
|
@@ -109,6 +121,7 @@ export interface AppendCodeAgentTranscriptEventInput {
|
|
|
109
121
|
message: string;
|
|
110
122
|
createdAt?: string;
|
|
111
123
|
metadata?: Record<string, unknown>;
|
|
124
|
+
signal?: CodeAgentTranscriptEventSignal;
|
|
112
125
|
}
|
|
113
126
|
|
|
114
127
|
export interface QueueCodeAgentFollowUpInput {
|
|
@@ -294,6 +307,7 @@ export function appendCodeAgentTranscriptEvent(
|
|
|
294
307
|
message: input.message,
|
|
295
308
|
createdAt,
|
|
296
309
|
metadata: input.metadata,
|
|
310
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
297
311
|
};
|
|
298
312
|
|
|
299
313
|
fs.mkdirSync(codeAgentTranscriptsDir(), { recursive: true });
|
|
@@ -1458,32 +1458,39 @@ function AgentPanelInner({
|
|
|
1458
1458
|
activeTab && (activeTabMessageCount > 0 || activeTab.status !== "idle");
|
|
1459
1459
|
|
|
1460
1460
|
return (
|
|
1461
|
-
|
|
1462
|
-
<div
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1461
|
+
<>
|
|
1462
|
+
<div
|
|
1463
|
+
aria-hidden="true"
|
|
1464
|
+
data-agent-page-chat-fade=""
|
|
1465
|
+
className="pointer-events-none absolute inset-x-0 top-0 z-50 h-16 bg-gradient-to-b from-background via-background/90 to-transparent opacity-0 transition-opacity duration-150"
|
|
1466
|
+
/>
|
|
1467
|
+
<div className="pointer-events-none absolute inset-x-0 top-3 z-[60] flex justify-end px-3 sm:top-4 sm:px-4">
|
|
1468
|
+
<div className="pointer-events-auto flex items-center gap-1">
|
|
1469
|
+
{canShareActiveTab ? (
|
|
1470
|
+
<ShareButton
|
|
1471
|
+
resourceType="chat_thread"
|
|
1472
|
+
resourceId={activeTab.id}
|
|
1473
|
+
resourceTitle={activeTab.label || "Chat"}
|
|
1474
|
+
shareUrl={getChatThreadShareUrl(activeTab.id)}
|
|
1475
|
+
trigger="icon"
|
|
1476
|
+
triggerClassName="h-8 w-8 border border-border bg-background/95 shadow-sm backdrop-blur hover:bg-accent"
|
|
1477
|
+
/>
|
|
1478
|
+
) : null}
|
|
1479
|
+
<button
|
|
1480
|
+
type="button"
|
|
1481
|
+
data-agent-page-new-chat=""
|
|
1482
|
+
aria-label={t("agentPanel.newChat")}
|
|
1483
|
+
onClick={() => {
|
|
1484
|
+
addTab();
|
|
1485
|
+
}}
|
|
1486
|
+
className="inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background/95 px-2.5 text-xs font-medium text-foreground shadow-sm backdrop-blur transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
1487
|
+
>
|
|
1488
|
+
<IconPlus size={14} />
|
|
1489
|
+
<span>{t("agentPanel.newChat")}</span>
|
|
1490
|
+
</button>
|
|
1491
|
+
</div>
|
|
1485
1492
|
</div>
|
|
1486
|
-
|
|
1493
|
+
</>
|
|
1487
1494
|
);
|
|
1488
1495
|
},
|
|
1489
1496
|
[getChatThreadShareUrl, t],
|
|
@@ -1629,6 +1629,17 @@ export interface AssistantChatProps {
|
|
|
1629
1629
|
historyReloadKey?: string | number | null;
|
|
1630
1630
|
/** Smooth the last assistant message while an external transcript is updating. */
|
|
1631
1631
|
externalStreaming?: boolean;
|
|
1632
|
+
/**
|
|
1633
|
+
* Optional host hooks for the inline `needsApproval` affordance beyond the
|
|
1634
|
+
* built-in Approve. Additive: omit entirely to keep today's default
|
|
1635
|
+
* behavior (Deny is local-only, no "Always allow" button). Code sessions
|
|
1636
|
+
* pass these through to the same `host.controlRun` commands their
|
|
1637
|
+
* standalone approval banner already uses (see CodeAgentsApp).
|
|
1638
|
+
*/
|
|
1639
|
+
approvalActions?: {
|
|
1640
|
+
onDeny?: (approvalKey: string) => void;
|
|
1641
|
+
onAlwaysAllow?: (approvalKey: string) => void;
|
|
1642
|
+
};
|
|
1632
1643
|
}
|
|
1633
1644
|
|
|
1634
1645
|
export const CHAT_STORAGE_PREFIX = "agent-chat:";
|
|
@@ -1852,6 +1863,7 @@ const AssistantChatInner = forwardRef<
|
|
|
1852
1863
|
onSlashCommand,
|
|
1853
1864
|
execMode,
|
|
1854
1865
|
onExecModeChange,
|
|
1866
|
+
approvalActions,
|
|
1855
1867
|
planModeDisabled,
|
|
1856
1868
|
planModeDisabledReason,
|
|
1857
1869
|
selectedModel,
|
|
@@ -4640,8 +4652,12 @@ const AssistantChatInner = forwardRef<
|
|
|
4640
4652
|
),
|
|
4641
4653
|
} as Parameters<typeof threadRuntime.append>[0]);
|
|
4642
4654
|
},
|
|
4655
|
+
...(approvalActions?.onDeny ? { onDeny: approvalActions.onDeny } : {}),
|
|
4656
|
+
...(approvalActions?.onAlwaysAllow
|
|
4657
|
+
? { onAlwaysAllow: approvalActions.onAlwaysAllow }
|
|
4658
|
+
: {}),
|
|
4643
4659
|
}),
|
|
4644
|
-
[appendThreadMessage, execMode, markOptimisticRunning],
|
|
4660
|
+
[appendThreadMessage, execMode, markOptimisticRunning, approvalActions],
|
|
4645
4661
|
);
|
|
4646
4662
|
|
|
4647
4663
|
return (
|
|
@@ -5189,33 +5205,33 @@ const AssistantChatInner = forwardRef<
|
|
|
5189
5205
|
onAttachmentError={setComposerError}
|
|
5190
5206
|
extraActionButton={
|
|
5191
5207
|
contextXRayEnabled ||
|
|
5192
|
-
composerExtraActionButton
|
|
5193
|
-
showRunningInUI ? (
|
|
5208
|
+
composerExtraActionButton ? (
|
|
5194
5209
|
<>
|
|
5195
5210
|
{contextXRayEnabled && (
|
|
5196
5211
|
<ContextMeter threadId={threadId} />
|
|
5197
5212
|
)}
|
|
5198
5213
|
{composerExtraActionButton}
|
|
5199
|
-
{showRunningInUI && (
|
|
5200
|
-
<Tooltip>
|
|
5201
|
-
<TooltipTrigger asChild>
|
|
5202
|
-
<button
|
|
5203
|
-
type="button"
|
|
5204
|
-
onClick={() => stopActiveRun()}
|
|
5205
|
-
aria-label="Stop response"
|
|
5206
|
-
className="shrink-0 flex h-7 w-7 cursor-pointer items-center justify-center rounded-full bg-primary text-primary-foreground shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
5207
|
-
>
|
|
5208
|
-
<IconPlayerStopFilled className="h-3 w-3" />
|
|
5209
|
-
</button>
|
|
5210
|
-
</TooltipTrigger>
|
|
5211
|
-
<TooltipContent>
|
|
5212
|
-
Stop response
|
|
5213
|
-
</TooltipContent>
|
|
5214
|
-
</Tooltip>
|
|
5215
|
-
)}
|
|
5216
5214
|
</>
|
|
5217
5215
|
) : undefined
|
|
5218
5216
|
}
|
|
5217
|
+
stopButton={
|
|
5218
|
+
showRunningInUI ? (
|
|
5219
|
+
<Tooltip>
|
|
5220
|
+
<TooltipTrigger asChild>
|
|
5221
|
+
<button
|
|
5222
|
+
type="button"
|
|
5223
|
+
onClick={() => stopActiveRun()}
|
|
5224
|
+
aria-label="Stop response"
|
|
5225
|
+
data-agent-composer-slot="stop-button"
|
|
5226
|
+
className="shrink-0 flex h-7 w-7 cursor-pointer items-center justify-center rounded-full bg-primary text-primary-foreground shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
5227
|
+
>
|
|
5228
|
+
<IconPlayerStopFilled className="h-3 w-3" />
|
|
5229
|
+
</button>
|
|
5230
|
+
</TooltipTrigger>
|
|
5231
|
+
<TooltipContent>Stop response</TooltipContent>
|
|
5232
|
+
</Tooltip>
|
|
5233
|
+
) : undefined
|
|
5234
|
+
}
|
|
5219
5235
|
/>
|
|
5220
5236
|
</>
|
|
5221
5237
|
)}
|