@tangle-network/agent-app 0.11.1 → 0.13.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.
Files changed (61) hide show
  1. package/dist/DesignCanvas-3JEEIT6Y.js +10 -0
  2. package/dist/DesignCanvas-3JEEIT6Y.js.map +1 -0
  3. package/dist/DesignCanvasEditor-37LPJIIR.js +9 -0
  4. package/dist/DesignCanvasEditor-37LPJIIR.js.map +1 -0
  5. package/dist/TimelineEditor-OXPJZDP2.js +12 -0
  6. package/dist/TimelineEditor-OXPJZDP2.js.map +1 -0
  7. package/dist/apply-Cp8c3K9D.d.ts +249 -0
  8. package/dist/chunk-2Q73HGDI.js +1743 -0
  9. package/dist/chunk-2Q73HGDI.js.map +1 -0
  10. package/dist/chunk-6UOE5CTA.js +1647 -0
  11. package/dist/chunk-6UOE5CTA.js.map +1 -0
  12. package/dist/chunk-7QCIYDGC.js +1119 -0
  13. package/dist/chunk-7QCIYDGC.js.map +1 -0
  14. package/dist/chunk-A76ZHWNF.js +194 -0
  15. package/dist/chunk-A76ZHWNF.js.map +1 -0
  16. package/dist/chunk-ABGSFUJQ.js +111 -0
  17. package/dist/chunk-ABGSFUJQ.js.map +1 -0
  18. package/dist/{chunk-4YTWB5MG.js → chunk-ETX4O4BB.js} +98 -1
  19. package/dist/chunk-ETX4O4BB.js.map +1 -0
  20. package/dist/chunk-F5KTWRO7.js +2276 -0
  21. package/dist/chunk-F5KTWRO7.js.map +1 -0
  22. package/dist/chunk-IHR6K3GF.js +2367 -0
  23. package/dist/chunk-IHR6K3GF.js.map +1 -0
  24. package/dist/chunk-JZAJE3JL.js +990 -0
  25. package/dist/chunk-JZAJE3JL.js.map +1 -0
  26. package/dist/chunk-ZYBWGSAZ.js +130 -0
  27. package/dist/chunk-ZYBWGSAZ.js.map +1 -0
  28. package/dist/design-canvas/drizzle.d.ts +569 -0
  29. package/dist/design-canvas/drizzle.js +183 -0
  30. package/dist/design-canvas/drizzle.js.map +1 -0
  31. package/dist/design-canvas/index.d.ts +261 -0
  32. package/dist/design-canvas/index.js +96 -0
  33. package/dist/design-canvas/index.js.map +1 -0
  34. package/dist/design-canvas-react/index.d.ts +916 -0
  35. package/dist/design-canvas-react/index.js +423 -0
  36. package/dist/design-canvas-react/index.js.map +1 -0
  37. package/dist/export-presets-Dl5Aa5xj.d.ts +284 -0
  38. package/dist/index.d.ts +11 -2
  39. package/dist/index.js +224 -6
  40. package/dist/mcp-CIupfjxV.d.ts +112 -0
  41. package/dist/mcp-rpc-DLw_r9PQ.d.ts +55 -0
  42. package/dist/model-BHLN208Z.d.ts +183 -0
  43. package/dist/runtime/index.d.ts +108 -1
  44. package/dist/runtime/index.js +7 -1
  45. package/dist/sequences/drizzle.d.ts +1244 -0
  46. package/dist/sequences/drizzle.js +368 -0
  47. package/dist/sequences/drizzle.js.map +1 -0
  48. package/dist/sequences/index.d.ts +331 -0
  49. package/dist/sequences/index.js +114 -0
  50. package/dist/sequences/index.js.map +1 -0
  51. package/dist/sequences-react/index.d.ts +752 -0
  52. package/dist/sequences-react/index.js +241 -0
  53. package/dist/sequences-react/index.js.map +1 -0
  54. package/dist/store-CUStmtdH.d.ts +64 -0
  55. package/dist/store-gckrNq-g.d.ts +242 -0
  56. package/dist/tools/index.d.ts +25 -108
  57. package/dist/tools/index.js +16 -6
  58. package/package.json +62 -2
  59. package/dist/chunk-4YTWB5MG.js.map +0 -1
  60. package/dist/chunk-OLCVUGGI.js +0 -137
  61. package/dist/chunk-OLCVUGGI.js.map +0 -1
