@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
|
@@ -100,6 +100,11 @@ function emitLlmGenerationTrackingEvent(args: {
|
|
|
100
100
|
successfulTools: number;
|
|
101
101
|
failedTools: number;
|
|
102
102
|
createdAt: number;
|
|
103
|
+
experimentAssignments?: Array<{
|
|
104
|
+
experimentId: string;
|
|
105
|
+
variantId: string;
|
|
106
|
+
}>;
|
|
107
|
+
modelSelectionSource?: string;
|
|
103
108
|
}): void {
|
|
104
109
|
const provider = llmProviderFromEngine(args.engineName, args.model);
|
|
105
110
|
const costUsd = costUsdFromCenticents(args.costCentsX100);
|
|
@@ -126,6 +131,7 @@ function emitLlmGenerationTrackingEvent(args: {
|
|
|
126
131
|
tool_calls: args.toolCalls,
|
|
127
132
|
successful_tools: args.successfulTools,
|
|
128
133
|
failed_tools: args.failedTools,
|
|
134
|
+
model_selection_source: args.modelSelectionSource,
|
|
129
135
|
created_at: new Date(args.createdAt).toISOString(),
|
|
130
136
|
created_at_ms: args.createdAt,
|
|
131
137
|
$ai_trace_id: args.runId,
|
|
@@ -145,6 +151,18 @@ function emitLlmGenerationTrackingEvent(args: {
|
|
|
145
151
|
$ai_request_count: 1,
|
|
146
152
|
$ai_total_cost_usd: costUsd,
|
|
147
153
|
};
|
|
154
|
+
if (args.experimentAssignments?.length) {
|
|
155
|
+
properties.experiment_ids = args.experimentAssignments
|
|
156
|
+
.map((assignment) => assignment.experimentId)
|
|
157
|
+
.join(",");
|
|
158
|
+
properties.experiment_variants = args.experimentAssignments
|
|
159
|
+
.map((assignment) => assignment.variantId)
|
|
160
|
+
.join(",");
|
|
161
|
+
if (args.experimentAssignments.length === 1) {
|
|
162
|
+
properties.experiment_id = args.experimentAssignments[0].experimentId;
|
|
163
|
+
properties.experiment_variant = args.experimentAssignments[0].variantId;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
148
166
|
if (error) properties.error_message = error;
|
|
149
167
|
|
|
150
168
|
for (const key of Object.keys(properties)) {
|
|
@@ -245,6 +263,12 @@ export async function instrumentAgentLoop(opts: {
|
|
|
245
263
|
* reads. */
|
|
246
264
|
userId: string | null;
|
|
247
265
|
config: ObservabilityConfig;
|
|
266
|
+
metadata?: Record<string, unknown> | null;
|
|
267
|
+
experimentAssignments?: Array<{
|
|
268
|
+
experimentId: string;
|
|
269
|
+
variantId: string;
|
|
270
|
+
}>;
|
|
271
|
+
modelSelectionSource?: string;
|
|
248
272
|
classifyError?: (error: unknown) =>
|
|
249
273
|
| {
|
|
250
274
|
status?: "success" | "error";
|
|
@@ -268,6 +292,15 @@ export async function instrumentAgentLoop(opts: {
|
|
|
268
292
|
"agent.thread_id": threadId ?? undefined,
|
|
269
293
|
"agent.user_id": userId ?? undefined,
|
|
270
294
|
"agent.model": loopOpts.model,
|
|
295
|
+
"agent.model_selection_source": opts.modelSelectionSource,
|
|
296
|
+
"agent.experiment_id":
|
|
297
|
+
opts.experimentAssignments?.length === 1
|
|
298
|
+
? opts.experimentAssignments[0].experimentId
|
|
299
|
+
: undefined,
|
|
300
|
+
"agent.experiment_variant":
|
|
301
|
+
opts.experimentAssignments?.length === 1
|
|
302
|
+
? opts.experimentAssignments[0].variantId
|
|
303
|
+
: undefined,
|
|
271
304
|
});
|
|
272
305
|
|
|
273
306
|
const spans: TraceSpan[] = [];
|
|
@@ -424,7 +457,7 @@ export async function instrumentAgentLoop(opts: {
|
|
|
424
457
|
let usage: AgentLoopUsage | undefined;
|
|
425
458
|
let runStatus: "success" | "error" = "success";
|
|
426
459
|
let errorMessage: string | null = null;
|
|
427
|
-
let runMetadata: Record<string, unknown> | null = null;
|
|
460
|
+
let runMetadata: Record<string, unknown> | null = opts.metadata ?? null;
|
|
428
461
|
try {
|
|
429
462
|
usage = await runAgentLoop({ ...loopOpts, send: instrumentedSend });
|
|
430
463
|
} catch (err: any) {
|
|
@@ -434,7 +467,11 @@ export async function instrumentAgentLoop(opts: {
|
|
|
434
467
|
classification?.errorMessage === undefined
|
|
435
468
|
? (err?.message ?? String(err))
|
|
436
469
|
: classification.errorMessage;
|
|
437
|
-
|
|
470
|
+
const errorMetadata = classification?.metadata ?? null;
|
|
471
|
+
runMetadata =
|
|
472
|
+
runMetadata || errorMetadata
|
|
473
|
+
? { ...(runMetadata ?? {}), ...(errorMetadata ?? {}) }
|
|
474
|
+
: null;
|
|
438
475
|
throw err;
|
|
439
476
|
} finally {
|
|
440
477
|
const runEnd = Date.now();
|
|
@@ -501,6 +538,8 @@ export async function instrumentAgentLoop(opts: {
|
|
|
501
538
|
successfulTools,
|
|
502
539
|
failedTools,
|
|
503
540
|
createdAt: runStart,
|
|
541
|
+
experimentAssignments: opts.experimentAssignments,
|
|
542
|
+
modelSelectionSource: opts.modelSelectionSource,
|
|
504
543
|
});
|
|
505
544
|
}
|
|
506
545
|
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
normalizeModelForEngine,
|
|
16
16
|
} from "../../agent/engine/index.js";
|
|
17
17
|
import type { ActionTool } from "../../agent/types.js";
|
|
18
|
+
import { resolveHostedDefaultModelExperiment } from "../../observability/hosted-model-experiment.js";
|
|
19
|
+
import { getRequestUserEmail } from "../../server/request-context.js";
|
|
18
20
|
import { getSetting } from "../../settings/index.js";
|
|
19
21
|
|
|
20
22
|
export const tool: ActionTool = {
|
|
@@ -82,13 +84,23 @@ export async function run(args: Record<string, string> = {}): Promise<string> {
|
|
|
82
84
|
? current?.model
|
|
83
85
|
: undefined;
|
|
84
86
|
const currentEngineName = currentEntry?.name ?? "anthropic";
|
|
85
|
-
|
|
87
|
+
let currentModel =
|
|
86
88
|
currentEntry && !envUnavailable
|
|
87
89
|
? normalizeModelForEngine(
|
|
88
90
|
currentEntry,
|
|
89
91
|
currentModelCandidate ?? currentEntry.defaultModel,
|
|
90
92
|
)
|
|
91
93
|
: (currentModelCandidate ?? DEFAULT_MODEL);
|
|
94
|
+
const hostedExperiment =
|
|
95
|
+
currentEntry && !currentModelCandidate
|
|
96
|
+
? resolveHostedDefaultModelExperiment({
|
|
97
|
+
userId: getRequestUserEmail(),
|
|
98
|
+
engineName: currentEntry.name,
|
|
99
|
+
isDefaultModelSelection: true,
|
|
100
|
+
supportedModels: currentEntry.supportedModels,
|
|
101
|
+
})
|
|
102
|
+
: null;
|
|
103
|
+
if (hostedExperiment) currentModel = hostedExperiment.model;
|
|
92
104
|
|
|
93
105
|
const result = {
|
|
94
106
|
engines: engines.map((e) => ({
|
|
@@ -107,6 +119,12 @@ export async function run(args: Record<string, string> = {}): Promise<string> {
|
|
|
107
119
|
: {
|
|
108
120
|
engine: currentEngineName,
|
|
109
121
|
model: currentModel,
|
|
122
|
+
...(hostedExperiment
|
|
123
|
+
? {
|
|
124
|
+
modelSelectionSource: "experiment",
|
|
125
|
+
experimentAssignment: hostedExperiment.assignment,
|
|
126
|
+
}
|
|
127
|
+
: {}),
|
|
110
128
|
},
|
|
111
129
|
};
|
|
112
130
|
|
|
@@ -321,7 +321,14 @@ export async function run(
|
|
|
321
321
|
orgDomain: callerOrgDomain,
|
|
322
322
|
orgSecret: callerOrgSecret,
|
|
323
323
|
onUpdate: onRemotePollUpdate,
|
|
324
|
-
...(callTimeoutMs
|
|
324
|
+
...(callTimeoutMs
|
|
325
|
+
? {
|
|
326
|
+
timeoutMs: callTimeoutMs,
|
|
327
|
+
// Integration callers must keep the timeout task id so the
|
|
328
|
+
// catch below can enqueue durable continuation polling.
|
|
329
|
+
returnRecoverableArtifactsOnTimeout: false,
|
|
330
|
+
}
|
|
331
|
+
: {}),
|
|
325
332
|
});
|
|
326
333
|
responseText =
|
|
327
334
|
formatDownstreamLlmCredentialFailure(agent.name, responseText) ??
|
|
@@ -348,8 +355,23 @@ export async function run(
|
|
|
348
355
|
`The ${agent.name} agent accepted this delegated subtask and will post its own final result to the originating integration thread automatically. ` +
|
|
349
356
|
`Do not call ${agent.name} again for this same subtask. Continue any other requested work, then answer with the completed results you have; if needed, mention that ${agent.name} is posting its result separately.`;
|
|
350
357
|
} else {
|
|
351
|
-
|
|
352
|
-
|
|
358
|
+
// The normal integration path must preserve the timeout task id so
|
|
359
|
+
// it can enqueue a durable continuation. If that enqueue fails,
|
|
360
|
+
// do not hide receiver-verified artifacts that were already
|
|
361
|
+
// returned with the last poll; this mirrors callAgent's default
|
|
362
|
+
// timeout behavior without treating arbitrary remote status text
|
|
363
|
+
// as a completed response.
|
|
364
|
+
const recoverableArtifactText =
|
|
365
|
+
extractRecoverableTimeoutArtifactText(pollErr);
|
|
366
|
+
if (recoverableArtifactText) {
|
|
367
|
+
responseText = expandRelativeUrls(
|
|
368
|
+
recoverableArtifactText,
|
|
369
|
+
agent.url,
|
|
370
|
+
);
|
|
371
|
+
} else {
|
|
372
|
+
const reason = pollErr?.message ?? "unknown error";
|
|
373
|
+
responseText = `The ${agent.name} agent is taking longer than expected and didn't reply in time. (${reason})`;
|
|
374
|
+
}
|
|
353
375
|
}
|
|
354
376
|
} else {
|
|
355
377
|
const reason = pollErr?.message ?? "unknown error";
|
|
@@ -490,6 +512,34 @@ function getA2ATaskTimeoutTaskId(err: unknown): string | null {
|
|
|
490
512
|
return match?.[1] ?? null;
|
|
491
513
|
}
|
|
492
514
|
|
|
515
|
+
/**
|
|
516
|
+
* Mirrors the A2A client's default timeout recovery for the exceptional case
|
|
517
|
+
* where an integration cannot enqueue a durable continuation. Only an
|
|
518
|
+
* explicitly receiver-marked task message is safe to surface as a completed
|
|
519
|
+
* partial result; ordinary working-state text remains a timeout failure.
|
|
520
|
+
*/
|
|
521
|
+
function extractRecoverableTimeoutArtifactText(err: unknown): string {
|
|
522
|
+
const candidate = err as
|
|
523
|
+
| { lastTask?: Task | unknown; name?: unknown }
|
|
524
|
+
| null
|
|
525
|
+
| undefined;
|
|
526
|
+
const lastTask =
|
|
527
|
+
err instanceof A2ATaskTimeoutError
|
|
528
|
+
? err.lastTask
|
|
529
|
+
: candidate?.name === "A2ATaskTimeoutError"
|
|
530
|
+
? (candidate.lastTask as Task | undefined)
|
|
531
|
+
: undefined;
|
|
532
|
+
const message = lastTask?.status?.message;
|
|
533
|
+
if (!message?.metadata?.agentNativeRecoverableArtifacts) return "";
|
|
534
|
+
|
|
535
|
+
return message.parts
|
|
536
|
+
.filter(
|
|
537
|
+
(part): part is { type: "text"; text: string } => part.type === "text",
|
|
538
|
+
)
|
|
539
|
+
.map((part) => part.text)
|
|
540
|
+
.join("\n");
|
|
541
|
+
}
|
|
542
|
+
|
|
493
543
|
async function formatExistingIntegrationContinuationIfRetry(
|
|
494
544
|
agent: {
|
|
495
545
|
name: string;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Search or list past agent chat threads.
|
|
5
5
|
*
|
|
6
6
|
* Usage:
|
|
7
|
-
* pnpm action search-chats [--query "search term"] [--limit N] [--format json]
|
|
7
|
+
* pnpm action search-chats [--query "search term"] [--limit N] [--format json] [--includeArchived]
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { searchThreads, listThreads } from "../../chat-threads/store.js";
|
|
@@ -40,15 +40,17 @@ export default async function searchChats(args: string[]): Promise<void> {
|
|
|
40
40
|
console.log(`Usage: pnpm action search-chats [options]
|
|
41
41
|
|
|
42
42
|
Options:
|
|
43
|
-
--query <text>
|
|
44
|
-
--limit N
|
|
45
|
-
--format json
|
|
46
|
-
--
|
|
43
|
+
--query <text> Search chats by title, preview, or content
|
|
44
|
+
--limit N Max results (default: 20)
|
|
45
|
+
--format json Output as JSON
|
|
46
|
+
--includeArchived Also include archived chats (excluded by default)
|
|
47
|
+
--help Show this help message
|
|
47
48
|
|
|
48
49
|
Examples:
|
|
49
50
|
pnpm action search-chats --query "email setup"
|
|
50
51
|
pnpm action search-chats --limit 5
|
|
51
|
-
pnpm action search-chats --format json
|
|
52
|
+
pnpm action search-chats --format json
|
|
53
|
+
pnpm action search-chats --includeArchived`);
|
|
52
54
|
return;
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -56,10 +58,11 @@ Examples:
|
|
|
56
58
|
const limit = parsed.limit ? parseInt(parsed.limit, 10) : 20;
|
|
57
59
|
if (isNaN(limit) || limit < 1) fail("--limit must be a positive integer");
|
|
58
60
|
|
|
61
|
+
const includeArchived = parsed.includeArchived === "true";
|
|
59
62
|
const query = parsed.query;
|
|
60
63
|
const threads = query
|
|
61
|
-
? await searchThreads(owner, query, limit)
|
|
62
|
-
: await listThreads(owner, limit, 0);
|
|
64
|
+
? await searchThreads(owner, query, limit, { includeArchived })
|
|
65
|
+
: await listThreads(owner, { limit, offset: 0, includeArchived });
|
|
63
66
|
|
|
64
67
|
if (parsed.format === "json") {
|
|
65
68
|
console.log(
|
|
@@ -22,7 +22,7 @@ export function registerFrameworkSecrets(): void {
|
|
|
22
22
|
key: "OPENAI_API_KEY",
|
|
23
23
|
label: "OpenAI API key",
|
|
24
24
|
description:
|
|
25
|
-
"
|
|
25
|
+
"Optional fallback for realtime voice when Builder is not connected, and for OpenAI transcription.",
|
|
26
26
|
docsUrl: "https://platform.openai.com/api-keys",
|
|
27
27
|
scope: "user",
|
|
28
28
|
kind: "api-key",
|
|
@@ -54,11 +54,16 @@ import {
|
|
|
54
54
|
listAgentEngines,
|
|
55
55
|
registerBuiltinEngines,
|
|
56
56
|
} from "../agent/engine/index.js";
|
|
57
|
-
import type {
|
|
57
|
+
import type {
|
|
58
|
+
AgentEngine,
|
|
59
|
+
EngineMessage,
|
|
60
|
+
EngineTool,
|
|
61
|
+
} from "../agent/engine/types.js";
|
|
58
62
|
import {
|
|
59
63
|
createProductionAgentHandler,
|
|
60
64
|
actionsToEngineTools,
|
|
61
65
|
executeAgentToolCall,
|
|
66
|
+
filterInitialEngineTools,
|
|
62
67
|
getActiveRunForThreadAsync,
|
|
63
68
|
abortRunDurably,
|
|
64
69
|
subscribeToRun,
|
|
@@ -1903,6 +1908,11 @@ async function createChatScriptEntries(): Promise<Record<string, ActionEntry>> {
|
|
|
1903
1908
|
description: "Output format",
|
|
1904
1909
|
enum: ["json", "text"],
|
|
1905
1910
|
},
|
|
1911
|
+
includeArchived: {
|
|
1912
|
+
type: "boolean",
|
|
1913
|
+
description:
|
|
1914
|
+
"Also include archived chats in the results. Archived chats are excluded by default.",
|
|
1915
|
+
},
|
|
1906
1916
|
},
|
|
1907
1917
|
},
|
|
1908
1918
|
},
|
|
@@ -1953,6 +1963,11 @@ async function createChatScriptEntries(): Promise<Record<string, ActionEntry>> {
|
|
|
1953
1963
|
description: "(search) Output format",
|
|
1954
1964
|
enum: ["json", "text"],
|
|
1955
1965
|
},
|
|
1966
|
+
includeArchived: {
|
|
1967
|
+
type: "boolean",
|
|
1968
|
+
description:
|
|
1969
|
+
"(search) Also include archived chats in the results. Archived chats are excluded by default, matching the 'archive' action's effect on the chat list.",
|
|
1970
|
+
},
|
|
1956
1971
|
id: {
|
|
1957
1972
|
type: "string",
|
|
1958
1973
|
description:
|
|
@@ -2940,6 +2955,22 @@ export function runA2AAgentLoop(
|
|
|
2940
2955
|
);
|
|
2941
2956
|
}
|
|
2942
2957
|
|
|
2958
|
+
/**
|
|
2959
|
+
* Keep delegated A2A turns on the same compact initial tool surface as
|
|
2960
|
+
* interactive chat. `tool-search` remains in the initial set, while the
|
|
2961
|
+
* complete registry is supplied separately so the run loop can load a matched
|
|
2962
|
+
* schema after a tool-search result.
|
|
2963
|
+
*/
|
|
2964
|
+
export function createA2AEngineToolSurface(
|
|
2965
|
+
availableTools: EngineTool[],
|
|
2966
|
+
initialToolNames?: string[],
|
|
2967
|
+
): { tools: EngineTool[]; availableTools: EngineTool[] } {
|
|
2968
|
+
return {
|
|
2969
|
+
tools: filterInitialEngineTools(availableTools, initialToolNames),
|
|
2970
|
+
availableTools,
|
|
2971
|
+
};
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2943
2974
|
/**
|
|
2944
2975
|
* Verbose framework sections returned by the `get-framework-context` tool.
|
|
2945
2976
|
* Keyed by topic so the agent can request specific sections.
|
|
@@ -2971,9 +3002,9 @@ Use for charts, visualizations, previews. Don't use for simple text/tables or ex
|
|
|
2971
3002
|
"chat-history": `### Chat History
|
|
2972
3003
|
|
|
2973
3004
|
You can search and restore previous chat conversations using \`chat-history\`:
|
|
2974
|
-
- \`chat-history\` (action: "search") — Search or list past chat threads by keyword
|
|
3005
|
+
- \`chat-history\` (action: "search") — Search or list past chat threads by keyword. Archived threads are excluded by default; pass \`includeArchived: true\` to also see them.
|
|
2975
3006
|
- \`chat-history\` (action: "open") — Open a chat thread in the UI as a new tab and focus it
|
|
2976
|
-
- \`chat-history\` (actions: "rename", "pin", "unpin", "archive") — Organize a known chat thread by ID
|
|
3007
|
+
- \`chat-history\` (actions: "rename", "pin", "unpin", "archive") — Organize a known chat thread by ID. Archiving a thread hides it from the default chat list and search.
|
|
2977
3008
|
|
|
2978
3009
|
When the user asks to find a previous conversation, use \`chat-history\` with action "search" first to find matching threads, then action "open" to restore the one they want.`,
|
|
2979
3010
|
|
|
@@ -5077,7 +5108,10 @@ export function createAgentChatPlugin(
|
|
|
5077
5108
|
},
|
|
5078
5109
|
);
|
|
5079
5110
|
|
|
5080
|
-
const
|
|
5111
|
+
const a2aToolSurface = createA2AEngineToolSurface(
|
|
5112
|
+
actionsToEngineTools(a2aActions),
|
|
5113
|
+
options?.initialToolNames,
|
|
5114
|
+
);
|
|
5081
5115
|
|
|
5082
5116
|
// Precise current time rides the user message (not the cached
|
|
5083
5117
|
// system-prompt prefix) — same pattern as the interactive handler.
|
|
@@ -5098,7 +5132,7 @@ export function createAgentChatPlugin(
|
|
|
5098
5132
|
const controller = new AbortController();
|
|
5099
5133
|
|
|
5100
5134
|
console.log(
|
|
5101
|
-
`[A2A] Starting agent loop: ${
|
|
5135
|
+
`[A2A] Starting agent loop: ${a2aToolSurface.tools.length}/${a2aToolSurface.availableTools.length} initial tools, prompt ${systemPrompt.length} chars`,
|
|
5102
5136
|
);
|
|
5103
5137
|
|
|
5104
5138
|
await runA2AAgentLoop(
|
|
@@ -5106,7 +5140,8 @@ export function createAgentChatPlugin(
|
|
|
5106
5140
|
engine: a2aEngine,
|
|
5107
5141
|
model,
|
|
5108
5142
|
systemPrompt,
|
|
5109
|
-
tools:
|
|
5143
|
+
tools: a2aToolSurface.tools,
|
|
5144
|
+
availableTools: a2aToolSurface.availableTools,
|
|
5110
5145
|
messages: a2aMessages,
|
|
5111
5146
|
actions: a2aActions,
|
|
5112
5147
|
send: (event) => {
|
|
@@ -298,6 +298,7 @@ const BUILDER_WAITLIST_USE_CASES = new Set([
|
|
|
298
298
|
BUILDER_WAITLIST_DEFAULT_USE_CASE,
|
|
299
299
|
"design_publish_app",
|
|
300
300
|
"docs_build_online_waitlist",
|
|
301
|
+
"docs_edit_online_waitlist",
|
|
301
302
|
]);
|
|
302
303
|
const BUILDER_WAITLIST_FORM_TIMEOUT_MS = 8000;
|
|
303
304
|
const BUILDER_WAITLIST_TEXT_LIMIT = 4000;
|
|
@@ -320,6 +321,7 @@ export interface BuilderWaitlistBody {
|
|
|
320
321
|
appUrl?: unknown;
|
|
321
322
|
pageUrl?: unknown;
|
|
322
323
|
source?: unknown;
|
|
324
|
+
template?: unknown;
|
|
323
325
|
useCase?: unknown;
|
|
324
326
|
}
|
|
325
327
|
|
|
@@ -352,6 +354,13 @@ function normalizeBuilderWaitlistUseCase(value: unknown): string {
|
|
|
352
354
|
: BUILDER_WAITLIST_DEFAULT_USE_CASE;
|
|
353
355
|
}
|
|
354
356
|
|
|
357
|
+
function normalizeBuilderWaitlistTemplate(value: unknown): string | undefined {
|
|
358
|
+
const template = cleanBuilderWaitlistText(value, 100);
|
|
359
|
+
return template && /^[a-z0-9][a-z0-9-]{0,99}$/.test(template)
|
|
360
|
+
? template
|
|
361
|
+
: undefined;
|
|
362
|
+
}
|
|
363
|
+
|
|
355
364
|
function isValidWaitlistEmail(email: string): boolean {
|
|
356
365
|
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
357
366
|
}
|
|
@@ -506,6 +515,7 @@ export function buildBuilderWaitlistFormPayload(
|
|
|
506
515
|
getOrigin(event);
|
|
507
516
|
const source =
|
|
508
517
|
cleanBuilderWaitlistText(body.source, 100) ?? BUILDER_WAITLIST_FORM_SOURCE;
|
|
518
|
+
const template = normalizeBuilderWaitlistTemplate(body.template);
|
|
509
519
|
const useCase = normalizeBuilderWaitlistUseCase(body.useCase);
|
|
510
520
|
|
|
511
521
|
return {
|
|
@@ -515,6 +525,7 @@ export function buildBuilderWaitlistFormPayload(
|
|
|
515
525
|
appUrl,
|
|
516
526
|
prompt: cleanBuilderWaitlistText(body.prompt),
|
|
517
527
|
source,
|
|
528
|
+
template,
|
|
518
529
|
useCase,
|
|
519
530
|
},
|
|
520
531
|
_hp: "",
|
|
@@ -522,6 +533,7 @@ export function buildBuilderWaitlistFormPayload(
|
|
|
522
533
|
submitterEmail: sessionEmail,
|
|
523
534
|
pageUrl: appUrl,
|
|
524
535
|
source,
|
|
536
|
+
template,
|
|
525
537
|
useCase,
|
|
526
538
|
},
|
|
527
539
|
};
|
|
@@ -2021,6 +2033,7 @@ export function createCoreRoutesPlugin(
|
|
|
2021
2033
|
body,
|
|
2022
2034
|
);
|
|
2023
2035
|
const waitlistSource = waitlistPayload.data.source;
|
|
2036
|
+
const waitlistTemplate = waitlistPayload.data.template;
|
|
2024
2037
|
const waitlistUseCase = waitlistPayload.data.useCase;
|
|
2025
2038
|
let formSubmission: { submitted: boolean; formId?: string };
|
|
2026
2039
|
try {
|
|
@@ -2039,6 +2052,7 @@ export function createCoreRoutesPlugin(
|
|
|
2039
2052
|
err instanceof Error ? err.message : "unknown_waitlist_error",
|
|
2040
2053
|
source: waitlistSource,
|
|
2041
2054
|
stage: "waitlist",
|
|
2055
|
+
template: waitlistTemplate ?? null,
|
|
2042
2056
|
useCase: waitlistUseCase,
|
|
2043
2057
|
},
|
|
2044
2058
|
);
|
|
@@ -2057,6 +2071,7 @@ export function createCoreRoutesPlugin(
|
|
|
2057
2071
|
formSubmitted: formSubmission.submitted,
|
|
2058
2072
|
source: waitlistSource,
|
|
2059
2073
|
stage: "waitlist",
|
|
2074
|
+
template: waitlistTemplate ?? null,
|
|
2060
2075
|
useCase: waitlistUseCase,
|
|
2061
2076
|
},
|
|
2062
2077
|
);
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type H3Event,
|
|
9
9
|
} from "h3";
|
|
10
10
|
|
|
11
|
+
import { getBuilderGatewayRequestHeaders } from "../agent/engine/builder-gateway-headers.js";
|
|
11
12
|
import {
|
|
12
13
|
actionsToEngineTools,
|
|
13
14
|
type ActionEntry,
|
|
@@ -18,7 +19,11 @@ import {
|
|
|
18
19
|
sanitizeToolErrorValue,
|
|
19
20
|
} from "../agent/tool-error-redaction.js";
|
|
20
21
|
import { getSession } from "./auth.js";
|
|
21
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
getBuilderGatewayBaseUrl,
|
|
24
|
+
resolveBuilderCredentials,
|
|
25
|
+
resolveSecret,
|
|
26
|
+
} from "./credential-provider.js";
|
|
22
27
|
import { getH3App } from "./framework-request-handler.js";
|
|
23
28
|
import { runWithRequestContext } from "./request-context.js";
|
|
24
29
|
|
|
@@ -336,12 +341,20 @@ function createSessionHandler(
|
|
|
336
341
|
: undefined,
|
|
337
342
|
},
|
|
338
343
|
async () => {
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
344
|
+
const builderCredentials = await resolveBuilderCredentials();
|
|
345
|
+
const builderConfigured = Boolean(
|
|
346
|
+
builderCredentials.privateKey?.trim() &&
|
|
347
|
+
builderCredentials.publicKey?.trim(),
|
|
348
|
+
);
|
|
349
|
+
const apiKey = builderConfigured
|
|
350
|
+
? null
|
|
351
|
+
: (await resolveSecret("OPENAI_API_KEY"))?.trim();
|
|
352
|
+
if (!builderConfigured && !apiKey) {
|
|
353
|
+
setResponseStatus(event, 409);
|
|
342
354
|
return {
|
|
343
355
|
error:
|
|
344
|
-
"
|
|
356
|
+
"Connect Builder or configure an OpenAI API key to use realtime voice.",
|
|
357
|
+
code: "realtime_voice_setup_required",
|
|
345
358
|
};
|
|
346
359
|
}
|
|
347
360
|
|
|
@@ -369,39 +382,73 @@ function createSessionHandler(
|
|
|
369
382
|
tool_choice: "auto",
|
|
370
383
|
};
|
|
371
384
|
|
|
372
|
-
const form = new FormData();
|
|
373
|
-
form.set("sdp", sdp);
|
|
374
|
-
form.set("session", JSON.stringify(session));
|
|
375
|
-
|
|
376
385
|
let upstream: Response;
|
|
377
386
|
try {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
387
|
+
if (builderConfigured) {
|
|
388
|
+
const gatewayUrl = new URL(
|
|
389
|
+
"realtime/calls",
|
|
390
|
+
getBuilderGatewayBaseUrl().endsWith("/")
|
|
391
|
+
? getBuilderGatewayBaseUrl()
|
|
392
|
+
: `${getBuilderGatewayBaseUrl()}/`,
|
|
393
|
+
);
|
|
394
|
+
gatewayUrl.searchParams.set(
|
|
395
|
+
"apiKey",
|
|
396
|
+
builderCredentials.publicKey!.trim(),
|
|
397
|
+
);
|
|
398
|
+
upstream = await fetch(gatewayUrl.toString(), {
|
|
399
|
+
method: "POST",
|
|
400
|
+
headers: {
|
|
401
|
+
"Content-Type": "application/json",
|
|
402
|
+
Authorization: `Bearer ${builderCredentials.privateKey!.trim()}`,
|
|
403
|
+
"x-builder-api-key": builderCredentials.publicKey!.trim(),
|
|
404
|
+
...getBuilderGatewayRequestHeaders(),
|
|
405
|
+
...(builderCredentials.userId
|
|
406
|
+
? { "x-builder-user-id": builderCredentials.userId }
|
|
407
|
+
: {}),
|
|
408
|
+
},
|
|
409
|
+
body: JSON.stringify({ sdp, session }),
|
|
410
|
+
});
|
|
411
|
+
} else {
|
|
412
|
+
const form = new FormData();
|
|
413
|
+
form.set("sdp", sdp);
|
|
414
|
+
form.set("session", JSON.stringify(session));
|
|
415
|
+
upstream = await fetch(OPENAI_REALTIME_CALLS_URL, {
|
|
416
|
+
method: "POST",
|
|
417
|
+
headers: {
|
|
418
|
+
Authorization: `Bearer ${apiKey}`,
|
|
419
|
+
"OpenAI-Safety-Identifier": await realtimeVoiceSafetyIdentifier(
|
|
420
|
+
auth.userEmail,
|
|
421
|
+
),
|
|
422
|
+
},
|
|
423
|
+
body: form,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
388
426
|
} catch {
|
|
389
427
|
setResponseStatus(event, 502);
|
|
390
|
-
return {
|
|
428
|
+
return {
|
|
429
|
+
error: builderConfigured
|
|
430
|
+
? "Could not reach the Builder realtime voice gateway"
|
|
431
|
+
: "Could not reach the OpenAI Realtime API",
|
|
432
|
+
};
|
|
391
433
|
}
|
|
392
434
|
|
|
393
435
|
if (!upstream.ok) {
|
|
394
|
-
const detail = await safeOpenAiErrorDetail(
|
|
395
|
-
|
|
436
|
+
const detail = await safeOpenAiErrorDetail(
|
|
437
|
+
upstream,
|
|
438
|
+
builderConfigured ? builderCredentials.privateKey! : apiKey!,
|
|
439
|
+
);
|
|
440
|
+
setResponseStatus(event, builderConfigured ? upstream.status : 502);
|
|
396
441
|
return {
|
|
397
|
-
error:
|
|
442
|
+
error: `${builderConfigured ? "Builder" : "OpenAI"} rejected the realtime session (${upstream.status})${detail ? `: ${detail}` : ""}`,
|
|
398
443
|
};
|
|
399
444
|
}
|
|
400
445
|
|
|
401
446
|
const answerSdp = await upstream.text().catch(() => "");
|
|
402
447
|
if (!answerSdp.trim()) {
|
|
403
448
|
setResponseStatus(event, 502);
|
|
404
|
-
return {
|
|
449
|
+
return {
|
|
450
|
+
error: `${builderConfigured ? "Builder" : "OpenAI"} returned an empty realtime session answer`,
|
|
451
|
+
};
|
|
405
452
|
}
|
|
406
453
|
|
|
407
454
|
setResponseStatus(event, upstream.status);
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
import { getOrgContext } from "../org/context.js";
|
|
23
23
|
import { getSession } from "./auth.js";
|
|
24
24
|
import {
|
|
25
|
-
|
|
25
|
+
resolveHasCompleteBuilderConnection,
|
|
26
26
|
resolveSecret,
|
|
27
27
|
} from "./credential-provider.js";
|
|
28
28
|
import { resolveGoogleRealtimeCredentials } from "./google-realtime-session.js";
|
|
@@ -90,8 +90,9 @@ export function createVoiceProvidersStatusHandler() {
|
|
|
90
90
|
let builder = false;
|
|
91
91
|
try {
|
|
92
92
|
builder =
|
|
93
|
-
(await withRequestContext(() =>
|
|
94
|
-
|
|
93
|
+
(await withRequestContext(() =>
|
|
94
|
+
resolveHasCompleteBuilderConnection(),
|
|
95
|
+
)) === true;
|
|
95
96
|
} catch {
|
|
96
97
|
builder = false;
|
|
97
98
|
}
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
export const DEFAULT_SSR_CACHE_CONTROL = "public, max-age=0, must-revalidate";
|
|
2
2
|
|
|
3
3
|
export const DEFAULT_SSR_CDN_CACHE_CONTROL =
|
|
4
|
-
"public, s-maxage=
|
|
4
|
+
"public, s-maxage=600, stale-while-revalidate=604800, stale-if-error=3600";
|
|
5
5
|
|
|
6
6
|
export const DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL =
|
|
7
|
-
"public, durable, s-maxage=
|
|
8
|
-
|
|
9
|
-
// React Router data requests can select a subset of route loaders with
|
|
10
|
-
// `?_routes=...`. Ignore every other query parameter (UTM tags, click ids,
|
|
11
|
-
// and similar tracking noise) so they cannot fragment Netlify's SSR cache.
|
|
12
|
-
export const DEFAULT_SSR_NETLIFY_VARY = "query=_routes";
|
|
7
|
+
"public, durable, s-maxage=600, stale-while-revalidate=604800, stale-if-error=3600";
|
|
13
8
|
|
|
14
9
|
export const DEFAULT_SSR_CACHE_HEADERS = {
|
|
15
10
|
"cache-control": DEFAULT_SSR_CACHE_CONTROL,
|
|
16
11
|
"cdn-cache-control": DEFAULT_SSR_CDN_CACHE_CONTROL,
|
|
17
12
|
"netlify-cdn-cache-control": DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL,
|
|
18
|
-
"netlify-vary": DEFAULT_SSR_NETLIFY_VARY,
|
|
19
13
|
} as const;
|
|
20
14
|
|
|
21
15
|
export const DEFAULT_SPECULATION_RULES_PATH =
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
@import "./agent-conversation.css";
|
|
26
26
|
@import "./rich-markdown-editor.css";
|
|
27
27
|
@import "./blocks.css";
|
|
28
|
+
@import "./chat-history-list.css";
|
|
28
29
|
|
|
29
30
|
/* Scan @agent-native/core's compiled client output for Tailwind classes.
|
|
30
31
|
Path is resolved relative to THIS file. After build, this CSS lives at
|