@agent-native/core-corpus 0.201.0 → 0.201.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/CHANGELOG.md +6 -0
- package/corpus/templates/analytics/actions/save-dashboard-view.ts +10 -1
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +136 -4
- package/corpus/templates/analytics/app/hooks/use-dashboard-views.ts +4 -0
- package/corpus/templates/analytics/app/i18n/en-US.ts +7 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +86 -23
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +4 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +55 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewsMenu.tsx +44 -7
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-filter-restore.ts +196 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/filter-vars.ts +2 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +158 -47
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +2 -0
- package/corpus/templates/analytics/changelog/2026-10-05-custom-date-controls-stay-beside-the-range-selector-and-dash.md +6 -0
- package/corpus/templates/analytics/server/db/schema.ts +20 -8
- package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +50 -3
- package/corpus/templates/analytics/server/lib/dashboard-view-remap.ts +52 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +77 -42
- package/corpus/templates/analytics/server/lib/migrate-analytics-artifacts.ts +23 -8
- package/corpus/templates/analytics/server/plugins/db.ts +7 -0
- package/corpus/templates/clips/CHANGELOG.md +4 -0
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +1 -1
- package/corpus/templates/clips/changelog/2026-10-05-the-agent-composer-is-easier-to-distinguish-from-the-shared-.md +6 -0
- package/corpus/templates/design/CHANGELOG.md +1 -0
- package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +1 -1
- package/corpus/templates/design/changelog/2026-10-05-design-frame-labels-apply-truncation-as-soon-as-resizing-end.md +6 -0
- package/corpus/templates/slides/CHANGELOG.md +7 -0
- package/corpus/templates/slides/agent-native.app-skill.json +2 -2
- package/corpus/templates/slides/app/components/home/SlidesHomeLibrary.tsx +11 -11
- package/corpus/templates/slides/app/context/DeckContext.tsx +16 -12
- package/corpus/templates/slides/app/hooks/use-new-deck-generation.ts +129 -6
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +4 -1
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +25 -8
- package/corpus/templates/slides/app/pages/Index.tsx +85 -42
- package/corpus/templates/slides/changelog/2026-10-05-file-uploads-explain-the-free-builder-io-option-and-how-to-c.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-05-slides-restores-pending-generation-questions-when-reopened.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-05-the-home-page-shows-both-library-tabs-and-starter-prompts-im.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-05-undo-stops-at-generated-deck.md +6 -0
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
createSharesTable,
|
|
9
9
|
uniqueIndex,
|
|
10
10
|
} from "@agent-native/core/db/schema";
|
|
11
|
+
import { sql } from "drizzle-orm";
|
|
11
12
|
import { boolean } from "drizzle-orm/pg-core";
|
|
12
13
|
|
|
13
14
|
export * from "./schema-monitoring.js";
|
|
@@ -76,14 +77,25 @@ export const dashboardRevisions = table(
|
|
|
76
77
|
}),
|
|
77
78
|
);
|
|
78
79
|
|
|
79
|
-
export const dashboardViews = table(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
export const dashboardViews = table(
|
|
81
|
+
"dashboard_views",
|
|
82
|
+
{
|
|
83
|
+
id: text("id").primaryKey(),
|
|
84
|
+
dashboardId: text("dashboard_id").notNull(),
|
|
85
|
+
name: text("name").notNull(),
|
|
86
|
+
filters: text("filters").notNull().default("{}"),
|
|
87
|
+
isDefault: boolean("is_default").notNull().default(false),
|
|
88
|
+
createdBy: text("created_by"),
|
|
89
|
+
createdAt: text("created_at").notNull().default(now()),
|
|
90
|
+
},
|
|
91
|
+
(t) => ({
|
|
92
|
+
defaultDashboardViewIdx: uniqueIndex(
|
|
93
|
+
"dashboard_views_default_per_dashboard_idx",
|
|
94
|
+
)
|
|
95
|
+
.on(t.dashboardId)
|
|
96
|
+
.where(sql`${t.isDefault} = true`),
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
87
99
|
|
|
88
100
|
export const dashboardReportSubscriptions = table(
|
|
89
101
|
"dashboard_report_subscriptions",
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
PRE_CAPPED_SIGNUPS_OVER_TIME_SQL,
|
|
15
15
|
PRE_CUSTOM_SPINE_SIGNUPS_OVER_TIME_SQL,
|
|
16
16
|
SIGNUPS_OVER_TIME_SQL,
|
|
17
|
+
buildFirstPartyDashboardFilters,
|
|
17
18
|
type ExactFirstPartyPanelReplacement,
|
|
18
19
|
repairFirstPartyObservedRetentionPanels,
|
|
19
20
|
} from "./first-party-metric-catalog";
|
|
@@ -800,12 +801,58 @@ export function repairKnownFirstPartyDashboardQueries(
|
|
|
800
801
|
const repaired = repairFirstPartyBigQueryDashboardQueries(
|
|
801
802
|
historical.config,
|
|
802
803
|
);
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
804
|
+
const defaultsRepaired = repairFirstPartyBigQueryDashboardFilterDefaults(
|
|
805
|
+
repaired.config,
|
|
806
|
+
);
|
|
807
|
+
return {
|
|
808
|
+
...defaultsRepaired,
|
|
809
|
+
changed:
|
|
810
|
+
historical.changed || repaired.changed || defaultsRepaired.changed,
|
|
811
|
+
};
|
|
806
812
|
}
|
|
807
813
|
if (dashboardId === FIRST_PARTY_DASHBOARD_ID) {
|
|
808
814
|
return repairCanonicalFirstPartyDashboardQueries(config);
|
|
809
815
|
}
|
|
810
816
|
return { config, changed: false };
|
|
811
817
|
}
|
|
818
|
+
|
|
819
|
+
function repairFirstPartyBigQueryDashboardFilterDefaults(
|
|
820
|
+
config: Record<string, unknown>,
|
|
821
|
+
): { config: Record<string, unknown>; changed: boolean } {
|
|
822
|
+
if (!Array.isArray(config.filters)) return { config, changed: false };
|
|
823
|
+
|
|
824
|
+
const canonicalDefaults = new Map(
|
|
825
|
+
buildFirstPartyDashboardFilters()
|
|
826
|
+
.filter(
|
|
827
|
+
(filter) => filter.id === "timeRange" || filter.id === "emailFilter",
|
|
828
|
+
)
|
|
829
|
+
.map((filter) => [filter.id, filter.default]),
|
|
830
|
+
);
|
|
831
|
+
const legacyDefaults = new Map<string, Set<unknown>>([
|
|
832
|
+
["timeRange", new Set(["all"])],
|
|
833
|
+
["emailFilter", new Set(["all"])],
|
|
834
|
+
]);
|
|
835
|
+
let changed = false;
|
|
836
|
+
const filters = config.filters.map((filter) => {
|
|
837
|
+
if (!filter || typeof filter !== "object" || Array.isArray(filter)) {
|
|
838
|
+
return filter;
|
|
839
|
+
}
|
|
840
|
+
const record = filter as Record<string, unknown>;
|
|
841
|
+
const expected =
|
|
842
|
+
typeof record.id === "string" ? canonicalDefaults.get(record.id) : null;
|
|
843
|
+
const legacy =
|
|
844
|
+
typeof record.id === "string" ? legacyDefaults.get(record.id) : null;
|
|
845
|
+
if (
|
|
846
|
+
!expected ||
|
|
847
|
+
record.default === expected ||
|
|
848
|
+
!legacy?.has(record.default)
|
|
849
|
+
)
|
|
850
|
+
return filter;
|
|
851
|
+
changed = true;
|
|
852
|
+
return { ...record, default: expected };
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
return changed
|
|
856
|
+
? { config: { ...config, filters }, changed: true }
|
|
857
|
+
: { config, changed: false };
|
|
858
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { and, eq } from "drizzle-orm";
|
|
2
|
+
|
|
3
|
+
export async function remapDashboardViews(
|
|
4
|
+
tx: any,
|
|
5
|
+
dashboards: { id: any; orgId: any },
|
|
6
|
+
dashboardViews: { id: any; dashboardId: any; isDefault: any },
|
|
7
|
+
orgId: string,
|
|
8
|
+
duplicateId: string,
|
|
9
|
+
canonicalId: string,
|
|
10
|
+
): Promise<void> {
|
|
11
|
+
for (const dashboardId of [duplicateId, canonicalId].sort()) {
|
|
12
|
+
const [dashboard] = await tx
|
|
13
|
+
.select({ id: dashboards.id })
|
|
14
|
+
.from(dashboards)
|
|
15
|
+
.where(and(eq(dashboards.id, dashboardId), eq(dashboards.orgId, orgId)))
|
|
16
|
+
.for("update");
|
|
17
|
+
|
|
18
|
+
if (!dashboard) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
`Dashboard ${dashboardId} was not available to lock in organization ${orgId}`,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const [canonicalDefault] = await tx
|
|
26
|
+
.select({ id: dashboardViews.id })
|
|
27
|
+
.from(dashboardViews)
|
|
28
|
+
.where(
|
|
29
|
+
and(
|
|
30
|
+
eq(dashboardViews.dashboardId, canonicalId),
|
|
31
|
+
eq(dashboardViews.isDefault, true),
|
|
32
|
+
),
|
|
33
|
+
)
|
|
34
|
+
.limit(1);
|
|
35
|
+
|
|
36
|
+
if (canonicalDefault) {
|
|
37
|
+
await tx
|
|
38
|
+
.update(dashboardViews)
|
|
39
|
+
.set({ isDefault: false })
|
|
40
|
+
.where(
|
|
41
|
+
and(
|
|
42
|
+
eq(dashboardViews.dashboardId, duplicateId),
|
|
43
|
+
eq(dashboardViews.isDefault, true),
|
|
44
|
+
),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await tx
|
|
49
|
+
.update(dashboardViews)
|
|
50
|
+
.set({ dashboardId: canonicalId })
|
|
51
|
+
.where(eq(dashboardViews.dashboardId, duplicateId));
|
|
52
|
+
}
|
|
@@ -3150,16 +3150,21 @@ export interface DashboardViewRecord {
|
|
|
3150
3150
|
dashboardId: string;
|
|
3151
3151
|
name: string;
|
|
3152
3152
|
filters: Record<string, string>;
|
|
3153
|
+
isDefault: boolean;
|
|
3153
3154
|
createdBy: string | null;
|
|
3154
3155
|
createdAt: string;
|
|
3155
3156
|
}
|
|
3156
3157
|
|
|
3157
3158
|
function rowToView(row: any): DashboardViewRecord {
|
|
3159
|
+
if (typeof row.isDefault !== "boolean") {
|
|
3160
|
+
throw new Error("Dashboard view is missing its default status");
|
|
3161
|
+
}
|
|
3158
3162
|
return {
|
|
3159
3163
|
id: row.id,
|
|
3160
3164
|
dashboardId: row.dashboardId,
|
|
3161
3165
|
name: row.name,
|
|
3162
3166
|
filters: safeJsonParse(row.filters, {} as Record<string, string>),
|
|
3167
|
+
isDefault: row.isDefault,
|
|
3163
3168
|
createdBy: row.createdBy ?? null,
|
|
3164
3169
|
createdAt: row.createdAt,
|
|
3165
3170
|
};
|
|
@@ -3213,7 +3218,12 @@ export async function listDashboardViews(
|
|
|
3213
3218
|
|
|
3214
3219
|
export async function saveDashboardView(
|
|
3215
3220
|
dashboardId: string,
|
|
3216
|
-
view: {
|
|
3221
|
+
view: {
|
|
3222
|
+
id?: string;
|
|
3223
|
+
name: string;
|
|
3224
|
+
filters: Record<string, string>;
|
|
3225
|
+
isDefault?: boolean;
|
|
3226
|
+
},
|
|
3217
3227
|
ctx: AccessCtx,
|
|
3218
3228
|
): Promise<DashboardViewRecord> {
|
|
3219
3229
|
await assertAccess("dashboard", dashboardId, "editor", {
|
|
@@ -3221,55 +3231,80 @@ export async function saveDashboardView(
|
|
|
3221
3231
|
orgId: ctx.orgId ?? undefined,
|
|
3222
3232
|
});
|
|
3223
3233
|
const db = getDb() as any;
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3234
|
+
const row = await db.transaction(async (tx: any) => {
|
|
3235
|
+
if (view.isDefault) {
|
|
3236
|
+
await tx
|
|
3237
|
+
.select({ id: schema.dashboards.id })
|
|
3238
|
+
.from(schema.dashboards)
|
|
3239
|
+
.where(eq(schema.dashboards.id, dashboardId))
|
|
3240
|
+
.for("update");
|
|
3241
|
+
await tx
|
|
3242
|
+
.update(schema.dashboardViews)
|
|
3243
|
+
.set({ isDefault: false })
|
|
3244
|
+
.where(
|
|
3245
|
+
and(
|
|
3246
|
+
eq(schema.dashboardViews.dashboardId, dashboardId),
|
|
3247
|
+
eq(schema.dashboardViews.isDefault, true),
|
|
3248
|
+
),
|
|
3249
|
+
);
|
|
3239
3250
|
}
|
|
3240
|
-
}
|
|
3241
3251
|
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3252
|
+
let id = view.id ?? nanoidFallback();
|
|
3253
|
+
let existing = false;
|
|
3254
|
+
if (view.id) {
|
|
3255
|
+
const [existingRow] = await tx
|
|
3256
|
+
.select({
|
|
3257
|
+
id: schema.dashboardViews.id,
|
|
3258
|
+
dashboardId: schema.dashboardViews.dashboardId,
|
|
3259
|
+
})
|
|
3260
|
+
.from(schema.dashboardViews)
|
|
3261
|
+
.where(eq(schema.dashboardViews.id, view.id))
|
|
3262
|
+
.limit(1);
|
|
3263
|
+
if (existingRow?.dashboardId === dashboardId) {
|
|
3264
|
+
existing = true;
|
|
3265
|
+
} else if (existingRow) {
|
|
3266
|
+
id = nanoidFallback();
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
|
|
3270
|
+
if (existing) {
|
|
3271
|
+
await tx
|
|
3272
|
+
.update(schema.dashboardViews)
|
|
3273
|
+
.set({
|
|
3274
|
+
name: view.name,
|
|
3275
|
+
filters: JSON.stringify(view.filters),
|
|
3276
|
+
...(view.isDefault ? { isDefault: true } : {}),
|
|
3277
|
+
})
|
|
3278
|
+
.where(
|
|
3279
|
+
and(
|
|
3280
|
+
eq(schema.dashboardViews.id, id),
|
|
3281
|
+
eq(schema.dashboardViews.dashboardId, dashboardId),
|
|
3282
|
+
),
|
|
3283
|
+
);
|
|
3284
|
+
} else {
|
|
3285
|
+
await tx.insert(schema.dashboardViews).values({
|
|
3286
|
+
id,
|
|
3287
|
+
dashboardId,
|
|
3288
|
+
name: view.name,
|
|
3289
|
+
filters: JSON.stringify(view.filters),
|
|
3290
|
+
isDefault: view.isDefault === true,
|
|
3291
|
+
createdBy: ctx.email || null,
|
|
3292
|
+
});
|
|
3293
|
+
}
|
|
3294
|
+
const [saved] = await tx
|
|
3295
|
+
.select()
|
|
3296
|
+
.from(schema.dashboardViews)
|
|
3246
3297
|
.where(
|
|
3247
3298
|
and(
|
|
3248
3299
|
eq(schema.dashboardViews.id, id),
|
|
3249
3300
|
eq(schema.dashboardViews.dashboardId, dashboardId),
|
|
3250
3301
|
),
|
|
3251
3302
|
);
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
filters: JSON.stringify(view.filters),
|
|
3258
|
-
createdBy: ctx.email || null,
|
|
3259
|
-
});
|
|
3260
|
-
}
|
|
3261
|
-
const [row] = await db
|
|
3262
|
-
.select()
|
|
3263
|
-
.from(schema.dashboardViews)
|
|
3264
|
-
.where(
|
|
3265
|
-
and(
|
|
3266
|
-
eq(schema.dashboardViews.id, id),
|
|
3267
|
-
eq(schema.dashboardViews.dashboardId, dashboardId),
|
|
3268
|
-
),
|
|
3269
|
-
);
|
|
3270
|
-
if (!row) {
|
|
3271
|
-
throw new Error("Dashboard view was not persisted");
|
|
3272
|
-
}
|
|
3303
|
+
if (!saved) {
|
|
3304
|
+
throw new Error("Dashboard view was not persisted");
|
|
3305
|
+
}
|
|
3306
|
+
return saved;
|
|
3307
|
+
});
|
|
3273
3308
|
const dash = await getDashboard(dashboardId, ctx);
|
|
3274
3309
|
if (dash) {
|
|
3275
3310
|
recordScopedChange(
|
|
@@ -12,6 +12,7 @@ import { and, eq, inArray, isNull } from "drizzle-orm";
|
|
|
12
12
|
|
|
13
13
|
import { normalizeDashboardConfig } from "../../shared/dashboard-config-normalization";
|
|
14
14
|
import { getDb, schema } from "../db/index.js";
|
|
15
|
+
import { remapDashboardViews } from "./dashboard-view-remap.js";
|
|
15
16
|
|
|
16
17
|
const migrationExtensions = table("tools", {
|
|
17
18
|
id: text("id").primaryKey(),
|
|
@@ -684,9 +685,14 @@ export async function migrateAnalyticsArtifacts(
|
|
|
684
685
|
|
|
685
686
|
for (const group of dashboardDuplicates) {
|
|
686
687
|
const canonical = oldest(group);
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
688
|
+
const duplicates = group
|
|
689
|
+
.filter((row) => row.id !== canonical.id)
|
|
690
|
+
.sort(
|
|
691
|
+
(a, b) =>
|
|
692
|
+
a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id),
|
|
693
|
+
);
|
|
694
|
+
for (const row of duplicates) {
|
|
695
|
+
duplicateDashboardMap.set(row.id, canonical.id);
|
|
690
696
|
}
|
|
691
697
|
}
|
|
692
698
|
for (const group of analysisDuplicates) {
|
|
@@ -820,10 +826,14 @@ export async function migrateAnalyticsArtifacts(
|
|
|
820
826
|
[{ sourceId: duplicateId, targetId: canonicalId }],
|
|
821
827
|
runId,
|
|
822
828
|
);
|
|
823
|
-
await
|
|
824
|
-
|
|
825
|
-
.
|
|
826
|
-
|
|
829
|
+
await remapDashboardViews(
|
|
830
|
+
tx,
|
|
831
|
+
schema.dashboards,
|
|
832
|
+
schema.dashboardViews,
|
|
833
|
+
ctx.orgId,
|
|
834
|
+
duplicateId,
|
|
835
|
+
canonicalId,
|
|
836
|
+
);
|
|
827
837
|
await tx
|
|
828
838
|
.update(schema.dashboardReportSubscriptions)
|
|
829
839
|
.set({ dashboardId: canonicalId, updatedAt: now })
|
|
@@ -833,7 +843,12 @@ export async function migrateAnalyticsArtifacts(
|
|
|
833
843
|
await tx
|
|
834
844
|
.update(schema.dashboards)
|
|
835
845
|
.set({ archivedAt: now, updatedAt: now, updatedBy: ctx.userEmail })
|
|
836
|
-
.where(
|
|
846
|
+
.where(
|
|
847
|
+
and(
|
|
848
|
+
eq(schema.dashboards.id, duplicateId),
|
|
849
|
+
eq(schema.dashboards.orgId, ctx.orgId),
|
|
850
|
+
),
|
|
851
|
+
);
|
|
837
852
|
summary.duplicateDashboardsArchived += 1;
|
|
838
853
|
}
|
|
839
854
|
|
|
@@ -1546,6 +1546,13 @@ ALTER TABLE analysis_revisions ADD COLUMN IF NOT EXISTS chat_context TEXT`,
|
|
|
1546
1546
|
sql: `ALTER TABLE error_issues ADD COLUMN IF NOT EXISTS test_identity_only BOOLEAN NOT NULL DEFAULT false;
|
|
1547
1547
|
ALTER TABLE error_events ADD COLUMN IF NOT EXISTS test_identity BOOLEAN NOT NULL DEFAULT false`,
|
|
1548
1548
|
},
|
|
1549
|
+
{
|
|
1550
|
+
version: 155,
|
|
1551
|
+
name: "dashboard-views-default",
|
|
1552
|
+
sql: `ALTER TABLE dashboard_views ADD COLUMN IF NOT EXISTS is_default BOOLEAN NOT NULL DEFAULT false;
|
|
1553
|
+
CREATE UNIQUE INDEX IF NOT EXISTS dashboard_views_default_per_dashboard_idx
|
|
1554
|
+
ON dashboard_views (dashboard_id) WHERE is_default = true`,
|
|
1555
|
+
},
|
|
1549
1556
|
],
|
|
1550
1557
|
{ table: "analytics_migrations" },
|
|
1551
1558
|
);
|
|
@@ -1564,7 +1564,7 @@ export default function ShareRoute() {
|
|
|
1564
1564
|
return (
|
|
1565
1565
|
<div
|
|
1566
1566
|
className={cn(
|
|
1567
|
-
"clips-recording-view relative flex h-[var(--agent-native-viewport-height,100vh)] min-h-0 w-full max-w-full flex-col overflow-y-auto bg-background lg:grid lg:grid-cols-[minmax(0,1fr)_360px] lg:grid-rows-[auto_minmax(0,1fr)] lg:overflow-hidden xl:grid-cols-[minmax(0,1fr)_420px] [&_.agent-composer-root]:!border-0
|
|
1567
|
+
"clips-recording-view relative flex h-[var(--agent-native-viewport-height,100vh)] min-h-0 w-full max-w-full flex-col overflow-y-auto bg-background lg:grid lg:grid-cols-[minmax(0,1fr)_360px] lg:grid-rows-[auto_minmax(0,1fr)] lg:overflow-hidden xl:grid-cols-[minmax(0,1fr)_420px] [&_.agent-composer-root]:!border-0",
|
|
1568
1568
|
sidePanelCollapsed &&
|
|
1569
1569
|
"lg:grid-cols-[minmax(0,1fr)_40px] xl:grid-cols-[minmax(0,1fr)_40px]",
|
|
1570
1570
|
)}
|
|
@@ -3,7 +3,7 @@ const CHROME_OPACITY_TRANSITION = "opacity 150ms ease-out";
|
|
|
3
3
|
const CHROME_BORDER_SETTLE_TRANSITION = `inset ${CHROME_SETTLE_MS}ms ease-out, border-width ${CHROME_SETTLE_MS}ms ease-out, border-radius ${CHROME_SETTLE_MS}ms ease-out, ${CHROME_OPACITY_TRANSITION}`;
|
|
4
4
|
const SELECTION_BOX_SETTLE_TRANSITION = `border-width ${CHROME_SETTLE_MS}ms ease-out, border-radius ${CHROME_SETTLE_MS}ms ease-out, ${CHROME_OPACITY_TRANSITION}`;
|
|
5
5
|
const CHROME_HANDLE_SETTLE_TRANSITION = `width ${CHROME_SETTLE_MS}ms ease-out, height ${CHROME_SETTLE_MS}ms ease-out, border-width ${CHROME_SETTLE_MS}ms ease-out, top ${CHROME_SETTLE_MS}ms ease-out, bottom ${CHROME_SETTLE_MS}ms ease-out, left ${CHROME_SETTLE_MS}ms ease-out, right ${CHROME_SETTLE_MS}ms ease-out, ${CHROME_OPACITY_TRANSITION}`;
|
|
6
|
-
const CHROME_LABEL_SETTLE_TRANSITION = `
|
|
6
|
+
const CHROME_LABEL_SETTLE_TRANSITION = `transform ${CHROME_SETTLE_MS}ms ease-out, ${CHROME_OPACITY_TRANSITION}`;
|
|
7
7
|
|
|
8
8
|
export function getChromeBorderTransition(chromeSettling: boolean) {
|
|
9
9
|
return chromeSettling
|
|
@@ -5,8 +5,15 @@ time from the command menu (Cmd+K → "What's new").
|
|
|
5
5
|
|
|
6
6
|
## 2026-10-05
|
|
7
7
|
|
|
8
|
+
### Improved
|
|
9
|
+
|
|
10
|
+
- The home page shows both library tabs and starter prompts immediately while content loads.
|
|
11
|
+
|
|
8
12
|
### Fixed
|
|
9
13
|
|
|
14
|
+
- File uploads explain the free Builder.io option and how to connect S3-compatible storage.
|
|
15
|
+
- Slides keeps a pending generation question and its chat available when you leave and reopen a deck.
|
|
16
|
+
- Prompt-generated Slides decks remain when Cmd+Z reaches deck creation.
|
|
10
17
|
- The Recent tab shows loading placeholders until your decks are ready.
|
|
11
18
|
|
|
12
19
|
## 2026-10-03
|
|
@@ -71,13 +71,13 @@
|
|
|
71
71
|
"generic-mcp"
|
|
72
72
|
],
|
|
73
73
|
"chatgpt": {
|
|
74
|
-
"version": "1.0.
|
|
74
|
+
"version": "1.0.1",
|
|
75
75
|
"interface": {
|
|
76
76
|
"displayName": "Agent-Native Slides",
|
|
77
77
|
"shortDescription": "On-brand presentations",
|
|
78
78
|
"longDescription": "Create and revise on-brand presentations in your Agent-Native Slides workspace. Start from a brief, inspect decks and design systems, add slides, update existing slide content, and duplicate a deck for a new draft. This connection edits presentations in Agent-Native Slides; it does not directly change PowerPoint or Google Slides files. It can access only decks and design systems available to your connected account.",
|
|
79
79
|
"developerName": "Builder.io",
|
|
80
|
-
"category": "
|
|
80
|
+
"category": "Creativity",
|
|
81
81
|
"capabilities": [
|
|
82
82
|
"Create presentations from a brief",
|
|
83
83
|
"Edit slides and decks",
|
|
@@ -13,7 +13,6 @@ interface SlidesHomeLibraryProps {
|
|
|
13
13
|
recentActions?: ReactNode;
|
|
14
14
|
templates: ReactNode;
|
|
15
15
|
recent?: ReactNode;
|
|
16
|
-
recentVisible: boolean;
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
export function SlidesHomeLibrary({
|
|
@@ -25,9 +24,8 @@ export function SlidesHomeLibrary({
|
|
|
25
24
|
recentActions,
|
|
26
25
|
templates,
|
|
27
26
|
recent,
|
|
28
|
-
recentVisible,
|
|
29
27
|
}: SlidesHomeLibraryProps) {
|
|
30
|
-
const activeValue =
|
|
28
|
+
const activeValue = value;
|
|
31
29
|
|
|
32
30
|
return (
|
|
33
31
|
<section
|
|
@@ -45,11 +43,15 @@ export function SlidesHomeLibrary({
|
|
|
45
43
|
>
|
|
46
44
|
<div className="flex flex-wrap items-center justify-between gap-3">
|
|
47
45
|
<TabsList variant="line">
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
<TabsTrigger
|
|
47
|
+
value="recent"
|
|
48
|
+
className="flex-none"
|
|
49
|
+
onClick={() => {
|
|
50
|
+
if (activeValue === "recent") onValueChange("recent");
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
{labels.recent}
|
|
54
|
+
</TabsTrigger>
|
|
53
55
|
<TabsTrigger
|
|
54
56
|
value="templates"
|
|
55
57
|
className="flex-none"
|
|
@@ -70,9 +72,7 @@ export function SlidesHomeLibrary({
|
|
|
70
72
|
)}
|
|
71
73
|
</div>
|
|
72
74
|
<TabsContent value="templates">{templates}</TabsContent>
|
|
73
|
-
{
|
|
74
|
-
<TabsContent value="recent">{recent}</TabsContent>
|
|
75
|
-
) : null}
|
|
75
|
+
<TabsContent value="recent">{recent}</TabsContent>
|
|
76
76
|
</Tabs>
|
|
77
77
|
</section>
|
|
78
78
|
);
|
|
@@ -476,6 +476,7 @@ interface DeckContextType {
|
|
|
476
476
|
noDefaultSlides?: boolean;
|
|
477
477
|
designSystemId?: string | null;
|
|
478
478
|
deferPersistence?: boolean;
|
|
479
|
+
undoableCreation?: boolean;
|
|
479
480
|
},
|
|
480
481
|
) => Deck;
|
|
481
482
|
ensureDeckPersisted: (id: string) => Promise<DeckPersistenceResult>;
|
|
@@ -5432,6 +5433,7 @@ export function DeckProvider({
|
|
|
5432
5433
|
noDefaultSlides?: boolean;
|
|
5433
5434
|
designSystemId?: string | null;
|
|
5434
5435
|
deferPersistence?: boolean;
|
|
5436
|
+
undoableCreation?: boolean;
|
|
5435
5437
|
},
|
|
5436
5438
|
): Deck => {
|
|
5437
5439
|
const insertIndex = decksRef.current.length;
|
|
@@ -5482,18 +5484,20 @@ export function DeckProvider({
|
|
|
5482
5484
|
});
|
|
5483
5485
|
}
|
|
5484
5486
|
setDecksLocal((prev) => [...prev, newDeck]);
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5487
|
+
if (options?.undoableCreation !== false) {
|
|
5488
|
+
undoControllerForDeck(newDeck.id).push({
|
|
5489
|
+
undo: [{ op: "delete-deck", deckId: newDeck.id }],
|
|
5490
|
+
redo: [
|
|
5491
|
+
{
|
|
5492
|
+
op: "restore-deck",
|
|
5493
|
+
deckId: newDeck.id,
|
|
5494
|
+
deck: newDeck,
|
|
5495
|
+
index: insertIndex,
|
|
5496
|
+
},
|
|
5497
|
+
],
|
|
5498
|
+
label: "Create deck",
|
|
5499
|
+
});
|
|
5500
|
+
}
|
|
5497
5501
|
return newDeck;
|
|
5498
5502
|
},
|
|
5499
5503
|
[noteLocalCreate, setDecksLocal, undoControllerForDeck],
|