@compilr-dev/sdk 0.17.17 → 0.17.18
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/dist/canvas/types.d.ts +22 -1
- package/dist/canvas/types.js +13 -0
- package/dist/platform/sqlite/canvas-repository.js +7 -5
- package/dist/platform/sqlite/db.js +5 -0
- package/dist/platform/sqlite/schema.d.ts +3 -2
- package/dist/platform/sqlite/schema.js +2 -1
- package/dist/platform/tools/canvas-tools.d.ts +1 -0
- package/dist/platform/tools/canvas-tools.js +10 -0
- package/package.json +1 -1
package/dist/canvas/types.d.ts
CHANGED
|
@@ -81,6 +81,8 @@ export interface CanvasRecord {
|
|
|
81
81
|
controls: ControlManifest;
|
|
82
82
|
/** Current tweak state; seeded from control defaults on create. */
|
|
83
83
|
values: Record<string, ParamValue>;
|
|
84
|
+
/** Page size / aspect (carousel slide aspect). Undefined = default 16:9. */
|
|
85
|
+
pageSize?: PageSize;
|
|
84
86
|
createdAt: Date;
|
|
85
87
|
updatedAt: Date;
|
|
86
88
|
}
|
|
@@ -92,6 +94,24 @@ export interface CanvasSummary {
|
|
|
92
94
|
title: string;
|
|
93
95
|
updatedAt: Date;
|
|
94
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Page size / aspect for a canvas — mainly the carousel slide aspect (16:9
|
|
99
|
+
* widescreen, 4:3 standard, 1:1 square, 4:5 portrait, 9:16 story). The agent may
|
|
100
|
+
* set it and the user may change it live. Infographic/board ignore it (sized by
|
|
101
|
+
* content / declared bounds). Default `16:9`.
|
|
102
|
+
*/
|
|
103
|
+
export type PageSize = '16:9' | '4:3' | '1:1' | '4:5' | '9:16';
|
|
104
|
+
export declare const DEFAULT_PAGE_SIZE: PageSize;
|
|
105
|
+
/** Pixel dimensions per page size (used for render aspect + export sizing). */
|
|
106
|
+
export declare const PAGE_SIZE_DIMENSIONS: Record<PageSize, {
|
|
107
|
+
w: number;
|
|
108
|
+
h: number;
|
|
109
|
+
}>;
|
|
110
|
+
/** Resolve a page size (or undefined) to pixel dimensions, defaulting to 16:9. */
|
|
111
|
+
export declare function pageSizeDimensions(pageSize: PageSize | undefined): {
|
|
112
|
+
w: number;
|
|
113
|
+
h: number;
|
|
114
|
+
};
|
|
95
115
|
export interface CreateCanvasInput {
|
|
96
116
|
projectId: number;
|
|
97
117
|
type: CanvasType;
|
|
@@ -99,7 +119,8 @@ export interface CreateCanvasInput {
|
|
|
99
119
|
content: string;
|
|
100
120
|
controls?: ControlManifest;
|
|
101
121
|
values?: Record<string, ParamValue>;
|
|
122
|
+
pageSize?: PageSize;
|
|
102
123
|
}
|
|
103
|
-
export type UpdateCanvasInput = Partial<Pick<CanvasRecord, 'title' | 'content' | 'controls' | 'values'>>;
|
|
124
|
+
export type UpdateCanvasInput = Partial<Pick<CanvasRecord, 'title' | 'content' | 'controls' | 'values' | 'pageSize'>>;
|
|
104
125
|
/** Seed a values map from a manifest's control defaults. */
|
|
105
126
|
export declare function seedValues(manifest: ControlManifest | undefined): Record<string, ParamValue>;
|
package/dist/canvas/types.js
CHANGED
|
@@ -10,6 +10,19 @@
|
|
|
10
10
|
* subpath `@compilr-dev/sdk/canvas` (the Desktop renderer needs the control types
|
|
11
11
|
* + validation without pulling node-only deps — same pattern as `.../errors`).
|
|
12
12
|
*/
|
|
13
|
+
export const DEFAULT_PAGE_SIZE = '16:9';
|
|
14
|
+
/** Pixel dimensions per page size (used for render aspect + export sizing). */
|
|
15
|
+
export const PAGE_SIZE_DIMENSIONS = {
|
|
16
|
+
'16:9': { w: 1280, h: 720 },
|
|
17
|
+
'4:3': { w: 1024, h: 768 },
|
|
18
|
+
'1:1': { w: 1080, h: 1080 },
|
|
19
|
+
'4:5': { w: 1080, h: 1350 },
|
|
20
|
+
'9:16': { w: 1080, h: 1920 },
|
|
21
|
+
};
|
|
22
|
+
/** Resolve a page size (or undefined) to pixel dimensions, defaulting to 16:9. */
|
|
23
|
+
export function pageSizeDimensions(pageSize) {
|
|
24
|
+
return PAGE_SIZE_DIMENSIONS[pageSize ?? DEFAULT_PAGE_SIZE];
|
|
25
|
+
}
|
|
13
26
|
/** Seed a values map from a manifest's control defaults. */
|
|
14
27
|
export function seedValues(manifest) {
|
|
15
28
|
const values = {};
|
|
@@ -30,6 +30,7 @@ function toCanvas(r) {
|
|
|
30
30
|
content: r.content,
|
|
31
31
|
controls: parseControls(r.controls),
|
|
32
32
|
values: parseValues(r.values),
|
|
33
|
+
pageSize: r.page_size ? r.page_size : undefined,
|
|
33
34
|
createdAt: new Date(r.created_at),
|
|
34
35
|
updatedAt: new Date(r.updated_at),
|
|
35
36
|
};
|
|
@@ -53,9 +54,9 @@ export class SQLiteCanvasRepository {
|
|
|
53
54
|
const controls = JSON.stringify(input.controls ?? { controls: [] });
|
|
54
55
|
const values = JSON.stringify(input.values ?? {});
|
|
55
56
|
const result = this.db
|
|
56
|
-
.prepare(`INSERT INTO canvases (project_id, type, title, content, controls, "values", created_at, updated_at)
|
|
57
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
58
|
-
.run(input.projectId, input.type, input.title, input.content, controls, values, now, now);
|
|
57
|
+
.prepare(`INSERT INTO canvases (project_id, type, title, content, controls, "values", page_size, created_at, updated_at)
|
|
58
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
59
|
+
.run(input.projectId, input.type, input.title, input.content, controls, values, input.pageSize ?? null, now, now);
|
|
59
60
|
const record = this.db
|
|
60
61
|
.prepare('SELECT * FROM canvases WHERE id = ?')
|
|
61
62
|
.get(Number(result.lastInsertRowid));
|
|
@@ -80,9 +81,10 @@ export class SQLiteCanvasRepository {
|
|
|
80
81
|
const content = input.content ?? existing.content;
|
|
81
82
|
const controls = input.controls ? JSON.stringify(input.controls) : existing.controls;
|
|
82
83
|
const values = input.values ? JSON.stringify(input.values) : existing.values;
|
|
84
|
+
const pageSize = input.pageSize !== undefined ? input.pageSize : existing.page_size;
|
|
83
85
|
this.db
|
|
84
|
-
.prepare(`UPDATE canvases SET title = ?, content = ?, controls = ?, "values" = ?, updated_at = ? WHERE id = ?`)
|
|
85
|
-
.run(title, content, controls, values, now, id);
|
|
86
|
+
.prepare(`UPDATE canvases SET title = ?, content = ?, controls = ?, "values" = ?, page_size = ?, updated_at = ? WHERE id = ?`)
|
|
87
|
+
.run(title, content, controls, values, pageSize, now, id);
|
|
86
88
|
const record = this.db.prepare('SELECT * FROM canvases WHERE id = ?').get(id);
|
|
87
89
|
return Promise.resolve(toCanvas(record));
|
|
88
90
|
}
|
|
@@ -175,4 +175,9 @@ function runMigrations(db, fromVersion, toVersion) {
|
|
|
175
175
|
`);
|
|
176
176
|
db.prepare('INSERT INTO schema_version (version) VALUES (?)').run(8);
|
|
177
177
|
}
|
|
178
|
+
if (fromVersion < 9 && toVersion >= 9) {
|
|
179
|
+
// Canvas page size / aspect (carousel slide aspect). NULL = default 16:9.
|
|
180
|
+
db.exec(`ALTER TABLE canvases ADD COLUMN page_size TEXT;`);
|
|
181
|
+
db.prepare('INSERT INTO schema_version (version) VALUES (?)').run(9);
|
|
182
|
+
}
|
|
178
183
|
}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Shared between CLI and Desktop — both access ~/.compilr-dev/projects.db
|
|
5
5
|
* Schema version must be kept in sync across all consumers.
|
|
6
6
|
*/
|
|
7
|
-
export declare const SCHEMA_VERSION =
|
|
8
|
-
export declare const SCHEMA_SQL = "\n-- Schema version tracking\nCREATE TABLE IF NOT EXISTS schema_version (\n version INTEGER PRIMARY KEY,\n applied_at DATETIME DEFAULT CURRENT_TIMESTAMP\n);\n\n-- Projects table\nCREATE TABLE IF NOT EXISTS projects (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT UNIQUE NOT NULL,\n display_name TEXT NOT NULL,\n description TEXT,\n type TEXT DEFAULT 'general',\n status TEXT DEFAULT 'active',\n path TEXT NOT NULL,\n docs_path TEXT,\n repo_pattern TEXT DEFAULT 'single',\n language TEXT,\n framework TEXT,\n package_manager TEXT,\n runtime_version TEXT,\n commands TEXT,\n git_remote TEXT,\n git_branch TEXT DEFAULT 'main',\n workflow_mode TEXT DEFAULT 'flexible',\n lifecycle_state TEXT DEFAULT 'setup',\n current_item_id TEXT,\n last_context TEXT,\n metadata TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n last_activity_at DATETIME\n);\n\n-- Work items (backlog items, tasks, bugs)\nCREATE TABLE IF NOT EXISTS work_items (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project_id INTEGER NOT NULL,\n item_number INTEGER NOT NULL,\n item_id TEXT NOT NULL,\n type TEXT NOT NULL,\n status TEXT DEFAULT 'backlog',\n priority TEXT DEFAULT 'medium',\n guided_step TEXT,\n owner TEXT,\n title TEXT NOT NULL,\n description TEXT,\n estimated_effort TEXT,\n actual_minutes INTEGER,\n completed_at DATETIME,\n completed_by TEXT,\n commit_hash TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n UNIQUE (project_id, item_id)\n);\n\n-- Project documents (PRD, architecture, plans, etc.)\nCREATE TABLE IF NOT EXISTS project_documents (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project_id INTEGER NOT NULL,\n doc_type TEXT NOT NULL,\n title TEXT NOT NULL,\n content TEXT NOT NULL,\n status TEXT,\n work_item_id INTEGER,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n FOREIGN KEY (work_item_id) REFERENCES work_items(id) ON DELETE SET NULL\n);\n\n-- Work item history (audit trail)\nCREATE TABLE IF NOT EXISTS work_item_history (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n work_item_id INTEGER NOT NULL,\n project_id INTEGER NOT NULL,\n action TEXT NOT NULL,\n old_value TEXT,\n new_value TEXT,\n notes TEXT,\n changed_by TEXT,\n changed_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (work_item_id) REFERENCES work_items(id) ON DELETE CASCADE,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\n\n-- Indexes\nCREATE INDEX IF NOT EXISTS idx_projects_path ON projects(path);\nCREATE INDEX IF NOT EXISTS idx_projects_docs_path ON projects(docs_path);\nCREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status);\nCREATE INDEX IF NOT EXISTS idx_work_items_project ON work_items(project_id);\nCREATE INDEX IF NOT EXISTS idx_work_items_status ON work_items(status);\nCREATE INDEX IF NOT EXISTS idx_work_items_priority ON work_items(priority);\nCREATE INDEX IF NOT EXISTS idx_work_items_owner ON work_items(owner);\nCREATE INDEX IF NOT EXISTS idx_project_documents_project ON project_documents(project_id);\nCREATE INDEX IF NOT EXISTS idx_project_documents_type ON project_documents(doc_type);\nCREATE INDEX IF NOT EXISTS idx_project_documents_status ON project_documents(status);\nCREATE INDEX IF NOT EXISTS idx_project_documents_work_item ON project_documents(work_item_id);\nCREATE INDEX IF NOT EXISTS idx_work_item_history_item ON work_item_history(work_item_id);\n\n-- Terminal sessions (multi-terminal awareness)\nCREATE TABLE IF NOT EXISTS terminal_sessions (\n id TEXT PRIMARY KEY,\n project_id INTEGER,\n pid INTEGER NOT NULL,\n tty_path TEXT,\n label TEXT,\n started_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n last_heartbeat DATETIME DEFAULT CURRENT_TIMESTAMP,\n active_agent TEXT DEFAULT 'default',\n agents_json TEXT DEFAULT '[]',\n status TEXT DEFAULT 'active',\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL\n);\nCREATE INDEX IF NOT EXISTS idx_terminal_sessions_project ON terminal_sessions(project_id);\nCREATE INDEX IF NOT EXISTS idx_terminal_sessions_status ON terminal_sessions(status);\n\n-- File locks (multi-terminal file lock awareness)\nCREATE TABLE IF NOT EXISTS file_locks (\n path TEXT NOT NULL,\n project_id INTEGER NOT NULL,\n session_id TEXT NOT NULL,\n agent_id TEXT NOT NULL,\n locked_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (path, project_id),\n FOREIGN KEY (session_id) REFERENCES terminal_sessions(id) ON DELETE CASCADE,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_file_locks_session ON file_locks(session_id);\n\n-- Session notifications (cross-session notifications)\nCREATE TABLE IF NOT EXISTS session_notifications (\n id TEXT PRIMARY KEY,\n project_id INTEGER NOT NULL,\n from_session_id TEXT NOT NULL,\n to_session_id TEXT,\n type TEXT NOT NULL,\n title TEXT NOT NULL,\n message TEXT,\n payload_json TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n read_at DATETIME,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n FOREIGN KEY (from_session_id) REFERENCES terminal_sessions(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_session_notifications_project ON session_notifications(project_id);\nCREATE INDEX IF NOT EXISTS idx_session_notifications_to_session ON session_notifications(to_session_id);\nCREATE INDEX IF NOT EXISTS idx_session_notifications_unread ON session_notifications(read_at);\n\n-- Work item comments\nCREATE TABLE IF NOT EXISTS work_item_comments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n work_item_id INTEGER NOT NULL,\n project_id INTEGER NOT NULL,\n author TEXT NOT NULL,\n content TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (work_item_id) REFERENCES work_items(id) ON DELETE CASCADE,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_work_item_comments_work_item ON work_item_comments(work_item_id);\nCREATE INDEX IF NOT EXISTS idx_work_item_comments_project ON work_item_comments(project_id);\n\n-- Canvases (visual reasoning surfaces: infographic / carousel / board)\nCREATE TABLE IF NOT EXISTS canvases (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project_id INTEGER NOT NULL,\n type TEXT NOT NULL,\n title TEXT NOT NULL,\n content TEXT NOT NULL,\n controls TEXT NOT NULL DEFAULT '{\"controls\":[]}',\n \"values\" TEXT NOT NULL DEFAULT '{}',\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_canvases_project ON canvases(project_id);\n";
|
|
7
|
+
export declare const SCHEMA_VERSION = 9;
|
|
8
|
+
export declare const SCHEMA_SQL = "\n-- Schema version tracking\nCREATE TABLE IF NOT EXISTS schema_version (\n version INTEGER PRIMARY KEY,\n applied_at DATETIME DEFAULT CURRENT_TIMESTAMP\n);\n\n-- Projects table\nCREATE TABLE IF NOT EXISTS projects (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT UNIQUE NOT NULL,\n display_name TEXT NOT NULL,\n description TEXT,\n type TEXT DEFAULT 'general',\n status TEXT DEFAULT 'active',\n path TEXT NOT NULL,\n docs_path TEXT,\n repo_pattern TEXT DEFAULT 'single',\n language TEXT,\n framework TEXT,\n package_manager TEXT,\n runtime_version TEXT,\n commands TEXT,\n git_remote TEXT,\n git_branch TEXT DEFAULT 'main',\n workflow_mode TEXT DEFAULT 'flexible',\n lifecycle_state TEXT DEFAULT 'setup',\n current_item_id TEXT,\n last_context TEXT,\n metadata TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n last_activity_at DATETIME\n);\n\n-- Work items (backlog items, tasks, bugs)\nCREATE TABLE IF NOT EXISTS work_items (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project_id INTEGER NOT NULL,\n item_number INTEGER NOT NULL,\n item_id TEXT NOT NULL,\n type TEXT NOT NULL,\n status TEXT DEFAULT 'backlog',\n priority TEXT DEFAULT 'medium',\n guided_step TEXT,\n owner TEXT,\n title TEXT NOT NULL,\n description TEXT,\n estimated_effort TEXT,\n actual_minutes INTEGER,\n completed_at DATETIME,\n completed_by TEXT,\n commit_hash TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n UNIQUE (project_id, item_id)\n);\n\n-- Project documents (PRD, architecture, plans, etc.)\nCREATE TABLE IF NOT EXISTS project_documents (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project_id INTEGER NOT NULL,\n doc_type TEXT NOT NULL,\n title TEXT NOT NULL,\n content TEXT NOT NULL,\n status TEXT,\n work_item_id INTEGER,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n FOREIGN KEY (work_item_id) REFERENCES work_items(id) ON DELETE SET NULL\n);\n\n-- Work item history (audit trail)\nCREATE TABLE IF NOT EXISTS work_item_history (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n work_item_id INTEGER NOT NULL,\n project_id INTEGER NOT NULL,\n action TEXT NOT NULL,\n old_value TEXT,\n new_value TEXT,\n notes TEXT,\n changed_by TEXT,\n changed_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (work_item_id) REFERENCES work_items(id) ON DELETE CASCADE,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\n\n-- Indexes\nCREATE INDEX IF NOT EXISTS idx_projects_path ON projects(path);\nCREATE INDEX IF NOT EXISTS idx_projects_docs_path ON projects(docs_path);\nCREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status);\nCREATE INDEX IF NOT EXISTS idx_work_items_project ON work_items(project_id);\nCREATE INDEX IF NOT EXISTS idx_work_items_status ON work_items(status);\nCREATE INDEX IF NOT EXISTS idx_work_items_priority ON work_items(priority);\nCREATE INDEX IF NOT EXISTS idx_work_items_owner ON work_items(owner);\nCREATE INDEX IF NOT EXISTS idx_project_documents_project ON project_documents(project_id);\nCREATE INDEX IF NOT EXISTS idx_project_documents_type ON project_documents(doc_type);\nCREATE INDEX IF NOT EXISTS idx_project_documents_status ON project_documents(status);\nCREATE INDEX IF NOT EXISTS idx_project_documents_work_item ON project_documents(work_item_id);\nCREATE INDEX IF NOT EXISTS idx_work_item_history_item ON work_item_history(work_item_id);\n\n-- Terminal sessions (multi-terminal awareness)\nCREATE TABLE IF NOT EXISTS terminal_sessions (\n id TEXT PRIMARY KEY,\n project_id INTEGER,\n pid INTEGER NOT NULL,\n tty_path TEXT,\n label TEXT,\n started_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n last_heartbeat DATETIME DEFAULT CURRENT_TIMESTAMP,\n active_agent TEXT DEFAULT 'default',\n agents_json TEXT DEFAULT '[]',\n status TEXT DEFAULT 'active',\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL\n);\nCREATE INDEX IF NOT EXISTS idx_terminal_sessions_project ON terminal_sessions(project_id);\nCREATE INDEX IF NOT EXISTS idx_terminal_sessions_status ON terminal_sessions(status);\n\n-- File locks (multi-terminal file lock awareness)\nCREATE TABLE IF NOT EXISTS file_locks (\n path TEXT NOT NULL,\n project_id INTEGER NOT NULL,\n session_id TEXT NOT NULL,\n agent_id TEXT NOT NULL,\n locked_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (path, project_id),\n FOREIGN KEY (session_id) REFERENCES terminal_sessions(id) ON DELETE CASCADE,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_file_locks_session ON file_locks(session_id);\n\n-- Session notifications (cross-session notifications)\nCREATE TABLE IF NOT EXISTS session_notifications (\n id TEXT PRIMARY KEY,\n project_id INTEGER NOT NULL,\n from_session_id TEXT NOT NULL,\n to_session_id TEXT,\n type TEXT NOT NULL,\n title TEXT NOT NULL,\n message TEXT,\n payload_json TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n read_at DATETIME,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,\n FOREIGN KEY (from_session_id) REFERENCES terminal_sessions(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_session_notifications_project ON session_notifications(project_id);\nCREATE INDEX IF NOT EXISTS idx_session_notifications_to_session ON session_notifications(to_session_id);\nCREATE INDEX IF NOT EXISTS idx_session_notifications_unread ON session_notifications(read_at);\n\n-- Work item comments\nCREATE TABLE IF NOT EXISTS work_item_comments (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n work_item_id INTEGER NOT NULL,\n project_id INTEGER NOT NULL,\n author TEXT NOT NULL,\n content TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (work_item_id) REFERENCES work_items(id) ON DELETE CASCADE,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_work_item_comments_work_item ON work_item_comments(work_item_id);\nCREATE INDEX IF NOT EXISTS idx_work_item_comments_project ON work_item_comments(project_id);\n\n-- Canvases (visual reasoning surfaces: infographic / carousel / board)\nCREATE TABLE IF NOT EXISTS canvases (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project_id INTEGER NOT NULL,\n type TEXT NOT NULL,\n title TEXT NOT NULL,\n content TEXT NOT NULL,\n controls TEXT NOT NULL DEFAULT '{\"controls\":[]}',\n \"values\" TEXT NOT NULL DEFAULT '{}',\n page_size TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_canvases_project ON canvases(project_id);\n";
|
|
9
9
|
export interface ProjectRecord {
|
|
10
10
|
id: number;
|
|
11
11
|
name: string;
|
|
@@ -71,6 +71,7 @@ export interface CanvasDbRecord {
|
|
|
71
71
|
content: string;
|
|
72
72
|
controls: string;
|
|
73
73
|
values: string;
|
|
74
|
+
page_size: string | null;
|
|
74
75
|
created_at: string;
|
|
75
76
|
updated_at: string;
|
|
76
77
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Shared between CLI and Desktop — both access ~/.compilr-dev/projects.db
|
|
5
5
|
* Schema version must be kept in sync across all consumers.
|
|
6
6
|
*/
|
|
7
|
-
export const SCHEMA_VERSION =
|
|
7
|
+
export const SCHEMA_VERSION = 9;
|
|
8
8
|
export const SCHEMA_SQL = `
|
|
9
9
|
-- Schema version tracking
|
|
10
10
|
CREATE TABLE IF NOT EXISTS schema_version (
|
|
@@ -181,6 +181,7 @@ CREATE TABLE IF NOT EXISTS canvases (
|
|
|
181
181
|
content TEXT NOT NULL,
|
|
182
182
|
controls TEXT NOT NULL DEFAULT '{"controls":[]}',
|
|
183
183
|
"values" TEXT NOT NULL DEFAULT '{}',
|
|
184
|
+
page_size TEXT,
|
|
184
185
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
185
186
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
186
187
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
14
14
|
import { truncateContent } from './truncate.js';
|
|
15
|
+
const PAGE_SIZES = ['16:9', '4:3', '1:1', '4:5', '9:16'];
|
|
15
16
|
import { seedValues } from '../../canvas/types.js';
|
|
16
17
|
import { validateControlManifest } from '../../canvas/validate.js';
|
|
17
18
|
const CANVAS_TYPES = ['infographic', 'carousel', 'board'];
|
|
@@ -91,6 +92,13 @@ export function createCanvasTools(config) {
|
|
|
91
92
|
controls: { type: 'array', items: { type: 'object' } },
|
|
92
93
|
},
|
|
93
94
|
},
|
|
95
|
+
page_size: {
|
|
96
|
+
type: 'string',
|
|
97
|
+
enum: PAGE_SIZES,
|
|
98
|
+
description: 'Optional page size / aspect — mainly the CAROUSEL slide aspect: 16:9 (widescreen, default), ' +
|
|
99
|
+
'4:3 (standard), 1:1 (square/Instagram), 4:5 (portrait), 9:16 (story/reel). Ignored for ' +
|
|
100
|
+
'infographic/board. Set 1:1 or 4:5 for social carousels.',
|
|
101
|
+
},
|
|
94
102
|
canvas_id: {
|
|
95
103
|
type: 'number',
|
|
96
104
|
description: 'Existing canvas id to update. Omit to create a new canvas.',
|
|
@@ -119,6 +127,7 @@ export function createCanvasTools(config) {
|
|
|
119
127
|
...(input.controls
|
|
120
128
|
? { controls: input.controls, values: seedValues(input.controls) }
|
|
121
129
|
: {}),
|
|
130
|
+
...(input.page_size ? { pageSize: input.page_size } : {}),
|
|
122
131
|
});
|
|
123
132
|
if (!updated)
|
|
124
133
|
return createErrorResult(`Canvas ${String(input.canvas_id)} not found.`);
|
|
@@ -136,6 +145,7 @@ export function createCanvasTools(config) {
|
|
|
136
145
|
content: input.html,
|
|
137
146
|
controls,
|
|
138
147
|
values: seedValues(controls),
|
|
148
|
+
pageSize: input.page_size,
|
|
139
149
|
});
|
|
140
150
|
return createSuccessResult(`Created canvas "${created.title}" (${created.type})\nID: ${String(created.id)}`);
|
|
141
151
|
}
|