@agent-native/core 0.161.23 → 0.162.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 +1 -1
- package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +18 -2
- package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/calendar/server/handlers/google-auth.ts +1 -8
- package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +88 -35
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +36 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +4 -3
- package/corpus/templates/clips/desktop/src/app.tsx +30 -40
- package/corpus/templates/clips/desktop/src/components/MicOffConfirmation.tsx +47 -0
- package/corpus/templates/clips/desktop/src/styles.css +110 -0
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +114 -7
- package/corpus/templates/clips/shared/recording-capture.ts +18 -13
- package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +3 -5
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +0 -3
- package/corpus/templates/content/app/components/editor/NotionConflictBanner.tsx +0 -4
- package/corpus/templates/content/app/components/editor/NotionSyncBar.tsx +4 -1
- package/corpus/templates/content/app/hooks/use-notion.ts +17 -15
- package/corpus/templates/crm/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/design/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/dispatch/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/factory/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/macros/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +18 -3
- package/corpus/templates/mail/server/handlers/google-auth.ts +1 -8
- package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +4 -0
- package/corpus/templates/slides/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/slides/actions/_await-fit-check.ts +30 -5
- package/corpus/templates/slides/actions/add-slide.ts +6 -2
- package/corpus/templates/slides/actions/create-deck.ts +2 -1
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +34 -1
- package/corpus/templates/slides/app/routes/p.$id.tsx +3 -1
- package/corpus/templates/slides/changelog/2026-08-18-generated-slides-preserve-speaker-notes.md +6 -0
- package/corpus/templates/slides/server/handlers/assets.ts +23 -12
- package/corpus/templates/slides/server/handlers/design-system-decode-job-status.ts +15 -6
- package/corpus/templates/slides/server/handlers/design-system-upload-start.ts +15 -6
- package/corpus/templates/slides/server/handlers/index-design-system-sources.ts +34 -19
- package/corpus/templates/slides/server/handlers/share.ts +1 -1
- package/corpus/templates/slides/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/slides/server/routes/api/deck-agent-context.json.get.ts +1 -1
- package/corpus/templates/slides/server/routes/api/exports/[filename].get.ts +9 -3
- package/corpus/templates/slides/server/routes/api/exports/google-slides.post.ts +12 -5
- package/corpus/templates/slides/server/routes/api/exports/html.post.ts +9 -7
- package/corpus/templates/slides/server/routes/api/exports/pptx.post.ts +9 -7
- package/corpus/templates/slides/shared/api.ts +7 -1
- package/corpus/templates/tasks/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/agent/engine/translate-anthropic.js +27 -2
- package/dist/agent/production-agent.d.ts +2 -2
- package/dist/agent/production-agent.js +16 -8
- package/dist/agent/thread-data-builder.d.ts +1 -0
- package/dist/agent/thread-data-builder.js +6 -4
- package/dist/agent/tool-approval-store.d.ts +10 -1
- package/dist/agent/tool-approval-store.js +19 -2
- package/dist/agent/types.d.ts +9 -0
- package/dist/client/AssistantChat.js +14 -6
- package/dist/client/EnvironmentBadge.d.ts +15 -0
- package/dist/client/EnvironmentBadge.js +79 -0
- package/dist/client/MultiTabAssistantChat.js +73 -17
- package/dist/client/agent-chat-adapter.js +11 -1
- package/dist/client/api-path.js +14 -1
- package/dist/client/app-providers.js +2 -1
- package/dist/client/chat/tool-call-display.d.ts +12 -2
- package/dist/client/chat/tool-call-display.js +17 -7
- package/dist/client/chat/widgets/WorkspaceFileWidget.js +1 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.d.ts +6 -0
- package/dist/client/chat/widgets/builtin-tool-renderers.js +19 -0
- package/dist/client/onboarding/FirstRunOnboarding.js +46 -32
- package/dist/client/onboarding/use-onboarding.d.ts +8 -1
- package/dist/client/onboarding/use-onboarding.js +22 -7
- package/dist/client/session-replay.js +58 -15
- package/dist/client/settings/SettingsTabsPage.js +19 -6
- package/dist/client/sse-event-processor.d.ts +7 -0
- package/dist/client/sse-event-processor.js +4 -1
- package/dist/client/ui/index.d.ts +1 -0
- package/dist/client/ui/index.js +1 -0
- package/dist/client/use-action.js +26 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/config.d.ts +15 -0
- package/dist/config.js +53 -0
- package/dist/extensions/fetch-tool.js +8 -2
- package/dist/mcp/embed-app.js +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/index.d.ts +10 -0
- package/dist/provider-api/index.js +45 -9
- package/dist/server/auth.js +10 -3
- package/dist/server/poll.js +7 -3
- package/dist/server/sentry.d.ts +1 -1
- package/dist/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/vite/client.d.ts +5 -0
- package/dist/vite/client.js +64 -2
- package/dist/workspace-files/actions.d.ts +1 -8
- package/dist/workspace-files/actions.js +5 -21
- package/dist/workspace-files/index.d.ts +1 -1
- package/dist/workspace-files/index.js +1 -1
- package/dist/workspace-files/store.d.ts +18 -0
- package/dist/workspace-files/store.js +24 -3
- package/package.json +3 -3
- package/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
|
@@ -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;
|
|
65
66
|
states: {
|
|
66
67
|
clientId: number;
|
|
67
68
|
state: string;
|
|
68
69
|
}[];
|
|
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;
|
|
80
81
|
users: {
|
|
81
82
|
clientId: number;
|
|
82
83
|
lastSeen: number;
|
|
83
84
|
}[];
|
|
84
|
-
error?: undefined;
|
|
85
85
|
}>>;
|
|
@@ -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
|
-
error: string;
|
|
17
16
|
ok?: undefined;
|
|
17
|
+
error: string;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
package/dist/config.d.ts
CHANGED
|
@@ -38,6 +38,11 @@ export interface AgentNativeRuntimeConfig {
|
|
|
38
38
|
database?: AgentNativeRuntimeDatabaseConfig;
|
|
39
39
|
environment?: AgentNativeRuntimeEnvironmentConfig;
|
|
40
40
|
}
|
|
41
|
+
export type AgentNativeDeploymentEnvironment = "local" | "beta" | "production" | "preview";
|
|
42
|
+
export interface AgentNativeDeploymentConfig {
|
|
43
|
+
/** The release lane that produced the currently running client bundle. */
|
|
44
|
+
environment?: AgentNativeDeploymentEnvironment;
|
|
45
|
+
}
|
|
41
46
|
export interface AgentNativeDiagnosticsConfig {
|
|
42
47
|
/** Fail a production Vite build when runtime configuration has issues. */
|
|
43
48
|
failOnBuild?: boolean;
|
|
@@ -73,6 +78,7 @@ export interface AgentNativeConfig {
|
|
|
73
78
|
version?: typeof AGENT_NATIVE_CONFIG_VERSION;
|
|
74
79
|
onboarding?: AgentNativeOnboardingConfig;
|
|
75
80
|
runtime?: AgentNativeRuntimeConfig;
|
|
81
|
+
deployment?: AgentNativeDeploymentConfig;
|
|
76
82
|
diagnostics?: AgentNativeDiagnosticsConfig;
|
|
77
83
|
instructions?: AgentNativeInstructionsConfig;
|
|
78
84
|
translations?: AgentNativeTranslationsConfig;
|
|
@@ -99,3 +105,12 @@ export declare function normalizeAgentNativeConfig(input: unknown, source?: stri
|
|
|
99
105
|
export declare function mergeAgentNativeConfigs(base: AgentNativeConfig, override: AgentNativeConfig): AgentNativeConfig;
|
|
100
106
|
export declare function resolveAgentNativeConfig(input: AgentNativeConfigInput | undefined, context: AgentNativeConfigContext): AgentNativeConfig;
|
|
101
107
|
export declare function resolveFirstRunOnboardingMode(setting: AgentNativeFirstRunOnboardingSetting, context: AgentNativeConfigContext): AgentNativeFirstRunOnboardingMode;
|
|
108
|
+
export declare function isAgentNativeDeploymentEnvironment(value: unknown): value is AgentNativeDeploymentEnvironment;
|
|
109
|
+
/**
|
|
110
|
+
* Resolve the public deployment lane from hosting facts at build time.
|
|
111
|
+
*
|
|
112
|
+
* Netlify exposes `CONTEXT` and `BRANCH` to builds. Keeping this inference in
|
|
113
|
+
* the Vite/config boundary means browser code consumes typed public config and
|
|
114
|
+
* never parses process.env itself.
|
|
115
|
+
*/
|
|
116
|
+
export declare function inferAgentNativeDeploymentEnvironment(env: Record<string, string | undefined>, mode?: string): AgentNativeDeploymentEnvironment | undefined;
|
package/dist/config.js
CHANGED
|
@@ -26,6 +26,7 @@ export function normalizeAgentNativeConfig(input, source = "agent-native config"
|
|
|
26
26
|
}
|
|
27
27
|
const onboardingValue = input.onboarding;
|
|
28
28
|
const runtimeValue = input.runtime;
|
|
29
|
+
const deploymentValue = input.deployment;
|
|
29
30
|
const diagnosticsValue = input.diagnostics;
|
|
30
31
|
const instructionsValue = input.instructions;
|
|
31
32
|
const translationsValue = input.translations;
|
|
@@ -46,6 +47,9 @@ export function normalizeAgentNativeConfig(input, source = "agent-native config"
|
|
|
46
47
|
if (runtimeValue !== undefined) {
|
|
47
48
|
normalized.runtime = normalizeRuntimeConfig(runtimeValue, `${source}.runtime`);
|
|
48
49
|
}
|
|
50
|
+
if (deploymentValue !== undefined) {
|
|
51
|
+
normalized.deployment = normalizeDeploymentConfig(deploymentValue, `${source}.deployment`);
|
|
52
|
+
}
|
|
49
53
|
if (diagnosticsValue !== undefined) {
|
|
50
54
|
normalized.diagnostics = normalizeDiagnosticsConfig(diagnosticsValue, `${source}.diagnostics`);
|
|
51
55
|
}
|
|
@@ -101,6 +105,12 @@ export function mergeAgentNativeConfigs(base, override) {
|
|
|
101
105
|
: undefined,
|
|
102
106
|
}
|
|
103
107
|
: undefined,
|
|
108
|
+
deployment: base.deployment || override.deployment
|
|
109
|
+
? {
|
|
110
|
+
...base.deployment,
|
|
111
|
+
...override.deployment,
|
|
112
|
+
}
|
|
113
|
+
: undefined,
|
|
104
114
|
diagnostics: base.diagnostics || override.diagnostics
|
|
105
115
|
? {
|
|
106
116
|
...base.diagnostics,
|
|
@@ -205,6 +215,18 @@ function normalizeRuntimeConfig(value, source) {
|
|
|
205
215
|
}
|
|
206
216
|
return result;
|
|
207
217
|
}
|
|
218
|
+
function normalizeDeploymentConfig(value, source) {
|
|
219
|
+
if (!isRecord(value)) {
|
|
220
|
+
throw new Error(`${source} must be an object`);
|
|
221
|
+
}
|
|
222
|
+
const environment = value.environment;
|
|
223
|
+
if (environment === undefined)
|
|
224
|
+
return {};
|
|
225
|
+
if (!isAgentNativeDeploymentEnvironment(environment)) {
|
|
226
|
+
throw new Error(`${source}.environment must be "local", "beta", "production", or "preview"`);
|
|
227
|
+
}
|
|
228
|
+
return { environment };
|
|
229
|
+
}
|
|
208
230
|
function normalizeDiagnosticsConfig(value, source) {
|
|
209
231
|
if (!isRecord(value)) {
|
|
210
232
|
throw new Error(`${source} must be an object`);
|
|
@@ -338,6 +360,37 @@ function isAgentNativeHarnessRuntime(value) {
|
|
|
338
360
|
value === "pi" ||
|
|
339
361
|
value === "opencode");
|
|
340
362
|
}
|
|
363
|
+
export function isAgentNativeDeploymentEnvironment(value) {
|
|
364
|
+
return (value === "local" ||
|
|
365
|
+
value === "beta" ||
|
|
366
|
+
value === "production" ||
|
|
367
|
+
value === "preview");
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Resolve the public deployment lane from hosting facts at build time.
|
|
371
|
+
*
|
|
372
|
+
* Netlify exposes `CONTEXT` and `BRANCH` to builds. Keeping this inference in
|
|
373
|
+
* the Vite/config boundary means browser code consumes typed public config and
|
|
374
|
+
* never parses process.env itself.
|
|
375
|
+
*/
|
|
376
|
+
export function inferAgentNativeDeploymentEnvironment(env, mode) {
|
|
377
|
+
const context = env.CONTEXT?.trim().toLowerCase();
|
|
378
|
+
const branch = env.BRANCH?.trim().toLowerCase();
|
|
379
|
+
if (branch === "production" || context === "production") {
|
|
380
|
+
return "production";
|
|
381
|
+
}
|
|
382
|
+
if (branch === "beta" || (context === "branch-deploy" && branch === "main")) {
|
|
383
|
+
return "beta";
|
|
384
|
+
}
|
|
385
|
+
if (context === "deploy-preview" ||
|
|
386
|
+
context === "branch-deploy" ||
|
|
387
|
+
branch?.startsWith("deploy-preview")) {
|
|
388
|
+
return "preview";
|
|
389
|
+
}
|
|
390
|
+
if (mode === "development")
|
|
391
|
+
return "local";
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
341
394
|
function isRecord(value) {
|
|
342
395
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
343
396
|
}
|
|
@@ -306,7 +306,7 @@ export function createFetchToolEntry(opts = {}) {
|
|
|
306
306
|
// saveToFile: write full body to workspace and return compact summary.
|
|
307
307
|
if (saveToFilePath) {
|
|
308
308
|
try {
|
|
309
|
-
const { writeWorkspaceFile, SAVE_TO_FILE_MAX_BYTES } = await import("../workspace-files/store.js");
|
|
309
|
+
const { writeWorkspaceFile, SAVE_TO_FILE_MAX_BYTES, isScratchWorkspacePath, toWorkspaceFileCard, } = await import("../workspace-files/store.js");
|
|
310
310
|
const { getRequestOrgId, getRequestUserEmail } = await import("../server/request-context.js");
|
|
311
311
|
const orgId = getRequestOrgId();
|
|
312
312
|
const email = getRequestUserEmail();
|
|
@@ -317,7 +317,7 @@ export function createFetchToolEntry(opts = {}) {
|
|
|
317
317
|
: null;
|
|
318
318
|
if (!scope)
|
|
319
319
|
throw new Error("No authenticated context for saveToFile");
|
|
320
|
-
await writeWorkspaceFile(scope, saveToFilePath, body, contentType, {
|
|
320
|
+
const meta = await writeWorkspaceFile(scope, saveToFilePath, body, contentType, {
|
|
321
321
|
maxFileBytes: SAVE_TO_FILE_MAX_BYTES,
|
|
322
322
|
});
|
|
323
323
|
const bytes = Buffer.byteLength(body, "utf8");
|
|
@@ -330,6 +330,12 @@ export function createFetchToolEntry(opts = {}) {
|
|
|
330
330
|
contentType,
|
|
331
331
|
responseMode: processedMode,
|
|
332
332
|
preview: preview.length < displayBody.length ? `${preview}…` : preview,
|
|
333
|
+
// A durable (non-scratch) file renders a download card the
|
|
334
|
+
// moment it's created — no separate show-workspace-file call
|
|
335
|
+
// needed to get a link.
|
|
336
|
+
...(isScratchWorkspacePath(saveToFilePath)
|
|
337
|
+
? {}
|
|
338
|
+
: { file: toWorkspaceFileCard(meta) }),
|
|
333
339
|
});
|
|
334
340
|
}
|
|
335
341
|
catch (saveErr) {
|
package/dist/mcp/embed-app.js
CHANGED
|
@@ -735,7 +735,7 @@ export function embedApp(options = {}) {
|
|
|
735
735
|
|
|
736
736
|
function stripDevOnlyModuleImports(code) {
|
|
737
737
|
return String(code).replace(
|
|
738
|
-
/\\bimport\\s+(?:[^"']+\\s+from\\s+)?["'][^"']*(?:virtual:react-router\\/inject-hmr-runtime|__x00__virtual:react-router\\/inject-hmr-runtime)[^"']*["']\\s*;?/g,
|
|
738
|
+
/\\bimport\\s+(?:[^"']+\\s+from\\s+)?["'][^"']*(?:virtual:react-router\\/(?:inject-)?hmr-runtime|__x00__virtual:react-router\\/(?:inject-)?hmr-runtime)[^"']*["']\\s*;?/g,
|
|
739
739
|
""
|
|
740
740
|
);
|
|
741
741
|
}
|
|
@@ -75,10 +75,10 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
75
75
|
user: "user";
|
|
76
76
|
}>>;
|
|
77
77
|
}, z.core.$strip>>, {
|
|
78
|
-
message?: undefined;
|
|
79
78
|
id?: undefined;
|
|
79
|
+
provider?: undefined;
|
|
80
80
|
deleted?: undefined;
|
|
81
|
-
|
|
81
|
+
message?: undefined;
|
|
82
82
|
providers: {
|
|
83
83
|
id: string;
|
|
84
84
|
label: string;
|
|
@@ -89,45 +89,45 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
89
89
|
updatedAt: number;
|
|
90
90
|
}[];
|
|
91
91
|
count: number;
|
|
92
|
-
|
|
92
|
+
found?: undefined;
|
|
93
93
|
registered?: undefined;
|
|
94
94
|
label?: undefined;
|
|
95
95
|
} | {
|
|
96
|
-
message?: undefined;
|
|
97
|
-
count?: undefined;
|
|
98
96
|
id?: undefined;
|
|
99
97
|
deleted?: undefined;
|
|
98
|
+
message?: undefined;
|
|
100
99
|
providers?: undefined;
|
|
100
|
+
count?: undefined;
|
|
101
101
|
found: boolean;
|
|
102
102
|
provider: import("../custom-registry.js").CustomProviderConfig;
|
|
103
103
|
registered?: undefined;
|
|
104
104
|
label?: undefined;
|
|
105
105
|
} | {
|
|
106
|
-
|
|
107
|
-
count?: undefined;
|
|
106
|
+
provider?: undefined;
|
|
108
107
|
deleted?: undefined;
|
|
108
|
+
message?: undefined;
|
|
109
109
|
providers?: undefined;
|
|
110
|
-
|
|
110
|
+
count?: undefined;
|
|
111
111
|
found: boolean;
|
|
112
112
|
id: string;
|
|
113
113
|
registered?: undefined;
|
|
114
114
|
label?: undefined;
|
|
115
115
|
} | {
|
|
116
|
+
provider?: undefined;
|
|
116
117
|
message?: undefined;
|
|
118
|
+
providers?: undefined;
|
|
117
119
|
count?: undefined;
|
|
118
120
|
found?: undefined;
|
|
119
|
-
providers?: undefined;
|
|
120
|
-
provider?: undefined;
|
|
121
121
|
deleted: boolean;
|
|
122
122
|
id: string;
|
|
123
123
|
registered?: undefined;
|
|
124
124
|
label?: undefined;
|
|
125
125
|
} | {
|
|
126
|
-
|
|
126
|
+
provider?: undefined;
|
|
127
127
|
deleted?: undefined;
|
|
128
|
-
found?: undefined;
|
|
129
128
|
providers?: undefined;
|
|
130
|
-
|
|
129
|
+
count?: undefined;
|
|
130
|
+
found?: undefined;
|
|
131
131
|
registered: boolean;
|
|
132
132
|
id: string;
|
|
133
133
|
label: string;
|
|
@@ -312,9 +312,6 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
|
|
|
312
312
|
scope?: "org" | "user" | undefined;
|
|
313
313
|
}, {
|
|
314
314
|
id?: undefined;
|
|
315
|
-
deleted?: undefined;
|
|
316
|
-
provider?: undefined;
|
|
317
|
-
found?: undefined;
|
|
318
315
|
providers: {
|
|
319
316
|
id: string;
|
|
320
317
|
label: string;
|
|
@@ -325,45 +322,48 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
|
|
|
325
322
|
updatedAt: number;
|
|
326
323
|
}[];
|
|
327
324
|
count: number;
|
|
325
|
+
provider?: undefined;
|
|
326
|
+
found?: undefined;
|
|
327
|
+
deleted?: undefined;
|
|
328
328
|
registered?: undefined;
|
|
329
329
|
label?: undefined;
|
|
330
330
|
message?: undefined;
|
|
331
331
|
} | {
|
|
332
332
|
id?: undefined;
|
|
333
|
-
deleted?: undefined;
|
|
334
333
|
providers?: undefined;
|
|
335
334
|
count?: undefined;
|
|
336
335
|
found: boolean;
|
|
337
336
|
provider: import("../custom-registry.js").CustomProviderConfig;
|
|
337
|
+
deleted?: undefined;
|
|
338
338
|
registered?: undefined;
|
|
339
339
|
label?: undefined;
|
|
340
340
|
message?: undefined;
|
|
341
341
|
} | {
|
|
342
|
-
deleted?: undefined;
|
|
343
|
-
provider?: undefined;
|
|
344
342
|
providers?: undefined;
|
|
345
343
|
count?: undefined;
|
|
344
|
+
provider?: undefined;
|
|
346
345
|
found: boolean;
|
|
347
346
|
id: string;
|
|
347
|
+
deleted?: undefined;
|
|
348
348
|
registered?: undefined;
|
|
349
349
|
label?: undefined;
|
|
350
350
|
message?: undefined;
|
|
351
351
|
} | {
|
|
352
|
-
provider?: undefined;
|
|
353
|
-
found?: undefined;
|
|
354
352
|
providers?: undefined;
|
|
355
353
|
count?: undefined;
|
|
354
|
+
provider?: undefined;
|
|
355
|
+
found?: undefined;
|
|
356
356
|
deleted: boolean;
|
|
357
357
|
id: string;
|
|
358
358
|
registered?: undefined;
|
|
359
359
|
label?: undefined;
|
|
360
360
|
message?: undefined;
|
|
361
361
|
} | {
|
|
362
|
-
deleted?: undefined;
|
|
363
|
-
provider?: undefined;
|
|
364
|
-
found?: undefined;
|
|
365
362
|
providers?: undefined;
|
|
366
363
|
count?: undefined;
|
|
364
|
+
provider?: undefined;
|
|
365
|
+
found?: undefined;
|
|
366
|
+
deleted?: undefined;
|
|
367
367
|
registered: boolean;
|
|
368
368
|
id: string;
|
|
369
369
|
label: string;
|
|
@@ -286,6 +286,16 @@ export interface ProviderApiConfig {
|
|
|
286
286
|
accessErrorGuidance?: string;
|
|
287
287
|
corpusRecipes?: readonly ProviderApiCorpusRecipe[];
|
|
288
288
|
templateUses?: readonly WorkspaceConnectionTemplateUse[];
|
|
289
|
+
/**
|
|
290
|
+
* Some provider APIs (Slack's Web API is the documented case) answer every
|
|
291
|
+
* request with HTTP 200 and encode the real outcome as a boolean field in
|
|
292
|
+
* the JSON body instead. When set, a response with this field explicitly
|
|
293
|
+
* `false` is treated as a failed request — `response.ok` is flipped to
|
|
294
|
+
* `false` — so a caller (or the agent) that only checks the transport-level
|
|
295
|
+
* `ok`, the same signal every other provider uses for success, can't
|
|
296
|
+
* mistake a rejected send for a delivered one.
|
|
297
|
+
*/
|
|
298
|
+
bodyOkField?: string;
|
|
289
299
|
}
|
|
290
300
|
export interface ProviderApiPlaceholder {
|
|
291
301
|
name: string;
|
|
@@ -991,6 +991,11 @@ const PROVIDER_CONFIGS = {
|
|
|
991
991
|
id: "slack",
|
|
992
992
|
label: "Slack Web API",
|
|
993
993
|
defaultBaseUrl: "https://slack.com/api",
|
|
994
|
+
// Slack answers every call with HTTP 200, success or failure — see
|
|
995
|
+
// bodyOkField's doc comment. Without this, a rejected chat.postMessage
|
|
996
|
+
// (not_in_channel, channel_not_found, msg_too_long, …) looks identical to
|
|
997
|
+
// a delivered one at the transport level.
|
|
998
|
+
bodyOkField: "ok",
|
|
994
999
|
auth: {
|
|
995
1000
|
type: "bearer",
|
|
996
1001
|
keys: ["SLACK_BOT_TOKEN"],
|
|
@@ -1301,7 +1306,7 @@ export async function executeProviderApiRequest(args, runtime) {
|
|
|
1301
1306
|
body: pageBody,
|
|
1302
1307
|
headers,
|
|
1303
1308
|
});
|
|
1304
|
-
const resp = await fetchWithTimeout(pageUrl.href, {
|
|
1309
|
+
const resp = applyBodyEnvelopeOutcome(await fetchWithTimeout(pageUrl.href, {
|
|
1305
1310
|
method,
|
|
1306
1311
|
headers,
|
|
1307
1312
|
body: pageBody,
|
|
@@ -1315,7 +1320,7 @@ export async function executeProviderApiRequest(args, runtime) {
|
|
|
1315
1320
|
target: describeProviderRequestTarget(pageUrl.href, auth.secretValues),
|
|
1316
1321
|
requestKey,
|
|
1317
1322
|
},
|
|
1318
|
-
});
|
|
1323
|
+
}), config);
|
|
1319
1324
|
return {
|
|
1320
1325
|
text: resp.text ??
|
|
1321
1326
|
(resp.json !== undefined ? JSON.stringify(resp.json) : ""),
|
|
@@ -1347,7 +1352,7 @@ export async function executeProviderApiRequest(args, runtime) {
|
|
|
1347
1352
|
body,
|
|
1348
1353
|
headers,
|
|
1349
1354
|
});
|
|
1350
|
-
const response = await fetchWithTimeout(url.href, {
|
|
1355
|
+
const response = applyBodyEnvelopeOutcome(await fetchWithTimeout(url.href, {
|
|
1351
1356
|
method,
|
|
1352
1357
|
headers,
|
|
1353
1358
|
body,
|
|
@@ -1361,12 +1366,12 @@ export async function executeProviderApiRequest(args, runtime) {
|
|
|
1361
1366
|
target: describeProviderRequestTarget(url.href, auth.secretValues),
|
|
1362
1367
|
requestKey,
|
|
1363
1368
|
},
|
|
1364
|
-
});
|
|
1369
|
+
}), config);
|
|
1365
1370
|
// saveToFile: write full body to workspace file and return compact summary.
|
|
1366
1371
|
if (args.saveToFile) {
|
|
1367
1372
|
const rawText = response.text ??
|
|
1368
1373
|
(response.json !== undefined ? JSON.stringify(response.json) : "");
|
|
1369
|
-
const saved = (await handleSaveToFile(args.saveToFile, rawText, response.contentType, response.status));
|
|
1374
|
+
const saved = (await handleSaveToFile(args.saveToFile, rawText, response.contentType, response.status, response.ok));
|
|
1370
1375
|
return {
|
|
1371
1376
|
provider: { id: config.id, label: config.label },
|
|
1372
1377
|
request: {
|
|
@@ -2119,7 +2124,7 @@ async function executeCustomProviderApiRequest(args, customConfig, runtime) {
|
|
|
2119
2124
|
if (args.saveToFile) {
|
|
2120
2125
|
const rawText = response.text ??
|
|
2121
2126
|
(response.json !== undefined ? JSON.stringify(response.json) : "");
|
|
2122
|
-
const saved = (await handleSaveToFile(args.saveToFile, rawText, response.contentType, response.status));
|
|
2127
|
+
const saved = (await handleSaveToFile(args.saveToFile, rawText, response.contentType, response.status, response.ok));
|
|
2123
2128
|
return {
|
|
2124
2129
|
provider: {
|
|
2125
2130
|
id: customConfig.id,
|
|
@@ -3817,6 +3822,31 @@ function providerQuotaExhaustedResponse(detail) {
|
|
|
3817
3822
|
},
|
|
3818
3823
|
};
|
|
3819
3824
|
}
|
|
3825
|
+
/**
|
|
3826
|
+
* Flip transport-level `ok` to `false` when the provider's own success field
|
|
3827
|
+
* (config.bodyOkField) says the call failed. See ProviderApiConfig's
|
|
3828
|
+
* bodyOkField doc comment: Slack answers every request with HTTP 200, so
|
|
3829
|
+
* without this a rejected send is indistinguishable from a delivered one to
|
|
3830
|
+
* any caller — including the agent — that trusts `response.ok`.
|
|
3831
|
+
*/
|
|
3832
|
+
function applyBodyEnvelopeOutcome(response, config) {
|
|
3833
|
+
const field = config.bodyOkField;
|
|
3834
|
+
if (!field || !response.ok)
|
|
3835
|
+
return response;
|
|
3836
|
+
const body = response.json;
|
|
3837
|
+
if (!body || typeof body !== "object" || Array.isArray(body))
|
|
3838
|
+
return response;
|
|
3839
|
+
if (body[field] !== false)
|
|
3840
|
+
return response;
|
|
3841
|
+
const error = stringOrNull(body.error);
|
|
3842
|
+
return {
|
|
3843
|
+
...response,
|
|
3844
|
+
ok: false,
|
|
3845
|
+
statusText: error
|
|
3846
|
+
? `${response.statusText} (${config.label} reported ${field}: false — ${error})`
|
|
3847
|
+
: `${response.statusText} (${config.label} reported ${field}: false)`,
|
|
3848
|
+
};
|
|
3849
|
+
}
|
|
3820
3850
|
async function fetchProviderResponse(url, fetchOptions, options) {
|
|
3821
3851
|
const startedAt = Date.now();
|
|
3822
3852
|
const res = await fetch(url, fetchOptions);
|
|
@@ -4000,8 +4030,8 @@ function dotGet(obj, path) {
|
|
|
4000
4030
|
* Handle saveToFile: write the full provider-api response body to a workspace
|
|
4001
4031
|
* file and return a compact summary.
|
|
4002
4032
|
*/
|
|
4003
|
-
async function handleSaveToFile(filePath, responseText, contentType, status) {
|
|
4004
|
-
const { writeWorkspaceFile, SAVE_TO_FILE_MAX_BYTES: maxSaveBytes } = await import("../workspace-files/store.js");
|
|
4033
|
+
async function handleSaveToFile(filePath, responseText, contentType, status, ok = true) {
|
|
4034
|
+
const { writeWorkspaceFile, SAVE_TO_FILE_MAX_BYTES: maxSaveBytes, isScratchWorkspacePath, toWorkspaceFileCard, } = await import("../workspace-files/store.js");
|
|
4005
4035
|
const { getRequestOrgId, getRequestUserEmail } = await import("../server/request-context.js");
|
|
4006
4036
|
const orgId = getRequestOrgId();
|
|
4007
4037
|
const email = getRequestUserEmail();
|
|
@@ -4014,7 +4044,7 @@ async function handleSaveToFile(filePath, responseText, contentType, status) {
|
|
|
4014
4044
|
throw new Error("saveToFile requires an authenticated request context (no user email or orgId found).");
|
|
4015
4045
|
}
|
|
4016
4046
|
const mimeType = contentType?.split(";")[0].trim() ?? "text/plain";
|
|
4017
|
-
await writeWorkspaceFile(scope, filePath, responseText, mimeType, {
|
|
4047
|
+
const meta = await writeWorkspaceFile(scope, filePath, responseText, mimeType, {
|
|
4018
4048
|
maxFileBytes: maxSaveBytes,
|
|
4019
4049
|
});
|
|
4020
4050
|
const bytes = Buffer.byteLength(responseText, "utf8");
|
|
@@ -4023,9 +4053,15 @@ async function handleSaveToFile(filePath, responseText, contentType, status) {
|
|
|
4023
4053
|
savedToFile: true,
|
|
4024
4054
|
savedTo: filePath,
|
|
4025
4055
|
status,
|
|
4056
|
+
ok,
|
|
4026
4057
|
bytes,
|
|
4027
4058
|
contentType: mimeType,
|
|
4028
4059
|
preview: preview.length < responseText.length ? `${preview}…` : preview,
|
|
4060
|
+
// A durable (non-scratch) file renders a download card the moment it's
|
|
4061
|
+
// created — no separate show-workspace-file call needed to get a link.
|
|
4062
|
+
...(isScratchWorkspacePath(filePath)
|
|
4063
|
+
? {}
|
|
4064
|
+
: { file: toWorkspaceFileCard(meta) }),
|
|
4029
4065
|
};
|
|
4030
4066
|
}
|
|
4031
4067
|
/**
|
package/dist/server/auth.js
CHANGED
|
@@ -636,9 +636,16 @@ async function ensureEmailVerifiedForRedirect(request, response) {
|
|
|
636
636
|
args: [email],
|
|
637
637
|
});
|
|
638
638
|
}
|
|
639
|
-
catch {
|
|
640
|
-
// Better Auth already handled the verification route
|
|
641
|
-
// best-effort
|
|
639
|
+
catch (error) {
|
|
640
|
+
// Better Auth already handled the verification route, so this repair
|
|
641
|
+
// staying best-effort (never blocking the response) is correct. But a
|
|
642
|
+
// failure here must never be silent: "repair didn't run" and "there was
|
|
643
|
+
// nothing to repair" are the same observable outcome to a caller unless
|
|
644
|
+
// this is logged, which is exactly the shape of "clicked the verify
|
|
645
|
+
// link, login still says not verified" (Slack C0ATH3CCZT4, reported
|
|
646
|
+
// 2026-07-31 and 2026-08-05) — this UPDATE is the only place that would
|
|
647
|
+
// show whether Better Auth's own write is failing too.
|
|
648
|
+
captureAuthError(error, { route: "verify-email", email });
|
|
642
649
|
}
|
|
643
650
|
}
|
|
644
651
|
async function emailFromVerificationResponseSession(response) {
|
package/dist/server/poll.js
CHANGED
|
@@ -1506,11 +1506,15 @@ export class AppSyncState {
|
|
|
1506
1506
|
// marker rows back into extension-source events for targeted client
|
|
1507
1507
|
// invalidation while preserving user/org scope.
|
|
1508
1508
|
if (extensionMarkerTs > this.lastExtensionMarkerTs) {
|
|
1509
|
+
// Bound the scan by the watermark instead of reading every marker row
|
|
1510
|
+
// ever written and filtering in memory: this table keeps one row per
|
|
1511
|
+
// session that has ever mutated an extension, so the unbounded read
|
|
1512
|
+
// grows with lifetime users rather than with pending work.
|
|
1509
1513
|
const extensionMarkerResult = await db.execute({
|
|
1510
|
-
sql: "SELECT session_id, value, updated_at FROM application_state WHERE key = ? ORDER BY updated_at ASC",
|
|
1511
|
-
args: [EXTENSION_CHANGE_MARKER_KEY],
|
|
1514
|
+
sql: "SELECT session_id, value, updated_at FROM application_state WHERE key = ? AND updated_at > ? ORDER BY updated_at ASC",
|
|
1515
|
+
args: [EXTENSION_CHANGE_MARKER_KEY, this.lastExtensionMarkerTs],
|
|
1512
1516
|
});
|
|
1513
|
-
const changedExtensionMarkers = extensionMarkerResult.rows
|
|
1517
|
+
const changedExtensionMarkers = extensionMarkerResult.rows;
|
|
1514
1518
|
if (this.lastExtensionMarkerTs > 0) {
|
|
1515
1519
|
this.recordExtensionChanges(changedExtensionMarkers
|
|
1516
1520
|
.map((row) => parseExtensionChangeMarker(row.session_id, row.value))
|
package/dist/server/sentry.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export declare function setSentryRequestContext(ctx: {
|
|
|
57
57
|
* this just records the error for observability.
|
|
58
58
|
*/
|
|
59
59
|
export declare function captureAuthError(error: unknown, context: {
|
|
60
|
-
route: "login" | "signup" | "logout" | "magic-link";
|
|
60
|
+
route: "login" | "signup" | "logout" | "magic-link" | "verify-email";
|
|
61
61
|
email?: string;
|
|
62
62
|
}): string | undefined;
|
|
63
63
|
export interface RouteErrorContext {
|
|
@@ -50,7 +50,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
|
|
|
50
50
|
|
|
51
51
|
For list/sidebar queries, use the same pattern — pass the counter into the queryKey of every list query you want to keep fresh.
|
|
52
52
|
|
|
53
|
-
4. **Fallback** polling calls `/_agent-native/poll?since=N`. It
|
|
53
|
+
4. **Fallback** polling calls `/_agent-native/poll?since=N`. It polls every 2 seconds only while an agent run is in flight; otherwise it idles at 60 seconds whether or not SSE is connected (`SSE_FALLBACK_INTERVAL_MS` and `IDLE_POLL_INTERVAL_MS`, both 60 s). A hidden tab polls no faster than every 10 seconds (`HIDDEN_POLL_INTERVAL_MS`). Polling is the universal serverless fallback: new framework writes are read from the durable `sync_events` log, while the older DB timestamp scan remains as a slower safety net for direct SQL writes and older processes.
|
|
54
54
|
|
|
55
55
|
5. When the agent writes to the database, the version increments, SSE/polling detects it, and React Query refetches the affected queries.
|
|
56
56
|
|
|
@@ -50,7 +50,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
|
|
|
50
50
|
|
|
51
51
|
For list/sidebar queries, use the same pattern — pass the counter into the queryKey of every list query you want to keep fresh.
|
|
52
52
|
|
|
53
|
-
4. **Fallback** polling calls `/_agent-native/poll?since=N`. It
|
|
53
|
+
4. **Fallback** polling calls `/_agent-native/poll?since=N`. It polls every 2 seconds only while an agent run is in flight; otherwise it idles at 60 seconds whether or not SSE is connected (`SSE_FALLBACK_INTERVAL_MS` and `IDLE_POLL_INTERVAL_MS`, both 60 s). A hidden tab polls no faster than every 10 seconds (`HIDDEN_POLL_INTERVAL_MS`). Polling is the universal serverless fallback: new framework writes are read from the durable `sync_events` log, while the older DB timestamp scan remains as a slower safety net for direct SQL writes and older processes.
|
|
54
54
|
|
|
55
55
|
5. When the agent writes to the database, the version increments, SSE/polling detects it, and React Query refetches the affected queries.
|
|
56
56
|
|
|
@@ -50,7 +50,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
|
|
|
50
50
|
|
|
51
51
|
For list/sidebar queries, use the same pattern — pass the counter into the queryKey of every list query you want to keep fresh.
|
|
52
52
|
|
|
53
|
-
4. **Fallback** polling calls `/_agent-native/poll?since=N`. It
|
|
53
|
+
4. **Fallback** polling calls `/_agent-native/poll?since=N`. It polls every 2 seconds only while an agent run is in flight; otherwise it idles at 60 seconds whether or not SSE is connected (`SSE_FALLBACK_INTERVAL_MS` and `IDLE_POLL_INTERVAL_MS`, both 60 s). A hidden tab polls no faster than every 10 seconds (`HIDDEN_POLL_INTERVAL_MS`). Polling is the universal serverless fallback: new framework writes are read from the durable `sync_events` log, while the older DB timestamp scan remains as a slower safety net for direct SQL writes and older processes.
|
|
54
54
|
|
|
55
55
|
5. When the agent writes to the database, the version increments, SSE/polling detects it, and React Query refetches the affected queries.
|
|
56
56
|
|
package/dist/vite/client.d.ts
CHANGED
|
@@ -193,6 +193,11 @@ export interface AgentNativeVitePluginOptions extends Omit<ClientConfigOptions,
|
|
|
193
193
|
}
|
|
194
194
|
export declare function stripMountedDevApiPath(reqUrl: string | undefined, base: string | undefined): string | undefined;
|
|
195
195
|
export declare function isFrameworkDevPath(reqUrl: string, base: string | undefined): boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Framework-owned dynamic dev paths whose responses are served by the h3 app:
|
|
198
|
+
* the `/_agent-native/*` API surface plus framework `/.well-known/*` documents.
|
|
199
|
+
*/
|
|
200
|
+
export declare function isFrameworkDynamicDevPath(reqUrl: string, base: string | undefined): boolean;
|
|
196
201
|
declare function nitroModuleGraphSignature(environment: unknown): string | null;
|
|
197
202
|
declare function nitroStartupGate(options?: {
|
|
198
203
|
now?: () => number;
|