@agent-native/core 0.168.13 → 0.169.1
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/templates/analytics/actions/bigquery-table-info.ts +3 -2
- package/corpus/templates/analytics/actions/search-bigquery-schema.ts +130 -4
- package/corpus/templates/analytics/agent-native.config.ts +1 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +36 -23
- package/corpus/templates/analytics/app/lib/dashboard-visibility.ts +41 -0
- package/corpus/templates/analytics/app/pages/DashboardOverview.tsx +34 -9
- package/corpus/templates/analytics/changelog/2026-08-21-dashboard-filters-keep-other-users-dashboards-out-of-mine.md +6 -0
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +14 -3
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +33 -3
- package/corpus/templates/brain/server/lib/brain.ts +27 -2
- package/corpus/templates/clips/actions/stop-meeting-recording.ts +87 -6
- package/corpus/templates/clips/app/components/library/search-bar.tsx +1 -1
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +3 -4
- package/corpus/templates/design/app/components/design/EditPanel.tsx +15 -47
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +3 -3
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +0 -7
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +2 -4
- package/corpus/templates/design/app/i18n-data.ts +10 -10
- package/corpus/templates/design/app/pages/DesignEditor.tsx +22 -22
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +39 -8
- package/corpus/templates/design/app/pages/DesignSystems.tsx +1 -1
- package/corpus/templates/design/app/pages/Index.tsx +1 -1
- package/corpus/templates/design/app/pages/design-editor/preview-navigation.ts +25 -0
- package/corpus/templates/mail/app/hooks/use-emails.ts +13 -3
- package/dist/agent/engine/credential-errors.d.ts +1 -1
- package/dist/agent/engine/credential-errors.js +2 -2
- package/dist/agent/engine/first-event-timeout.d.ts +8 -0
- package/dist/agent/engine/first-event-timeout.js +8 -0
- package/dist/agent/production-agent.d.ts +0 -30
- package/dist/agent/production-agent.js +17 -38
- package/dist/agent/run-loop-with-resume.d.ts +38 -25
- package/dist/agent/run-loop-with-resume.js +140 -55
- package/dist/agent/run-manager.d.ts +83 -68
- package/dist/agent/run-manager.js +280 -94
- package/dist/agent/run-store.d.ts +31 -0
- package/dist/agent/run-store.js +42 -12
- package/dist/app-config/agent.d.ts +2 -0
- package/dist/app-config/agent.js +33 -0
- package/dist/app-config/run-lifecycle-invariants.d.ts +248 -0
- package/dist/app-config/run-lifecycle-invariants.js +342 -0
- package/dist/app-config/schema.d.ts +2 -0
- package/dist/app-config/store.js +9 -1
- package/dist/client/AssistantChat.js +47 -15
- package/dist/client/ConnectBuilderCard.d.ts +3 -1
- package/dist/client/ConnectBuilderCard.js +6 -3
- package/dist/client/agent-chat-adapter.d.ts +0 -2
- package/dist/client/agent-chat-adapter.js +7 -23
- package/dist/client/chat/message-components.d.ts +7 -0
- package/dist/client/chat/message-components.js +1 -1
- package/dist/client/chat/run-recovery.js +5 -2
- package/dist/client/chat/tool-call-display.js +9 -3
- package/dist/client/error-format.js +12 -0
- package/dist/client/navigation/index.d.ts +1 -0
- package/dist/client/navigation/index.js +1 -0
- package/dist/client/route-state.js +6 -0
- package/dist/client/workspace-app-navigation.d.ts +10 -0
- package/dist/client/workspace-app-navigation.js +38 -0
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.d.ts +13 -0
- package/dist/deploy/build.js +51 -0
- package/dist/jobs/background-automation-runner.d.ts +25 -0
- package/dist/jobs/background-automation-runner.js +104 -21
- package/dist/jobs/run-history.d.ts +7 -1
- package/dist/jobs/run-history.js +57 -14
- package/dist/localization/core-messages/ar-SA.js +1 -1
- package/dist/localization/core-messages/de-DE.js +1 -1
- package/dist/localization/core-messages/en-US.d.ts +1 -1
- package/dist/localization/core-messages/en-US.js +1 -1
- package/dist/localization/core-messages/es-ES.js +1 -1
- package/dist/localization/core-messages/fr-FR.js +1 -1
- package/dist/localization/core-messages/hi-IN.js +1 -1
- package/dist/localization/core-messages/ja-JP.js +1 -1
- package/dist/localization/core-messages/ko-KR.js +1 -1
- package/dist/localization/core-messages/pt-BR.js +1 -1
- package/dist/localization/core-messages/zh-CN.js +1 -1
- package/dist/localization/core-messages/zh-TW.js +1 -1
- package/dist/localization/core-messages.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/observability/traces.d.ts +13 -0
- package/dist/observability/traces.js +369 -317
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
- package/dist/provider-api/actions/provider-api.d.ts +13 -13
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/db/check-scoping.js +9 -6
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat-plugin.js +2 -4
- package/dist/server/builder-browser.d.ts +4 -0
- package/dist/server/builder-browser.js +23 -1
- package/dist/server/core-routes-plugin.js +13 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +3 -3
- /package/corpus/templates/dispatch/app/routes/{apps.$appId.tsx → apps.$appId.$.tsx} +0 -0
|
@@ -121,6 +121,8 @@ function getPollAbortMs(interval) {
|
|
|
121
121
|
return Math.max(POLL_ABORT_MIN_MS, interval * 4);
|
|
122
122
|
}
|
|
123
123
|
const ACTIVE_RUN_CLEAR_TIMEOUT_MS = 5_000;
|
|
124
|
+
const ACTIVE_RUN_CLEAR_STABLE_POLLS = 2;
|
|
125
|
+
const ACTIVE_RUN_CLEAR_RETRY_DELAY_MS = 1_000;
|
|
124
126
|
const ACTIVE_RUN_STUCK_THRESHOLD_MS = 90_000;
|
|
125
127
|
const BACKGROUND_ACTIVE_RUN_STUCK_THRESHOLD_MS = 13 * 60_000;
|
|
126
128
|
const ACTIVE_RUN_POLL_INTERVAL_MS = 150;
|
|
@@ -303,6 +305,7 @@ export async function waitForThreadRunToClear(apiUrl, threadId) {
|
|
|
303
305
|
return true;
|
|
304
306
|
const deadline = Date.now() + ACTIVE_RUN_CLEAR_TIMEOUT_MS;
|
|
305
307
|
let activeRunToResume = null;
|
|
308
|
+
let consecutiveClearPolls = 0;
|
|
306
309
|
const resumeActiveRun = (info) => {
|
|
307
310
|
if (!info.runId)
|
|
308
311
|
return;
|
|
@@ -323,11 +326,22 @@ export async function waitForThreadRunToClear(apiUrl, threadId) {
|
|
|
323
326
|
const res = await fetch(`${apiUrl}/runs/active?threadId=${encodeURIComponent(threadId)}`);
|
|
324
327
|
if (res.ok) {
|
|
325
328
|
const info = (await res.json());
|
|
326
|
-
|
|
329
|
+
const runLooksClear = !info?.active ||
|
|
327
330
|
info?.status !== "running" ||
|
|
328
|
-
activeRunLooksStale(info)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
+
activeRunLooksStale(info);
|
|
332
|
+
if (runLooksClear) {
|
|
333
|
+
consecutiveClearPolls += 1;
|
|
334
|
+
// A terminal/no-active snapshot can briefly appear between a
|
|
335
|
+
// foreground run and its server-owned continuation. Require two
|
|
336
|
+
// consecutive clear polls before releasing a queued follow-up.
|
|
337
|
+
if (consecutiveClearPolls >= ACTIVE_RUN_CLEAR_STABLE_POLLS) {
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
consecutiveClearPolls = 0;
|
|
343
|
+
}
|
|
344
|
+
if (!runLooksClear && info.runId) {
|
|
331
345
|
activeRunToResume = info;
|
|
332
346
|
if (info.awaitingRedispatch === true) {
|
|
333
347
|
// This is not the brief terminal-write lag the 5s waiter was built
|
|
@@ -340,8 +354,12 @@ export async function waitForThreadRunToClear(apiUrl, threadId) {
|
|
|
340
354
|
}
|
|
341
355
|
}
|
|
342
356
|
}
|
|
357
|
+
else {
|
|
358
|
+
consecutiveClearPolls = 0;
|
|
359
|
+
}
|
|
343
360
|
}
|
|
344
361
|
catch {
|
|
362
|
+
consecutiveClearPolls = 0;
|
|
345
363
|
// Transient poll failure — try again until the short grace period ends.
|
|
346
364
|
}
|
|
347
365
|
await new Promise((resolve) => window.setTimeout(resolve, ACTIVE_RUN_POLL_INTERVAL_MS));
|
|
@@ -1730,6 +1748,15 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1730
1748
|
tabId,
|
|
1731
1749
|
onActiveRunChange: setHasActiveServerRun,
|
|
1732
1750
|
});
|
|
1751
|
+
// Server truth must participate in submit gating, not only in the missing
|
|
1752
|
+
// final-response warning. The local lifecycle can clear during a transport
|
|
1753
|
+
// handoff while the server still owns the turn.
|
|
1754
|
+
const serverRunState = useRunStuckDetection({
|
|
1755
|
+
threadId: threadId ?? null,
|
|
1756
|
+
enabled: isActiveComposer,
|
|
1757
|
+
apiUrl,
|
|
1758
|
+
});
|
|
1759
|
+
const serverRunActive = serverRunState.runId != null && serverRunState.status === "running";
|
|
1733
1760
|
// Real running state drives submission/queue gating; UI running also covers
|
|
1734
1761
|
// short auto-continuation gaps so the latest assistant message does not flash
|
|
1735
1762
|
// into a done state while the agent is still working.
|
|
@@ -1739,19 +1766,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1739
1766
|
isReconnecting,
|
|
1740
1767
|
optimisticRunning,
|
|
1741
1768
|
isAutoResuming,
|
|
1742
|
-
hasActiveServerRun,
|
|
1769
|
+
hasActiveServerRun: hasActiveServerRun || serverRunActive,
|
|
1743
1770
|
hasTerminalRunError: runErrorInfo !== null,
|
|
1744
1771
|
});
|
|
1745
1772
|
const textStreaming = showRunningInUI || externalStreaming;
|
|
1746
|
-
// Server truth about this thread's run, used to suppress the "agent stopped
|
|
1747
|
-
// without sending a final message" notice while the server still has the
|
|
1748
|
-
// turn in flight. The poll backs itself off to 15s while nothing is running.
|
|
1749
|
-
const serverRunState = useRunStuckDetection({
|
|
1750
|
-
threadId: threadId ?? null,
|
|
1751
|
-
enabled: isActiveComposer,
|
|
1752
|
-
apiUrl,
|
|
1753
|
-
});
|
|
1754
|
-
const serverRunActive = serverRunState.runId != null && serverRunState.status === "running";
|
|
1755
1773
|
const storedActiveRun = getActiveRun();
|
|
1756
1774
|
const activeChatRunId = (serverRunState.status === "running" ? serverRunState.runId : null) ??
|
|
1757
1775
|
(activeRunMatchesThread(storedActiveRun, threadId)
|
|
@@ -3318,6 +3336,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3318
3336
|
dequeueInFlightRef.current = true;
|
|
3319
3337
|
let cancelled = false;
|
|
3320
3338
|
let started = false;
|
|
3339
|
+
let retryTimer = null;
|
|
3321
3340
|
const timer = window.setTimeout(() => {
|
|
3322
3341
|
started = true;
|
|
3323
3342
|
void (async () => {
|
|
@@ -3329,8 +3348,19 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3329
3348
|
// complete. Starting the queued turn during that window can reconnect
|
|
3330
3349
|
// to the old run and replay the old answer under the new prompt.
|
|
3331
3350
|
const runCleared = await waitForThreadRunToClear(apiUrl, threadId);
|
|
3332
|
-
if (cancelled
|
|
3351
|
+
if (cancelled)
|
|
3333
3352
|
return;
|
|
3353
|
+
if (!runCleared) {
|
|
3354
|
+
// The server still owns this turn (including a deferred durable
|
|
3355
|
+
// successor). Keep the queued message visible and retry after a
|
|
3356
|
+
// short delay so one transient idle snapshot cannot strand it.
|
|
3357
|
+
retryTimer = window.setTimeout(() => {
|
|
3358
|
+
if (!cancelled) {
|
|
3359
|
+
setQueueWakeVersion((version) => version + 1);
|
|
3360
|
+
}
|
|
3361
|
+
}, ACTIVE_RUN_CLEAR_RETRY_DELAY_MS);
|
|
3362
|
+
return;
|
|
3363
|
+
}
|
|
3334
3364
|
if (queueStopVersionRef.current !== stopVersion ||
|
|
3335
3365
|
queuedMessagesRef.current[0]?.id !== next.id) {
|
|
3336
3366
|
return;
|
|
@@ -3391,6 +3421,8 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3391
3421
|
return () => {
|
|
3392
3422
|
cancelled = true;
|
|
3393
3423
|
window.clearTimeout(timer);
|
|
3424
|
+
if (retryTimer !== null)
|
|
3425
|
+
window.clearTimeout(retryTimer);
|
|
3394
3426
|
if (!started) {
|
|
3395
3427
|
dequeueInFlightRef.current = false;
|
|
3396
3428
|
}
|
|
@@ -12,10 +12,12 @@ export interface ConnectBuilderCardProps {
|
|
|
12
12
|
/** The user's feature/change request, forwarded to the selected coding
|
|
13
13
|
* agent when they click Send. Empty for generic "connect Builder" prompts. */
|
|
14
14
|
prompt?: string;
|
|
15
|
+
/** Formatted staged chat context forwarded with the Builder request. */
|
|
16
|
+
context?: string;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* Rich inline card rendered for the `connect-builder` tool call. Shows the
|
|
18
20
|
* Builder handoff when available, or routes local development requests to the
|
|
19
21
|
* external coding agent.
|
|
20
22
|
*/
|
|
21
|
-
export declare function ConnectBuilderCard({ configured: initialConfigured, builderEnabled: initialBuilderEnabled, connectUrl: initialConnectUrl, orgName: initialOrgName, prompt, }: ConnectBuilderCardProps): React.JSX.Element;
|
|
23
|
+
export declare function ConnectBuilderCard({ configured: initialConfigured, builderEnabled: initialBuilderEnabled, connectUrl: initialConnectUrl, orgName: initialOrgName, prompt, context, }: ConnectBuilderCardProps): React.JSX.Element;
|
|
@@ -30,7 +30,7 @@ function hasElectronShellBridge() {
|
|
|
30
30
|
* Builder handoff when available, or routes local development requests to the
|
|
31
31
|
* external coding agent.
|
|
32
32
|
*/
|
|
33
|
-
export function ConnectBuilderCard({ configured: initialConfigured, builderEnabled: initialBuilderEnabled = true, connectUrl: initialConnectUrl, orgName: initialOrgName, prompt = "", }) {
|
|
33
|
+
export function ConnectBuilderCard({ configured: initialConfigured, builderEnabled: initialBuilderEnabled = true, connectUrl: initialConnectUrl, orgName: initialOrgName, prompt = "", context = "", }) {
|
|
34
34
|
// The connect-poll state machine is shared — the tool-call result is
|
|
35
35
|
// frozen at render time, so the hook's mount-time fetch + focus refresh
|
|
36
36
|
// is what catches a flow the user completed in another tab.
|
|
@@ -89,7 +89,10 @@ export function ConnectBuilderCard({ configured: initialConfigured, builderEnabl
|
|
|
89
89
|
const res = await fetch(new URL(agentNativePath("/_agent-native/builder/run"), origin).href, {
|
|
90
90
|
method: "POST",
|
|
91
91
|
headers: { "Content-Type": "application/json" },
|
|
92
|
-
body: JSON.stringify({
|
|
92
|
+
body: JSON.stringify({
|
|
93
|
+
prompt,
|
|
94
|
+
...(context.trim() ? { context } : {}),
|
|
95
|
+
}),
|
|
93
96
|
});
|
|
94
97
|
const data = await res.json().catch(() => ({}));
|
|
95
98
|
if (!res.ok) {
|
|
@@ -108,7 +111,7 @@ export function ConnectBuilderCard({ configured: initialConfigured, builderEnabl
|
|
|
108
111
|
setSendErr(e instanceof Error ? e.message : "Send failed");
|
|
109
112
|
setSending(false);
|
|
110
113
|
}
|
|
111
|
-
}, [prompt]);
|
|
114
|
+
}, [context, prompt]);
|
|
112
115
|
const handleJoinWaitlist = useCallback(async () => {
|
|
113
116
|
setJoiningWaitlist(true);
|
|
114
117
|
setWaitlistErr(null);
|
|
@@ -15,8 +15,6 @@ export type AgentChatSurfaceKind =
|
|
|
15
15
|
| "desktop";
|
|
16
16
|
export declare const BACKGROUND_FOLLOW_ATTACH_WATCHDOG_MS = 90000;
|
|
17
17
|
export declare const BACKGROUND_FOLLOW_IDLE_TIMEOUT_MS = 210000;
|
|
18
|
-
export declare const MAX_FOLLOWED_BACKGROUND_RUNS = 24;
|
|
19
|
-
export declare const MAX_BACKGROUND_FOLLOW_WALL_TIME_MS: number;
|
|
20
18
|
/**
|
|
21
19
|
* True when an action was streamed but never returned a result yet — i.e. a
|
|
22
20
|
* `tool_start` with no matching `tool_done`. The server is still executing it,
|
|
@@ -170,29 +170,13 @@ export const BACKGROUND_FOLLOW_IDLE_TIMEOUT_MS = 210_000;
|
|
|
170
170
|
// 22 minutes, all error:stale_run, user watching a spinner). These bound the
|
|
171
171
|
// whole turn instead, and an identical repeated failure counts as no progress.
|
|
172
172
|
//
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
// MAX_BACKGROUND_RUN_CONTINUATIONS (20, production-agent.ts)
|
|
181
|
-
//
|
|
182
|
-
// They were originally set to 10 min / 6 runs, which put the whole-turn client
|
|
183
|
-
// budget BELOW the 13-minute ceiling of a single legal chunk. Any turn needing
|
|
184
|
-
// a second full-length chunk was killed by the client while the server was
|
|
185
|
-
// healthy and had 80 minutes left — measured in prod as turns dying at 11-25
|
|
186
|
-
// minutes with `last_progress_at` tracking the abort, i.e. still streaming
|
|
187
|
-
// tokens and completing tools when the client gave up. That is the top
|
|
188
|
-
// non-auth cause of "the chat just stopped" reports.
|
|
189
|
-
//
|
|
190
|
-
// Killing a turn that is NOT progressing is already covered twice over, by
|
|
191
|
-
// mechanisms that read progress rather than a clock: the 210s idle timeout
|
|
192
|
-
// above, and MAX_REPEATED_BACKGROUND_TERMINAL_REASONS below. Do not re-tighten
|
|
193
|
-
// these two to catch a stuck turn — fix the progress signal instead.
|
|
194
|
-
export const MAX_FOLLOWED_BACKGROUND_RUNS = 24;
|
|
195
|
-
export const MAX_BACKGROUND_FOLLOW_WALL_TIME_MS = 95 * 60_000;
|
|
173
|
+
// Defined in `app-config/run-lifecycle-invariants.ts`, not here, because the
|
|
174
|
+
// CLIENT-ABOVE-SERVER relationship they belong to is checked there against the
|
|
175
|
+
// RESOLVED server configuration — the server bounds are runtime-configurable
|
|
176
|
+
// now, so a spec pinning them against module constants stopped enforcing
|
|
177
|
+
// anything. Re-exported under the same names so importers are unchanged; that
|
|
178
|
+
// module has no runtime imports, so the bundle pays nothing for it.
|
|
179
|
+
import { MAX_BACKGROUND_FOLLOW_WALL_TIME_MS, MAX_FOLLOWED_BACKGROUND_RUNS, } from "../app-config/run-lifecycle-invariants.js";
|
|
196
180
|
const MAX_REPEATED_BACKGROUND_TERMINAL_REASONS = 3;
|
|
197
181
|
// A re-observed terminal run whose outcome would be an ERROR (never a
|
|
198
182
|
// genuine "done" success) gets a short extra grace window before the follow
|
|
@@ -115,6 +115,13 @@ export declare function shouldShowMissingFinalResponse({ isCurrentTurnRunning, s
|
|
|
115
115
|
hasActiveTool?: boolean;
|
|
116
116
|
userStoppedRun?: boolean;
|
|
117
117
|
}): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* "The agent stopped" is derived from local client state, which dips to
|
|
120
|
+
* not-running at every chunk boundary and transport re-attach while the turn is
|
|
121
|
+
* still alive server-side. Requiring the shape to hold for a beat keeps the
|
|
122
|
+
* notice off the screen for those gaps without hiding a real stop for long.
|
|
123
|
+
*/
|
|
124
|
+
export declare const MISSING_FINAL_RESPONSE_SETTLE_MS = 3000;
|
|
118
125
|
export declare function useSettledFlag(active: boolean, delayMs: number): boolean;
|
|
119
126
|
export declare function shouldShowAssistantWorkSummary({ isLast, isComplete, hasCollapsibleWork, hasUnresolvedTool, hasActiveTool, chatRunning, }: {
|
|
120
127
|
isLast: boolean;
|
|
@@ -728,7 +728,7 @@ export function shouldShowMissingFinalResponse({ isCurrentTurnRunning, serverRun
|
|
|
728
728
|
* still alive server-side. Requiring the shape to hold for a beat keeps the
|
|
729
729
|
* notice off the screen for those gaps without hiding a real stop for long.
|
|
730
730
|
*/
|
|
731
|
-
const MISSING_FINAL_RESPONSE_SETTLE_MS =
|
|
731
|
+
export const MISSING_FINAL_RESPONSE_SETTLE_MS = 3_000;
|
|
732
732
|
export function useSettledFlag(active, delayMs) {
|
|
733
733
|
const [settled, setSettled] = useState(false);
|
|
734
734
|
useEffect(() => {
|
|
@@ -120,6 +120,9 @@ function isMissingLlmProviderRunError(info) {
|
|
|
120
120
|
((code === "missing_credentials" || code === "missing_api_key") &&
|
|
121
121
|
!text.trim()));
|
|
122
122
|
}
|
|
123
|
+
function isDesktopChatRelayRunError(info) {
|
|
124
|
+
return [info.message, info.details].some((value) => typeof value === "string" && /desktop app chat relay failed/i.test(value));
|
|
125
|
+
}
|
|
123
126
|
// ─── BuilderConnectCta ────────────────────────────────────────────────────────
|
|
124
127
|
// Renders a single row with left-aligned copy and a right-aligned action.
|
|
125
128
|
// Click opens the Builder OAuth popup via the shared
|
|
@@ -210,7 +213,7 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
210
213
|
});
|
|
211
214
|
const canRecover = info.recoverable === true;
|
|
212
215
|
const shouldShowBuilderReconnect = isBuilderReconnectRunError(info);
|
|
213
|
-
const
|
|
216
|
+
const shouldShowProviderSetup = isMissingLlmProviderRunError(info) || isDesktopChatRelayRunError(info);
|
|
214
217
|
const isProviderAuthError = isProviderAuthenticationError([info.message, info.details].filter(Boolean).join("\n"), info.errorCode);
|
|
215
218
|
// Blocked on something the reader goes and fixes elsewhere, then comes back
|
|
216
219
|
// to. Recoverable runs and email verification keep a retry path; rejected
|
|
@@ -292,7 +295,7 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
292
295
|
onDismiss();
|
|
293
296
|
}
|
|
294
297
|
}, [builderReconnectResolved, onDismiss]);
|
|
295
|
-
if (
|
|
298
|
+
if (shouldShowProviderSetup) {
|
|
296
299
|
return (_jsxs("div", { className: "w-full", children: [_jsx(BuilderSetupCard, { fullWidth: true, layout: "sidebar", onConnected: handleMissingProviderConnected }), providerConnected ? (_jsx("div", { className: "flex justify-center px-3 pt-1", children: _jsxs("button", { type: "button", onClick: handleMissingProviderRetry, disabled: retryRequested, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-60", children: [_jsx(IconRefresh, { size: 13 }), t("agentChat.common.retry")] }) })) : null] }));
|
|
297
300
|
}
|
|
298
301
|
return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: runErrorHeadline(info, {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IconLoader2, IconAlertTriangle, IconCircleX, IconCheck, IconChevronRight, IconCopy, IconCode, IconBrandSlack, IconTerminal2, IconDatabase, IconSearch, IconFileCode, IconShieldCheck, IconX, } from "@tabler/icons-react";
|
|
3
3
|
import React, { useState, useEffect, useCallback, useLayoutEffect, useRef, } from "react";
|
|
4
|
+
import { formatAgentChatContextItemsForPrompt } from "../agent-chat.js";
|
|
4
5
|
import { AgentTaskCard } from "../AgentTaskCard.js";
|
|
5
6
|
import { writeClipboardText } from "../clipboard.js";
|
|
6
7
|
import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
|
|
@@ -12,6 +13,7 @@ import { findMcpIntegrationForToolName } from "../resources/mcp-integration-cata
|
|
|
12
13
|
import { McpIntegrationLogo } from "../resources/McpIntegrationLogo.js";
|
|
13
14
|
import { BashCell, EditCell, WriteCell, FilesChangedSummary, } from "../tool-cells/index.js";
|
|
14
15
|
import { humanizeToolName, isCallAgentToolCallShadowed, isToolCallActive, } from "../tool-display.js";
|
|
16
|
+
import { useAgentChatContext } from "../use-agent-chat-context.js";
|
|
15
17
|
import { cn } from "../utils.js";
|
|
16
18
|
import { ActionChatUiSurface } from "./action-chat-ui-surface.js";
|
|
17
19
|
import { SmoothMarkdownText, HighlightedCodeBlock, } from "./markdown-renderer.js";
|
|
@@ -280,6 +282,10 @@ function ApprovalAffordance({ toolName, toolCallId, approval, }) {
|
|
|
280
282
|
}
|
|
281
283
|
// ─── ToolCallDisplay ──────────────────────────────────────────────────────────
|
|
282
284
|
export function ToolCallDisplay({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, structuredMeta, activity, approval, repeatCount, isLatestRunning = isRunning, isActiveTail, }) {
|
|
285
|
+
const { items: agentChatContextItems } = useAgentChatContext(toolName === "connect-builder");
|
|
286
|
+
const builderContext = toolName === "connect-builder"
|
|
287
|
+
? formatAgentChatContextItemsForPrompt(agentChatContextItems)
|
|
288
|
+
: "";
|
|
283
289
|
const isDelegatedAgentCall = toolName === "call-agent" || toolName.startsWith("agent:");
|
|
284
290
|
const effectiveIsRunning = isRunning ||
|
|
285
291
|
(isDelegatedAgentCall &&
|
|
@@ -306,9 +312,9 @@ export function ToolCallDisplay({ toolName, toolCallId, argsText, args, result,
|
|
|
306
312
|
if (toolKind === "write") {
|
|
307
313
|
return wrapToolDisplay(_jsx(WriteCell, { meta: structuredMeta, isRunning: effectiveIsRunning }));
|
|
308
314
|
}
|
|
309
|
-
return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, toolCallId: toolCallId, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: effectiveIsRunning, outcome: outcome, isActiveTail: showActiveTail, structuredMeta: structuredMeta, approval: approval, repeatCount: repeatCount }));
|
|
315
|
+
return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, toolCallId: toolCallId, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: effectiveIsRunning, outcome: outcome, isActiveTail: showActiveTail, structuredMeta: structuredMeta, approval: approval, repeatCount: repeatCount, context: builderContext }));
|
|
310
316
|
}
|
|
311
|
-
function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, isActiveTail, structuredMeta, approval, repeatCount, }) {
|
|
317
|
+
function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, isActiveTail, structuredMeta, approval, repeatCount, context, }) {
|
|
312
318
|
const t = useT();
|
|
313
319
|
const suppressInlineOpenApp = React.useContext(SuppressInlineOpenAppContext);
|
|
314
320
|
const isRawCallAgent = toolName === "call-agent";
|
|
@@ -339,7 +345,7 @@ function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result,
|
|
|
339
345
|
return (_jsx(ConnectBuilderCard, { configured: !!parsed.configured, builderEnabled: parsed.builderEnabled !== false,
|
|
340
346
|
// Ignore obsolete direct-auth URLs from older tool results. The
|
|
341
347
|
// card fetches a fresh app-local connect URL on mount and click.
|
|
342
|
-
connectUrl: parsed.connectUrl || "", orgName: parsed.orgName ?? null, prompt: typeof parsed.prompt === "string" ? parsed.prompt : "" }));
|
|
348
|
+
connectUrl: parsed.connectUrl || "", orgName: parsed.orgName ?? null, prompt: typeof parsed.prompt === "string" ? parsed.prompt : "", context: context }));
|
|
343
349
|
}
|
|
344
350
|
}
|
|
345
351
|
catch {
|
|
@@ -80,6 +80,18 @@ const KNOWN_CHAT_ERROR_KEYS = new Map([
|
|
|
80
80
|
"No LLM provider is connected. Open this app's Manage agent > LLM, then connect Builder.io or add a provider key.",
|
|
81
81
|
"agentChat.errorMessages.noProviderConnected",
|
|
82
82
|
],
|
|
83
|
+
[
|
|
84
|
+
"No LLM provider is connected. Open this app's Manage agent > LLM, then connect Builder.io (free tier available) or add a provider key.",
|
|
85
|
+
"agentChat.errorMessages.noProviderConnected",
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
"No LLM provider is connected. Open Settings > Agent > AI providers, then connect Builder.io or add a provider key.",
|
|
89
|
+
"agentChat.errorMessages.noProviderConnected",
|
|
90
|
+
],
|
|
91
|
+
[
|
|
92
|
+
"No LLM provider is connected. Open Settings > Agent > AI providers, then connect Builder.io (free tier available) or add a provider key.",
|
|
93
|
+
"agentChat.errorMessages.noProviderConnected",
|
|
94
|
+
],
|
|
83
95
|
[
|
|
84
96
|
"The provider behind this model rejected the request. Pick a different model, then retry.",
|
|
85
97
|
"agentChat.errorMessages.builderModelUnauthorized",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { agentNativePath, appApiPath, appBasePath, appPath, } from "../api-path.js";
|
|
2
2
|
export { useAgentRouteState, useSemanticNavigationState, type AgentRouteLocation, type SemanticNavigationCommandEnvelope, type UseAgentRouteStateOptions, type UseAgentRouteStateResult, type UseSemanticNavigationStateOptions, type UseSemanticNavigationStateResult, } from "../route-state.js";
|
|
3
|
+
export { AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE, postAgentNativeWorkspaceAppRoute, type AgentNativeWorkspaceAppRouteMessage, } from "../workspace-app-navigation.js";
|
|
3
4
|
export { COMMAND_MENU_OPEN_EVENT, CommandMenu, openAgentSidebar, openAgentSettings, openCommandMenu, submitToAgent, useCommandMenuShortcut, type CommandMenuProps, type CommandMenuDoc, type CommandDocsGroupProps, type CommandGroupProps, type CommandItemProps, type CommandShortcutProps, } from "../CommandMenu.js";
|
|
4
5
|
export { buildOpenRouteLink, buildOpenRoutePath, buildLegacyAgentSettingsRoute, buildResourceRoute, buildSettingsRoute, buildStandardAppRoute, buildTeamRoute, createStandardOpenPathResolver, STANDARD_APP_ROUTES, STANDARD_SETTINGS_TABS, type BuildResourceRouteOptions, type BuildStandardAppRouteOptions, type NavigationLink, type NavigationTarget, type StandardAppRouteId, type StandardOpenPathResolverOptions, type StandardOpenPathRoute, type StandardSettingsTabId, } from "../../navigation/index.js";
|
|
5
6
|
export { postNavigate, isInAgentEmbed, AGENT_NAVIGATE_MESSAGE_TYPE, type AgentNavigateMessage, } from "../embed.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { agentNativePath, appApiPath, appBasePath, appPath, } from "../api-path.js";
|
|
2
2
|
export { useAgentRouteState, useSemanticNavigationState, } from "../route-state.js";
|
|
3
|
+
export { AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE, postAgentNativeWorkspaceAppRoute, } from "../workspace-app-navigation.js";
|
|
3
4
|
export { COMMAND_MENU_OPEN_EVENT, CommandMenu, openAgentSidebar, openAgentSettings, openCommandMenu, submitToAgent, useCommandMenuShortcut, } from "../CommandMenu.js";
|
|
4
5
|
export { buildOpenRouteLink, buildOpenRoutePath, buildLegacyAgentSettingsRoute, buildResourceRoute, buildSettingsRoute, buildStandardAppRoute, buildTeamRoute, createStandardOpenPathResolver, STANDARD_APP_ROUTES, STANDARD_SETTINGS_TABS, } from "../../navigation/index.js";
|
|
5
6
|
export { postNavigate, isInAgentEmbed, AGENT_NAVIGATE_MESSAGE_TYPE, } from "../embed.js";
|
|
@@ -4,6 +4,7 @@ import { useLocation, useNavigate, } from "react-router";
|
|
|
4
4
|
import { isWorkspaceAppPath } from "./api-path.js";
|
|
5
5
|
import { deleteClientAppState, readClientAppState, setClientAppState, } from "./application-state.js";
|
|
6
6
|
import { navigateWithAgentChatViewTransition, } from "./chat-view-transition.js";
|
|
7
|
+
import { postAgentNativeWorkspaceAppRoute } from "./workspace-app-navigation.js";
|
|
7
8
|
const SAFE_BROWSER_TAB_ID_RE = /^[A-Za-z0-9_-]{1,96}$/;
|
|
8
9
|
function normalizeBrowserTabId(browserTabId) {
|
|
9
10
|
if (typeof browserTabId !== "string")
|
|
@@ -195,6 +196,11 @@ export function useAgentRouteState(options) {
|
|
|
195
196
|
const location = useLocation();
|
|
196
197
|
const navigate = useNavigate();
|
|
197
198
|
const browserTabId = useMemo(() => normalizeBrowserTabId(options.browserTabId), [options.browserTabId]);
|
|
199
|
+
useEffect(() => {
|
|
200
|
+
if (options.enabled === false)
|
|
201
|
+
return;
|
|
202
|
+
postAgentNativeWorkspaceAppRoute(`${location.pathname}${location.search}${location.hash}`);
|
|
203
|
+
}, [location.hash, location.pathname, location.search, options.enabled]);
|
|
198
204
|
const navigationKeys = useMemo(() => {
|
|
199
205
|
const scopedKey = appStateKeyForBrowserTab(navigationKey, browserTabId);
|
|
200
206
|
const keys = [scopedKey];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE: "agent-native:workspace-app-route";
|
|
2
|
+
export interface AgentNativeWorkspaceAppRouteMessage {
|
|
3
|
+
type: typeof AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE;
|
|
4
|
+
path: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Report an app-local route to its immediate embedding host. The host checks
|
|
8
|
+
* the iframe source and origin before applying the route to its own URL.
|
|
9
|
+
*/
|
|
10
|
+
export declare function postAgentNativeWorkspaceAppRoute(path: string): boolean;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export const AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE = "agent-native:workspace-app-route";
|
|
2
|
+
function normalizeWorkspaceAppRoute(path) {
|
|
3
|
+
if (typeof path !== "string" ||
|
|
4
|
+
!path.startsWith("/") ||
|
|
5
|
+
path.startsWith("//")) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
if (/[\u0000-\u001f\u007f]/.test(path))
|
|
9
|
+
return null;
|
|
10
|
+
try {
|
|
11
|
+
const url = new URL(path, "http://agent-native.invalid");
|
|
12
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// coercion-ok: malformed route input is not reported to the host.
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Report an app-local route to its immediate embedding host. The host checks
|
|
21
|
+
* the iframe source and origin before applying the route to its own URL.
|
|
22
|
+
*/
|
|
23
|
+
export function postAgentNativeWorkspaceAppRoute(path) {
|
|
24
|
+
if (typeof window === "undefined")
|
|
25
|
+
return false;
|
|
26
|
+
const parentWindow = window.parent;
|
|
27
|
+
if (!parentWindow || parentWindow === window)
|
|
28
|
+
return false;
|
|
29
|
+
const normalizedPath = normalizeWorkspaceAppRoute(path);
|
|
30
|
+
if (!normalizedPath)
|
|
31
|
+
return false;
|
|
32
|
+
const message = {
|
|
33
|
+
type: AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE,
|
|
34
|
+
path: normalizedPath,
|
|
35
|
+
};
|
|
36
|
+
parentWindow.postMessage(message, "*");
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
ok?: undefined;
|
|
17
16
|
error: string;
|
|
17
|
+
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
package/dist/deploy/build.d.ts
CHANGED
|
@@ -254,6 +254,19 @@ export declare function assertSingleTemplateNetlifyBuildOutput(projectCwd: strin
|
|
|
254
254
|
* Netlify platform 404s. Preserve any real redirects from `public/_redirects`.
|
|
255
255
|
*/
|
|
256
256
|
export declare function writeSingleTemplateNetlifyRedirects(projectCwd: string): void;
|
|
257
|
+
/**
|
|
258
|
+
* Whether the emitted bundle actually imports the `libsql` native addon.
|
|
259
|
+
*
|
|
260
|
+
* The `@libsql/client` node entry `require`s it; `@libsql/client/web` and
|
|
261
|
+
* `better-sqlite3` do not. Probing the emitted output is the only gate that
|
|
262
|
+
* cannot be wrong: `getDialect()` reads `DATABASE_URL` at RUNTIME, and neither
|
|
263
|
+
* the docs nor the beta deploy workflow sets it at build time, so build-time
|
|
264
|
+
* dialect is unknowable. This mirrors `findServerlessBrowserRuntimeConsumer`,
|
|
265
|
+
* which already gates the Chromium copy the same way — the asymmetry is why a
|
|
266
|
+
* 9.3MB Linux SQLite driver shipped in the docs function, a deployment that
|
|
267
|
+
* runs Postgres and can never load it.
|
|
268
|
+
*/
|
|
269
|
+
export declare function bundleImportsLibsqlNativeAddon(serverDir: string): boolean;
|
|
257
270
|
/**
|
|
258
271
|
* Nitro's file tracer can over-include optional desktop/dev packages that are
|
|
259
272
|
* present in a monorepo install but cannot run in serverless. Netlify installs
|
package/dist/deploy/build.js
CHANGED
|
@@ -3389,9 +3389,60 @@ export function writeSingleTemplateNetlifyRedirects(projectCwd) {
|
|
|
3389
3389
|
}
|
|
3390
3390
|
console.log('[deploy] Removed Netlify fallback rewrite to /.netlify/functions/server (incompatible with Nitro config.path: "/*").');
|
|
3391
3391
|
}
|
|
3392
|
+
/**
|
|
3393
|
+
* Whether the emitted bundle actually imports the `libsql` native addon.
|
|
3394
|
+
*
|
|
3395
|
+
* The `@libsql/client` node entry `require`s it; `@libsql/client/web` and
|
|
3396
|
+
* `better-sqlite3` do not. Probing the emitted output is the only gate that
|
|
3397
|
+
* cannot be wrong: `getDialect()` reads `DATABASE_URL` at RUNTIME, and neither
|
|
3398
|
+
* the docs nor the beta deploy workflow sets it at build time, so build-time
|
|
3399
|
+
* dialect is unknowable. This mirrors `findServerlessBrowserRuntimeConsumer`,
|
|
3400
|
+
* which already gates the Chromium copy the same way — the asymmetry is why a
|
|
3401
|
+
* 9.3MB Linux SQLite driver shipped in the docs function, a deployment that
|
|
3402
|
+
* runs Postgres and can never load it.
|
|
3403
|
+
*/
|
|
3404
|
+
export function bundleImportsLibsqlNativeAddon(serverDir) {
|
|
3405
|
+
const bareImport = /(?:require\(|from\s*)["']libsql["']/;
|
|
3406
|
+
const stack = [serverDir];
|
|
3407
|
+
while (stack.length > 0) {
|
|
3408
|
+
const dir = stack.pop();
|
|
3409
|
+
let entries;
|
|
3410
|
+
try {
|
|
3411
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
3412
|
+
}
|
|
3413
|
+
catch {
|
|
3414
|
+
continue;
|
|
3415
|
+
}
|
|
3416
|
+
for (const entry of entries) {
|
|
3417
|
+
const full = path.join(dir, entry.name);
|
|
3418
|
+
if (entry.isDirectory()) {
|
|
3419
|
+
// The copied native package itself is the thing being gated; its own
|
|
3420
|
+
// files must never count as a consumer.
|
|
3421
|
+
if (entry.name === "node_modules" || entry.name === "@libsql")
|
|
3422
|
+
continue;
|
|
3423
|
+
stack.push(full);
|
|
3424
|
+
continue;
|
|
3425
|
+
}
|
|
3426
|
+
if (!/\.(?:mjs|cjs|js)$/.test(entry.name))
|
|
3427
|
+
continue;
|
|
3428
|
+
try {
|
|
3429
|
+
if (bareImport.test(fs.readFileSync(full, "utf8")))
|
|
3430
|
+
return true;
|
|
3431
|
+
}
|
|
3432
|
+
catch {
|
|
3433
|
+
continue;
|
|
3434
|
+
}
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
return false;
|
|
3438
|
+
}
|
|
3392
3439
|
function copyInstalledLibsqlNativePackages(serverDir) {
|
|
3393
3440
|
if (!serverDir || !fs.existsSync(serverDir))
|
|
3394
3441
|
return;
|
|
3442
|
+
if (!bundleImportsLibsqlNativeAddon(serverDir)) {
|
|
3443
|
+
console.log("[deploy] Skipped the libsql native package: the emitted bundle never imports the `libsql` addon.");
|
|
3444
|
+
return;
|
|
3445
|
+
}
|
|
3395
3446
|
const nodeModulesRoots = nodeModulesAncestors(cwd);
|
|
3396
3447
|
const destScopeDir = path.join(serverDir, "node_modules", "@libsql");
|
|
3397
3448
|
let copied = 0;
|
|
@@ -5,7 +5,23 @@ import { type AutomationExecutionIdentity } from "../automations/service.js";
|
|
|
5
5
|
import { type Resource } from "../resources/store.js";
|
|
6
6
|
import { type RequestContext } from "../server/request-context.js";
|
|
7
7
|
import type { JobFrontmatter } from "./frontmatter.js";
|
|
8
|
+
/**
|
|
9
|
+
* Default hard abort for one in-process automation run. Read through
|
|
10
|
+
* `resolveBackgroundRunHardTimeoutMs()` at the use site — this is the host's
|
|
11
|
+
* real function budget for scheduled work, and it differs by deployment.
|
|
12
|
+
*/
|
|
8
13
|
export declare const BACKGROUND_RUN_HARD_TIMEOUT_MS: number;
|
|
14
|
+
/**
|
|
15
|
+
* Terminal failure of a background automation, carrying the machine-readable
|
|
16
|
+
* code the failure taxonomy already computes.
|
|
17
|
+
*
|
|
18
|
+
* The code used to be produced and then dropped, so "how often are runs cut
|
|
19
|
+
* off?" was a `LIKE '%no_progress%'` over an English sentence.
|
|
20
|
+
*/
|
|
21
|
+
export declare class BackgroundAutomationRunError extends Error {
|
|
22
|
+
readonly errorCode: string;
|
|
23
|
+
constructor(message: string, errorCode: string);
|
|
24
|
+
}
|
|
9
25
|
export interface BackgroundAutomationContext {
|
|
10
26
|
name: string;
|
|
11
27
|
meta: JobFrontmatter;
|
|
@@ -35,6 +51,15 @@ export interface BackgroundAutomationRunOptions {
|
|
|
35
51
|
actionAutomation?: ActionAutomationContext;
|
|
36
52
|
/** Reuse a history row created by a durable run-now enqueue. */
|
|
37
53
|
historyId?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Per-run overrides for the run-manager no-progress backstop. `startRun` has
|
|
56
|
+
* always accepted these; the automation path had no way to reach them, and
|
|
57
|
+
* the one indirect route (zeroing `agent.runSoftTimeoutMs`) is global and
|
|
58
|
+
* would strip foreground chat of its chunk boundary. Additive: unset means
|
|
59
|
+
* the configured/default behaviour, unchanged.
|
|
60
|
+
*/
|
|
61
|
+
noProgressTimeoutMs?: number;
|
|
62
|
+
backgroundNoProgressTimeoutMs?: number;
|
|
38
63
|
}
|
|
39
64
|
export interface BackgroundAutomationRunResult {
|
|
40
65
|
responseText: string;
|