@assistkick/create 1.31.0 → 1.33.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 (65) hide show
  1. package/package.json +1 -1
  2. package/templates/assistkick-product-system/package.json +3 -1
  3. package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +10 -3
  4. package/templates/assistkick-product-system/packages/frontend/src/constants/graph.ts +8 -1
  5. package/templates/assistkick-product-system/packages/shared/db/migrate.ts +174 -3
  6. package/templates/assistkick-product-system/packages/shared/db/migrations/0003_solid_manta.sql +1 -0
  7. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0003_snapshot.json +992 -18
  8. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +7 -0
  9. package/templates/assistkick-product-system/packages/shared/db/schema.ts +1 -0
  10. package/templates/assistkick-product-system/packages/shared/lib/constants.ts +12 -0
  11. package/templates/assistkick-product-system/packages/shared/lib/embedding_service.test.ts +75 -0
  12. package/templates/assistkick-product-system/packages/shared/lib/embedding_service.ts +100 -0
  13. package/templates/assistkick-product-system/packages/shared/lib/relevance_search.ts +50 -38
  14. package/templates/assistkick-product-system/packages/shared/package.json +1 -0
  15. package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +11 -3
  16. package/templates/assistkick-product-system/packages/shared/tools/delete_note.ts +50 -0
  17. package/templates/assistkick-product-system/packages/shared/tools/save_note.ts +79 -0
  18. package/templates/assistkick-product-system/packages/shared/tools/search_nodes.ts +6 -1
  19. package/templates/assistkick-product-system/packages/shared/tools/search_notes.ts +99 -0
  20. package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +15 -0
  21. package/templates/assistkick-product-system/packages/shared/db/migrations/0000_dashing_gorgon.sql +0 -128
  22. package/templates/assistkick-product-system/packages/shared/db/migrations/0001_vengeful_wallop.sql +0 -1
  23. package/templates/assistkick-product-system/packages/shared/db/migrations/0002_greedy_excalibur.sql +0 -4
  24. package/templates/assistkick-product-system/packages/shared/db/migrations/0003_lonely_cyclops.sql +0 -17
  25. package/templates/assistkick-product-system/packages/shared/db/migrations/0004_tidy_matthew_murdock.sql +0 -9
  26. package/templates/assistkick-product-system/packages/shared/db/migrations/0005_mysterious_falcon.sql +0 -692
  27. package/templates/assistkick-product-system/packages/shared/db/migrations/0006_next_venom.sql +0 -9
  28. package/templates/assistkick-product-system/packages/shared/db/migrations/0007_deep_barracuda.sql +0 -39
  29. package/templates/assistkick-product-system/packages/shared/db/migrations/0008_puzzling_hannibal_king.sql +0 -1
  30. package/templates/assistkick-product-system/packages/shared/db/migrations/0009_amused_beast.sql +0 -8
  31. package/templates/assistkick-product-system/packages/shared/db/migrations/0010_spotty_moira_mactaggert.sql +0 -9
  32. package/templates/assistkick-product-system/packages/shared/db/migrations/0011_goofy_snowbird.sql +0 -3
  33. package/templates/assistkick-product-system/packages/shared/db/migrations/0011_supreme_doctor_octopus.sql +0 -3
  34. package/templates/assistkick-product-system/packages/shared/db/migrations/0013_reflective_prowler.sql +0 -15
  35. package/templates/assistkick-product-system/packages/shared/db/migrations/0014_nifty_punisher.sql +0 -15
  36. package/templates/assistkick-product-system/packages/shared/db/migrations/0015_magenta_jazinda.sql +0 -1
  37. package/templates/assistkick-product-system/packages/shared/db/migrations/0016_giant_xorn.sql +0 -1
  38. package/templates/assistkick-product-system/packages/shared/db/migrations/0017_sloppy_mentor.sql +0 -6
  39. package/templates/assistkick-product-system/packages/shared/db/migrations/0018_vengeful_kabuki.sql +0 -9
  40. package/templates/assistkick-product-system/packages/shared/db/migrations/0019_careful_sentinels.sql +0 -8
  41. package/templates/assistkick-product-system/packages/shared/db/migrations/0020_clever_spot.sql +0 -27
  42. package/templates/assistkick-product-system/packages/shared/db/migrations/0021_graceful_hex.sql +0 -1
  43. package/templates/assistkick-product-system/packages/shared/db/migrations/0022_short_kingpin.sql +0 -1
  44. package/templates/assistkick-product-system/packages/shared/db/migrations/0023_ambiguous_sharon_carter.sql +0 -1
  45. package/templates/assistkick-product-system/packages/shared/db/migrations/0024_fat_unus.sql +0 -1
  46. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0004_snapshot.json +0 -921
  47. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0005_snapshot.json +0 -1042
  48. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0006_snapshot.json +0 -1101
  49. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0007_snapshot.json +0 -1336
  50. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0008_snapshot.json +0 -1275
  51. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0009_snapshot.json +0 -1327
  52. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0010_snapshot.json +0 -1393
  53. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0011_snapshot.json +0 -1436
  54. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0013_snapshot.json +0 -1538
  55. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0014_snapshot.json +0 -1545
  56. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0015_snapshot.json +0 -1552
  57. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0016_snapshot.json +0 -1560
  58. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0017_snapshot.json +0 -1598
  59. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0018_snapshot.json +0 -1657
  60. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0019_snapshot.json +0 -1709
  61. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0020_snapshot.json +0 -1733
  62. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0021_snapshot.json +0 -1740
  63. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0022_snapshot.json +0 -1755
  64. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0023_snapshot.json +0 -1762
  65. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0024_snapshot.json +0 -1769
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistkick/create",
3
- "version": "1.31.0",
3
+ "version": "1.33.0",
4
4
  "description": "Scaffold assistkick-product-system into any project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,7 +17,9 @@
