@compilr-dev/sdk 0.15.0 → 0.16.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.
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Canvas contract barrel — exposed at `@compilr-dev/sdk/canvas` (renderer-safe:
3
+ * pure types + validation, no node deps). Tools live in the platform module.
4
+ */
5
+ export * from './types.js';
6
+ export * from './validate.js';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Canvas contract barrel — exposed at `@compilr-dev/sdk/canvas` (renderer-safe:
3
+ * pure types + validation, no node deps). Tools live in the platform module.
4
+ */
5
+ export * from './types.js';
6
+ export * from './validate.js';
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Canvas — shared contract types.
3
+ *
4
+ * A Canvas is a persisted visual artifact the agent authors as HTML/SVG, with an
5
+ * optional controls manifest that surfaces live parameters ("Tweaks"). These
6
+ * types are the host-agnostic contract: the SDK owns them + the tools; hosts
7
+ * (Desktop) own the renderer.
8
+ *
9
+ * Intentionally dependency-free so this module can be exposed at the renderer-safe
10
+ * subpath `@compilr-dev/sdk/canvas` (the Desktop renderer needs the control types
11
+ * + validation without pulling node-only deps — same pattern as `.../errors`).
12
+ */
13
+ export type CanvasType = 'infographic' | 'carousel' | 'board';
14
+ /** A control's runtime value. */
15
+ export type ParamValue = string | number | boolean;
16
+ export interface SliderControl {
17
+ type: 'slider';
18
+ param: string;
19
+ label: string;
20
+ default: number;
21
+ min: number;
22
+ max: number;
23
+ step?: number;
24
+ unit?: string;
25
+ group?: string;
26
+ }
27
+ export interface NumberControl {
28
+ type: 'number';
29
+ param: string;
30
+ label: string;
31
+ default: number;
32
+ min?: number;
33
+ max?: number;
34
+ step?: number;
35
+ group?: string;
36
+ }
37
+ export interface ToggleControl {
38
+ type: 'toggle';
39
+ param: string;
40
+ label: string;
41
+ default: boolean;
42
+ group?: string;
43
+ }
44
+ export interface SelectControl {
45
+ type: 'select';
46
+ param: string;
47
+ label: string;
48
+ default: string;
49
+ options: string[];
50
+ group?: string;
51
+ }
52
+ export interface ColorControl {
53
+ type: 'color';
54
+ param: string;
55
+ label: string;
56
+ default: string;
57
+ group?: string;
58
+ }
59
+ export interface TextControl {
60
+ type: 'text';
61
+ param: string;
62
+ label: string;
63
+ default: string;
64
+ placeholder?: string;
65
+ group?: string;
66
+ }
67
+ export type Control = SliderControl | NumberControl | ToggleControl | SelectControl | ColorControl | TextControl;
68
+ export interface ControlManifest {
69
+ controls: Control[];
70
+ }
71
+ /** Full persisted canvas. `content` is the agent's raw HTML/SVG only — the CSP + bridge are injected by the host renderer, never stored. */
72
+ export interface CanvasRecord {
73
+ id: string;
74
+ projectId: string;
75
+ type: CanvasType;
76
+ title: string;
77
+ content: string;
78
+ controls: ControlManifest;
79
+ /** Current tweak state; seeded from control defaults on create. */
80
+ values: Record<string, ParamValue>;
81
+ createdAt: Date;
82
+ updatedAt: Date;
83
+ }
84
+ /** Lightweight list entry (no content). */
85
+ export interface CanvasSummary {
86
+ id: string;
87
+ projectId: string;
88
+ type: CanvasType;
89
+ title: string;
90
+ updatedAt: Date;
91
+ }
92
+ /**
93
+ * Host-implemented persistence for canvases (DB-backed). Optional field on
94
+ * PlatformContext — the canvas tools are absent when a host doesn't provide it.
95
+ */
96
+ export interface ICanvasService {
97
+ create(input: {
98
+ type: CanvasType;
99
+ title: string;
100
+ content: string;
101
+ controls?: ControlManifest;
102
+ values?: Record<string, ParamValue>;
103
+ /** Defaults to the current project when omitted. */
104
+ projectId?: string;
105
+ }): Promise<CanvasRecord>;
106
+ update(id: string, patch: Partial<Pick<CanvasRecord, 'title' | 'content' | 'controls' | 'values'>>): Promise<CanvasRecord>;
107
+ get(id: string): Promise<CanvasRecord | null>;
108
+ /** Metadata only; scoped to the current project when projectId omitted. */
109
+ list(projectId?: string): Promise<CanvasSummary[]>;
110
+ delete(id: string): Promise<CanvasRecord | null>;
111
+ }
112
+ /** Seed a values map from a manifest's control defaults. */
113
+ export declare function seedValues(manifest: ControlManifest | undefined): Record<string, ParamValue>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Canvas — shared contract types.
3
+ *
4
+ * A Canvas is a persisted visual artifact the agent authors as HTML/SVG, with an
5
+ * optional controls manifest that surfaces live parameters ("Tweaks"). These
6
+ * types are the host-agnostic contract: the SDK owns them + the tools; hosts
7
+ * (Desktop) own the renderer.
8
+ *
9
+ * Intentionally dependency-free so this module can be exposed at the renderer-safe
10
+ * subpath `@compilr-dev/sdk/canvas` (the Desktop renderer needs the control types
11
+ * + validation without pulling node-only deps — same pattern as `.../errors`).
12
+ */
13
+ /** Seed a values map from a manifest's control defaults. */
14
+ export function seedValues(manifest) {
15
+ const values = {};
16
+ if (!manifest)
17
+ return values;
18
+ for (const c of manifest.controls)
19
+ values[c.param] = c.default;
20
+ return values;
21
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Canvas controls-manifest validation. Dependency-free (renderer-safe subpath).
3
+ */
4
+ import type { ControlManifest } from './types.js';
5
+ export interface ManifestValidationResult {
6
+ ok: boolean;
7
+ errors: string[];
8
+ }
9
+ /**
10
+ * Validate a controls manifest: array shape, unique + well-formed param names,
11
+ * and per-type default sanity (in range / in options / correct primitive).
12
+ */
13
+ export declare function validateControlManifest(manifest: ControlManifest): ManifestValidationResult;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Canvas controls-manifest validation. Dependency-free (renderer-safe subpath).
3
+ */
4
+ /** Param names must be usable as a CSS custom property suffix and a JS key. */
5
+ const PARAM_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
6
+ const HEX_RE = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
7
+ /**
8
+ * Validate a controls manifest: array shape, unique + well-formed param names,
9
+ * and per-type default sanity (in range / in options / correct primitive).
10
+ */
11
+ export function validateControlManifest(manifest) {
12
+ const errors = [];
13
+ // Treat the manifest as untrusted (agent JSON), not the static type.
14
+ const rawControls = manifest.controls;
15
+ if (!Array.isArray(rawControls)) {
16
+ return { ok: false, errors: ['manifest.controls must be an array'] };
17
+ }
18
+ const seen = new Set();
19
+ for (const raw of rawControls) {
20
+ const param = raw.param;
21
+ if (typeof param !== 'string' || !PARAM_RE.test(param)) {
22
+ errors.push(`invalid param name "${String(param)}" (must match ${PARAM_RE.source})`);
23
+ }
24
+ else if (seen.has(param)) {
25
+ errors.push(`duplicate param "${param}"`);
26
+ }
27
+ if (typeof param === 'string')
28
+ seen.add(param);
29
+ validateDefault(raw, errors);
30
+ }
31
+ return { ok: errors.length === 0, errors };
32
+ }
33
+ function validateDefault(control, errors) {
34
+ const c = control;
35
+ const p = c.param;
36
+ switch (c.type) {
37
+ case 'slider': {
38
+ const { min, max, default: d } = c;
39
+ if (typeof min === 'number' && typeof max === 'number' && min > max) {
40
+ errors.push(`${p}: min ${String(min)} > max ${String(max)}`);
41
+ }
42
+ if (typeof d !== 'number') {
43
+ errors.push(`${p}: slider default must be a number`);
44
+ }
45
+ else if (typeof min === 'number' && typeof max === 'number' && (d < min || d > max)) {
46
+ errors.push(`${p}: default ${String(d)} out of range [${String(min)}, ${String(max)}]`);
47
+ }
48
+ break;
49
+ }
50
+ case 'number': {
51
+ const { min, max, default: d } = c;
52
+ if (typeof d !== 'number') {
53
+ errors.push(`${p}: number default must be a number`);
54
+ }
55
+ else {
56
+ if (typeof min === 'number' && d < min)
57
+ errors.push(`${p}: default < min`);
58
+ if (typeof max === 'number' && d > max)
59
+ errors.push(`${p}: default > max`);
60
+ }
61
+ break;
62
+ }
63
+ case 'toggle':
64
+ if (typeof c.default !== 'boolean')
65
+ errors.push(`${p}: toggle default must be boolean`);
66
+ break;
67
+ case 'select': {
68
+ const opts = c.options;
69
+ if (!Array.isArray(opts) || opts.length === 0) {
70
+ errors.push(`${p}: select needs a non-empty options array`);
71
+ }
72
+ else if (!opts.includes(c.default)) {
73
+ errors.push(`${p}: default "${String(c.default)}" is not in options`);
74
+ }
75
+ break;
76
+ }
77
+ case 'color':
78
+ if (typeof c.default !== 'string' || !HEX_RE.test(c.default)) {
79
+ errors.push(`${p}: color default must be a hex color (e.g. #FF5722)`);
80
+ }
81
+ break;
82
+ case 'text':
83
+ if (typeof c.default !== 'string')
84
+ errors.push(`${p}: text default must be a string`);
85
+ break;
86
+ default:
87
+ errors.push(`${p}: unknown control type "${c.type}"`);
88
+ }
89
+ }
package/dist/index.d.ts CHANGED
@@ -64,7 +64,7 @@ export { detectProject, suggestProjectType, detectCommon } from './detection/ind
64
64
  export type { DetectProjectOptions, DetectionResult, ContentSummary } from './detection/index.js';
65
65
  export { createGuideTool, SHARED_GUIDE_ENTRIES, searchGuideEntries, topicToGuideEntry, } from './guide/index.js';
66
66
  export type { GuideEntry, ContentTopic, ContentSection, GuideToolConfig } from './guide/index.js';
67
- export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createImageTools, ProjectAnchorStore, FileArtifactService, } from './platform/index.js';
67
+ export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createCanvasTools, createImageTools, ProjectAnchorStore, FileArtifactService, } from './platform/index.js';
68
68
  export type { ProjectAnchorStoreConfig, FileArtifactServiceConfig, ImageToolsConfig, ImageResizer, } from './platform/index.js';
