feat(canvas): @xyflow/svelte dep + typed canvas API client

This commit is contained in:
Benjiyaya
2026-09-06 05:15:00 +08:00
parent 082e767c8e
commit dd51b914a9
3 changed files with 293 additions and 30 deletions
+195 -1
View File
@@ -8,7 +8,8 @@
"name": "calliope-web",
"version": "1.3.2",
"dependencies": {
"@tanstack/svelte-query": "^5.66.0"
"@tanstack/svelte-query": "^5.66.0",
"@xyflow/svelte": "^1.6.5"
},
"devDependencies": {
"@sveltejs/adapter-static": "^3.0.8",
@@ -1179,6 +1180,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/@svelte-put/shortcut": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@svelte-put/shortcut/-/shortcut-4.2.0.tgz",
"integrity": "sha512-hqNLo4yEc++SLgAkZUvuwMxIAsii9qjQtTuzfcYVf3xRxa+0HFcfaWFK7LdU3l+15s9SYVNbPB0qQj9CHFqSuw==",
"license": "MIT",
"peerDependencies": {
"svelte": "^5.1.0"
}
},
"node_modules/@sveltejs/acorn-typescript": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.11.tgz",
@@ -1323,6 +1333,55 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/d3-color": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
"integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
"license": "MIT"
},
"node_modules/@types/d3-drag": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz",
"integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==",
"license": "MIT",
"dependencies": {
"@types/d3-selection": "*"
}
},
"node_modules/@types/d3-interpolate": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
"integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
"license": "MIT",
"dependencies": {
"@types/d3-color": "*"
}
},
"node_modules/@types/d3-selection": {
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz",
"integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==",
"license": "MIT"
},
"node_modules/@types/d3-transition": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz",
"integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==",
"license": "MIT",
"dependencies": {
"@types/d3-selection": "*"
}
},
"node_modules/@types/d3-zoom": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz",
"integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==",
"license": "MIT",
"dependencies": {
"@types/d3-interpolate": "*",
"@types/d3-selection": "*"
}
},
"node_modules/@types/estree": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
@@ -1352,6 +1411,36 @@
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"license": "MIT"
},
"node_modules/@xyflow/svelte": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/@xyflow/svelte/-/svelte-1.6.5.tgz",
"integrity": "sha512-bSPLuFlaa5mVWNg4FIZEt0vY2x+8eImnq57p4G6TlfkFPVBVVOyiBynhn4IN76oVOm7wWyFLHaCloV+4biLYhw==",
"license": "MIT",
"dependencies": {
"@svelte-put/shortcut": "^4.1.0",
"@xyflow/system": "0.0.81"
},
"peerDependencies": {
"svelte": "^5.25.0"
}
},
"node_modules/@xyflow/system": {
"version": "0.0.81",
"resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.81.tgz",
"integrity": "sha512-hfbafW4i7uLq7ILok8QWFFm4KMFw22lbZNJHKfHOMSOOoCk5e5m8yfr84UV9NaJajmogWaLVnp2XFU9JQejlqg==",
"license": "MIT",
"dependencies": {
"@types/d3-drag": "^3.0.7",
"@types/d3-interpolate": "^3.0.4",
"@types/d3-selection": "^3.0.10",
"@types/d3-transition": "^3.0.8",
"@types/d3-zoom": "^3.0.8",
"d3-drag": "^3.0.0",
"d3-interpolate": "^3.0.1",
"d3-selection": "^3.0.0",
"d3-zoom": "^3.0.0"
}
},
"node_modules/acorn": {
"version": "8.17.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz",
@@ -1759,6 +1848,111 @@
"node": ">=4"
}
},
"node_modules/d3-color": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
"integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-dispatch": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
"integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-drag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
"integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
"license": "ISC",
"dependencies": {
"d3-dispatch": "1 - 3",
"d3-selection": "3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-ease": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
"integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-interpolate": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
"integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
"license": "ISC",
"dependencies": {
"d3-color": "1 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-selection": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-timer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
"integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-transition": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
"integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
"license": "ISC",
"dependencies": {
"d3-color": "1 - 3",
"d3-dispatch": "1 - 3",
"d3-ease": "1 - 3",
"d3-interpolate": "1 - 3",
"d3-timer": "1 - 3"
},
"engines": {
"node": ">=12"
},
"peerDependencies": {
"d3-selection": "2 - 3"
}
},
"node_modules/d3-zoom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
"integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
"license": "ISC",
"dependencies": {
"d3-dispatch": "1 - 3",
"d3-drag": "2 - 3",
"d3-interpolate": "1 - 3",
"d3-selection": "2 - 3",
"d3-transition": "2 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+30 -29
View File
@@ -1,34 +1,35 @@
{
"name": "calliope-web",
"version": "1.3.2",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"devDependencies": {
"@sveltejs/adapter-static": "^3.0.8",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"devDependencies": {
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.70.3",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@types/node": "^22.13.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.20.0",
"eslint-plugin-svelte": "^2.46.0",
"postcss": "^8.5.0",
"prettier": "^3.5.0",
"prettier-plugin-svelte": "^3.3.0",
"svelte": "^5.20.0",
"svelte-check": "^4.1.0",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.0",
"vite": "^6.1.0"
},
"dependencies": {
"@tanstack/svelte-query": "^5.66.0"
},
"type": "module"
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@types/node": "^22.13.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.20.0",
"eslint-plugin-svelte": "^2.46.0",
"postcss": "^8.5.0",
"prettier": "^3.5.0",
"prettier-plugin-svelte": "^3.3.0",
"svelte": "^5.20.0",
"svelte-check": "^4.1.0",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.0",
"vite": "^6.1.0"
},
"dependencies": {
"@tanstack/svelte-query": "^5.66.0",
"@xyflow/svelte": "^1.6.5"
},
"type": "module"
}
+68
View File
@@ -439,3 +439,71 @@ export const agentApi = {
cancel: (id: number) =>
api<{ ok: boolean }>(`/api/agent/sessions/${id}/cancel`, { method: 'POST' }),
};
export interface CanvasInfo {
id: number;
title: string;
project_id: number | null;
agent_session_id: number | null;
updated_at: string;
}
export interface CanvasNode {
id: number;
canvas_id: number;
type: 'entity' | 'image' | 'video' | 'text' | 'workflow';
title: string | null;
x: number;
y: number;
width: number | null;
height: number | null;
workflow_id: number | null;
artifact_path: string | null;
job_id: number | null;
status: string;
input_values_json: string;
entity_type: string | null;
entity_id: number | null;
}
export interface CanvasGraph {
canvas: CanvasInfo & {
project?: { id: number; title: string } | null;
viewport_json?: string | null;
};
nodes: CanvasNode[];
}
export const canvasApi = {
list: () => api<CanvasInfo[]>('/api/canvas'),
ensureForProject: (projectId: number, title?: string) =>
api<CanvasGraph>('/api/canvas', {
method: 'POST',
body: JSON.stringify({ project_id: projectId, ...(title ? { title } : {}) }),
}),
ensureForSession: (sessionId: number) =>
api<CanvasGraph>('/api/canvas', {
method: 'POST',
body: JSON.stringify({ agent_session_id: sessionId }),
}),
get: (id: number) => api<CanvasGraph>(`/api/canvas/${id}`),
patchCanvas: (id: number, payload: { title?: string; viewport_json?: string }) =>
api<CanvasInfo & { project?: { id: number; title: string } | null; viewport_json?: string | null }>(
`/api/canvas/${id}`,
{
method: 'PATCH',
body: JSON.stringify(payload),
},
),
patchNode: (
canvasId: number,
nodeId: number,
payload: { x?: number; y?: number; title?: string },
) =>
api<CanvasNode>(`/api/canvas/${canvasId}/nodes/${nodeId}`, {
method: 'PATCH',
body: JSON.stringify(payload),
}),
deleteNode: (canvasId: number, nodeId: number) =>
api<{ ok: boolean }>(`/api/canvas/${canvasId}/nodes/${nodeId}`, { method: 'DELETE' }),
};