17
17
  "remotion:render": "pnpm --filter @assistkick/video render"
18
18
  },
19
19
  "pnpm": {
20
- "onlyBuiltDependencies": ["esbuild", "node-pty", "isolated-vm"]
20
+ "onlyBuiltDependencies": [
21
+ "onnxruntime-node"
22
+ ]
21
23
  },
22
24
  "devDependencies": {
23
25
  "@libsql/client": "^0.17.0",
@@ -1,5 +1,5 @@
1
- import React, { useState, useCallback } from 'react';
2
- import { NODE_COLORS, EDGE_COLORS, EDGE_LABELS, LEGEND_LABELS, NODE_SHAPES, nodeShapePath } from '../constants/graph';
1
+ import React, { useState, useCallback, useEffect } from 'react';
2
+ import { NODE_COLORS, EDGE_COLORS, EDGE_LABELS, LEGEND_LABELS, NODE_SHAPES, nodeShapePath, DEFAULT_HIDDEN_TYPES } from '../constants/graph';
3
3
 
4
4
  interface GraphLegendProps {
5
5
  visible: boolean;
@@ -8,12 +8,19 @@ interface GraphLegendProps {
8
8
  }
9
9
 
10
10
  export function GraphLegend({ visible, onTypeToggle, onSearchChange }: GraphLegendProps) {
11
- const [hiddenTypes, setHiddenTypes] = useState<Set<string>>(new Set());
11
+ const [hiddenTypes, setHiddenTypes] = useState<Set<string>>(() => new Set(DEFAULT_HIDDEN_TYPES));
12
12
  const [edgesCollapsed, setEdgesCollapsed] = useState(() => {
13
13
  const stored = localStorage.getItem('legend-edges-collapsed');
14
14
  return stored === null ? true : stored === 'true';
15
15
  });
16
16
 
17
+ // Apply default hidden types on mount
18
+ useEffect(() => {
19
+ if (hiddenTypes.size > 0) {
20
+ onTypeToggle(hiddenTypes);
21
+ }
22
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
23
+
17
24
  const handleTypeClick = useCallback((type: string) => {
18
25
  setHiddenTypes(prev => {
19
26
  const next = new Set(prev);
@@ -16,6 +16,7 @@ export const NODE_COLORS: Record<string, string> = {
16
16
  flow: '#66d9e8',
17
17
  assumption: '#adb5bd',
18
18
  open_question: '#ffe066',
19
+ note: '#a9e34b',
19
20
  };
20
21
 
21
22
  export const EDGE_LABELS: Record<string, string> = {
@@ -60,6 +61,7 @@ export const TYPE_LABELS: Record<string, string> = {
60
61
  flow: 'FLOW',
61
62
  assumption: 'ASMP',
62
63
  open_question: 'OQ',
64
+ note: 'NOTE',
63
65
  };
64
66
 
65
67
  export const LEGEND_LABELS: Record<string, string> = {
@@ -76,6 +78,7 @@ export const LEGEND_LABELS: Record<string, string> = {
76
78
  flow: 'Flow',
77
79
  assumption: 'Assumption',
78
80
  open_question: 'Open Question',
81
+ note: 'Note',
79
82
  };
80
83
 
81
84
  export const NODE_SHAPES: Record<string, string> = {
@@ -92,6 +95,7 @@ export const NODE_SHAPES: Record<string, string> = {
92
95
  flow: 'arrow',
93
96
  assumption: 'triangle-down',
94
97
  open_question: 'octagon',
98
+ note: 'circle',
95
99
  };
96
100
 
97
101
  export const nodeShapePath = (shape: string, r: number): string => {
@@ -174,9 +178,12 @@ export const nodeShapePath = (shape: string, r: number): string => {
174
178
  export const ALL_NODE_TYPES = [
175
179
  'feature', 'epic', 'component', 'data_entity', 'decision', 'tech_choice',
176
180
  'non_functional_requirement', 'design_token', 'design_pattern',
177
- 'user_role', 'flow', 'assumption', 'open_question',
181
+ 'user_role', 'flow', 'assumption', 'open_question', 'note',
178
182
  ];
179
183
 
184
+ /** Node types hidden by default in graph visualization. */
185
+ export const DEFAULT_HIDDEN_TYPES = new Set(['note']);
186
+
180
187
  export const COLUMNS = [
181
188
  { id: 'backlog', label: 'Backlog' },
182
189
  { id: 'todo', label: 'Todo' },
@@ -14,7 +14,7 @@ import { migrate } from 'drizzle-orm/libsql/migrator';
14
14
  import { drizzle } from 'drizzle-orm/libsql';
15
15
  import { createClient } from '@libsql/client';
16
16
  import { getTableColumns, getTableName } from 'drizzle-orm';
17
- import { existsSync, mkdirSync } from 'node:fs';
17
+ import { existsSync, mkdirSync, readFileSync } from 'node:fs';
18
18
  import { join } from 'node:path';
19
19
  import * as schema from './schema.js';
20
20
 
@@ -108,6 +108,164 @@ async function syncColumns() {
108
108
  return added;
109
109
  }
110
110
 
111
+ /**
112
+ * Read a SKILL.md file from the skills directory.
113
+ * Returns the content or a placeholder if the file is not found.
114
+ */
115
+ function readSkillContent(skillsDir: string, skillFolder: string): string {
116
+ const skillPath = join(skillsDir, skillFolder, 'SKILL.md');
117
+ if (existsSync(skillPath)) {
118
+ return readFileSync(skillPath, 'utf-8');
119
+ }
120
+ return `Placeholder — SKILL.md not found for ${skillFolder}`;
121
+ }
122
+
123
+ /**
124
+ * Escape single quotes for SQLite string literals.
125
+ */
126
+ function sqlEscape(value: string): string {
127
+ return value.replace(/'/g, "''");
128
+ }
129
+
130
+ /**
131
+ * Seed default agents and workflows if they don't already exist.
132
+ * Uses INSERT OR IGNORE so existing rows are never overwritten.
133
+ */
134
+ async function seedDefaults() {
135
+ const skillsDir = join(import.meta.dirname, '..', '..', '..', '..', '.claude', 'skills');
136
+ const now = new Date().toISOString();
137
+
138
+ const defaultAgents = [
139
+ { id: '7f83eec8-e762-46eb-9459-9f31096d5faf', name: 'Default Developer', skill: 'assistkick-developer' },
140
+ { id: 'cc66d167-b1aa-40c0-9b19-c683c432ffa4', name: 'Default Reviewer', skill: 'assistkick-code-reviewer' },
141
+ { id: '055ed5fa-83bd-42c1-a913-7a0ea7540f0f', name: 'Default Debugger', skill: 'assistkick-debugger' },
142
+ { id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', name: 'Default Video Script Writer', skill: 'assistkick-video-script-writer' },
143
+ { id: 'b2c3d4e5-f6a7-8901-bcde-f12345678901', name: 'Default Video Composition Agent', skill: 'assistkick-video-composition-agent' },
144
+ ];
145
+
146
+ let seeded = 0;
147
+
148
+ for (const agent of defaultAgents) {
149
+ const grounding = readSkillContent(skillsDir, agent.skill);
150
+ const escaped = sqlEscape(grounding);
151
+ await client.execute(
152
+ `INSERT OR IGNORE INTO agents (id, name, model, skills, grounding, default_grounding, project_id, is_default, created_at, updated_at)
153
+ VALUES ('${agent.id}', '${sqlEscape(agent.name)}', 'claude-opus-4-6', '[]', '${escaped}', '${escaped}', NULL, 1, '${now}', '${now}')`
154
+ );
155
+ const check = await client.execute(`SELECT id FROM agents WHERE id = '${agent.id}'`);
156
+ if (check.rows.length > 0) seeded++;
157
+ }
158
+
159
+ // Default Pipeline workflow
160
+ const defaultPipelineGraph = JSON.stringify({
161
+ nodes: [
162
+ { id: 'start_1', type: 'start', position: { x: 50, y: 250 }, data: { label: 'Start' } },
163
+ { id: 'transition_1', type: 'transitionCard', position: { x: 250, y: 250 }, data: { label: 'Move to In Progress', fromColumn: 'todo', toColumn: 'in_progress' } },
164
+ { id: 'agent_dev', type: 'runAgent', position: { x: 500, y: 250 }, data: { label: 'Run Developer', agentId: '7f83eec8-e762-46eb-9459-9f31096d5faf' } },
165
+ { id: 'transition_2', type: 'transitionCard', position: { x: 750, y: 250 }, data: { label: 'Move to In Review', fromColumn: 'in_progress', toColumn: 'in_review' } },
166
+ { id: 'agent_rev', type: 'runAgent', position: { x: 1000, y: 250 }, data: { label: 'Run Reviewer', agentId: 'cc66d167-b1aa-40c0-9b19-c683c432ffa4' } },
167
+ { id: 'check_pos', type: 'checkCardPosition', position: { x: 1250, y: 250 }, data: { label: 'Check Card Position' } },
168
+ { id: 'end_success', type: 'end', position: { x: 1500, y: 100 }, data: { label: 'End (Success)', outcome: 'success' } },
169
+ { id: 'check_cycle', type: 'checkCycleCount', position: { x: 1500, y: 400 }, data: { label: 'Check Cycle Count', maxCycles: 3 } },
170
+ { id: 'set_meta', type: 'setCardMetadata', position: { x: 1750, y: 400 }, data: { label: 'Set dev_blocked', key: 'dev_blocked', value: 'true' } },
171
+ { id: 'end_blocked', type: 'end', position: { x: 2000, y: 400 }, data: { label: 'End (Blocked)', outcome: 'blocked' } },
172
+ ],
173
+ edges: [
174
+ { id: 'e_start_t1', source: 'start_1', target: 'transition_1' },
175
+ { id: 'e_t1_dev', source: 'transition_1', target: 'agent_dev' },
176
+ { id: 'e_dev_t2', source: 'agent_dev', target: 'transition_2' },
177
+ { id: 'e_t2_rev', source: 'transition_2', target: 'agent_rev' },
178
+ { id: 'e_rev_check', source: 'agent_rev', target: 'check_pos' },
179
+ { id: 'e_check_success', source: 'check_pos', target: 'end_success', sourceHandle: 'qa', data: { label: 'qa' } },
180
+ { id: 'e_check_cycle', source: 'check_pos', target: 'check_cycle', sourceHandle: 'todo', data: { label: 'todo' } },
181
+ { id: 'e_cycle_dev', source: 'check_cycle', target: 'agent_dev', sourceHandle: 'under_limit', data: { label: '< 3' } },
182
+ { id: 'e_cycle_meta', source: 'check_cycle', target: 'set_meta', sourceHandle: 'at_limit', data: { label: '>= 3' } },
183
+ { id: 'e_meta_blocked', source: 'set_meta', target: 'end_blocked' },
184
+ ],
185
+ });
186
+
187
+ await client.execute(
188
+ `INSERT OR IGNORE INTO workflows (id, name, description, project_id, feature_type, trigger_column, is_default, graph_data, created_at, updated_at)
189
+ VALUES ('d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a', 'Default Pipeline', 'Default workflow replicating the standard develop-review-loop pipeline.', NULL, NULL, NULL, 1, '${sqlEscape(defaultPipelineGraph)}', '${now}', '${now}')`
190
+ );
191
+
192
+ // Video Script Generation workflow
193
+ const videoScriptGraph = JSON.stringify({
194
+ nodes: [
195
+ { id: 'start', type: 'start', position: { x: 50, y: 250 }, data: { label: 'Start' } },
196
+ { id: 'agent_script', type: 'runAgent', position: { x: 300, y: 250 }, data: { label: 'Run Script Writer', agentId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', agentName: 'Default Video Script Writer' } },
197
+ { id: 'transition_review', type: 'transitionCard', position: { x: 600, y: 250 }, data: { label: 'Move to Review', fromColumn: 'todo', toColumn: 'in_review' } },
198
+ { id: 'end_success', type: 'end', position: { x: 900, y: 250 }, data: { label: 'End (Success)', outcome: 'success' } },
199
+ ],
200
+ edges: [
201
+ { id: 'e1', source: 'start', target: 'agent_script' },
202
+ { id: 'e2', source: 'agent_script', target: 'transition_review' },
203
+ { id: 'e3', source: 'transition_review', target: 'end_success' },
204
+ ],
205
+ });
206
+
207
+ await client.execute(
208
+ `INSERT OR IGNORE INTO workflows (id, name, description, project_id, feature_type, trigger_column, is_default, graph_data, created_at, updated_at)
209
+ VALUES ('wf-video-script-gen', 'Video Script Generation', 'Generate video script from feature description. Available when video feature is in TODO.', NULL, 'video', 'todo', 0, '${sqlEscape(videoScriptGraph)}', '${now}', '${now}')`
210
+ );
211
+
212
+ // Video Generate Preview workflow
213
+ const videoPreviewGraph = JSON.stringify({
214
+ nodes: [
215
+ { id: 'start', type: 'start', position: { x: 50, y: 250 }, data: { label: 'Start' } },
216
+ { id: 'agent_comp', type: 'runAgent', position: { x: 300, y: 250 }, data: { label: 'Run Composition Builder', agentId: 'b2c3d4e5-f6a7-8901-bcde-f12345678901', agentName: 'Default Video Composition Agent' } },
217
+ { id: 'rebuild', type: 'rebuildBundle', position: { x: 600, y: 250 }, data: { label: 'Rebuild Bundle' } },
218
+ { id: 'tts', type: 'generateTTS', position: { x: 900, y: 250 }, data: { label: 'Generate TTS', scriptPath: 'script.md', force: false, voiceId: '' } },
219
+ { id: 'transition_qa', type: 'transitionCard', position: { x: 1200, y: 250 }, data: { label: 'Move to QA', fromColumn: 'in_review', toColumn: 'qa' } },
220
+ { id: 'end_success', type: 'end', position: { x: 1500, y: 250 }, data: { label: 'End (Success)', outcome: 'success' } },
221
+ ],
222
+ edges: [
223
+ { id: 'e1', source: 'start', target: 'agent_comp' },
224
+ { id: 'e2', source: 'agent_comp', target: 'rebuild' },
225
+ { id: 'e3', source: 'rebuild', target: 'tts' },
226
+ { id: 'e4', source: 'tts', target: 'transition_qa' },
227
+ { id: 'e5', source: 'transition_qa', target: 'end_success' },
228
+ ],
229
+ });
230
+
231
+ await client.execute(
232
+ `INSERT OR IGNORE INTO workflows (id, name, description, project_id, feature_type, trigger_column, is_default, graph_data, created_at, updated_at)
233
+ VALUES ('wf-video-gen-preview', 'Video Generate Preview', 'Build composition, rebuild bundle, and generate TTS audio. Available when video feature is in Review.', NULL, 'video', 'in_review', 0, '${sqlEscape(videoPreviewGraph)}', '${now}', '${now}')`
234
+ );
235
+
236
+ // Video Rendering Pipeline workflow
237
+ const videoRenderGraph = JSON.stringify({
238
+ nodes: [
239
+ { id: 'start', type: 'start', position: { x: 50, y: 250 }, data: { label: 'Start' } },
240
+ { id: 'render', type: 'renderVideo', position: { x: 300, y: 250 }, data: { label: 'Render Video', compositionId: '', resolution: '1920x1080', aspectRatio: '', fileOutputPrefix: '' } },
241
+ { id: 'transition_done', type: 'transitionCard', position: { x: 600, y: 250 }, data: { label: 'Move to Done', fromColumn: 'qa', toColumn: 'done' } },
242
+ { id: 'end_success', type: 'end', position: { x: 900, y: 250 }, data: { label: 'End (Success)', outcome: 'success' } },
243
+ ],
244
+ edges: [
245
+ { id: 'e1', source: 'start', target: 'render' },
246
+ { id: 'e2', source: 'render', target: 'transition_done' },
247
+ { id: 'e3', source: 'transition_done', target: 'end_success' },
248
+ ],
249
+ });
250
+
251
+ await client.execute(
252
+ `INSERT OR IGNORE INTO workflows (id, name, description, project_id, feature_type, trigger_column, is_default, graph_data, created_at, updated_at)
253
+ VALUES ('wf-video-render', 'Video Rendering Pipeline', 'Render video with configurable resolution and output settings. Available when video feature is in QA.', NULL, 'video', 'qa', 0, '${sqlEscape(videoRenderGraph)}', '${now}', '${now}')`
254
+ );
255
+
256
+ return seeded;
257
+ }
258
+
259
+ /**
260
+ * Backfill embeddings for all nodes that don't have one yet.
261
+ * Uses the embedding service to compute vectors locally.
262
+ */
263
+ async function backfillEmbeddings() {
264
+ const { backfillEmbeddings: runBackfill } = await import('../lib/embedding_service.js');
265
+ const count = await runBackfill((msg) => console.log(msg));
266
+ return count;
267
+ }
268
+
111
269
  async function main() {
112
270
  console.log('Running migrations...');
113
271
  await migrate(db, { migrationsFolder: './db/migrations' });
@@ -121,12 +279,25 @@ async function main() {
121
279
  console.log('Column sync complete — all columns present.');
122
280
  }
123
281
 
282
+ console.log('Seeding defaults...');
283
+ const seeded = await seedDefaults();
284
+ console.log(`Seed complete — ${seeded} default agent(s) present.`);
285
+
286
+ console.log('Backfilling embeddings...');
287
+ const embedded = await backfillEmbeddings();
288
+ if (embedded > 0) {
289
+ console.log(`Embedding backfill complete — embedded ${embedded} node(s).`);
290
+ } else {
291
+ console.log('Embedding backfill complete — all nodes have embeddings.');
292
+ }
293
+
124
294
  client.close();
125
- process.exit(0);
295
+ // Allow onnxruntime native cleanup to complete before exit
296
+ setTimeout(() => process.exit(0), 100);
126
297
  }
127
298
 
128
299
  main().catch((err) => {
129
300
  console.error('Migration failed:', err);
130
301
  client.close();
131
- process.exit(1);
302
+ setTimeout(() => process.exit(1), 100);
132
303
  });
@@ -0,0 +1 @@
1
+ ALTER TABLE `nodes` ADD `embedding` text;