69
69
  export { STEP_ORDER, GUIDED_STEP_CRITERIA, getNextStep, isValidTransition, getStepCriteria, formatStepDisplay, getStepNumber, } from './platform/index.js';
70
70
  export type { CustomSkill, CompilrSkillExtension, ForkedFromMarker, SkillEligibilityContext, SkillCollision, SkillDiffLine, SkillValidationIssue, ScopeConfig, SkillResolution, } from './skills/index.js';
@@ -80,6 +80,8 @@ export type { ProjectTypeConfig, ProjectPhase, SuggestedAgent, DocumentTemplate,
80
80
  export { defineTool, createSuccessResult, createErrorResult, mergeHooks, createLoggingHooks, createClaudeProvider, createOpenAIProvider, createGeminiNativeProvider, createOllamaProvider, createTogetherProvider, createGroqProvider, createFireworksProvider, createPerplexityProvider, createOpenRouterProvider, createMockProvider, MockProvider, Agent, ContextManager, DEFAULT_CONTEXT_CONFIG, createTaskTool, createSuggestTool, defaultAgentTypes, TOOL_SETS, BUILTIN_GUARDRAILS, TOOL_NAMES, getDefaultShellManager, builtinSkills, AnchorManager, MCPManager, AgentError, ProviderError, ToolError, ToolTimeoutError, MaxIterationsError, AbortError, } from '@compilr-dev/agents';
81
81
  export { classifyAgentError, isApiKeyError } from './errors/classify.js';
82
82
  export type { AgentErrorCategory, AgentErrorInfo } from './errors/classify.js';
83
+ export { validateControlManifest, seedValues } from './canvas/index.js';
84
+ export type { CanvasType, ParamValue, Control, ControlManifest, CanvasRecord, CanvasSummary, ICanvasService, SliderControl, NumberControl, ToggleControl, SelectControl, ColorControl, TextControl, ManifestValidationResult, } from './canvas/index.js';
83
85
  export type { Tool, HooksConfig, AgentEvent, Message, LLMProvider, AnchorInput, ToolExecutionResult, AgentRunResult, PermissionHandler, PermissionHandlerResponse, ToolPermission, AgentTypeConfig, GuardrailTriggeredHandler, BeforeLLMHookResult, BeforeToolHook, BeforeToolHookResult, AfterToolHook, AgentState, AgentConfig, SessionInfo, Anchor, AnchorScope, AnchorClearOptions, AnchorPriority, AnchorQueryOptions, FileAccessType, FileAccess, GuardrailResult, GuardrailContext, MCPClient, MCPToolDefinition, } from '@compilr-dev/agents';
84
86
  export { DEFAULT_PERMISSION_RULES, WRITE_TOOLS, findMatchingRule, permissionModeLabel, permissionLevelLabel, } from './permissions.js';
85
87
  export type { PermissionRule, PermissionMode, PermissionLevel } from './permissions.js';
package/dist/index.js CHANGED
@@ -147,7 +147,7 @@ export { createGuideTool, SHARED_GUIDE_ENTRIES, searchGuideEntries, topicToGuide
147
147
  // =============================================================================
148
148
  // Platform Tools (runtime — createPlatformTools factory + individual factories)
149
149
  // =============================================================================
150
- export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createImageTools, ProjectAnchorStore, FileArtifactService, } from './platform/index.js';
150
+ export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createCanvasTools, createImageTools, ProjectAnchorStore, FileArtifactService, } from './platform/index.js';
151
151
  // =============================================================================
