@agent-native/core 0.146.0 → 0.146.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/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/analytics/actions/compose-dashboard.ts +2 -27
- package/corpus/templates/analytics/actions/get-sql-dashboard.ts +7 -8
- package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +18 -2
- package/corpus/templates/analytics/actions/mutate-dashboard.ts +16 -24
- package/corpus/templates/analytics/actions/rename-dashboard.ts +2 -24
- package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +2 -24
- package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +2 -25
- package/corpus/templates/analytics/actions/update-dashboard.ts +4 -32
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +1 -40
- package/corpus/templates/analytics/changelog/2026-08-07-language-selection-now-lives-in-settings-instead-of-the-comm.md +6 -0
- package/corpus/templates/analytics/netlify.toml +7 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +13 -13
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +4 -2
- package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +0 -35
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +5 -3
- package/corpus/templates/analytics/server/lib/dashboard-collab-sync.ts +77 -0
- package/corpus/templates/analytics/server/lib/demo-dashboards.ts +2 -23
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +28 -74
- package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +5 -9
- package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/assets/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/brain/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/clips/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/clips/app/components/player/video-player.tsx +1 -1
- package/corpus/templates/clips/changelog/2026-08-07-fixed-trimmed-clips-durations-so-the-main-player-display-mat.md +6 -0
- package/corpus/templates/clips/chrome-extension/STORE_DRAFT.md +1 -1
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/content/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/design/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/dispatch/changelog/2026-08-07-language-selection-now-lives-in-settings-instead-of-the-disp.md +6 -0
- package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/factory/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +59 -22
- package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/forms/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/macros/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/mail/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/plan/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +10 -1
- package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +10 -3
- package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/slides/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/corpus/templates/slides/actions/generate-image-api.ts +123 -0
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +10 -2
- package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-08-07-deleting-a-deck-no-longer-freezes-the-slides-browser.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-07-slides-verify-generated-images-are-persisted-on-the-target-s.md +6 -0
- package/corpus/templates/slides/server/lib/slide-image-insertion.ts +141 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/dist/client/AgentPanel.d.ts +10 -4
- package/dist/client/AgentPanel.js +29 -82
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/migrations.js +22 -4
- package/dist/deploy/build.d.ts +1 -0
- package/dist/deploy/build.js +27 -22
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/builder-browser.d.ts +34 -0
- package/dist/server/builder-browser.js +179 -0
- package/dist/server/core-routes-plugin.d.ts +5 -0
- package/dist/server/core-routes-plugin.js +24 -8
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/shared/cache-control.d.ts +2 -2
- package/dist/shared/cache-control.js +2 -2
- package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/dist/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/dist/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/dist/vite/client.js +13 -1
- package/docs/content/drop-in-agent.mdx +3 -3
- package/docs/content/getting-started-actions.mdx +1 -2
- package/docs/content/getting-started-pages.mdx +1 -2
- package/docs/content/getting-started.mdx +0 -4
- package/docs/content/what-is-agent-native.mdx +4 -4
- package/package.json +3 -3
- package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/src/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/src/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/src/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +4 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +8 -0
- package/docs/content/getting-started-database.mdx +0 -173
package/corpus/README.md
CHANGED
|
@@ -27,6 +27,10 @@ The build location depends on the host. Treat this as a hard routing rule:
|
|
|
27
27
|
`resourceIds` when available. This is the Builder handoff.
|
|
28
28
|
- Do not substitute the generic `create_workspace_app` MCP tool in an online
|
|
29
29
|
host. That tool is a local workspace scaffolder, not the Builder handoff.
|
|
30
|
+
- Connect the Agent-Native Dispatch MCP connector only. Dispatch uses the
|
|
31
|
+
authenticated Builder Projects API to reuse or provision the workspace
|
|
32
|
+
project before starting the Builder Cloud Agent; a separate Builder CMS MCP
|
|
33
|
+
connection is not required for this workflow.
|
|
30
34
|
- If `start-workspace-app-creation` is not available or Dispatch is not
|
|
31
35
|
authenticated, stop with the connector setup needed. Do not fall back to a
|
|
32
36
|
local build or claim that the app exists.
|
|
@@ -50,6 +50,14 @@ skills. For a ChatGPT Project or any host that exposes only the MCP connector,
|
|
|
50
50
|
also place the skill instructions or this reference in the Project
|
|
51
51
|
instructions/knowledge files. Then add and authenticate the Dispatch MCP
|
|
52
52
|
connector from the packaged `adapters/chatgpt-mcp/connector.json`.
|
|
53
|
+
This single connector is enough: Dispatch provisions or reuses the Builder
|
|
54
|
+
project through the Builder Projects API, so do not ask the user to add a
|
|
55
|
+
separate Builder CMS MCP for app creation.
|
|
56
|
+
Builder's separate Fusion MCP is available as a custom remote connector at
|
|
57
|
+
`https://mcp.builder.io/mcp/fusion` for direct Builder work. It can run an
|
|
58
|
+
existing project, but it cannot provision the repo-backed Agent-Native
|
|
59
|
+
workspace project, so it is optional and not a replacement for the Dispatch
|
|
60
|
+
handoff in this skill. Do not add Builder's CMS MCP for this workflow.
|
|
53
61
|
|
|
54
62
|
For Claude Web, ChatGPT Web, and their web Projects, the host is an
|
|
55
63
|
orchestrator, not the build environment. After forming the source brief, call
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { defineAction, embedApp } from "@agent-native/core";
|
|
2
|
-
import {
|
|
3
|
-
hasCollabState,
|
|
4
|
-
applyText,
|
|
5
|
-
seedFromText,
|
|
6
|
-
} from "@agent-native/core/collab";
|
|
7
2
|
import {
|
|
8
3
|
getRequestUserEmail,
|
|
9
4
|
getRequestOrgId,
|
|
@@ -11,6 +6,7 @@ import {
|
|
|
11
6
|
} from "@agent-native/core/server";
|
|
12
7
|
import { z } from "zod";
|
|
13
8
|
|
|
9
|
+
import { queueDashboardCollabSync } from "../server/lib/dashboard-collab-sync";
|
|
14
10
|
import { validateFirstPartyDashboardTimeScope } from "../server/lib/dashboard-time-scope";
|
|
15
11
|
import {
|
|
16
12
|
getDashboard,
|
|
@@ -27,27 +23,6 @@ import {
|
|
|
27
23
|
usesFirstPartyDashboardFilters,
|
|
28
24
|
} from "../server/lib/first-party-metric-catalog";
|
|
29
25
|
|
|
30
|
-
/**
|
|
31
|
-
* Push the saved config through the collab layer so open dashboard editors get
|
|
32
|
-
* the change in real time (mirrors update-dashboard).
|
|
33
|
-
*/
|
|
34
|
-
async function syncToCollab(
|
|
35
|
-
dashboardId: string,
|
|
36
|
-
config: Record<string, unknown>,
|
|
37
|
-
): Promise<void> {
|
|
38
|
-
const docId = `dash-${dashboardId}`;
|
|
39
|
-
const configStr = JSON.stringify(config);
|
|
40
|
-
try {
|
|
41
|
-
if (await hasCollabState(docId)) {
|
|
42
|
-
await applyText(docId, configStr, "content", "agent");
|
|
43
|
-
} else {
|
|
44
|
-
await seedFromText(docId, configStr);
|
|
45
|
-
}
|
|
46
|
-
} catch {
|
|
47
|
-
// Collab sync is best-effort — the SQL write is the source of truth.
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
26
|
const WINDOWS = new Set<MetricWindow>(["30d", "90d", "all"]);
|
|
52
27
|
|
|
53
28
|
function normalizeWindow(raw: unknown): MetricWindow | undefined {
|
|
@@ -329,7 +304,7 @@ export default defineAction({
|
|
|
329
304
|
? (finalConfig.panels as unknown[]).length
|
|
330
305
|
: 0;
|
|
331
306
|
|
|
332
|
-
|
|
307
|
+
queueDashboardCollabSync(args.dashboardId, finalConfig, "agent");
|
|
333
308
|
|
|
334
309
|
const parts: string[] = [];
|
|
335
310
|
if (existing && !args.overwrite) {
|
|
@@ -65,16 +65,15 @@ export default defineAction({
|
|
|
65
65
|
const dash = await getDashboard(args.id, ctx);
|
|
66
66
|
if (!dash || dash.kind !== "sql") {
|
|
67
67
|
const seed = loadDashboardSeed(args.id);
|
|
68
|
-
if (seed)
|
|
69
|
-
|
|
70
|
-
args.id,
|
|
68
|
+
if (seed) {
|
|
69
|
+
const config =
|
|
71
70
|
args.id === FIRST_PARTY_DASHBOARD_ID
|
|
72
71
|
? repairCanonicalFirstPartyDashboardQueries(seed).config
|
|
73
|
-
: seed
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
: seed;
|
|
73
|
+
return buildDashboardSeedAgentContext(args.id, config, {
|
|
74
|
+
includeConfig: args.includeConfig === true,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
78
77
|
throw Object.assign(new Error("Dashboard not found"), {
|
|
79
78
|
statusCode: 404,
|
|
80
79
|
});
|
|
@@ -100,16 +100,32 @@ export default defineAction({
|
|
|
100
100
|
`BigQuery backfill already targets ${existingJob.table}; prepare the existing migration before changing tables.`,
|
|
101
101
|
);
|
|
102
102
|
}
|
|
103
|
+
const initialCursor =
|
|
104
|
+
existingJob?.cursor ?? current.backfillCursor ?? null;
|
|
105
|
+
if (
|
|
106
|
+
!existingJob &&
|
|
107
|
+
current.sink === "dual" &&
|
|
108
|
+
!initialCursor &&
|
|
109
|
+
ready.rowCount > 0
|
|
110
|
+
) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
"Refusing to restart an existing dual-write BigQuery backfill without its legacy cursor; recover the migration cursor before preparing again.",
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
const initialCompleted =
|
|
116
|
+
existingJob?.status === "completed" ||
|
|
117
|
+
current.backfillCompleted === true;
|
|
103
118
|
await saveFirstPartyAnalyticsBackend(scope, {
|
|
104
119
|
sink: "dual",
|
|
105
120
|
table: ready.table.fullyQualified,
|
|
106
|
-
backfillCursor:
|
|
107
|
-
backfillCompleted:
|
|
121
|
+
backfillCursor: initialCursor,
|
|
122
|
+
backfillCompleted: initialCompleted,
|
|
108
123
|
});
|
|
109
124
|
const job = await queueFirstPartyAnalyticsBigQueryBackfill(
|
|
110
125
|
scope,
|
|
111
126
|
ready.table.fullyQualified,
|
|
112
127
|
limit,
|
|
128
|
+
initialCursor,
|
|
113
129
|
);
|
|
114
130
|
return {
|
|
115
131
|
sink: "dual" as const,
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { defineAction, embedApp } from "@agent-native/core";
|
|
2
|
-
import {
|
|
3
|
-
applyText,
|
|
4
|
-
hasCollabState,
|
|
5
|
-
seedFromText,
|
|
6
|
-
} from "@agent-native/core/collab";
|
|
7
2
|
import {
|
|
8
3
|
buildDeepLink,
|
|
9
4
|
getRequestOrgId,
|
|
@@ -11,6 +6,10 @@ import {
|
|
|
11
6
|
} from "@agent-native/core/server";
|
|
12
7
|
import { z } from "zod";
|
|
13
8
|
|
|
9
|
+
import {
|
|
10
|
+
DASHBOARD_COLLAB_SYNC_TIMEOUT_MS,
|
|
11
|
+
queueDashboardCollabSync,
|
|
12
|
+
} from "../server/lib/dashboard-collab-sync";
|
|
14
13
|
import {
|
|
15
14
|
getDashboard,
|
|
16
15
|
upsertDashboardWithRetry,
|
|
@@ -171,24 +170,6 @@ function cloneConfig(config: Record<string, unknown>): Record<string, unknown> {
|
|
|
171
170
|
return JSON.parse(JSON.stringify(config)) as Record<string, unknown>;
|
|
172
171
|
}
|
|
173
172
|
|
|
174
|
-
async function syncToCollab(
|
|
175
|
-
dashboardId: string,
|
|
176
|
-
config: Record<string, unknown>,
|
|
177
|
-
): Promise<void> {
|
|
178
|
-
const docId = `dash-${dashboardId}`;
|
|
179
|
-
const configStr = JSON.stringify(config);
|
|
180
|
-
try {
|
|
181
|
-
const exists = await hasCollabState(docId);
|
|
182
|
-
if (exists) {
|
|
183
|
-
await applyText(docId, configStr, "content", "agent");
|
|
184
|
-
} else {
|
|
185
|
-
await seedFromText(docId, configStr);
|
|
186
|
-
}
|
|
187
|
-
} catch {
|
|
188
|
-
// SQL remains the source of truth; live collab sync is best-effort.
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
173
|
function sqlValidationScope(
|
|
193
174
|
operations: DashboardMutationOperation[],
|
|
194
175
|
): ReadonlySet<string> | "all" | null {
|
|
@@ -399,7 +380,10 @@ export default defineAction({
|
|
|
399
380
|
// structurally identical to the winning attempt's `root`, but reflects
|
|
400
381
|
// exactly what was saved.
|
|
401
382
|
root = saved.config as Record<string, unknown>;
|
|
402
|
-
|
|
383
|
+
// SQL is the durable source of truth. Collab sync is a convenience for
|
|
384
|
+
// already-open editors, so it must never hold the saved mutation hostage
|
|
385
|
+
// behind an unavailable database or a stale per-document write lock.
|
|
386
|
+
queueDashboardCollabSync(dashboardId, root, "agent");
|
|
403
387
|
}
|
|
404
388
|
|
|
405
389
|
const compact = compactDashboardResult(root, movedPanelIdsFrom(operations));
|
|
@@ -421,6 +405,14 @@ export default defineAction({
|
|
|
421
405
|
insertedPanelIds: mutation.insertedPanelIds,
|
|
422
406
|
removedPanelIds: mutation.removedPanelIds,
|
|
423
407
|
dashboardFieldsChanged: mutation.dashboardFieldsChanged,
|
|
408
|
+
...(args.dryRun === true
|
|
409
|
+
? { collabSync: { status: "skipped" as const } }
|
|
410
|
+
: {
|
|
411
|
+
collabSync: {
|
|
412
|
+
status: "queued" as const,
|
|
413
|
+
timeoutMs: DASHBOARD_COLLAB_SYNC_TIMEOUT_MS,
|
|
414
|
+
},
|
|
415
|
+
}),
|
|
424
416
|
...(args.returnConfig === true ? { config: root } : {}),
|
|
425
417
|
...(args.returnTypes === true
|
|
426
418
|
? {
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
-
import {
|
|
3
|
-
hasCollabState,
|
|
4
|
-
applyText,
|
|
5
|
-
seedFromText,
|
|
6
|
-
} from "@agent-native/core/collab";
|
|
7
2
|
import {
|
|
8
3
|
getRequestUserEmail,
|
|
9
4
|
getRequestOrgId,
|
|
10
5
|
} from "@agent-native/core/server";
|
|
11
6
|
import { z } from "zod";
|
|
12
7
|
|
|
8
|
+
import { queueDashboardCollabSync } from "../server/lib/dashboard-collab-sync";
|
|
13
9
|
import { upsertDashboardWithRetry } from "../server/lib/dashboards-store";
|
|
14
10
|
|
|
15
11
|
function resolveScope() {
|
|
@@ -19,24 +15,6 @@ function resolveScope() {
|
|
|
19
15
|
return { orgId, email };
|
|
20
16
|
}
|
|
21
17
|
|
|
22
|
-
async function syncToCollab(
|
|
23
|
-
dashboardId: string,
|
|
24
|
-
config: Record<string, unknown>,
|
|
25
|
-
requestSource?: string,
|
|
26
|
-
): Promise<void> {
|
|
27
|
-
const docId = `dash-${dashboardId}`;
|
|
28
|
-
const configStr = JSON.stringify(config);
|
|
29
|
-
try {
|
|
30
|
-
if (await hasCollabState(docId)) {
|
|
31
|
-
await applyText(docId, configStr, "content", requestSource);
|
|
32
|
-
} else {
|
|
33
|
-
await seedFromText(docId, configStr);
|
|
34
|
-
}
|
|
35
|
-
} catch {
|
|
36
|
-
// Best-effort: SQL remains the source of truth.
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
18
|
export default defineAction({
|
|
41
19
|
description: "Rename a saved analytics dashboard by ID.",
|
|
42
20
|
schema: z.object({
|
|
@@ -54,7 +32,7 @@ export default defineAction({
|
|
|
54
32
|
const updated = await upsertDashboardWithRetry(args.id, ctx, (existing) => {
|
|
55
33
|
return { kind: existing.kind, body: { ...existing.config, name } };
|
|
56
34
|
});
|
|
57
|
-
|
|
35
|
+
queueDashboardCollabSync(
|
|
58
36
|
args.id,
|
|
59
37
|
updated.config,
|
|
60
38
|
actionContext?.caller === "frontend" ? undefined : "agent",
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { defineAction, embedApp } from "@agent-native/core";
|
|
2
|
-
import {
|
|
3
|
-
applyText,
|
|
4
|
-
hasCollabState,
|
|
5
|
-
seedFromText,
|
|
6
|
-
} from "@agent-native/core/collab";
|
|
7
2
|
import {
|
|
8
3
|
buildDeepLink,
|
|
9
4
|
getRequestOrgId,
|
|
@@ -11,6 +6,7 @@ import {
|
|
|
11
6
|
} from "@agent-native/core/server";
|
|
12
7
|
import { z } from "zod";
|
|
13
8
|
|
|
9
|
+
import { queueDashboardCollabSync } from "../server/lib/dashboard-collab-sync";
|
|
14
10
|
import { upsertDashboardWithRetry } from "../server/lib/dashboards-store";
|
|
15
11
|
import {
|
|
16
12
|
compactDashboardResult,
|
|
@@ -74,24 +70,6 @@ function resolveTarget(args: {
|
|
|
74
70
|
return { position: args.position ?? "top" };
|
|
75
71
|
}
|
|
76
72
|
|
|
77
|
-
async function syncToCollab(
|
|
78
|
-
dashboardId: string,
|
|
79
|
-
config: Record<string, unknown>,
|
|
80
|
-
): Promise<void> {
|
|
81
|
-
const docId = `dash-${dashboardId}`;
|
|
82
|
-
const configStr = JSON.stringify(config);
|
|
83
|
-
try {
|
|
84
|
-
const exists = await hasCollabState(docId);
|
|
85
|
-
if (exists) {
|
|
86
|
-
await applyText(docId, configStr, "content", "agent");
|
|
87
|
-
} else {
|
|
88
|
-
await seedFromText(docId, configStr);
|
|
89
|
-
}
|
|
90
|
-
} catch {
|
|
91
|
-
// SQL remains the source of truth; live collab sync is best-effort.
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
73
|
export default defineAction({
|
|
96
74
|
agentTool: false,
|
|
97
75
|
description:
|
|
@@ -172,7 +150,7 @@ export default defineAction({
|
|
|
172
150
|
},
|
|
173
151
|
);
|
|
174
152
|
const root = saved.config as Record<string, unknown>;
|
|
175
|
-
|
|
153
|
+
queueDashboardCollabSync(dashboardId, root, "agent");
|
|
176
154
|
|
|
177
155
|
const compact = compactDashboardResult(root, orderResult.movedPanelIds);
|
|
178
156
|
return {
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
-
import {
|
|
3
|
-
applyText,
|
|
4
|
-
hasCollabState,
|
|
5
|
-
seedFromText,
|
|
6
|
-
} from "@agent-native/core/collab";
|
|
7
2
|
import {
|
|
8
3
|
getRequestOrgId,
|
|
9
4
|
getRequestUserEmail,
|
|
10
5
|
} from "@agent-native/core/server";
|
|
11
6
|
import { z } from "zod";
|
|
12
7
|
|
|
8
|
+
import { queueDashboardCollabSync } from "../server/lib/dashboard-collab-sync";
|
|
13
9
|
import { restoreDashboardRevision } from "../server/lib/dashboards-store";
|
|
14
10
|
|
|
15
11
|
function resolveScope() {
|
|
@@ -19,25 +15,6 @@ function resolveScope() {
|
|
|
19
15
|
return { orgId, email };
|
|
20
16
|
}
|
|
21
17
|
|
|
22
|
-
async function syncToCollab(
|
|
23
|
-
dashboardId: string,
|
|
24
|
-
config: Record<string, unknown>,
|
|
25
|
-
requestSource?: string,
|
|
26
|
-
): Promise<void> {
|
|
27
|
-
const docId = `dash-${dashboardId}`;
|
|
28
|
-
const configStr = JSON.stringify(config);
|
|
29
|
-
try {
|
|
30
|
-
const exists = await hasCollabState(docId);
|
|
31
|
-
if (exists) {
|
|
32
|
-
await applyText(docId, configStr, "content", requestSource);
|
|
33
|
-
} else {
|
|
34
|
-
await seedFromText(docId, configStr);
|
|
35
|
-
}
|
|
36
|
-
} catch {
|
|
37
|
-
// SQL is the source of truth; open editors also refetch on the dashboards signal.
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
18
|
export default defineAction({
|
|
42
19
|
description:
|
|
43
20
|
"Restore a dashboard to a saved history revision, snapshotting the current dashboard first.",
|
|
@@ -63,7 +40,7 @@ export default defineAction({
|
|
|
63
40
|
);
|
|
64
41
|
}
|
|
65
42
|
const { dashboard, snapshotRevisionId } = restored;
|
|
66
|
-
|
|
43
|
+
queueDashboardCollabSync(
|
|
67
44
|
dashboard.id,
|
|
68
45
|
dashboard.config,
|
|
69
46
|
actionContext?.caller === "frontend" ? undefined : "agent",
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { defineAction, embedApp } from "@agent-native/core";
|
|
2
|
-
import {
|
|
3
|
-
hasCollabState,
|
|
4
|
-
applyText,
|
|
5
|
-
seedFromText,
|
|
6
|
-
} from "@agent-native/core/collab";
|
|
7
2
|
import {
|
|
8
3
|
getRequestUserEmail,
|
|
9
4
|
getRequestOrgId,
|
|
@@ -13,6 +8,7 @@ import { z } from "zod";
|
|
|
13
8
|
|
|
14
9
|
import { interpolate } from "../app/pages/adhoc/sql-dashboard/interpolate";
|
|
15
10
|
import { dryRunQuery } from "../server/lib/bigquery";
|
|
11
|
+
import { queueDashboardCollabSync } from "../server/lib/dashboard-collab-sync";
|
|
16
12
|
import { validateFirstPartyDashboardTimeScope } from "../server/lib/dashboard-time-scope";
|
|
17
13
|
import {
|
|
18
14
|
upsertDashboard,
|
|
@@ -536,30 +532,6 @@ function opCanChangePanelSql(op: JsonOp): boolean {
|
|
|
536
532
|
);
|
|
537
533
|
}
|
|
538
534
|
|
|
539
|
-
/**
|
|
540
|
-
* Push a config update through the collab layer so open dashboard editors
|
|
541
|
-
* receive the change in real time. Seeds the collab state if it doesn't
|
|
542
|
-
* exist yet (e.g. dashboard was created before the collab plugin was added).
|
|
543
|
-
*/
|
|
544
|
-
async function syncToCollab(
|
|
545
|
-
dashboardId: string,
|
|
546
|
-
config: Record<string, unknown>,
|
|
547
|
-
requestSource?: string,
|
|
548
|
-
): Promise<void> {
|
|
549
|
-
const docId = `dash-${dashboardId}`;
|
|
550
|
-
const configStr = JSON.stringify(config);
|
|
551
|
-
try {
|
|
552
|
-
const exists = await hasCollabState(docId);
|
|
553
|
-
if (exists) {
|
|
554
|
-
await applyText(docId, configStr, "content", requestSource);
|
|
555
|
-
} else {
|
|
556
|
-
await seedFromText(docId, configStr);
|
|
557
|
-
}
|
|
558
|
-
} catch {
|
|
559
|
-
// Collab sync is best-effort — the SQL write is the source of truth
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
|
|
563
535
|
function isAgentCaller(caller: string | undefined): boolean {
|
|
564
536
|
return caller === "tool" || caller === "mcp" || caller === "a2a";
|
|
565
537
|
}
|
|
@@ -642,7 +614,7 @@ export default defineAction({
|
|
|
642
614
|
const sqlError = await validatePanelSql(args.config);
|
|
643
615
|
if (sqlError) throw new Error(sqlError);
|
|
644
616
|
await upsertDashboard(dashboardId, "sql", args.config, ctx);
|
|
645
|
-
|
|
617
|
+
queueDashboardCollabSync(
|
|
646
618
|
dashboardId,
|
|
647
619
|
args.config,
|
|
648
620
|
isAgentCaller(actionContext?.caller) ? "agent" : undefined,
|
|
@@ -675,7 +647,7 @@ export default defineAction({
|
|
|
675
647
|
},
|
|
676
648
|
);
|
|
677
649
|
const root = saved.config as Record<string, unknown>;
|
|
678
|
-
|
|
650
|
+
queueDashboardCollabSync(
|
|
679
651
|
dashboardId,
|
|
680
652
|
root,
|
|
681
653
|
isAgentCaller(actionContext?.caller) ? "agent" : undefined,
|
|
@@ -721,7 +693,7 @@ export default defineAction({
|
|
|
721
693
|
},
|
|
722
694
|
);
|
|
723
695
|
const root = saved.config as Record<string, unknown>;
|
|
724
|
-
|
|
696
|
+
queueDashboardCollabSync(
|
|
725
697
|
dashboardId,
|
|
726
698
|
root,
|
|
727
699
|
isAgentCaller(actionContext?.caller) ? "agent" : undefined,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChangelogDialog } from "@agent-native/core/client/changelog";
|
|
2
2
|
import { callAction, useChangeVersions } from "@agent-native/core/client/hooks";
|
|
3
|
-
import {
|
|
3
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
4
4
|
import { useOrgRole } from "@agent-native/core/client/org";
|
|
5
5
|
import {
|
|
6
6
|
IconFlask,
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
IconMoon,
|
|
12
12
|
IconHistory,
|
|
13
13
|
IconHierarchy2,
|
|
14
|
-
IconLanguage,
|
|
15
14
|
IconRefresh,
|
|
16
15
|
IconSettings,
|
|
17
16
|
} from "@tabler/icons-react";
|
|
@@ -41,13 +40,6 @@ import {
|
|
|
41
40
|
CommandGroup,
|
|
42
41
|
CommandItem,
|
|
43
42
|
} from "@/components/ui/command";
|
|
44
|
-
import {
|
|
45
|
-
Dialog,
|
|
46
|
-
DialogContent,
|
|
47
|
-
DialogHeader,
|
|
48
|
-
DialogTitle,
|
|
49
|
-
} from "@/components/ui/dialog";
|
|
50
|
-
import { Label } from "@/components/ui/label";
|
|
51
43
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
52
44
|
import { useReplayStorageStatus } from "@/hooks/use-replay-storage-status";
|
|
53
45
|
import { dashboardCacheScope } from "@/lib/prefetch-keys";
|
|
@@ -263,7 +255,6 @@ export function CommandPalette() {
|
|
|
263
255
|
const dashboardScope = dashboardCacheScope(auth);
|
|
264
256
|
const [open, setOpen] = useState(false);
|
|
265
257
|
const [changelogOpen, setChangelogOpen] = useState(false);
|
|
266
|
-
const [languageOpen, setLanguageOpen] = useState(false);
|
|
267
258
|
const [searchQuery, setSearchQuery] = useState("");
|
|
268
259
|
const [selectedCommand, setSelectedCommand] = useState("");
|
|
269
260
|
const commandListRef = useRef<HTMLDivElement>(null);
|
|
@@ -553,25 +544,6 @@ export function CommandPalette() {
|
|
|
553
544
|
key="appearance"
|
|
554
545
|
heading={t("commandPalette.groupAppearance")}
|
|
555
546
|
>
|
|
556
|
-
<CommandItem
|
|
557
|
-
value={`appearance:language:${t("settings.languageTitle")}`}
|
|
558
|
-
onSelect={() => {
|
|
559
|
-
setOpen(false);
|
|
560
|
-
setLanguageOpen(true);
|
|
561
|
-
}}
|
|
562
|
-
keywords={commandPaletteKeywords(
|
|
563
|
-
t("settings.languageTitle"),
|
|
564
|
-
t("settings.languageLabel"),
|
|
565
|
-
"language",
|
|
566
|
-
"locale",
|
|
567
|
-
"translation",
|
|
568
|
-
"internationalization",
|
|
569
|
-
"i18n",
|
|
570
|
-
)}
|
|
571
|
-
>
|
|
572
|
-
<IconLanguage className="me-2 h-4 w-4 text-muted-foreground" />
|
|
573
|
-
{t("settings.languageTitle")}
|
|
574
|
-
</CommandItem>
|
|
575
547
|
<CommandItem
|
|
576
548
|
value={`appearance:theme:${
|
|
577
549
|
isDark
|
|
@@ -678,17 +650,6 @@ export function CommandPalette() {
|
|
|
678
650
|
onOpenChange={setChangelogOpen}
|
|
679
651
|
markdown={changelog}
|
|
680
652
|
/>
|
|
681
|
-
<Dialog open={languageOpen} onOpenChange={setLanguageOpen}>
|
|
682
|
-
<DialogContent className="max-w-sm">
|
|
683
|
-
<DialogHeader>
|
|
684
|
-
<DialogTitle>{t("settings.languageTitle")}</DialogTitle>
|
|
685
|
-
</DialogHeader>
|
|
686
|
-
<div className="space-y-1.5">
|
|
687
|
-
<Label>{t("settings.languageLabel")}</Label>
|
|
688
|
-
<LanguagePicker label={t("settings.languageLabel")} />
|
|
689
|
-
</div>
|
|
690
|
-
</DialogContent>
|
|
691
|
-
</Dialog>
|
|
692
653
|
</>
|
|
693
654
|
);
|
|
694
655
|
}
|
|
@@ -18,6 +18,13 @@ AGENT_PROD_CODE_EXECUTION = "sandboxed"
|
|
|
18
18
|
# turns on the durable background worker instead of the short foreground wall.
|
|
19
19
|
AGENT_CHAT_DURABLE_BACKGROUND = "true"
|
|
20
20
|
|
|
21
|
+
[context.production.environment]
|
|
22
|
+
# Analytics owns its schema at release time (`migrate:production` above), so
|
|
23
|
+
# production request functions skip migrations. Preview functions still run
|
|
24
|
+
# request-path migrations because previews do not run the production release
|
|
25
|
+
# migration step.
|
|
26
|
+
AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
|
|
27
|
+
|
|
21
28
|
# A2A delegation calls run a full agent loop (LLM + tool calls + DB queries).
|
|
22
29
|
# Hosted agent chat uses a soft timeout before this function timeout so the
|
|
23
30
|
# hidden auto-continuation path can hand off before Netlify kills the function.
|