@agent-native/core 0.0.0-beta-20260819181349 → 0.0.0-beta-20260819183007
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/plan/app/pages/PlansPage.tsx +0 -12
- package/corpus/templates/plan/changelog/2026-08-19-plan-prompts-now-guide-you-to-connect-ai-before-sending-and-.md +6 -0
- package/dist/a2a/task-store.d.ts +1 -0
- package/dist/a2a/task-store.js +1 -1
- package/dist/agent/observational-memory/store.d.ts +1 -0
- package/dist/agent/observational-memory/store.js +1 -1
- package/dist/agent/run-store.d.ts +1 -0
- package/dist/agent/run-store.js +1 -1
- package/dist/agent/tool-approval-store.d.ts +1 -0
- package/dist/agent/tool-approval-store.js +1 -1
- package/dist/application-state/store.d.ts +1 -0
- package/dist/application-state/store.js +1 -1
- package/dist/browser-sessions/store.d.ts +1 -0
- package/dist/browser-sessions/store.js +1 -1
- package/dist/checkpoints/store.d.ts +1 -0
- package/dist/checkpoints/store.js +1 -1
- package/dist/client/agent-chat-adapter.js +22 -10
- package/dist/client/chat/message-components.d.ts +4 -0
- package/dist/client/chat/message-components.js +28 -1
- package/dist/client/chat/run-recovery.js +26 -0
- package/dist/client/sse-event-processor.js +13 -8
- package/dist/coding-tools/sandbox/executions-store.d.ts +1 -0
- package/dist/coding-tools/sandbox/executions-store.js +1 -1
- package/dist/collab/awareness-store.d.ts +1 -0
- package/dist/collab/awareness-store.js +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/storage.d.ts +1 -0
- package/dist/collab/storage.js +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.js +3 -3
- package/dist/db/ddl-guard.js +8 -0
- package/dist/db/migration-runtime.d.ts +23 -0
- package/dist/db/migration-runtime.js +41 -0
- package/dist/db/migrations.d.ts +1 -2
- package/dist/db/migrations.js +2 -24
- package/dist/email-catalog/log.d.ts +1 -0
- package/dist/email-catalog/log.js +1 -1
- package/dist/guards/index.d.ts +1 -0
- package/dist/guards/index.js +1 -0
- package/dist/guards/release-schema-complete.d.ts +22 -0
- package/dist/guards/release-schema-complete.js +144 -0
- package/dist/integrations/a2a-continuations-store.d.ts +1 -0
- package/dist/integrations/a2a-continuations-store.js +1 -1
- package/dist/integrations/awaiting-input-store.d.ts +1 -0
- package/dist/integrations/awaiting-input-store.js +1 -1
- package/dist/integrations/config-store.d.ts +1 -0
- package/dist/integrations/config-store.js +1 -1
- package/dist/integrations/controls-store.d.ts +1 -0
- package/dist/integrations/controls-store.js +1 -1
- package/dist/integrations/identity-links-store.d.ts +1 -0
- package/dist/integrations/identity-links-store.js +1 -1
- package/dist/integrations/installations-store.d.ts +1 -0
- package/dist/integrations/installations-store.js +1 -1
- package/dist/integrations/remote-commands-store.d.ts +1 -0
- package/dist/integrations/remote-commands-store.js +1 -1
- package/dist/integrations/remote-devices-store.d.ts +1 -0
- package/dist/integrations/remote-devices-store.js +1 -1
- package/dist/integrations/remote-push-store.d.ts +1 -0
- package/dist/integrations/remote-push-store.js +1 -1
- package/dist/integrations/remote-run-events-store.d.ts +1 -0
- package/dist/integrations/remote-run-events-store.js +1 -1
- package/dist/integrations/scope-store.d.ts +1 -0
- package/dist/integrations/scope-store.js +1 -1
- package/dist/integrations/thread-mapping-store.d.ts +1 -0
- package/dist/integrations/thread-mapping-store.js +1 -1
- package/dist/integrations/usage-budget-store.d.ts +1 -0
- package/dist/integrations/usage-budget-store.js +1 -1
- package/dist/jobs/run-history.d.ts +1 -0
- package/dist/jobs/run-history.js +1 -1
- package/dist/jobs/scheduler-health.d.ts +1 -0
- package/dist/jobs/scheduler-health.js +1 -1
- package/dist/mcp/approval-store.d.ts +1 -0
- package/dist/mcp/approval-store.js +1 -1
- package/dist/mcp/connect-store.d.ts +1 -0
- package/dist/mcp/connect-store.js +1 -1
- package/dist/mcp/oauth-store.d.ts +1 -0
- package/dist/mcp/oauth-store.js +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/notifications/store.d.ts +1 -0
- package/dist/notifications/store.js +1 -1
- package/dist/oauth-tokens/store.d.ts +1 -0
- package/dist/oauth-tokens/store.js +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/store.d.ts +1 -0
- package/dist/progress/store.js +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +13 -13
- package/dist/provider-api/corpus-jobs-store.d.ts +1 -0
- package/dist/provider-api/corpus-jobs-store.js +1 -1
- package/dist/provider-api/custom-registry.d.ts +1 -0
- package/dist/provider-api/custom-registry.js +1 -1
- package/dist/provider-api/quota-governor.d.ts +1 -0
- package/dist/provider-api/quota-governor.js +1 -1
- package/dist/provider-api/staged-datasets-store.d.ts +1 -0
- package/dist/provider-api/staged-datasets-store.js +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/resources/store.d.ts +1 -0
- package/dist/resources/store.js +1 -1
- package/dist/search/index.js +3 -0
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/secrets/storage.d.ts +1 -0
- package/dist/secrets/storage.js +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-teams-run-queue.d.ts +1 -0
- package/dist/server/agent-teams-run-queue.js +1 -1
- package/dist/server/auth.d.ts +1 -0
- package/dist/server/auth.js +1 -1
- package/dist/server/embed-session.d.ts +1 -0
- package/dist/server/embed-session.js +1 -1
- package/dist/server/identity-sso-store.d.ts +1 -0
- package/dist/server/identity-sso-store.js +1 -1
- package/dist/server/release-migrations.js +5 -0
- package/dist/server/release-schema.d.ts +46 -0
- package/dist/server/release-schema.js +307 -0
- package/dist/settings/store.d.ts +1 -0
- package/dist/settings/store.js +1 -1
- package/dist/styles/agent-native.css +17 -15
- package/dist/triggers/routes.d.ts +11 -0
- package/dist/triggers/routes.js +10 -0
- package/dist/usage/alerts-store.d.ts +1 -0
- package/dist/usage/alerts-store.js +1 -1
- package/dist/usage/store.d.ts +1 -0
- package/dist/usage/store.js +1 -1
- package/package.json +3 -3
package/corpus/README.md
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SIDEBAR_STATE_CHANGE_EVENT,
|
|
3
|
-
BuilderSetupCard,
|
|
4
3
|
sendToAgentChat,
|
|
5
4
|
setAgentChatContextItem,
|
|
6
5
|
useAgentEngineConfigured,
|
|
@@ -8466,23 +8465,12 @@ function CreatePlanDialog({
|
|
|
8466
8465
|
</DialogDescription>
|
|
8467
8466
|
</DialogHeader>
|
|
8468
8467
|
<div className="grid gap-3">
|
|
8469
|
-
{canCreate && agentMissing ? (
|
|
8470
|
-
<BuilderSetupCard
|
|
8471
|
-
fullWidth
|
|
8472
|
-
onConnected={() =>
|
|
8473
|
-
window.dispatchEvent(
|
|
8474
|
-
new Event("agent-engine:configured-changed"),
|
|
8475
|
-
)
|
|
8476
|
-
}
|
|
8477
|
-
/>
|
|
8478
|
-
) : null}
|
|
8479
8468
|
<div className="rounded-xl border border-border bg-background p-2 shadow-sm">
|
|
8480
8469
|
<PromptComposer
|
|
8481
8470
|
autoFocus
|
|
8482
8471
|
disabled={composerLocked}
|
|
8483
8472
|
attachmentsEnabled={false}
|
|
8484
8473
|
showModelSelector={false}
|
|
8485
|
-
modelStatusChecksEnabled={false}
|
|
8486
8474
|
placeholder={t("plansPage.create.placeholder")}
|
|
8487
8475
|
draftScope="plans:create-plan"
|
|
8488
8476
|
initialText={promptSeed}
|
package/dist/a2a/task-store.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Task, Message, TaskState, Artifact } from "./types.js";
|
|
2
2
|
export declare const MAX_A2A_IDEMPOTENCY_KEY_CHARS = 128;
|
|
3
3
|
export declare const A2A_PERSONAL_OWNER_SCOPE = "__personal__";
|
|
4
|
+
export declare function ensureTable(): Promise<void>;
|
|
4
5
|
export interface A2AApprovalRecord {
|
|
5
6
|
id: string;
|
|
6
7
|
taskId: string;
|
package/dist/a2a/task-store.js
CHANGED
|
@@ -5,7 +5,7 @@ let _initPromise;
|
|
|
5
5
|
export const MAX_A2A_IDEMPOTENCY_KEY_CHARS = 128;
|
|
6
6
|
const A2A_IDEMPOTENCY_INDEX = "idx_a2a_tasks_owner_scope_idempotency";
|
|
7
7
|
export const A2A_PERSONAL_OWNER_SCOPE = "__personal__";
|
|
8
|
-
async function ensureTable() {
|
|
8
|
+
export async function ensureTable() {
|
|
9
9
|
if (!_initPromise) {
|
|
10
10
|
_initPromise = (async () => {
|
|
11
11
|
const client = getDbExec();
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* runtime even before the migration plugin is registered.
|
|
13
13
|
*/
|
|
14
14
|
import type { ObservationalMemoryEntry, ObservationalMemoryOwner, ObservationalMemoryTier } from "./types.js";
|
|
15
|
+
export declare function ensureTable(): Promise<void>;
|
|
15
16
|
/** Reset the cached ensureTable promise — test-only seam. */
|
|
16
17
|
export declare function __resetObservationalMemoryTableCache(): void;
|
|
17
18
|
export interface InsertObservationalMemoryInput extends ObservationalMemoryOwner {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import { getDbExec, isPostgres } from "../../db/client.js";
|
|
15
15
|
import { ensureTableExists, ensureIndexExists } from "../../db/ddl-guard.js";
|
|
16
16
|
let tableReady = null;
|
|
17
|
-
async function ensureTable() {
|
|
17
|
+
export async function ensureTable() {
|
|
18
18
|
if (tableReady)
|
|
19
19
|
return tableReady;
|
|
20
20
|
tableReady = (async () => {
|
|
@@ -217,6 +217,7 @@ export declare const IN_FLIGHT_RUN_STALE_GRACE_MS: number;
|
|
|
217
217
|
* is reaped like any other stale run.
|
|
218
218
|
*/
|
|
219
219
|
export declare const IN_FLIGHT_GRACE_MAX_LIVENESS_GAP_MS = 120000;
|
|
220
|
+
export declare function ensureRunTables(): Promise<void>;
|
|
220
221
|
/**
|
|
221
222
|
* Persist a zombie tool-call completion to the ledger. Called by the detached
|
|
222
223
|
* promise continuation after `Promise.race` abandons it. Best-effort — never
|
package/dist/agent/run-store.js
CHANGED
|
@@ -294,7 +294,7 @@ export const IN_FLIGHT_RUN_STALE_GRACE_MS = 14.5 * 60_000; // 870_000
|
|
|
294
294
|
* is reaped like any other stale run.
|
|
295
295
|
*/
|
|
296
296
|
export const IN_FLIGHT_GRACE_MAX_LIVENESS_GAP_MS = 120_000;
|
|
297
|
-
async function ensureRunTables() {
|
|
297
|
+
export async function ensureRunTables() {
|
|
298
298
|
if (!_initPromise) {
|
|
299
299
|
_initPromise = (async () => {
|
|
300
300
|
const client = getDbExec();
|
|
@@ -11,7 +11,7 @@ import { AGENT_TOOL_APPROVAL_INDEX_SQL, AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL, A
|
|
|
11
11
|
const APPROVAL_TTL_MS = 60 * 60_000;
|
|
12
12
|
const APPROVAL_CLEANUP_AGE_MS = 24 * 60 * 60_000;
|
|
13
13
|
let initPromise;
|
|
14
|
-
async function ensureAgentToolApprovalTable() {
|
|
14
|
+
export async function ensureAgentToolApprovalTable() {
|
|
15
15
|
if (!initPromise) {
|
|
16
16
|
initPromise = (async () => {
|
|
17
17
|
const createSql = AGENT_TOOL_APPROVAL_TABLE_SQL[isPostgres() ? "postgres" : "sqlite"];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { StoreWriteOptions } from "../settings/store.js";
|
|
2
|
+
export declare function ensureTable(): Promise<void>;
|
|
2
3
|
export declare function appStateGet(sessionId: string, key: string): Promise<Record<string, unknown> | null>;
|
|
3
4
|
/**
|
|
4
5
|
* Read several application-state keys for one session in a single SQL query,
|
|
@@ -11,7 +11,7 @@ const MAX_HOSTED_APP_STATE_VALUE_BYTES = 1024 * 1024;
|
|
|
11
11
|
function escapeLike(s) {
|
|
12
12
|
return s.replace(/[!%_]/g, (match) => `!${match}`);
|
|
13
13
|
}
|
|
14
|
-
async function ensureTable() {
|
|
14
|
+
export async function ensureTable() {
|
|
15
15
|
if (!_initPromise) {
|
|
16
16
|
_initPromise = (async () => {
|
|
17
17
|
const client = getDbExec();
|
|
@@ -2,6 +2,7 @@ import type { AgentNativeBrowserSessionRecord, AgentNativeBrowserSessionRequest,
|
|
|
2
2
|
export declare const DEFAULT_BROWSER_SESSION_TTL_MS = 45000;
|
|
3
3
|
export declare const DEFAULT_BROWSER_SESSION_REQUEST_TIMEOUT_MS = 30000;
|
|
4
4
|
export declare const DEFAULT_BROWSER_SESSION_REQUEST_POLL_MS = 250;
|
|
5
|
+
export declare function ensureTables(): Promise<void>;
|
|
5
6
|
export declare function registerBrowserSession(ownerEmailInput: string, input: RegisterAgentNativeBrowserSessionInput): Promise<AgentNativeBrowserSessionRecord>;
|
|
6
7
|
export declare function listBrowserSessions(ownerEmailInput: string, options?: {
|
|
7
8
|
includeExpired?: boolean;
|
|
@@ -13,7 +13,7 @@ function nowMs() {
|
|
|
13
13
|
function sleep(ms) {
|
|
14
14
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
15
15
|
}
|
|
16
|
-
async function ensureTables() {
|
|
16
|
+
export async function ensureTables() {
|
|
17
17
|
if (!initPromise) {
|
|
18
18
|
initPromise = (async () => {
|
|
19
19
|
const client = getDbExec();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare function ensureCheckpointTable(): Promise<void>;
|
|
1
2
|
export declare function insertCheckpoint(id: string, threadId: string, runId: string | null, commitSha: string, message: string): Promise<void>;
|
|
2
3
|
export declare function getCheckpointsByThread(threadId: string): Promise<Array<{
|
|
3
4
|
id: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getDbExec, intType, isPostgres } from "../db/client.js";
|
|
2
2
|
import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
|
|
3
3
|
let _initPromise;
|
|
4
|
-
async function ensureCheckpointTable() {
|
|
4
|
+
export async function ensureCheckpointTable() {
|
|
5
5
|
if (!_initPromise) {
|
|
6
6
|
_initPromise = (async () => {
|
|
7
7
|
const client = getDbExec();
|
|
@@ -1429,6 +1429,16 @@ function isMissingCredentialMessage(message) {
|
|
|
1429
1429
|
msg.includes("no llm provider") ||
|
|
1430
1430
|
msg.includes("llm provider is connected"));
|
|
1431
1431
|
}
|
|
1432
|
+
function isMissingProviderErrorMessage(message, errorCode) {
|
|
1433
|
+
const text = message.toLowerCase();
|
|
1434
|
+
const code = (errorCode ?? "").toLowerCase();
|
|
1435
|
+
return (text.includes("no llm provider") ||
|
|
1436
|
+
text.includes("missing credentials") ||
|
|
1437
|
+
text.includes("missing api key") ||
|
|
1438
|
+
text.includes("missing_api_key") ||
|
|
1439
|
+
((code === "missing_credentials" || code === "missing_api_key") &&
|
|
1440
|
+
text.includes("llm provider")));
|
|
1441
|
+
}
|
|
1432
1442
|
function missingCredentialFailure(message) {
|
|
1433
1443
|
try {
|
|
1434
1444
|
const parsed = JSON.parse(message);
|
|
@@ -1439,9 +1449,10 @@ function missingCredentialFailure(message) {
|
|
|
1439
1449
|
: message;
|
|
1440
1450
|
const errorCode = typeof parsed.errorCode === "string"
|
|
1441
1451
|
? parsed.errorCode
|
|
1442
|
-
:
|
|
1452
|
+
: isMissingCredentialMessage(raw)
|
|
1453
|
+
? "missing_credentials"
|
|
1454
|
+
: "authentication_error";
|
|
1443
1455
|
return {
|
|
1444
|
-
text: formatChatErrorText(raw, typeof parsed.upgradeUrl === "string" ? parsed.upgradeUrl : undefined, errorCode),
|
|
1445
1456
|
runError: {
|
|
1446
1457
|
message: normalizeChatError(raw).message,
|
|
1447
1458
|
errorCode,
|
|
@@ -1450,10 +1461,11 @@ function missingCredentialFailure(message) {
|
|
|
1450
1461
|
}
|
|
1451
1462
|
catch {
|
|
1452
1463
|
return {
|
|
1453
|
-
text: formatChatErrorText(message, undefined, "missing_credentials"),
|
|
1454
1464
|
runError: {
|
|
1455
1465
|
message: normalizeChatError(message).message,
|
|
1456
|
-
errorCode:
|
|
1466
|
+
errorCode: isMissingCredentialMessage(message)
|
|
1467
|
+
? "missing_credentials"
|
|
1468
|
+
: "authentication_error",
|
|
1457
1469
|
},
|
|
1458
1470
|
};
|
|
1459
1471
|
}
|
|
@@ -2290,10 +2302,12 @@ export function createAgentChatAdapter(options) {
|
|
|
2290
2302
|
settleInterruptedToolCalls(content, undefined, {
|
|
2291
2303
|
includeActivity: true,
|
|
2292
2304
|
});
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2305
|
+
if (!isMissingProviderErrorMessage(args.message, args.errorCode)) {
|
|
2306
|
+
content.push({
|
|
2307
|
+
type: "text",
|
|
2308
|
+
text: formatChatErrorText(args.message, undefined, args.errorCode),
|
|
2309
|
+
});
|
|
2310
|
+
}
|
|
2297
2311
|
settleTerminalChatRun();
|
|
2298
2312
|
yield {
|
|
2299
2313
|
content: [...content],
|
|
@@ -3351,7 +3365,6 @@ export function createAgentChatAdapter(options) {
|
|
|
3351
3365
|
detail: { ...failure.runError, tabId },
|
|
3352
3366
|
}));
|
|
3353
3367
|
}
|
|
3354
|
-
content.push({ type: "text", text: failure.text });
|
|
3355
3368
|
settleTerminalChatRun();
|
|
3356
3369
|
yield {
|
|
3357
3370
|
content: [...content],
|
|
@@ -3664,7 +3677,6 @@ export function createAgentChatAdapter(options) {
|
|
|
3664
3677
|
detail: { ...failure.runError, tabId },
|
|
3665
3678
|
}));
|
|
3666
3679
|
}
|
|
3667
|
-
content.push({ type: "text", text: failure.text });
|
|
3668
3680
|
settleTerminalChatRun();
|
|
3669
3681
|
yield {
|
|
3670
3682
|
content: [...content],
|
|
@@ -71,6 +71,10 @@ export declare function MessageActionsMenu({ showRevert, onRevert, threadId, }?:
|
|
|
71
71
|
export declare function UserMessage(): React.JSX.Element | null;
|
|
72
72
|
export declare function messageTextFromContent(content: unknown): string;
|
|
73
73
|
export declare function isMissingFinalResponseWarningText(text: string): boolean;
|
|
74
|
+
export declare function isMissingCredentialAssistantMessage(message: {
|
|
75
|
+
content?: unknown;
|
|
76
|
+
metadata?: unknown;
|
|
77
|
+
}): boolean;
|
|
74
78
|
export declare function latestUserMessageText(messages: readonly unknown[]): string;
|
|
75
79
|
export declare function userMessageTextBeforeAssistant(messages: readonly unknown[], assistantMessageId: string): string;
|
|
76
80
|
export declare function assistantMessageHasUnresolvedTool(content: unknown): boolean;
|
|
@@ -539,6 +539,32 @@ function missingFinalResponseWarningText(content) {
|
|
|
539
539
|
}
|
|
540
540
|
return null;
|
|
541
541
|
}
|
|
542
|
+
export function isMissingCredentialAssistantMessage(message) {
|
|
543
|
+
const metadata = message.metadata;
|
|
544
|
+
const runError = metadata?.custom?.runError ?? metadata?.runError;
|
|
545
|
+
const errorCode = typeof runError?.errorCode === "string"
|
|
546
|
+
? runError.errorCode.toLowerCase()
|
|
547
|
+
: "";
|
|
548
|
+
const errorMessage = typeof runError?.message === "string" ? runError.message : "";
|
|
549
|
+
if (/no llm provider(?: key)? (?:is connected|was found)|missing credentials|missing api key|missing_api_key/i.test(errorMessage) ||
|
|
550
|
+
((errorCode === "missing_credentials" || errorCode === "missing_api_key") &&
|
|
551
|
+
!errorMessage &&
|
|
552
|
+
!message.content)) {
|
|
553
|
+
return true;
|
|
554
|
+
}
|
|
555
|
+
const text = Array.isArray(message.content)
|
|
556
|
+
? message.content
|
|
557
|
+
.filter((part) => Boolean(part) &&
|
|
558
|
+
typeof part === "object" &&
|
|
559
|
+
part.type === "text" &&
|
|
560
|
+
typeof part.text === "string")
|
|
561
|
+
.map((part) => part.text)
|
|
562
|
+
.join("\n")
|
|
563
|
+
: typeof message.content === "string"
|
|
564
|
+
? message.content
|
|
565
|
+
: "";
|
|
566
|
+
return /^Error:\s*(?:No LLM provider(?: key)? (?:is connected|was found))/i.test(text.trim());
|
|
567
|
+
}
|
|
542
568
|
export function latestUserMessageText(messages) {
|
|
543
569
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
544
570
|
const message = messages[index];
|
|
@@ -847,6 +873,7 @@ export function AssistantMessage() {
|
|
|
847
873
|
const activeTurnId = React.useContext(ChatRunningTurnIdContext);
|
|
848
874
|
const lastRunDurationMs = React.useContext(ChatRunDurationContext);
|
|
849
875
|
const msg = messageRuntime.getState();
|
|
876
|
+
const isMissingCredential = isMissingCredentialAssistantMessage(msg);
|
|
850
877
|
const persistedDurationMs = getAssistantRunDurationMs(msg);
|
|
851
878
|
const timestamp = formatMessageTimestamp(msg.createdAt, locale, t("agentChat.history.yesterday"));
|
|
852
879
|
const isLast = msg.isLast;
|
|
@@ -1052,7 +1079,7 @@ export function AssistantMessage() {
|
|
|
1052
1079
|
chatRunning,
|
|
1053
1080
|
isLast,
|
|
1054
1081
|
});
|
|
1055
|
-
if (!hasRenderableContent)
|
|
1082
|
+
if (!hasRenderableContent || isMissingCredential)
|
|
1056
1083
|
return null;
|
|
1057
1084
|
return (_jsxs("div", { className: "group relative", style: { contentVisibility: isComplete ? "auto" : "visible" }, children: [_jsxs("div", { className: "w-full max-w-[95%] text-sm leading-relaxed text-foreground", children: [isComplete && (_jsx(McpConnectionSuggestion, { text: responseConnectionText, contextText: responseConnectionContext, variant: "response" })), _jsx(ToolCallStackMotion, { children: _jsx(MessagePrimitive.GroupedParts, { groupBy: groupAssistantWorkParts, children: ({ part, children }) => {
|
|
1058
1085
|
switch (part.type) {
|
|
@@ -112,6 +112,14 @@ function isConnectionRecoveryRunError(info) {
|
|
|
112
112
|
message.includes("connection kept failing") ||
|
|
113
113
|
message.includes("automatic recovery attempts"));
|
|
114
114
|
}
|
|
115
|
+
function isMissingLlmProviderRunError(info) {
|
|
116
|
+
const code = (info.errorCode ?? "").toLowerCase();
|
|
117
|
+
const text = [info.message, info.details].filter(Boolean).join("\n");
|
|
118
|
+
const hasCredentialSetupText = /no llm provider(?: key)? (?:is connected|was found)|missing credentials|missing api key|missing_api_key|(?:api[_ -]?key|auth[_ -]?token)\s*(?:(?:is|was)\s+)?(?:not\s+(?:set|configured|available|present|provided|found)|missing|unavailable|empty|unset|unconfigured)/i.test(text);
|
|
119
|
+
return (hasCredentialSetupText ||
|
|
120
|
+
((code === "missing_credentials" || code === "missing_api_key") &&
|
|
121
|
+
!text.trim()));
|
|
122
|
+
}
|
|
115
123
|
// ─── BuilderConnectCta ────────────────────────────────────────────────────────
|
|
116
124
|
// Renders a single row with left-aligned copy and a right-aligned action.
|
|
117
125
|
// Click opens the Builder OAuth popup via the shared
|
|
@@ -194,11 +202,15 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
194
202
|
const [copyState, setCopyState] = useState("idle");
|
|
195
203
|
const [forking, setForking] = useState(false);
|
|
196
204
|
const [forkError, setForkError] = useState(null);
|
|
205
|
+
const [providerConnected, setProviderConnected] = useState(false);
|
|
206
|
+
const retryRequestedRef = useRef(false);
|
|
207
|
+
const [retryRequested, setRetryRequested] = useState(false);
|
|
197
208
|
const builderReconnect = useBuilderConnectFlow({
|
|
198
209
|
trackingSource: "assistant_chat_reconnect_error",
|
|
199
210
|
});
|
|
200
211
|
const canRecover = info.recoverable === true;
|
|
201
212
|
const shouldShowBuilderReconnect = isBuilderReconnectRunError(info);
|
|
213
|
+
const shouldShowMissingProviderSetup = isMissingLlmProviderRunError(info);
|
|
202
214
|
const isProviderAuthError = isProviderAuthenticationError([info.message, info.details].filter(Boolean).join("\n"), info.errorCode);
|
|
203
215
|
// Blocked on something the reader goes and fixes elsewhere, then comes back
|
|
204
216
|
// to. Without a retry the card is a dead end and its own copy ("then retry")
|
|
@@ -241,6 +253,17 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
241
253
|
onRetry();
|
|
242
254
|
onDismiss();
|
|
243
255
|
}, [onDismiss, onProviderConnected, onRetry]);
|
|
256
|
+
const handleMissingProviderConnected = useCallback(() => {
|
|
257
|
+
setProviderConnected(true);
|
|
258
|
+
onProviderConnected?.();
|
|
259
|
+
}, [onProviderConnected]);
|
|
260
|
+
const handleMissingProviderRetry = useCallback(() => {
|
|
261
|
+
if (retryRequestedRef.current)
|
|
262
|
+
return;
|
|
263
|
+
retryRequestedRef.current = true;
|
|
264
|
+
setRetryRequested(true);
|
|
265
|
+
onRetry();
|
|
266
|
+
}, [onRetry]);
|
|
244
267
|
const handleFork = useCallback(async () => {
|
|
245
268
|
if (!onFork || forking)
|
|
246
269
|
return;
|
|
@@ -264,6 +287,9 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
264
287
|
onDismiss();
|
|
265
288
|
}
|
|
266
289
|
}, [builderReconnectResolved, onDismiss]);
|
|
290
|
+
if (shouldShowMissingProviderSetup) {
|
|
291
|
+
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] }));
|
|
292
|
+
}
|
|
267
293
|
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, {
|
|
268
294
|
recoverable: t("agentChat.error.stopped"),
|
|
269
295
|
terminal: t("agentChat.error.failed"),
|
|
@@ -605,6 +605,12 @@ function isMissingCredentialText(message, errorCode) {
|
|
|
605
605
|
msg.includes("no llm provider") ||
|
|
606
606
|
msg.includes("llm provider is connected"));
|
|
607
607
|
}
|
|
608
|
+
function isMissingProviderErrorText(message, errorCode) {
|
|
609
|
+
const code = String(errorCode ?? "").toLowerCase();
|
|
610
|
+
return (code === "missing_api_key" ||
|
|
611
|
+
code === "missing_credentials" ||
|
|
612
|
+
/no llm provider(?: key)? (?:is connected|was found)/i.test(message));
|
|
613
|
+
}
|
|
608
614
|
function dispatchActivityClear(tabId) {
|
|
609
615
|
if (typeof window === "undefined")
|
|
610
616
|
return;
|
|
@@ -1389,10 +1395,6 @@ export function processEvent(ev, content, toolCallCounter, tabId, state) {
|
|
|
1389
1395
|
// the last preparation activity, so do not leave its label mounted.
|
|
1390
1396
|
dispatchActivityClear(tabId);
|
|
1391
1397
|
settleInterruptedToolCalls(content, undefined, { includeActivity: true });
|
|
1392
|
-
content.push({
|
|
1393
|
-
type: "text",
|
|
1394
|
-
text: formatChatErrorText(errMsg, undefined, errorCode),
|
|
1395
|
-
});
|
|
1396
1398
|
return {
|
|
1397
1399
|
action: "missing_api_key",
|
|
1398
1400
|
result: {
|
|
@@ -1472,6 +1474,7 @@ export function processEvent(ev, content, toolCallCounter, tabId, state) {
|
|
|
1472
1474
|
};
|
|
1473
1475
|
}
|
|
1474
1476
|
const normalized = normalizeChatError(errMsg, ev.errorCode);
|
|
1477
|
+
const missingProviderError = isMissingProviderErrorText(errMsg, ev.errorCode);
|
|
1475
1478
|
if (isMissingCredentialText(errMsg, ev.errorCode)) {
|
|
1476
1479
|
dispatchMissingApiKey(tabId);
|
|
1477
1480
|
}
|
|
@@ -1492,10 +1495,12 @@ export function processEvent(ev, content, toolCallCounter, tabId, state) {
|
|
|
1492
1495
|
}));
|
|
1493
1496
|
}
|
|
1494
1497
|
settleInterruptedToolCalls(content, undefined, { includeActivity: true });
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1498
|
+
if (!missingProviderError) {
|
|
1499
|
+
content.push({
|
|
1500
|
+
type: "text",
|
|
1501
|
+
text: formatChatErrorText(errMsg, ev.upgradeUrl, ev.errorCode),
|
|
1502
|
+
});
|
|
1503
|
+
}
|
|
1499
1504
|
return {
|
|
1500
1505
|
action: "error",
|
|
1501
1506
|
result: {
|
|
@@ -84,6 +84,7 @@ export declare const SANDBOX_EXECUTION_DEFAULT_MAX_ATTEMPTS = 2;
|
|
|
84
84
|
* the caller's `maxOutputChars`) is applied first; this bounds even that.
|
|
85
85
|
*/
|
|
86
86
|
export declare const SANDBOX_EXECUTION_MAX_STORED_OUTPUT_CHARS = 200000;
|
|
87
|
+
export declare function ensureTable(): Promise<void>;
|
|
87
88
|
/** Test-only: forget the memoized init so a fresh in-memory DB re-creates. */
|
|
88
89
|
export declare function resetSandboxExecutionsStoreForTests(): void;
|
|
89
90
|
/** Enqueue a new execution row in `queued` state. */
|
|
@@ -40,7 +40,7 @@ export const SANDBOX_EXECUTION_DEFAULT_MAX_ATTEMPTS = 2;
|
|
|
40
40
|
export const SANDBOX_EXECUTION_MAX_STORED_OUTPUT_CHARS = 200_000;
|
|
41
41
|
const TABLE = "sandbox_executions";
|
|
42
42
|
let _initPromise;
|
|
43
|
-
async function ensureTable() {
|
|
43
|
+
export async function ensureTable() {
|
|
44
44
|
if (!_initPromise) {
|
|
45
45
|
_initPromise = _doEnsureTable().catch((err) => {
|
|
46
46
|
// Don't cache the rejection — let the next caller retry a fresh init.
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* state hasn't changed; expired rows are purged opportunistically.
|
|
15
15
|
*/
|
|
16
16
|
import type { AwarenessEntry } from "./awareness.js";
|
|
17
|
+
export declare function ensureTable(): Promise<void>;
|
|
17
18
|
/**
|
|
18
19
|
* Mirror a client's awareness state to SQL. Throttled: unchanged state is
|
|
19
20
|
* rewritten at most every {@link WRITE_THROTTLE_MS} (to refresh last_seen).
|
|
@@ -22,7 +22,7 @@ const WRITE_THROTTLE_MS = 2_000;
|
|
|
22
22
|
/** Minimum interval between opportunistic purges per document. */
|
|
23
23
|
const PURGE_INTERVAL_MS = 30_000;
|
|
24
24
|
let _initPromise;
|
|
25
|
-
async function ensureTable() {
|
|
25
|
+
export async function ensureTable() {
|
|
26
26
|
if (!_initPromise) {
|
|
27
27
|
_initPromise = (async () => {
|
|
28
28
|
const client = getDbExec();
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
-
error?: undefined;
|
|
66
65
|
states: {
|
|
67
66
|
clientId: number;
|
|
68
67
|
state: string;
|
|
69
68
|
}[];
|
|
69
|
+
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
-
error?: undefined;
|
|
81
80
|
users: {
|
|
82
81
|
clientId: number;
|
|
83
82
|
lastSeen: number;
|
|
84
83
|
}[];
|
|
84
|
+
error?: undefined;
|
|
85
85
|
}>>;
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
error: string;
|
|
30
29
|
ok?: undefined;
|
|
30
|
+
error: string;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
package/dist/collab/storage.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Uses a framework-level `_collab_docs` table (TEXT columns with base64
|
|
5
5
|
* encoding for binary Yjs state) that works across SQLite and Postgres.
|
|
6
6
|
*/
|
|
7
|
+
export declare function ensureTable(): Promise<void>;
|
|
7
8
|
export interface YDocStateRecord {
|
|
8
9
|
state: Uint8Array;
|
|
9
10
|
version: number;
|
package/dist/collab/storage.js
CHANGED
|
@@ -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/db/client.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from "path";
|
|
1
2
|
/**
|
|
2
3
|
* Central database client abstraction.
|
|
3
4
|
*
|
|
@@ -8,7 +9,7 @@
|
|
|
8
9
|
* (dynamic import) so this module can be loaded in any runtime (Node.js,
|
|
9
10
|
* Cloudflare Workers, edge) without failing on missing native deps.
|
|
10
11
|
*/
|
|
11
|
-
import
|
|
12
|
+
import { isMigrationAuthorizedRuntime } from "./migration-runtime.js";
|
|
12
13
|
import { beginDatabaseOperation, recordDatabaseRetry, } from "./request-telemetry.js";
|
|
13
14
|
const recyclingPostgresPools = new WeakSet();
|
|
14
15
|
const loggedNeonPools = new WeakSet();
|
|
@@ -803,9 +804,8 @@ export function isSchemaMutationStatement(statement) {
|
|
|
803
804
|
* is the only supported production opt-in.
|
|
804
805
|
*/
|
|
805
806
|
export function assertSchemaMutationAllowed(statement) {
|
|
806
|
-
const migrationRuntime = globalThis.__AGENT_NATIVE_MIGRATION_RUNTIME__ === true;
|
|
807
807
|
if (isProductionServerlessFunctionRuntime() &&
|
|
808
|
-
!
|
|
808
|
+
!isMigrationAuthorizedRuntime() &&
|
|
809
809
|
isSchemaMutationStatement(statement)) {
|
|
810
810
|
throw new Error("Schema mutation attempted in a production serverless request. Run migrations in the release job instead.");
|
|
811
811
|
}
|
package/dist/db/ddl-guard.js
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
* behaviour there.
|
|
30
30
|
*/
|
|
31
31
|
import { getDbExec, isPostgres, isProductionServerlessFunctionRuntime, } from "./client.js";
|
|
32
|
+
import { isMigrationAuthorizedRuntime } from "./migration-runtime.js";
|
|
32
33
|
const PLAIN_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
33
34
|
/**
|
|
34
35
|
* Skip on-demand schema DDL entirely. For deployments that run real migrations,
|
|
@@ -45,6 +46,13 @@ const PLAIN_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
|
45
46
|
* down the DDL path this flag exists to avoid.
|
|
46
47
|
*/
|
|
47
48
|
function schemaEnsureDisabled() {
|
|
49
|
+
// The release runner is the deployment that OWNS schema creation, so it is the
|
|
50
|
+
// one caller that must never be skipped. Without this, the skip below applies
|
|
51
|
+
// to `migrate:production` too — the Netlify build environment also sets
|
|
52
|
+
// `NETLIFY=true` — and the release step reports success having created
|
|
53
|
+
// nothing.
|
|
54
|
+
if (isMigrationAuthorizedRuntime())
|
|
55
|
+
return false;
|
|
48
56
|
if (isProductionServerlessFunctionRuntime())
|
|
49
57
|
return true;
|
|
50
58
|
const raw = process.env.AGENT_NATIVE_SKIP_ENSURE_TABLES?.trim();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration duty: the process-local claim that the current call is allowed to
|
|
3
|
+
* create or alter schema.
|
|
4
|
+
*
|
|
5
|
+
* Its own module, and deliberately dependency-free, because both `./client.js`
|
|
6
|
+
* and `./ddl-guard.js` need to read it. Putting the reader on `client.js` would
|
|
7
|
+
* mean every `vi.mock("../db/client.js")` in the codebase has to stub one more
|
|
8
|
+
* export to keep `ensureTable()` working — the exact coupling `ddl-guard.ts`
|
|
9
|
+
* was split out to avoid.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* A runtime that is ALLOWED to migrate: release scripts, scheduled jobs, and
|
|
13
|
+
* durable background workers, which are off the request path and may take as
|
|
14
|
+
* long as they need. Claimed with {@link withMigrationRuntime}.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isMigrationAuthorizedRuntime(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Run an explicit release-time migration job with migration duty enabled.
|
|
19
|
+
*
|
|
20
|
+
* The flag is process-local and restored even when the job fails, so a build
|
|
21
|
+
* step can opt in without creating a permanent escape hatch for request code.
|
|
22
|
+
*/
|
|
23
|
+
export declare function withMigrationRuntime<T>(run: () => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration duty: the process-local claim that the current call is allowed to
|
|
3
|
+
* create or alter schema.
|
|
4
|
+
*
|
|
5
|
+
* Its own module, and deliberately dependency-free, because both `./client.js`
|
|
6
|
+
* and `./ddl-guard.js` need to read it. Putting the reader on `client.js` would
|
|
7
|
+
* mean every `vi.mock("../db/client.js")` in the codebase has to stub one more
|
|
8
|
+
* export to keep `ensureTable()` working — the exact coupling `ddl-guard.ts`
|
|
9
|
+
* was split out to avoid.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* A runtime that is ALLOWED to migrate: release scripts, scheduled jobs, and
|
|
13
|
+
* durable background workers, which are off the request path and may take as
|
|
14
|
+
* long as they need. Claimed with {@link withMigrationRuntime}.
|
|
15
|
+
*/
|
|
16
|
+
export function isMigrationAuthorizedRuntime() {
|
|
17
|
+
return (globalThis
|
|
18
|
+
.__AGENT_NATIVE_MIGRATION_RUNTIME__ === true);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Run an explicit release-time migration job with migration duty enabled.
|
|
22
|
+
*
|
|
23
|
+
* The flag is process-local and restored even when the job fails, so a build
|
|
24
|
+
* step can opt in without creating a permanent escape hatch for request code.
|
|
25
|
+
*/
|
|
26
|
+
export async function withMigrationRuntime(run) {
|
|
27
|
+
const runtime = globalThis;
|
|
28
|
+
const previous = runtime.__AGENT_NATIVE_MIGRATION_RUNTIME__;
|
|
29
|
+
runtime.__AGENT_NATIVE_MIGRATION_RUNTIME__ = true;
|
|
30
|
+
try {
|
|
31
|
+
return await run();
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
if (previous === undefined) {
|
|
35
|
+
delete runtime.__AGENT_NATIVE_MIGRATION_RUNTIME__;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
runtime.__AGENT_NATIVE_MIGRATION_RUNTIME__ = previous;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|