152
152
  // Platform Workflow (pure step-criteria logic)
153
153
  // =============================================================================
@@ -196,6 +196,9 @@ AgentError, ProviderError, ToolError, ToolTimeoutError, MaxIterationsError, Abor
196
196
  // Error classification — shared by hosts to map provider/agent failures
197
197
  // (esp. missing/invalid API key) into stable categories + host-specific copy.
198
198
  export { classifyAgentError, isApiKeyError } from './errors/classify.js';
199
+ // Canvas contract — shared visual-canvas types + controls-manifest validation.
200
+ // Also exposed at the renderer-safe subpath `@compilr-dev/sdk/canvas`.
201
+ export { validateControlManifest, seedValues } from './canvas/index.js';
199
202
  // =============================================================================
200
203
  // Shared Permission Defaults & Utilities
201
204
  // =============================================================================
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import type { IProjectRepository, IWorkItemRepository, IDocumentRepository, IPlanRepository, ICommentRepository } from './repositories.js';
8
8
  import type { IAnchorService, IArtifactService, IEpisodeService } from './services.js';
9
+ import type { ICanvasService } from '../canvas/types.js';
9
10
  export interface PlatformContext {
10
11
  readonly projects: IProjectRepository;
11
12
  readonly workItems: IWorkItemRepository;
@@ -15,6 +16,7 @@ export interface PlatformContext {
15
16
  readonly anchors?: IAnchorService;
16
17
  readonly artifacts?: IArtifactService;
17
18
  readonly episodes?: IEpisodeService;
19
+ readonly canvas?: ICanvasService;
18
20
  readonly comments?: ICommentRepository;
19
21
  }
20
22
  export interface PlatformHooks {
@@ -5,7 +5,7 @@ export type { ProjectType, ProjectStatus, RepoPattern, WorkflowMode, LifecycleSt
5
5
  export type { IProjectRepository, IWorkItemRepository, IDocumentRepository, IPlanRepository, ICommentRepository, } from './repositories.js';
6
6
  export type { IAnchorService, IArtifactService, IEpisodeService, AnchorData, ArtifactType, ArtifactData, ArtifactSummaryData, WorkEpisode, ProjectWorkSummary, } from './services.js';
7
7
  export type { PlatformContext, PlatformToolsConfig, PlatformHooks } from './context.js';
8
- export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createImageTools, } from './tools/index.js';
8
+ export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createCanvasTools, createImageTools, } from './tools/index.js';
9
9
  export type { ImageToolsConfig, ImageResizer } from './tools/index.js';
10
10
  export { createSQLiteRepositories, SQLiteProjectRepository, SQLiteWorkItemRepository, SQLiteDocumentRepository, SQLitePlanRepository, SQLiteCommentRepository, getDatabase, closeDatabase, closeAllDatabases, databaseExists, SCHEMA_VERSION, SCHEMA_SQL, } from './sqlite/index.js';
11
11
  export type { SQLiteRepositories, CreateSQLiteRepositoriesOptions, ProjectDeleteHooks, ProjectRecord, WorkItemRecord, ProjectDocumentRecord, WorkItemCommentRecord, } from './sqlite/index.js';
@@ -2,7 +2,7 @@
2
2
  * Platform — Repository interfaces, data models, tools, and workflow.
3
3
  */
4
4
  // Platform tools (runtime)
5
- export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createImageTools, } from './tools/index.js';
5
+ export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createCanvasTools, createImageTools, } from './tools/index.js';
6
6
  // SQLite implementations (concrete repositories)