@@ -0,0 +1,183 @@
1
+ // src/design-canvas/schema.ts
2
+ import { sql } from "drizzle-orm";
3
+ import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
4
+ var hexId = () => text("id").primaryKey().default(sql`(lower(hex(randomblob(16))))`);
5
+ var jsonMetadata = () => text("metadata", { mode: "json" }).$type().default({});
6
+ var createdAt = () => integer("created_at", { mode: "timestamp" }).notNull().default(sql`(unixepoch())`);
7
+ var updatedAt = () => integer("updated_at", { mode: "timestamp" }).notNull().default(sql`(unixepoch())`);
8
+ function createDesignCanvasTables(opts) {
9
+ const { workspaceTable, userTable } = opts;
10
+ const designDocuments = sqliteTable("design_document", {
11
+ id: hexId(),
12
+ workspaceId: text("workspace_id").notNull().references(() => workspaceTable.id, { onDelete: "cascade" }),
13
+ title: text("title").notNull(),
14
+ /** Full SceneDocument serialized as JSON — persisted and replaced atomically. */
15
+ document: text("document", { mode: "json" }).$type().notNull(),
16
+ /** Monotonic revision; starts at 1, incremented by every successful save. */
17
+ rev: integer("rev").notNull().default(1),
18
+ /** True when this document is a slot-fillable template for data binding. */
19
+ isTemplate: integer("is_template", { mode: "boolean" }).notNull().default(false),
20
+ createdBy: text("created_by").notNull().references(() => userTable.id),
21
+ createdAt: createdAt(),
22
+ updatedAt: updatedAt()
23
+ }, (table) => [
24
+ index("idx_design_document_workspace_updated").on(table.workspaceId, table.updatedAt),
25
+ index("idx_design_document_workspace_template").on(table.workspaceId, table.isTemplate)
26
+ ]);
27
+ const designDecisions = sqliteTable("design_decision", {
28
+ id: hexId(),
29
+ documentId: text("document_id").notNull().references(() => designDocuments.id, { onDelete: "cascade" }),
30
+ workspaceId: text("workspace_id").notNull().references(() => workspaceTable.id, { onDelete: "cascade" }),
31
+ kind: text("kind", { enum: ["human_edit", "agent_edit", "agent_proposal", "export", "note"] }).notNull(),
32
+ instruction: text("instruction").notNull(),
33
+ reasoningSummary: text("reasoning_summary"),
34
+ metadata: jsonMetadata(),
35
+ createdBy: text("created_by").notNull().references(() => userTable.id),
36
+ createdAt: createdAt()
37
+ }, (table) => [
38
+ index("idx_design_decision_document").on(table.documentId, table.createdAt),
39
+ index("idx_design_decision_workspace").on(table.workspaceId)
40
+ ]);
41
+ const designExports = sqliteTable("design_export", {
42
+ id: hexId(),
43
+ documentId: text("document_id").notNull().references(() => designDocuments.id, { onDelete: "cascade" }),
44
+ workspaceId: text("workspace_id").notNull().references(() => workspaceTable.id, { onDelete: "cascade" }),
45
+ format: text("format", { enum: ["png", "jpeg", "json"] }).notNull(),
46
+ status: text("status", { enum: ["queued", "processing", "completed", "failed"] }).notNull().default("queued"),
47
+ resultUrl: text("result_url"),
48
+ metadata: jsonMetadata(),
49
+ createdBy: text("created_by").notNull().references(() => userTable.id),
50
+ createdAt: createdAt()
51
+ }, (table) => [
52
+ index("idx_design_export_document").on(table.documentId, table.createdAt),
53
+ index("idx_design_export_workspace").on(table.workspaceId)
54
+ ]);
55
+ return { designDocuments, designDecisions, designExports };
56
+ }
57
+
58
+ // src/design-canvas/drizzle-store.ts
59
+ import { and, desc, eq, sql as sql2 } from "drizzle-orm";
60
+ var DEFAULT_LIST_LIMIT = 50;
61
+ function createDrizzleSceneStore(options) {
62
+ const { db, tables, scope } = options;
63
+ const { designDocuments, designDecisions, designExports } = tables;
64
+ const docScope = () => and(
65
+ eq(designDocuments.id, scope.documentId),
66
+ eq(designDocuments.workspaceId, scope.workspaceId)
67
+ );
68
+ const decisionScope = () => and(
69
+ eq(designDecisions.documentId, scope.documentId),
70
+ eq(designDecisions.workspaceId, scope.workspaceId)
71
+ );
72
+ const exportScope = () => and(
73
+ eq(designExports.documentId, scope.documentId),
74
+ eq(designExports.workspaceId, scope.workspaceId)
75
+ );
76
+ async function requireDocumentRow() {
77
+ const [row] = await db.select().from(designDocuments).where(docScope()).limit(1);
78
+ if (!row) {
79
+ throw new Error(`Design document ${scope.documentId} not found in workspace ${scope.workspaceId}`);
80
+ }
81
+ return row;
82
+ }
83
+ return {
84
+ async getDocument() {
85
+ const row = await requireDocumentRow();
86
+ return mapDocument(row);
87
+ },
88
+ async saveDocument(document, expectedRev) {
89
+ const result = await db.update(designDocuments).set({
90
+ document,
91
+ rev: sql2`${designDocuments.rev} + 1`,
92
+ updatedAt: /* @__PURE__ */ new Date()
93
+ }).where(and(
94
+ docScope(),
95
+ eq(designDocuments.rev, expectedRev)
96
+ )).returning();
97
+ if (result.length === 0) {
98
+ const [existing] = await db.select().from(designDocuments).where(docScope()).limit(1);
99
+ if (!existing) {
100
+ throw new Error(
101
+ `Design document ${scope.documentId} not found in workspace ${scope.workspaceId}`
102
+ );
103
+ }
104
+ throw new Error(
105
+ `Stale revision: expected rev ${expectedRev} but document is at rev ${existing.rev}. Refetch the document and replay your operations.`
106
+ );
107
+ }
108
+ const [row] = result;
109
+ if (!row) throw new Error("saveDocument UPDATE returned no row");
110
+ return mapDocument(row);
111
+ },
112
+ async recordDecision(input) {
113
+ await requireDocumentRow();
114
+ const [row] = await db.insert(designDecisions).values({
115
+ documentId: scope.documentId,
116
+ workspaceId: scope.workspaceId,
117
+ kind: input.kind,
118
+ instruction: input.instruction,
119
+ reasoningSummary: input.reasoningSummary ?? null,
120
+ metadata: input.metadata ?? {},
121
+ createdBy: scope.userId
122
+ }).returning();
123
+ if (!row) throw new Error("design_decision insert returned no row");
124
+ return mapDecision(row);
125
+ },
126
+ async createExport(format, metadata) {
127
+ await requireDocumentRow();
128
+ const [row] = await db.insert(designExports).values({
129
+ documentId: scope.documentId,
130
+ workspaceId: scope.workspaceId,
131
+ format,
132
+ metadata: metadata ?? {},
133
+ createdBy: scope.userId
134
+ }).returning();
135
+ if (!row) throw new Error("design_export insert returned no row");
136
+ return mapExport(row);
137
+ },
138
+ async listDecisions(limit = DEFAULT_LIST_LIMIT) {
139
+ assertListLimit(limit);
140
+ const rows = await db.select().from(designDecisions).where(decisionScope()).orderBy(desc(designDecisions.createdAt), desc(sql2`rowid`)).limit(limit);
141
+ return rows.map(mapDecision);
142
+ },
143
+ async listExports(limit = DEFAULT_LIST_LIMIT) {
144
+ assertListLimit(limit);
145
+ const rows = await db.select().from(designExports).where(exportScope()).orderBy(desc(designExports.createdAt), desc(sql2`rowid`)).limit(limit);
146
+ return rows.map(mapExport);
147
+ }
148
+ };
149
+ }
150
+ function mapDocument(row) {
151
+ return {
152
+ document: row.document,
153
+ rev: row.rev
154
+ };
155
+ }
156
+ function mapDecision(row) {
157
+ return {
158
+ id: row.id,
159
+ kind: row.kind,
160
+ instruction: row.instruction,
161
+ reasoningSummary: row.reasoningSummary,
162
+ metadata: row.metadata ?? {},
163
+ createdAt: row.createdAt
164
+ };
165
+ }
166
+ function mapExport(row) {
167
+ return {
168
+ id: row.id,
169
+ format: row.format,
170
+ status: row.status,
171
+ resultUrl: row.resultUrl,
172
+ metadata: row.metadata ?? {},
173
+ createdAt: row.createdAt
174
+ };
175
+ }
176
+ function assertListLimit(limit) {
177
+ if (!Number.isInteger(limit) || limit < 1) throw new Error("limit must be a positive integer");
178
+ }
179
+ export {
180
+ createDesignCanvasTables,
181
+ createDrizzleSceneStore
182
+ };
183
+ //# sourceMappingURL=drizzle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/design-canvas/schema.ts","../../src/design-canvas/drizzle-store.ts"],"sourcesContent":["/**\n * Drizzle schema factory for design-canvas tables. The product owns the\n * workspace/user tables; the factory wires design-canvas foreign keys into\n * them so the whole graph lives in one drizzle schema with real cascade\n * semantics. Column names and conventions mirror the sequences schema so\n * products with both surfaces share a DDL style.\n *\n * The `document` column persists the full SceneDocument as JSON. Rev starts\n * at 1 on insert and increments atomically on every successful saveDocument —\n * optimistic concurrency without merge machinery.\n *\n * `isTemplate` marks documents that serve as fill-in-slots templates; the\n * index on (workspaceId, isTemplate) makes template browsing fast.\n */\n\nimport { sql } from 'drizzle-orm'\nimport { index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'\nimport type { AnySQLiteColumn, AnySQLiteTable } from 'drizzle-orm/sqlite-core'\nimport type { SceneDocument } from './model'\n\n/** A product table referenced by FK — only the `id` column is touched. */\nexport type DesignCanvasParentTable = AnySQLiteTable & { id: AnySQLiteColumn }\n\nexport interface CreateDesignCanvasTablesOptions {\n workspaceTable: DesignCanvasParentTable\n userTable: DesignCanvasParentTable\n}\n\nconst hexId = () => text('id').primaryKey().default(sql`(lower(hex(randomblob(16))))`)\n\nconst jsonMetadata = () => text('metadata', { mode: 'json' }).$type<Record<string, unknown>>().default({})\n\nconst createdAt = () => integer('created_at', { mode: 'timestamp' }).notNull().default(sql`(unixepoch())`)\n\nconst updatedAt = () => integer('updated_at', { mode: 'timestamp' }).notNull().default(sql`(unixepoch())`)\n\nexport function createDesignCanvasTables(opts: CreateDesignCanvasTablesOptions) {\n const { workspaceTable, userTable } = opts\n\n const designDocuments = sqliteTable('design_document', {\n id: hexId(),\n workspaceId: text('workspace_id').notNull().references(() => workspaceTable.id, { onDelete: 'cascade' }),\n title: text('title').notNull(),\n /** Full SceneDocument serialized as JSON — persisted and replaced atomically. */\n document: text('document', { mode: 'json' }).$type<SceneDocument>().notNull(),\n /** Monotonic revision; starts at 1, incremented by every successful save. */\n rev: integer('rev').notNull().default(1),\n /** True when this document is a slot-fillable template for data binding. */\n isTemplate: integer('is_template', { mode: 'boolean' }).notNull().default(false),\n createdBy: text('created_by').notNull().references(() => userTable.id),\n createdAt: createdAt(),\n updatedAt: updatedAt(),\n }, (table) => [\n index('idx_design_document_workspace_updated').on(table.workspaceId, table.updatedAt),\n index('idx_design_document_workspace_template').on(table.workspaceId, table.isTemplate),\n ])\n\n const designDecisions = sqliteTable('design_decision', {\n id: hexId(),\n documentId: text('document_id').notNull().references(() => designDocuments.id, { onDelete: 'cascade' }),\n workspaceId: text('workspace_id').notNull().references(() => workspaceTable.id, { onDelete: 'cascade' }),\n kind: text('kind', { enum: ['human_edit', 'agent_edit', 'agent_proposal', 'export', 'note'] }).notNull(),\n instruction: text('instruction').notNull(),\n reasoningSummary: text('reasoning_summary'),\n metadata: jsonMetadata(),\n createdBy: text('created_by').notNull().references(() => userTable.id),\n createdAt: createdAt(),\n }, (table) => [\n index('idx_design_decision_document').on(table.documentId, table.createdAt),\n index('idx_design_decision_workspace').on(table.workspaceId),\n ])\n\n const designExports = sqliteTable('design_export', {\n id: hexId(),\n documentId: text('document_id').notNull().references(() => designDocuments.id, { onDelete: 'cascade' }),\n workspaceId: text('workspace_id').notNull().references(() => workspaceTable.id, { onDelete: 'cascade' }),\n format: text('format', { enum: ['png', 'jpeg', 'json'] }).notNull(),\n status: text('status', { enum: ['queued', 'processing', 'completed', 'failed'] }).notNull().default('queued'),\n resultUrl: text('result_url'),\n metadata: jsonMetadata(),\n createdBy: text('created_by').notNull().references(() => userTable.id),\n createdAt: createdAt(),\n }, (table) => [\n index('idx_design_export_document').on(table.documentId, table.createdAt),\n index('idx_design_export_workspace').on(table.workspaceId),\n ])\n\n return { designDocuments, designDecisions, designExports }\n}\n\nexport type DesignCanvasTables = ReturnType<typeof createDesignCanvasTables>\n\nexport type DesignDocumentRow = DesignCanvasTables['designDocuments']['$inferSelect']\nexport type DesignDecisionRow = DesignCanvasTables['designDecisions']['$inferSelect']\nexport type DesignExportRow = DesignCanvasTables['designExports']['$inferSelect']\n","/**\n * Drizzle-backed `SceneStore` over the tables from `createDesignCanvasTables`.\n * Works against any SQLite drizzle driver (better-sqlite3, D1, libsql).\n *\n * Defense in depth: RBAC runs before the store is constructed, but every\n * query still pins `workspaceId` AND `documentId` from the scope in its WHERE\n * clause, so a leaked or attacker-supplied row id from another workspace can\n * never read or write across the boundary — it surfaces as \"not found\".\n *\n * Optimistic concurrency for saveDocument: the UPDATE WHERE clause includes\n * `rev = expectedRev`; when 0 rows are changed (stale revision or missing\n * document), the store reads back the row to emit a precise error — either\n * \"stale rev\" or \"not found\" — so callers know whether to refetch-and-replay\n * or abort.\n */\n\nimport { and, desc, eq, sql } from 'drizzle-orm'\nimport type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core'\nimport type { SceneDocument } from './model'\nimport type {\n NewSceneDecision,\n SceneDecision,\n SceneDocumentRecord,\n SceneExportFormat,\n SceneExportRecord,\n SceneStore,\n SceneStoreScope,\n} from './store'\nimport type {\n DesignCanvasTables,\n DesignDecisionRow,\n DesignDocumentRow,\n DesignExportRow,\n} from './schema'\n\n/** Any SQLite drizzle database — `any` erases the driver-specific run-result\n * and schema generics so better-sqlite3, D1, and libsql handles all fit. */\nexport type DesignCanvasDatabase = BaseSQLiteDatabase<'sync' | 'async', any, any>\n\nexport interface CreateDrizzleSceneStoreOptions {\n db: DesignCanvasDatabase\n tables: DesignCanvasTables\n scope: SceneStoreScope\n}\n\nconst DEFAULT_LIST_LIMIT = 50\n\nexport function createDrizzleSceneStore(options: CreateDrizzleSceneStoreOptions): SceneStore {\n const { db, tables, scope } = options\n const { designDocuments, designDecisions, designExports } = tables\n\n const docScope = () => and(\n eq(designDocuments.id, scope.documentId),\n eq(designDocuments.workspaceId, scope.workspaceId),\n )\n\n const decisionScope = () => and(\n eq(designDecisions.documentId, scope.documentId),\n eq(designDecisions.workspaceId, scope.workspaceId),\n )\n\n const exportScope = () => and(\n eq(designExports.documentId, scope.documentId),\n eq(designExports.workspaceId, scope.workspaceId),\n )\n\n async function requireDocumentRow(): Promise<DesignDocumentRow> {\n const [row] = await db.select().from(designDocuments).where(docScope()).limit(1)\n if (!row) {\n throw new Error(`Design document ${scope.documentId} not found in workspace ${scope.workspaceId}`)\n }\n return row\n }\n\n return {\n async getDocument(): Promise<SceneDocumentRecord> {\n const row = await requireDocumentRow()\n return mapDocument(row)\n },\n\n async saveDocument(document: SceneDocument, expectedRev: number): Promise<SceneDocumentRecord> {\n const result = await db\n .update(designDocuments)\n .set({\n document,\n rev: sql`${designDocuments.rev} + 1`,\n updatedAt: new Date(),\n })\n .where(and(\n docScope(),\n eq(designDocuments.rev, expectedRev),\n ))\n .returning()\n\n if (result.length === 0) {\n // Distinguish stale-rev from missing document so callers get an\n // actionable error message rather than a generic \"not found\".\n const [existing] = await db.select().from(designDocuments).where(docScope()).limit(1)\n if (!existing) {\n throw new Error(\n `Design document ${scope.documentId} not found in workspace ${scope.workspaceId}`,\n )\n }\n throw new Error(\n `Stale revision: expected rev ${expectedRev} but document is at rev ${existing.rev}. ` +\n `Refetch the document and replay your operations.`,\n )\n }\n\n const [row] = result\n if (!row) throw new Error('saveDocument UPDATE returned no row')\n return mapDocument(row)\n },\n\n async recordDecision(input: NewSceneDecision): Promise<SceneDecision> {\n // Verify the document exists in this workspace before writing the FK row.\n await requireDocumentRow()\n const [row] = await db.insert(designDecisions).values({\n documentId: scope.documentId,\n workspaceId: scope.workspaceId,\n kind: input.kind,\n instruction: input.instruction,\n reasoningSummary: input.reasoningSummary ?? null,\n metadata: input.metadata ?? {},\n createdBy: scope.userId,\n }).returning()\n if (!row) throw new Error('design_decision insert returned no row')\n return mapDecision(row)\n },\n\n async createExport(format: SceneExportFormat, metadata?: Record<string, unknown>): Promise<SceneExportRecord> {\n await requireDocumentRow()\n const [row] = await db.insert(designExports).values({\n documentId: scope.documentId,\n workspaceId: scope.workspaceId,\n format,\n metadata: metadata ?? {},\n createdBy: scope.userId,\n }).returning()\n if (!row) throw new Error('design_export insert returned no row')\n return mapExport(row)\n },\n\n async listDecisions(limit = DEFAULT_LIST_LIMIT): Promise<SceneDecision[]> {\n assertListLimit(limit)\n const rows = await db.select().from(designDecisions)\n .where(decisionScope())\n .orderBy(desc(designDecisions.createdAt), desc(sql`rowid`))\n .limit(limit)\n return rows.map(mapDecision)\n },\n\n async listExports(limit = DEFAULT_LIST_LIMIT): Promise<SceneExportRecord[]> {\n assertListLimit(limit)\n const rows = await db.select().from(designExports)\n .where(exportScope())\n .orderBy(desc(designExports.createdAt), desc(sql`rowid`))\n .limit(limit)\n return rows.map(mapExport)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Row → model mapping. `metadata` is nullable with a `{}` default in the\n// schema; SQL NULL and `{}` are both \"no metadata\" — `?? {}` is a lossless\n// representation conversion, not an error-hiding fallback.\n// ---------------------------------------------------------------------------\n\nfunction mapDocument(row: DesignDocumentRow): SceneDocumentRecord {\n return {\n document: row.document,\n rev: row.rev,\n }\n}\n\nfunction mapDecision(row: DesignDecisionRow): SceneDecision {\n return {\n id: row.id,\n kind: row.kind,\n instruction: row.instruction,\n reasoningSummary: row.reasoningSummary,\n metadata: row.metadata ?? {},\n createdAt: row.createdAt,\n }\n}\n\nfunction mapExport(row: DesignExportRow): SceneExportRecord {\n return {\n id: row.id,\n format: row.format,\n status: row.status,\n resultUrl: row.resultUrl,\n metadata: row.metadata ?? {},\n createdAt: row.createdAt,\n }\n}\n\nfunction assertListLimit(limit: number): void {\n if (!Number.isInteger(limit) || limit < 1) throw new Error('limit must be a positive integer')\n}\n"],"mappings":"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","names":["sql"]}
@@ -0,0 +1,261 @@
1
+ import { c as SceneDocument, f as SceneElementKind, d as SceneElement, g as ScenePage } from '../model-BHLN208Z.js';
2
+ export { B as Bounds, E as EllipseElement, G as GroupElement, I as ImageElement, L as LineElement, N as NewPageOptions, P as PageBleed, a as PageGuides, R as RectElement, S as SCENE_ELEMENT_KINDS, b as SCENE_SCHEMA_VERSION, e as SceneElementBase, h as SceneSettings, T as TextElement, V as VideoElement, i as assertColor, j as assertFinite, k as assertPositiveFinite, l as assertSceneMediaSrc, m as boundsIntersect, n as collectSlots, o as createEmptyDocument, p as createPage, q as elementAabb, r as elementExtent, s as estimateTextHeight, t as findElement, u as requireElement, v as requirePage } from '../model-BHLN208Z.js';
3
+ import { n as SceneOperation, p as ScenePlan } from '../export-presets-Dl5Aa5xj.js';
4
+ export { A as AddElementOperation, a as AddPageOperation, b as ApplyDataOperation, B as BindSlotOperation, C as CHANNEL_PRESETS, c as ChannelPreset, d as ChannelPresetId, e as ChannelScaleResult, D as DeleteElementOperation, f as DeletePageOperation, g as DuplicatePageOperation, E as EXPORT_PRESETS, h as ExportCropRect, i as ExportFormat, j as ExportPreset, G as GroupElementsOperation, R as ReorderElementOperation, k as ReorderPageOperation, S as SCENE_OPERATION_TYPES, l as SIZE_PRESETS, m as SceneAttrsPatch, o as SceneOperationType, q as SetAttrsOperation, r as SetDocumentTitleOperation, s as SetPageGuidesOperation, t as SetPagePropsOperation, u as SizePreset, U as UngroupElementOperation, v as bleedAwareExportBounds, w as bleedAwareExportRect, x as findPreset, y as matchPreset, z as requireChannelPreset, F as scaleForPreset, H as scalePageForChannelPreset } from '../export-presets-Dl5Aa5xj.js';
5
+ import { d as SceneStore, N as NewSceneDecision, a as SceneDocumentRecord } from '../store-CUStmtdH.js';
6
+ export { S as SceneDecision, b as SceneExportFormat, c as SceneExportRecord, e as SceneStoreScope } from '../store-CUStmtdH.js';
7
+ import { c as McpToolDefinition } from '../mcp-rpc-DLw_r9PQ.js';
8
+ import { f as ToolHeaderNames, a as AppToolMcpServer } from '../mcp-CIupfjxV.js';
9
+ import { b as AppToolContext } from '../types-By4B3K37.js';
10
+
11
+ /**
12
+ * Pre-write validation for scene operations. Every rule runs against a
13
+ * `SceneDocument` snapshot BEFORE any mutation, so a rejected batch leaves no
14
+ * partial state. Batch errors carry the shape `operation N (type): reason` —
15
+ * precise enough for an LLM planner to repair the offending operation and
16
+ * resubmit.
17
+ *
18
+ * Validation is static: a batch is checked against the document as given, so
19
+ * an operation may not reference entities created by an earlier operation in
20
+ * the same batch. Dispatchers that chain operations must refresh the document
21
+ * between applications and validate per-operation.
22
+ *
23
+ * Slot typing contract (for apply_data bindings):
24
+ * text elements → value is any string
25
+ * image elements → value must pass assertSceneMediaSrc (src rewrite)
26
+ * video elements → value must pass assertSceneMediaSrc (src rewrite)
27
+ * rect elements → value must pass assertColor (fill recolor)
28
+ * ellipse elements → value must pass assertColor (fill recolor)
29
+ * line elements → value must pass assertColor (stroke recolor)
30
+ * group elements → value must pass assertColor (fill/stroke passed down to children)
31
+ */
32
+
33
+ declare function validateSceneOperations(document: SceneDocument, operations: SceneOperation[]): void;
34
+ declare function validateSceneOperation(document: SceneDocument, operation: SceneOperation): void;
35
+ /**
36
+ * Validates that a slot binding value matches the slot element's kind.
37
+ * text → any string; image/video → media src; rect/ellipse/line/group → color.
38
+ */
39
+ declare function validateSlotValue(slotName: string, elementKind: SceneElementKind, value: string): void;
40
+
41
+ /**
42
+ * Pure application of validated scene operations to a SceneDocument.
43
+ * `applySceneOperations` deep-clones the document then mutates the clone,
44
+ * returning the new document and per-op results. It never touches the store,
45
+ * a clock, or a PRNG — all id generation goes through the caller-supplied
46
+ * `mintId` option so callers control determinism (counter in tests,
47
+ * crypto.randomUUID in production).
48
+ *
49
+ * Rotation semantics for group/ungroup:
50
+ * Group: children retain their absolute rotation. The group origin is the
51
+ * min-x, min-y corner of the AABB union of all member elements. Children
52
+ * are rebased so their position in group-local space equals
53
+ * (element.x - group.x, element.y - group.y). A rotated child appears at
54
+ * the same absolute page position after grouping because the group's additive
55
+ * translation preserves the child's own-origin transform.
56
+ * Ungroup: inverse — child.x += group.x, child.y += group.y; rotation stays.
57
+ * This is consistent with Konva's transform-about-own-origin model without
58
+ * needing a full matrix concatenation for the common case.
59
+ *
60
+ * `storeApplyScenePlan` layers store I/O on top: getDocument → validate →
61
+ * apply → saveDocument(expectedRev) → recordDecision, retrying once on
62
+ * stale-rev by refetch + revalidate + reapply.
63
+ */
64
+
65
+ type SceneApplyResult = {
66
+ kind: 'element';
67
+ pageId: string;
68
+ element: SceneElement;
69
+ } | {
70
+ kind: 'page';
71
+ page: ScenePage;
72
+ } | {
73
+ kind: 'document';
74
+ };
75
+ interface ApplySceneOptions {
76
+ /**
77
+ * Provides fresh ids when duplicate_page re-mints element ids. Never called
78
+ * by any other operation. Counter-based in tests; crypto.randomUUID in
79
+ * production (wrapped so `mintId()` has no arguments, matching this signature).
80
+ */
81
+ mintId: () => string;
82
+ }
83
+ /** Full form: returns the new document AND per-op results. `mintId` must be
84
+ * provided when any operation in the list may be `duplicate_page` (which
85
+ * re-mints element ids); for all other operation types it is never called. */
86
+ declare function applySceneOperations(document: SceneDocument, operations: SceneOperation[], options: ApplySceneOptions): {
87
+ document: SceneDocument;
88
+ results: SceneApplyResult[];
89
+ };
90
+ /** Convenience 2-arg form: returns the new document directly. Uses a
91
+ * monotonic counter as the mintId so `duplicate_page` never collides within
92
+ * a single call (suitable for editor-local optimistic state; server will
93
+ * re-mint on persist). */
94
+ declare function applySceneOperations(document: SceneDocument, operations: SceneOperation[]): SceneDocument;
95
+ /** Apply a single operation to a document and return the new document.
96
+ * Equivalent to `applySceneOperations(doc, [op])` but returns `SceneDocument`
97
+ * directly — the common case in editor commands and tests. */
98
+ declare function applySceneOperation(document: SceneDocument, operation: SceneOperation): SceneDocument;
99
+ declare function storeApplyScenePlan(store: SceneStore, plan: ScenePlan, opts: {
100
+ actorKind: NewSceneDecision['kind'];
101
+ mintId: () => string;
102
+ }): Promise<{
103
+ record: SceneDocumentRecord;
104
+ results: SceneApplyResult[];
105
+ }>;
106
+
107
+ /**
108
+ * Template helpers for design-canvas documents. A template is any document
109
+ * whose elements carry `slot` names — those slots define the fillable surface
110
+ * that data sources and agents target. The helpers here are pure (no store,
111
+ * no Konva) so they run server-side, in MCP tools, or in tests without a DOM.
112
+ *
113
+ * Binding semantics (shared with `apply_data` operation):
114
+ * - text elements: binding value replaces `element.text`
115
+ * - image/video elements: binding value replaces `element.src`
116
+ * - rect/ellipse elements with a slot: binding value replaces `element.fill`
117
+ * (color-slot convention — background swatch templates)
118
+ * - line/group slots are reserved; binding them throws a loud error
119
+ * Unknown binding keys (no matching slot) throw — callers must preflight with
120
+ * `validateBindings` or accept that the throw is the signal to fix their data.
121
+ */
122
+
123
+ type SlotFillKind = 'text' | 'src' | 'color';
124
+ interface TemplateSlot {
125
+ name: string;
126
+ pageId: string;
127
+ elementId: string;
128
+ elementKind: SceneElementKind;
129
+ fillKind: SlotFillKind;
130
+ }
131
+ /**
132
+ * Wraps `collectSlots` with kind-aware fill typing so callers know WHAT to
133
+ * put in each slot without inspecting the element tree themselves.
134
+ * Throws when duplicate slot names exist (propagated from collectSlots).
135
+ */
136
+ declare function listTemplateSlots(document: SceneDocument): TemplateSlot[];
137
+ /**
138
+ * Preflight check: every key in `bindings` must name a slot in the document.
139
+ * Returns a list of problems; an empty array means the bindings are clean.
140
+ * Does NOT throw — designed to run before `instantiateTemplate` so callers
141
+ * can surface a structured error instead of catching.
142
+ */
143
+ declare function validateBindings(document: SceneDocument, bindings: Record<string, string>): string[];
144
+ interface InstantiateOptions {
145
+ /** Human-readable title for the new document. */
146
+ title: string;
147
+ /** Slot bindings to apply after id re-minting. Partial application allowed. */
148
+ bindings?: Record<string, string>;
149
+ /**
150
+ * Caller-supplied id factory — every page/element id in the source document
151
+ * is replaced with a fresh value from this callback. The callback receives
152
+ * the source id so implementations can build stable deterministic ids (e.g.
153
+ * `crypto.randomUUID()` or `nanoid()` from the host).
154
+ */
155
+ mintId(sourceId: string): string;
156
+ }
157
+ /**
158
+ * Produces a new `SceneDocument` from a template:
159
+ * 1. Re-mints every page and element id via `options.mintId` (slot *names* are
160
+ * preserved so apply_data still targets them by name).
161
+ * 2. Applies `options.bindings` with the same semantics as `apply_data`.
162
+ * 3. Stamps `metadata.templateSourceId` with the source document's title so
163
+ * the lineage is traceable without storing separate template provenance rows.
164
+ *
165
+ * Throws when bindings reference unknown slots (validated via `validateBindings`
166
+ * before mutation so no partial state is possible).
167
+ */
168
+ declare function instantiateTemplate(document: SceneDocument, options: InstantiateOptions): SceneDocument;
169
+ /**
170
+ * Applies slot bindings to a document in place (mutates a deep copy produced
171
+ * by the caller). Unknown slot names throw — the preflight in `instantiateTemplate`
172
+ * guarantees this is unreachable there; exported so the `apply_data` operation
173
+ * handler can reuse it without duplicating the switch.
174
+ */
175
+ declare function applyBindingsToDocument(document: SceneDocument, bindings: Record<string, string>): SceneDocument;
176
+
177
+ /**
178
+ * Design-canvas MCP tool registry — what the in-sandbox agent sees over the
179
+ * live agent→canvas channel. Each entry carries an LLM-facing description, a
180
+ * JSON Schema for the arguments, and the typed dispatch that validates the
181
+ * resulting operations, applies them through the store, and records ONE
182
+ * decision row per mutating call.
183
+ *
184
+ * Every mutation: validate → apply via storeApplyScenePlan → recordDecision.
185
+ * Throws anywhere become isError results the model reads to correct its call.
186
+ *
187
+ * Convenience sugar tools (add_text, move_element, etc.) expand to the
188
+ * underlying operation primitives before reaching the kernel — no separate
189
+ * code path to drift.
190
+ */
191
+
192
+ interface DesignCanvasMcpToolEnv {
193
+ store: SceneStore;
194
+ mintId: () => string;
195
+ }
196
+ declare const CANVAS_MCP_TOOLS: McpToolDefinition<DesignCanvasMcpToolEnv>[];
197
+
198
+ declare function findCanvasMcpTool(name: string): McpToolDefinition<DesignCanvasMcpToolEnv> | undefined;
199
+ declare const CANVAS_MCP_TOOL_NAMES: string[];
200
+ declare const CANVAS_ELEMENT_KINDS: readonly string[];
201
+
202
+ /**
203
+ * Streamable-HTTP MCP server for one design-canvas document — the live
204
+ * agent→canvas channel. JSON-RPC 2.0 over POST, stateless per request
205
+ * (Workers-compatible: no session table, no SSE).
206
+ *
207
+ * Trust boundary: the product authenticates the request (capability token,
208
+ * workspace RBAC) BEFORE constructing the scoped {@link SceneStore} and
209
+ * calling this handler — the handler trusts its store completely. Tool
210
+ * execution failures (argument shape, validation, stale rev) become `isError`
211
+ * tool results carrying the thrown message verbatim so the model can read WHY
212
+ * and retry.
213
+ *
214
+ * The JSON-RPC envelope (initialize/ping/tools/list/tools/call, -32601) lives
215
+ * in {@link createMcpToolHandler}; this module wires the canvas tool list +
216
+ * the caller-supplied id-minting function.
217
+ */
218
+
219
+ interface DesignCanvasMcpServerInfo {
220
+ name: string;
221
+ version: string;
222
+ }
223
+ interface CreateDesignCanvasMcpHandlerOptions {
224
+ /** Already scoped + authorized for one (workspace, document, actor). */
225
+ store: SceneStore;
226
+ /** Id-minting function threaded into every mutating tool. Must return
227
+ * a string unique within the document scope — use crypto.randomUUID()
228
+ * in production; a deterministic counter in tests. */
229
+ mintId: () => string;
230
+ serverInfo?: DesignCanvasMcpServerInfo;
231
+ }
232
+ declare function createDesignCanvasMcpHandler(opts: CreateDesignCanvasMcpHandlerOptions): (request: Request) => Promise<Response>;
233
+
234
+ /**
235
+ * Profile entry for the design-canvas MCP server — what a product spreads
236
+ * into its sandbox `AgentProfile.mcp` map so the in-sandbox agent gets the
237
+ * live canvas channel. Same shape and conventions as the sequences entry in
238
+ * ../sequences/mcp-entry: transport 'http', capability token in the
239
+ * Authorization header (server-set, never a tool argument).
240
+ */
241
+
242
+ declare const DEFAULT_DESIGN_CANVAS_MCP_DESCRIPTION = "Live visual asset editor for the current design document: read scene state, add/move/resize/delete elements, manage pages, bind template slots, apply data, and queue exports. All coordinates are CSS pixels.";
243
+ interface BuildDesignCanvasMcpServerEntryOptions {
244
+ /** App base URL the sandbox reaches back to (trailing slash tolerated). */
245
+ baseUrl: string;
246
+ /** Product route serving `createDesignCanvasMcpHandler` for ONE document —
247
+ * the document id is part of the path, never a tool argument. */
248
+ path: string;
249
+ /** Capability token the product minted for this (user, document) scope.
250
+ * With no token there is no entry to build — omit the server instead. */
251
+ token: string;
252
+ description?: string;
253
+ /** Identity headers for products whose route recovers the user via
254
+ * `authenticateToolRequest`. Omit when the bearer token is self-contained. */
255
+ ctx?: AppToolContext;
256
+ headerNames?: ToolHeaderNames;
257
+ }
258
+ /** Build the `AgentProfileMcpServer`-shaped entry for the design-canvas channel. */
259
+ declare function buildDesignCanvasMcpServerEntry(opts: BuildDesignCanvasMcpServerEntryOptions): AppToolMcpServer;
260
+
261
+ export { type ApplySceneOptions, type BuildDesignCanvasMcpServerEntryOptions, CANVAS_ELEMENT_KINDS, CANVAS_MCP_TOOLS, CANVAS_MCP_TOOL_NAMES, type CreateDesignCanvasMcpHandlerOptions, DEFAULT_DESIGN_CANVAS_MCP_DESCRIPTION, type DesignCanvasMcpServerInfo, type DesignCanvasMcpToolEnv, type InstantiateOptions, NewSceneDecision, type SceneApplyResult, SceneDocument, SceneDocumentRecord, SceneElement, SceneElementKind, SceneOperation, ScenePage, ScenePlan, SceneStore, type SlotFillKind, type TemplateSlot, applyBindingsToDocument, applySceneOperation, applySceneOperations, buildDesignCanvasMcpServerEntry, createDesignCanvasMcpHandler, findCanvasMcpTool, instantiateTemplate, listTemplateSlots, storeApplyScenePlan, validateBindings, validateSceneOperation, validateSceneOperations, validateSlotValue };
@@ -0,0 +1,96 @@
1
+ import {
2
+ CANVAS_ELEMENT_KINDS,
3
+ CANVAS_MCP_TOOLS,
4
+ CANVAS_MCP_TOOL_NAMES,
5
+ DEFAULT_DESIGN_CANVAS_MCP_DESCRIPTION,
6
+ SCENE_OPERATION_TYPES,
7
+ applyBindingsToDocument,
8
+ buildDesignCanvasMcpServerEntry,
9
+ createDesignCanvasMcpHandler,
10
+ findCanvasMcpTool,
11
+ instantiateTemplate,
12
+ listTemplateSlots,
13
+ validateBindings
14
+ } from "../chunk-7QCIYDGC.js";
15
+ import {
16
+ CHANNEL_PRESETS,
17
+ EXPORT_PRESETS,
18
+ SCENE_ELEMENT_KINDS,
19
+ SCENE_SCHEMA_VERSION,
20
+ SIZE_PRESETS,
21
+ applySceneOperation,
22
+ applySceneOperations,
23
+ assertColor,
24
+ assertFinite,
25
+ assertPositiveFinite,
26
+ assertSceneMediaSrc,
27
+ bleedAwareExportBounds,
28
+ bleedAwareExportRect,
29
+ boundsIntersect,
30
+ collectSlots,
31
+ createEmptyDocument,
32
+ createPage,
33
+ elementAabb,
34
+ elementExtent,
35
+ estimateTextHeight,
36
+ findElement,
37
+ findPreset,
38
+ matchPreset,
39
+ requireChannelPreset,
40
+ requireElement,
41
+ requirePage,
42
+ scaleForPreset,
43
+ scalePageForChannelPreset,
44
+ storeApplyScenePlan,
45
+ validateSceneOperation,
46
+ validateSceneOperations,
47
+ validateSlotValue
48
+ } from "../chunk-JZAJE3JL.js";
49
+ import "../chunk-A76ZHWNF.js";
50
+ export {
51
+ CANVAS_ELEMENT_KINDS,
52
+ CANVAS_MCP_TOOLS,
53
+ CANVAS_MCP_TOOL_NAMES,
54
+ CHANNEL_PRESETS,
55
+ DEFAULT_DESIGN_CANVAS_MCP_DESCRIPTION,
56
+ EXPORT_PRESETS,
57
+ SCENE_ELEMENT_KINDS,
58
+ SCENE_OPERATION_TYPES,
59
+ SCENE_SCHEMA_VERSION,
60
+ SIZE_PRESETS,
61
+ applyBindingsToDocument,
62
+ applySceneOperation,
63
+ applySceneOperations,
64
+ assertColor,
65
+ assertFinite,
66
+ assertPositiveFinite,
67
+ assertSceneMediaSrc,
68
+ bleedAwareExportBounds,
69
+ bleedAwareExportRect,
70
+ boundsIntersect,
71
+ buildDesignCanvasMcpServerEntry,
72
+ collectSlots,
73
+ createDesignCanvasMcpHandler,
74
+ createEmptyDocument,
75
+ createPage,
76
+ elementAabb,
77
+ elementExtent,
78
+ estimateTextHeight,
79
+ findCanvasMcpTool,
80
+ findElement,
81
+ findPreset,
82
+ instantiateTemplate,
83
+ listTemplateSlots,
84
+ matchPreset,
85
+ requireChannelPreset,
86
+ requireElement,
87
+ requirePage,
88
+ scaleForPreset,
89
+ scalePageForChannelPreset,
90
+ storeApplyScenePlan,
91
+ validateBindings,
92
+ validateSceneOperation,
93
+ validateSceneOperations,
94
+ validateSlotValue
95
+ };
96
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}