7
7
  export { createSQLiteRepositories, SQLiteProjectRepository, SQLiteWorkItemRepository, SQLiteDocumentRepository, SQLitePlanRepository, SQLiteCommentRepository, getDatabase, closeDatabase, closeAllDatabases, databaseExists, SCHEMA_VERSION, SCHEMA_SQL, } from './sqlite/index.js';
8
8
  // File-based anchor service (shared by CLI and Desktop)
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Canvas Tools — agent authoring + management of visual canvases.
3
+ *
4
+ * 4 tools: canvas_write (create/update), canvas_list, canvas_get, canvas_delete.
5
+ *
6
+ * `content` is the agent's raw HTML/SVG; the host renderer injects the CSP +
7
+ * bridge and renders it in a sandboxed iframe. `controls` is the optional Tweaks
8
+ * manifest (validated here). Persistence is delegated to ICanvasService.
9
+ */
10
+ import type { PlatformToolsConfig } from '../context.js';
11
+ import type { ControlManifest } from '../../canvas/types.js';
12
+ export declare function createCanvasTools(config: PlatformToolsConfig): (import("@compilr-dev/agents").Tool<{
13
+ type: string;
14
+ title: string;
15
+ html: string;
16
+ controls?: ControlManifest;
17
+ canvasId?: string;
18
+ projectId?: string;
19
+ }> | import("@compilr-dev/agents").Tool<{
20
+ canvasId: string;
21
+ }>)[];
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Canvas Tools — agent authoring + management of visual canvases.
3
+ *
4
+ * 4 tools: canvas_write (create/update), canvas_list, canvas_get, canvas_delete.
5
+ *
6
+ * `content` is the agent's raw HTML/SVG; the host renderer injects the CSP +
7
+ * bridge and renders it in a sandboxed iframe. `controls` is the optional Tweaks
8
+ * manifest (validated here). Persistence is delegated to ICanvasService.
9
+ */
10
+ import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
11
+ import { truncateContent } from './truncate.js';
12
+ import { seedValues } from '../../canvas/types.js';
13
+ import { validateControlManifest } from '../../canvas/validate.js';
14
+ const CANVAS_TYPES = ['infographic', 'carousel', 'board'];
15
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
16
+ export function createCanvasTools(config) {
17
+ const canvas = config.context.canvas;
18
+ if (!canvas)
19
+ throw new Error('canvas service required');
20
+ // ---------------------------------------------------------------------------
21
+ // canvas_write — create (no canvasId) or update (canvasId given)
22
+ // ---------------------------------------------------------------------------
23
+ const canvasWriteTool = defineTool({
24
+ name: 'canvas_write',
25
+ description: 'Create or update a visual canvas (infographic, carousel, or board) rendered from HTML/SVG. ' +
26
+ 'Optionally declare a controls manifest ("Tweaks") of live parameters the user can adjust: ' +
27
+ 'each control is { type: slider|number|toggle|select|color|text, param, label, default, ...type config }. ' +
28
+ 'Bind params in your HTML via CSS custom properties var(--param), [data-bind="param"] text, and ' +
29
+ '[data-show="param"] visibility; for computed updates define window.applyParams(values) in a <script>. ' +
30
+ 'Pass canvasId to update an existing canvas; omit it to create a new one.',
31
+ inputSchema: {
32
+ type: 'object',
33
+ properties: {
34
+ type: {
35
+ type: 'string',
36
+ enum: CANVAS_TYPES,
37
+ description: 'Canvas kind: infographic (single composition), carousel (slide sheets), board (infinite 2D).',
38
+ },
39
+ title: { type: 'string', description: 'Canvas title (shown in the library and tab).' },
40
+ html: {
41
+ type: 'string',
42
+ description: 'The canvas content as HTML/SVG. Raw content only — the app injects the sandbox/CSP. ' +
43
+ 'May include a <script> defining window.applyParams(values) for live recompute.',
44
+ },
45
+ controls: {
46
+ type: 'object',
47
+ description: 'Optional Tweaks manifest: { "controls": [ { "type": "slider", "param": "headline", "label": "Headline", "default": 40, "min": 24, "max": 72 }, ... ] }.',
48
+ properties: {
49
+ controls: { type: 'array', items: { type: 'object' } },
50
+ },
51
+ },
52
+ canvasId: {
53
+ type: 'string',
54
+ description: 'Existing canvas id to update. Omit to create a new canvas.',
55
+ },
56
+ projectId: {
57
+ type: 'string',
58
+ description: 'Optional project id. Defaults to the current project.',
59
+ },
60
+ },
61
+ required: ['type', 'title', 'html'],
62
+ },
63
+ execute: async (input) => {
64
+ try {
65
+ if (input.controls) {
66
+ const check = validateControlManifest(input.controls);
67
+ if (!check.ok) {
68
+ return createErrorResult(`Invalid controls manifest:\n- ${check.errors.join('\n- ')}`);
69
+ }
70
+ }
71
+ if (input.canvasId) {
72
+ const updated = await canvas.update(input.canvasId, {
73
+ title: input.title,
74
+ content: input.html,
75
+ // Re-seed values from the new manifest when controls are (re)declared.
76
+ // Phase 1 keeps this simple; a later phase can preserve prior tweaks
77
+ // for surviving params.
78
+ ...(input.controls
79
+ ? { controls: input.controls, values: seedValues(input.controls) }
80
+ : {}),
81
+ });
82
+ return createSuccessResult(`Updated canvas "${updated.title}" (${updated.type})\nID: ${updated.id}`);
83
+ }
84
+ const controls = input.controls ?? { controls: [] };
85
+ const created = await canvas.create({
86
+ type: input.type,
87
+ title: input.title,
88
+ content: input.html,
89
+ controls,
90
+ values: seedValues(controls),
91
+ projectId: input.projectId,
92
+ });
93
+ return createSuccessResult(`Created canvas "${created.title}" (${created.type})\nID: ${created.id}`);
94
+ }
95
+ catch (error) {
96
+ return createErrorResult(`Failed to write canvas: ${error instanceof Error ? error.message : String(error)}`);
97
+ }
98
+ },
99
+ });
100
+ // ---------------------------------------------------------------------------
101
+ // canvas_list
102
+ // ---------------------------------------------------------------------------
103
+ const canvasListTool = defineTool({
104
+ name: 'canvas_list',
105
+ description: 'List the canvases in the current (or given) project.',
106
+ inputSchema: {
107
+ type: 'object',
108
+ properties: {
109
+ projectId: { type: 'string', description: 'Optional project id. Defaults to current.' },
110
+ },
111
+ required: [],
112
+ },
113
+ execute: async (input) => {
114
+ try {
115
+ const items = await canvas.list(input.projectId);
116
+ if (items.length === 0)
117
+ return createSuccessResult('No canvases yet.');
118
+ const lines = items.map((c) => `- [${c.type}] ${c.title} (id: ${c.id})`);
119
+ return createSuccessResult([`${String(items.length)} canvas(es):`, ...lines].join('\n'));
120
+ }
121
+ catch (error) {
122
+ return createErrorResult(`Failed to list canvases: ${error instanceof Error ? error.message : String(error)}`);
123
+ }
124
+ },
125
+ });
126
+ // ---------------------------------------------------------------------------
127
+ // canvas_get
128
+ // ---------------------------------------------------------------------------
129
+ const canvasGetTool = defineTool({
130
+ name: 'canvas_get',
131
+ description: 'Get a canvas by id, including its content, controls manifest, and current values.',
132
+ inputSchema: {
133
+ type: 'object',
134
+ properties: {
135
+ canvasId: { type: 'string', description: 'Canvas id.' },
136
+ },
137
+ required: ['canvasId'],
138
+ },
139
+ execute: async (input) => {
140
+ try {
141
+ const c = await canvas.get(input.canvasId);
142
+ if (!c)
143
+ return createErrorResult(`Canvas "${input.canvasId}" not found.`);
144
+ const tc = truncateContent(c.content);
145
+ const output = `Canvas "${c.title}" (${c.type})\n` +
146
+ `ID: ${c.id}\n` +
147
+ `Controls: ${String(c.controls.controls.length)}\n\n` +
148
+ `--- content ---\n` +
149
+ tc.content;
150
+ return createSuccessResult(output);
151
+ }
152
+ catch (error) {
153
+ return createErrorResult(`Failed to get canvas: ${error instanceof Error ? error.message : String(error)}`);
154
+ }
155
+ },
156
+ });
157
+ // ---------------------------------------------------------------------------
158
+ // canvas_delete
159
+ // ---------------------------------------------------------------------------
160
+ const canvasDeleteTool = defineTool({
161
+ name: 'canvas_delete',
162
+ description: 'Delete a canvas by id.',
163
+ inputSchema: {
164
+ type: 'object',
165
+ properties: {
166
+ canvasId: { type: 'string', description: 'Canvas id.' },
167
+ },
168
+ required: ['canvasId'],
169
+ },
170
+ execute: async (input) => {
171
+ try {
172
+ const deleted = await canvas.delete(input.canvasId);
173
+ if (!deleted)
174
+ return createErrorResult(`Canvas "${input.canvasId}" not found.`);
175
+ return createSuccessResult(`Deleted canvas "${deleted.title}"`);
176
+ }
177
+ catch (error) {
178
+ return createErrorResult(`Failed to delete canvas: ${error instanceof Error ? error.message : String(error)}`);
179
+ }
180
+ },
181
+ });
182
+ return [canvasWriteTool, canvasListTool, canvasGetTool, canvasDeleteTool];
183
+ }
@@ -31,5 +31,6 @@ export { createBacklogTools } from './backlog-tools.js';
31
31
  export { createAnchorTools } from './anchor-tools.js';
32
32
  export { createArtifactTools } from './artifact-tools.js';
33
33
  export { createEpisodeTools } from './episode-tools.js';
34
+ export { createCanvasTools } from './canvas-tools.js';
34
35
  export { createImageTools } from './image-tools.js';
35
36
  export type { ImageToolsConfig, ImageResizer } from './image-tools.js';
@@ -16,6 +16,7 @@ import { createBacklogTools } from './backlog-tools.js';
16
16
  import { createAnchorTools } from './anchor-tools.js';
17
17
  import { createArtifactTools } from './artifact-tools.js';
18
18
  import { createEpisodeTools } from './episode-tools.js';
19
+ import { createCanvasTools } from './canvas-tools.js';
19
20
  import { createImageTools } from './image-tools.js';
20
21
  /**
21
22
  * Create all platform tools operating against the given context.
@@ -54,6 +55,9 @@ export function createPlatformTools(config, options) {
54
55
  if (config.context.episodes) {
55
56
  tools.push(...createEpisodeTools(config));
56
57
  }
58
+ if (config.context.canvas) {
59
+ tools.push(...createCanvasTools(config));
60
+ }
57
61
  return tools;
58
62
  }
59
63
  // Re-export individual factory functions for selective use
@@ -65,4 +69,5 @@ export { createBacklogTools } from './backlog-tools.js';
65
69
  export { createAnchorTools } from './anchor-tools.js';
66
70
  export { createArtifactTools } from './artifact-tools.js';
67
71
  export { createEpisodeTools } from './episode-tools.js';
72
+ export { createCanvasTools } from './canvas-tools.js';
68
73
  export { createImageTools } from './image-tools.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compilr-dev/sdk",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "Universal agent runtime for building AI-powered applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -21,6 +21,10 @@
21
21
  "./errors": {
22
22
  "types": "./dist/errors/classify.d.ts",
23
23
  "import": "./dist/errors/classify.js"
24
+ },
25
+ "./canvas": {
26
+ "types": "./dist/canvas/index.d.ts",
27
+ "import": "./dist/canvas/index.js"
24
28
  }
25
29
  },
26
30
  "files": [