clitrigger 0.1.5 → 0.1.7

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 (112) hide show
  1. package/README.md +146 -97
  2. package/README_KR.md +268 -0
  3. package/dist/client/assets/index-BiXO2oR3.js +541 -0
  4. package/dist/client/assets/index-tGOot928.css +1 -0
  5. package/dist/client/index.html +2 -2
  6. package/dist/server/data/cli-models-registry.json +34 -0
  7. package/dist/server/db/queries.d.ts +95 -48
  8. package/dist/server/db/queries.d.ts.map +1 -1
  9. package/dist/server/db/queries.js +328 -129
  10. package/dist/server/db/queries.js.map +1 -1
  11. package/dist/server/db/schema.d.ts.map +1 -1
  12. package/dist/server/db/schema.js +67 -35
  13. package/dist/server/db/schema.js.map +1 -1
  14. package/dist/server/index.d.ts.map +1 -1
  15. package/dist/server/index.js +43 -20
  16. package/dist/server/index.js.map +1 -1
  17. package/dist/server/lib/git.d.ts +3 -0
  18. package/dist/server/lib/git.d.ts.map +1 -0
  19. package/dist/server/lib/git.js +7 -0
  20. package/dist/server/lib/git.js.map +1 -0
  21. package/dist/server/routes/{pipelines.d.ts → analytics.d.ts} +1 -1
  22. package/dist/server/routes/analytics.d.ts.map +1 -0
  23. package/dist/server/routes/analytics.js +102 -0
  24. package/dist/server/routes/analytics.js.map +1 -0
  25. package/dist/server/routes/cli-status.d.ts +3 -0
  26. package/dist/server/routes/cli-status.d.ts.map +1 -0
  27. package/dist/server/routes/cli-status.js +28 -0
  28. package/dist/server/routes/cli-status.js.map +1 -0
  29. package/dist/server/routes/discussions.js +5 -5
  30. package/dist/server/routes/discussions.js.map +1 -1
  31. package/dist/server/routes/execution.d.ts.map +1 -1
  32. package/dist/server/routes/execution.js +9 -5
  33. package/dist/server/routes/execution.js.map +1 -1
  34. package/dist/server/routes/images.d.ts +21 -0
  35. package/dist/server/routes/images.d.ts.map +1 -1
  36. package/dist/server/routes/images.js +163 -1
  37. package/dist/server/routes/images.js.map +1 -1
  38. package/dist/server/routes/logs.js +3 -3
  39. package/dist/server/routes/logs.js.map +1 -1
  40. package/dist/server/routes/models.d.ts.map +1 -1
  41. package/dist/server/routes/models.js +2 -0
  42. package/dist/server/routes/models.js.map +1 -1
  43. package/dist/server/routes/planner.d.ts +3 -0
  44. package/dist/server/routes/planner.d.ts.map +1 -0
  45. package/dist/server/routes/planner.js +344 -0
  46. package/dist/server/routes/planner.js.map +1 -0
  47. package/dist/server/routes/projects.d.ts.map +1 -1
  48. package/dist/server/routes/projects.js +159 -1
  49. package/dist/server/routes/projects.js.map +1 -1
  50. package/dist/server/routes/schedules.d.ts.map +1 -1
  51. package/dist/server/routes/schedules.js +39 -0
  52. package/dist/server/routes/schedules.js.map +1 -1
  53. package/dist/server/routes/sessions.d.ts +3 -0
  54. package/dist/server/routes/sessions.d.ts.map +1 -0
  55. package/dist/server/routes/sessions.js +200 -0
  56. package/dist/server/routes/sessions.js.map +1 -0
  57. package/dist/server/routes/todos.d.ts.map +1 -1
  58. package/dist/server/routes/todos.js +16 -4
  59. package/dist/server/routes/todos.js.map +1 -1
  60. package/dist/server/services/claude-manager.d.ts.map +1 -1
  61. package/dist/server/services/claude-manager.js +63 -28
  62. package/dist/server/services/claude-manager.js.map +1 -1
  63. package/dist/server/services/cli-adapters.d.ts +60 -0
  64. package/dist/server/services/cli-adapters.d.ts.map +1 -1
  65. package/dist/server/services/cli-adapters.js +123 -5
  66. package/dist/server/services/cli-adapters.js.map +1 -1
  67. package/dist/server/services/cli-status.d.ts +8 -0
  68. package/dist/server/services/cli-status.d.ts.map +1 -0
  69. package/dist/server/services/cli-status.js +57 -0
  70. package/dist/server/services/cli-status.js.map +1 -0
  71. package/dist/server/services/discussion-orchestrator.d.ts.map +1 -1
  72. package/dist/server/services/discussion-orchestrator.js +33 -6
  73. package/dist/server/services/discussion-orchestrator.js.map +1 -1
  74. package/dist/server/services/log-streamer.d.ts +12 -0
  75. package/dist/server/services/log-streamer.d.ts.map +1 -1
  76. package/dist/server/services/log-streamer.js +116 -31
  77. package/dist/server/services/log-streamer.js.map +1 -1
  78. package/dist/server/services/model-sync.d.ts +22 -0
  79. package/dist/server/services/model-sync.d.ts.map +1 -0
  80. package/dist/server/services/model-sync.js +181 -0
  81. package/dist/server/services/model-sync.js.map +1 -0
  82. package/dist/server/services/orchestrator.d.ts +18 -0
  83. package/dist/server/services/orchestrator.d.ts.map +1 -1
  84. package/dist/server/services/orchestrator.js +81 -11
  85. package/dist/server/services/orchestrator.js.map +1 -1
  86. package/dist/server/services/pty-output-filter.d.ts.map +1 -1
  87. package/dist/server/services/pty-output-filter.js +91 -8
  88. package/dist/server/services/pty-output-filter.js.map +1 -1
  89. package/dist/server/services/session-manager.d.ts +22 -0
  90. package/dist/server/services/session-manager.d.ts.map +1 -0
  91. package/dist/server/services/session-manager.js +249 -0
  92. package/dist/server/services/session-manager.js.map +1 -0
  93. package/dist/server/services/worktree-manager.d.ts +11 -1
  94. package/dist/server/services/worktree-manager.d.ts.map +1 -1
  95. package/dist/server/services/worktree-manager.js +128 -32
  96. package/dist/server/services/worktree-manager.js.map +1 -1
  97. package/dist/server/websocket/events.d.ts +13 -22
  98. package/dist/server/websocket/events.d.ts.map +1 -1
  99. package/dist/server/websocket/index.d.ts.map +1 -1
  100. package/dist/server/websocket/index.js +17 -2
  101. package/dist/server/websocket/index.js.map +1 -1
  102. package/package.json +3 -3
  103. package/README_EN.md +0 -219
  104. package/dist/client/assets/index-B4peRpUi.js +0 -134
  105. package/dist/client/assets/index-Bjyoy6lB.css +0 -1
  106. package/dist/server/routes/pipelines.d.ts.map +0 -1
  107. package/dist/server/routes/pipelines.js +0 -315
  108. package/dist/server/routes/pipelines.js.map +0 -1
  109. package/dist/server/services/pipeline-orchestrator.d.ts +0 -43
  110. package/dist/server/services/pipeline-orchestrator.d.ts.map +0 -1
  111. package/dist/server/services/pipeline-orchestrator.js +0 -503
  112. package/dist/server/services/pipeline-orchestrator.js.map +0 -1
@@ -164,12 +164,13 @@ export function deleteProject(id) {
164
164
  const result = db.prepare('DELETE FROM projects WHERE id = ?').run(id);
165
165
  return result.changes > 0;
166
166
  }
167
- export function createTodo(projectId, title, description, priority = 0, cliTool, cliModel, scheduleId, dependsOn, maxTurns) {
167
+ export function createTodo(projectId, title, description, priority = 0, cliTool, cliModel, scheduleId, dependsOn, maxTurns, useWorktree) {
168
168
  const db = getDatabase();
169
169
  const id = uuidv4();
170
170
  const now = new Date().toISOString();
171
- db.prepare(`INSERT INTO todos (id, project_id, title, description, priority, cli_tool, cli_model, schedule_id, depends_on, max_turns, created_at, updated_at)
172
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, projectId, title, description ?? null, priority, cliTool ?? null, cliModel ?? null, scheduleId ?? null, dependsOn ?? null, maxTurns ?? null, now, now);
171
+ const normalizedUseWorktree = useWorktree === 0 || useWorktree === 1 ? useWorktree : null;
172
+ db.prepare(`INSERT INTO todos (id, project_id, title, description, priority, cli_tool, cli_model, schedule_id, depends_on, max_turns, use_worktree, created_at, updated_at)
173
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, projectId, title, description ?? null, priority, cliTool ?? null, cliModel ?? null, scheduleId ?? null, dependsOn ?? null, maxTurns ?? null, normalizedUseWorktree, now, now);
173
174
  return getTodoById(id);
174
175
  }
175
176
  export function getTodosByProjectId(projectId) {
@@ -256,6 +257,19 @@ export function updateTodo(id, updates) {
256
257
  fields.push('round_count = ?');
257
258
  values.push(updates.round_count);
258
259
  }
260
+ if (updates.total_cost_usd !== undefined) {
261
+ fields.push('total_cost_usd = ?');
262
+ values.push(updates.total_cost_usd);
263
+ }
264
+ if (updates.total_tokens !== undefined) {
265
+ fields.push('total_tokens = ?');
266
+ values.push(updates.total_tokens);
267
+ }
268
+ if (updates.use_worktree !== undefined) {
269
+ const v = updates.use_worktree === 0 || updates.use_worktree === 1 ? updates.use_worktree : null;
270
+ fields.push('use_worktree = ?');
271
+ values.push(v);
272
+ }
259
273
  if (fields.length === 0)
260
274
  return getTodoById(id);
261
275
  fields.push('updated_at = ?');
@@ -295,125 +309,6 @@ export function deleteTaskLogsByTodoId(todoId) {
295
309
  const result = db.prepare('DELETE FROM task_logs WHERE todo_id = ?').run(todoId);
296
310
  return result.changes;
297
311
  }
298
- export function createPipeline(projectId, title, description) {
299
- const db = getDatabase();
300
- const id = uuidv4();
301
- const now = new Date().toISOString();
302
- db.prepare(`INSERT INTO pipelines (id, project_id, title, description, created_at, updated_at)
303
- VALUES (?, ?, ?, ?, ?, ?)`).run(id, projectId, title, description, now, now);
304
- return getPipelineById(id);
305
- }
306
- export function getPipelinesByProjectId(projectId) {
307
- const db = getDatabase();
308
- return db.prepare('SELECT * FROM pipelines WHERE project_id = ? ORDER BY created_at DESC').all(projectId);
309
- }
310
- export function getPipelineById(id) {
311
- const db = getDatabase();
312
- return db.prepare('SELECT * FROM pipelines WHERE id = ?').get(id);
313
- }
314
- export function updatePipeline(id, updates) {
315
- const db = getDatabase();
316
- const fields = [];
317
- const values = [];
318
- if (updates.title !== undefined) {
319
- fields.push('title = ?');
320
- values.push(updates.title);
321
- }
322
- if (updates.description !== undefined) {
323
- fields.push('description = ?');
324
- values.push(updates.description);
325
- }
326
- if (updates.current_phase !== undefined) {
327
- fields.push('current_phase = ?');
328
- values.push(updates.current_phase);
329
- }
330
- if (updates.branch_name !== undefined) {
331
- fields.push('branch_name = ?');
332
- values.push(updates.branch_name);
333
- }
334
- if (updates.worktree_path !== undefined) {
335
- fields.push('worktree_path = ?');
336
- values.push(updates.worktree_path);
337
- }
338
- if (updates.process_pid !== undefined) {
339
- fields.push('process_pid = ?');
340
- values.push(updates.process_pid);
341
- }
342
- if (fields.length === 0)
343
- return getPipelineById(id);
344
- fields.push('updated_at = ?');
345
- values.push(new Date().toISOString());
346
- values.push(id);
347
- db.prepare(`UPDATE pipelines SET ${fields.join(', ')} WHERE id = ?`).run(...values);
348
- return getPipelineById(id);
349
- }
350
- export function updatePipelineStatus(id, status) {
351
- const db = getDatabase();
352
- db.prepare('UPDATE pipelines SET status = ?, updated_at = ? WHERE id = ?').run(status, new Date().toISOString(), id);
353
- return getPipelineById(id);
354
- }
355
- export function getPipelinesByStatus(status) {
356
- const db = getDatabase();
357
- return db.prepare('SELECT * FROM pipelines WHERE status = ? ORDER BY created_at DESC').all(status);
358
- }
359
- export function deletePipeline(id) {
360
- const db = getDatabase();
361
- const result = db.prepare('DELETE FROM pipelines WHERE id = ?').run(id);
362
- return result.changes > 0;
363
- }
364
- export function createPipelinePhase(pipelineId, phaseType, phaseOrder) {
365
- const db = getDatabase();
366
- const id = uuidv4();
367
- const now = new Date().toISOString();
368
- db.prepare(`INSERT INTO pipeline_phases (id, pipeline_id, phase_type, phase_order, created_at)
369
- VALUES (?, ?, ?, ?, ?)`).run(id, pipelineId, phaseType, phaseOrder, now);
370
- return db.prepare('SELECT * FROM pipeline_phases WHERE id = ?').get(id);
371
- }
372
- export function getPipelinePhases(pipelineId) {
373
- const db = getDatabase();
374
- return db.prepare('SELECT * FROM pipeline_phases WHERE pipeline_id = ? ORDER BY phase_order ASC').all(pipelineId);
375
- }
376
- export function updatePipelinePhase(id, updates) {
377
- const db = getDatabase();
378
- const fields = [];
379
- const values = [];
380
- if (updates.status !== undefined) {
381
- fields.push('status = ?');
382
- values.push(updates.status);
383
- }
384
- if (updates.output !== undefined) {
385
- fields.push('output = ?');
386
- values.push(updates.output);
387
- }
388
- if (updates.started_at !== undefined) {
389
- fields.push('started_at = ?');
390
- values.push(updates.started_at);
391
- }
392
- if (updates.completed_at !== undefined) {
393
- fields.push('completed_at = ?');
394
- values.push(updates.completed_at);
395
- }
396
- if (fields.length === 0)
397
- return undefined;
398
- values.push(id);
399
- db.prepare(`UPDATE pipeline_phases SET ${fields.join(', ')} WHERE id = ?`).run(...values);
400
- return db.prepare('SELECT * FROM pipeline_phases WHERE id = ?').get(id);
401
- }
402
- export function createPipelineLog(pipelineId, phaseType, logType, message) {
403
- const db = getDatabase();
404
- const id = uuidv4();
405
- const now = new Date().toISOString();
406
- db.prepare(`INSERT INTO pipeline_logs (id, pipeline_id, phase_type, log_type, message, created_at)
407
- VALUES (?, ?, ?, ?, ?, ?)`).run(id, pipelineId, phaseType, logType, message, now);
408
- return db.prepare('SELECT * FROM pipeline_logs WHERE id = ?').get(id);
409
- }
410
- export function getPipelineLogs(pipelineId, phaseType) {
411
- const db = getDatabase();
412
- if (phaseType) {
413
- return db.prepare('SELECT * FROM pipeline_logs WHERE pipeline_id = ? AND phase_type = ? ORDER BY created_at ASC').all(pipelineId, phaseType);
414
- }
415
- return db.prepare('SELECT * FROM pipeline_logs WHERE pipeline_id = ? ORDER BY created_at ASC').all(pipelineId);
416
- }
417
312
  export function createSchedule(projectId, title, description, cronExpression, cliTool, cliModel, skipIfRunning = 1, scheduleType = 'recurring', runAt) {
418
313
  const db = getDatabase();
419
314
  const id = uuidv4();
@@ -556,7 +451,7 @@ export function addModel(cliTool, modelValue, modelLabel) {
556
451
  const id = uuidv4();
557
452
  const maxOrder = db.prepare('SELECT MAX(sort_order) as max_order FROM cli_models WHERE cli_tool = ?').get(cliTool);
558
453
  const sortOrder = (maxOrder.max_order ?? -1) + 1;
559
- db.prepare(`INSERT INTO cli_models (id, cli_tool, model_value, model_label, sort_order, is_default) VALUES (?, ?, ?, ?, ?, 0)`).run(id, cliTool, modelValue, modelLabel, sortOrder);
454
+ db.prepare(`INSERT INTO cli_models (id, cli_tool, model_value, model_label, sort_order, is_default, source) VALUES (?, ?, ?, ?, ?, 0, 'user')`).run(id, cliTool, modelValue, modelLabel, sortOrder);
560
455
  return db.prepare('SELECT * FROM cli_models WHERE id = ?').get(id);
561
456
  }
562
457
  export function removeModel(id) {
@@ -569,9 +464,57 @@ export function removeModel(id) {
569
464
  }
570
465
  export function isModelSupported(cliTool, modelValue) {
571
466
  const db = getDatabase();
572
- const row = db.prepare('SELECT 1 FROM cli_models WHERE cli_tool = ? AND model_value = ?').get(cliTool, modelValue);
467
+ const row = db.prepare('SELECT 1 FROM cli_models WHERE cli_tool = ? AND model_value = ? AND deprecated = 0').get(cliTool, modelValue);
573
468
  return !!row;
574
469
  }
470
+ /**
471
+ * Upsert a discovered model. Updates label/source/last_verified_at and clears
472
+ * the deprecated flag on conflict. Does not overwrite user-added (source='user')
473
+ * entries except to refresh their verified timestamp.
474
+ */
475
+ export function upsertDiscoveredModel(cliTool, modelValue, modelLabel, source, now) {
476
+ const db = getDatabase();
477
+ const existing = db.prepare('SELECT * FROM cli_models WHERE cli_tool = ? AND model_value = ?').get(cliTool, modelValue);
478
+ if (existing) {
479
+ if (existing.source === 'user') {
480
+ db.prepare(`UPDATE cli_models SET deprecated = 0, last_verified_at = ? WHERE id = ?`).run(now, existing.id);
481
+ }
482
+ else {
483
+ db.prepare(`UPDATE cli_models SET model_label = ?, source = ?, deprecated = 0, last_verified_at = ? WHERE id = ?`).run(modelLabel, source, now, existing.id);
484
+ }
485
+ return;
486
+ }
487
+ const id = uuidv4();
488
+ const maxOrder = db.prepare('SELECT MAX(sort_order) as max_order FROM cli_models WHERE cli_tool = ?').get(cliTool);
489
+ const sortOrder = (maxOrder.max_order ?? -1) + 1;
490
+ db.prepare(`INSERT INTO cli_models (id, cli_tool, model_value, model_label, sort_order, is_default, deprecated, last_verified_at, source)
491
+ VALUES (?, ?, ?, ?, ?, 0, 0, ?, ?)`).run(id, cliTool, modelValue, modelLabel, sortOrder, now, source);
492
+ }
493
+ /**
494
+ * Mark any non-user, non-default cli_models entries for the given tool as
495
+ * deprecated if their model_value is NOT in the discovered list.
496
+ */
497
+ export function markDeprecatedExcept(cliTool, discoveredValues) {
498
+ const db = getDatabase();
499
+ if (discoveredValues.length === 0) {
500
+ db.prepare(`UPDATE cli_models SET deprecated = 1
501
+ WHERE cli_tool = ? AND is_default = 0 AND source IN ('seed','probe','registry')`).run(cliTool);
502
+ return;
503
+ }
504
+ const placeholders = discoveredValues.map(() => '?').join(',');
505
+ db.prepare(`UPDATE cli_models SET deprecated = 1
506
+ WHERE cli_tool = ? AND is_default = 0 AND source IN ('seed','probe','registry')
507
+ AND model_value NOT IN (${placeholders})`).run(cliTool, ...discoveredValues);
508
+ }
509
+ export function getCliVersion(cliTool) {
510
+ const db = getDatabase();
511
+ return db.prepare('SELECT * FROM cli_versions WHERE cli_tool = ?').get(cliTool);
512
+ }
513
+ export function setCliVersion(cliTool, version, syncedAt) {
514
+ const db = getDatabase();
515
+ db.prepare(`INSERT INTO cli_versions (cli_tool, last_version, last_synced_at) VALUES (?, ?, ?)
516
+ ON CONFLICT(cli_tool) DO UPDATE SET last_version = excluded.last_version, last_synced_at = excluded.last_synced_at`).run(cliTool, version, syncedAt);
517
+ }
575
518
  // ── CLI Fallback ──
576
519
  export function getNextFallbackCli(projectId, currentCliTool) {
577
520
  const project = getProjectById(projectId);
@@ -625,14 +568,14 @@ export function deletePluginConfigs(projectId, pluginId) {
625
568
  const db = getDatabase();
626
569
  db.prepare('DELETE FROM plugin_configs WHERE project_id = ? AND plugin_id = ?').run(projectId, pluginId);
627
570
  }
628
- export function createDiscussionAgent(projectId, name, role, systemPrompt, cliTool, cliModel, avatarColor) {
571
+ export function createDiscussionAgent(projectId, name, role, systemPrompt, cliTool, cliModel, avatarColor, canImplement = false) {
629
572
  const db = getDatabase();
630
573
  const id = uuidv4();
631
574
  const now = new Date().toISOString();
632
575
  const maxOrder = db.prepare('SELECT MAX(sort_order) as max_order FROM discussion_agents WHERE project_id = ?').get(projectId);
633
576
  const sortOrder = (maxOrder.max_order ?? -1) + 1;
634
- db.prepare(`INSERT INTO discussion_agents (id, project_id, name, role, system_prompt, cli_tool, cli_model, avatar_color, sort_order, created_at, updated_at)
635
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, projectId, name, role, systemPrompt, cliTool ?? null, cliModel ?? null, avatarColor ?? null, sortOrder, now, now);
577
+ db.prepare(`INSERT INTO discussion_agents (id, project_id, name, role, system_prompt, cli_tool, cli_model, avatar_color, sort_order, can_implement, created_at, updated_at)
578
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, projectId, name, role, systemPrompt, cliTool ?? null, cliModel ?? null, avatarColor ?? null, sortOrder, canImplement ? 1 : 0, now, now);
636
579
  return getDiscussionAgentById(id);
637
580
  }
638
581
  export function getDiscussionAgentsByProjectId(projectId) {
@@ -675,6 +618,10 @@ export function updateDiscussionAgent(id, updates) {
675
618
  fields.push('sort_order = ?');
676
619
  values.push(updates.sort_order);
677
620
  }
621
+ if (updates.can_implement !== undefined) {
622
+ fields.push('can_implement = ?');
623
+ values.push(updates.can_implement ? 1 : 0);
624
+ }
678
625
  if (fields.length === 0)
679
626
  return getDiscussionAgentById(id);
680
627
  fields.push('updated_at = ?');
@@ -836,13 +783,265 @@ export function deleteDiscussionLogs(discussionId) {
836
783
  const result = db.prepare('DELETE FROM discussion_logs WHERE discussion_id = ?').run(discussionId);
837
784
  return result.changes;
838
785
  }
786
+ export function createSession(projectId, title, description, cliTool, cliModel, useWorktree) {
787
+ const db = getDatabase();
788
+ const id = uuidv4();
789
+ const now = new Date().toISOString();
790
+ db.prepare(`INSERT INTO sessions (id, project_id, title, description, cli_tool, cli_model, use_worktree, created_at, updated_at)
791
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, projectId, title, description ?? null, cliTool ?? null, cliModel ?? null, useWorktree ? 1 : 0, now, now);
792
+ return getSessionById(id);
793
+ }
794
+ export function getSessionsByProjectId(projectId) {
795
+ const db = getDatabase();
796
+ return db.prepare('SELECT * FROM sessions WHERE project_id = ? ORDER BY created_at DESC').all(projectId);
797
+ }
798
+ export function getSessionById(id) {
799
+ const db = getDatabase();
800
+ return db.prepare('SELECT * FROM sessions WHERE id = ?').get(id);
801
+ }
802
+ export function updateSession(id, updates) {
803
+ const db = getDatabase();
804
+ const fields = [];
805
+ const values = [];
806
+ if (updates.title !== undefined) {
807
+ fields.push('title = ?');
808
+ values.push(updates.title);
809
+ }
810
+ if (updates.description !== undefined) {
811
+ fields.push('description = ?');
812
+ values.push(updates.description);
813
+ }
814
+ if (updates.cli_tool !== undefined) {
815
+ fields.push('cli_tool = ?');
816
+ values.push(updates.cli_tool);
817
+ }
818
+ if (updates.cli_model !== undefined) {
819
+ fields.push('cli_model = ?');
820
+ values.push(updates.cli_model);
821
+ }
822
+ if (updates.process_pid !== undefined) {
823
+ fields.push('process_pid = ?');
824
+ values.push(updates.process_pid);
825
+ }
826
+ if (updates.branch_name !== undefined) {
827
+ fields.push('branch_name = ?');
828
+ values.push(updates.branch_name);
829
+ }
830
+ if (updates.worktree_path !== undefined) {
831
+ fields.push('worktree_path = ?');
832
+ values.push(updates.worktree_path);
833
+ }
834
+ if (updates.use_worktree !== undefined) {
835
+ fields.push('use_worktree = ?');
836
+ values.push(updates.use_worktree);
837
+ }
838
+ if (updates.token_usage !== undefined) {
839
+ fields.push('token_usage = ?');
840
+ values.push(updates.token_usage);
841
+ }
842
+ if (updates.total_cost_usd !== undefined) {
843
+ fields.push('total_cost_usd = ?');
844
+ values.push(updates.total_cost_usd);
845
+ }
846
+ if (updates.total_tokens !== undefined) {
847
+ fields.push('total_tokens = ?');
848
+ values.push(updates.total_tokens);
849
+ }
850
+ if (fields.length === 0)
851
+ return getSessionById(id);
852
+ fields.push('updated_at = ?');
853
+ values.push(new Date().toISOString());
854
+ values.push(id);
855
+ db.prepare(`UPDATE sessions SET ${fields.join(', ')} WHERE id = ?`).run(...values);
856
+ return getSessionById(id);
857
+ }
858
+ export function updateSessionStatus(id, status) {
859
+ const db = getDatabase();
860
+ db.prepare('UPDATE sessions SET status = ?, updated_at = ? WHERE id = ?').run(status, new Date().toISOString(), id);
861
+ return getSessionById(id);
862
+ }
863
+ export function getSessionsByStatus(status) {
864
+ const db = getDatabase();
865
+ return db.prepare('SELECT * FROM sessions WHERE status = ? ORDER BY created_at DESC').all(status);
866
+ }
867
+ export function deleteSession(id) {
868
+ const db = getDatabase();
869
+ const result = db.prepare('DELETE FROM sessions WHERE id = ?').run(id);
870
+ return result.changes > 0;
871
+ }
872
+ export function createSessionLog(sessionId, logType, message) {
873
+ const db = getDatabase();
874
+ const id = uuidv4();
875
+ const now = new Date().toISOString();
876
+ db.prepare(`INSERT INTO session_logs (id, session_id, log_type, message, created_at)
877
+ VALUES (?, ?, ?, ?, ?)`).run(id, sessionId, logType, message, now);
878
+ return db.prepare('SELECT * FROM session_logs WHERE id = ?').get(id);
879
+ }
880
+ export function getSessionLogsBySessionId(sessionId) {
881
+ const db = getDatabase();
882
+ return db.prepare('SELECT * FROM session_logs WHERE session_id = ? ORDER BY created_at ASC').all(sessionId);
883
+ }
884
+ export function deleteSessionLogsBySessionId(sessionId) {
885
+ const db = getDatabase();
886
+ const result = db.prepare('DELETE FROM session_logs WHERE session_id = ?').run(sessionId);
887
+ return result.changes;
888
+ }
889
+ // ── Planner Items ──
890
+ const PLANNER_TAG_COLORS = ['gray', 'brown', 'orange', 'yellow', 'green', 'blue', 'purple', 'pink', 'red'];
891
+ export function createPlannerItem(projectId, title, description, tags, dueDate, priority = 0) {
892
+ const db = getDatabase();
893
+ const id = uuidv4();
894
+ const now = new Date().toISOString();
895
+ db.prepare(`INSERT INTO planner_items (id, project_id, title, description, tags, due_date, priority, created_at, updated_at)
896
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, projectId, title, description ?? null, tags ?? null, dueDate ?? null, priority, now, now);
897
+ return getPlannerItemById(id);
898
+ }
899
+ export function getPlannerItemsByProjectId(projectId) {
900
+ const db = getDatabase();
901
+ return db.prepare('SELECT * FROM planner_items WHERE project_id = ? ORDER BY priority DESC, created_at ASC').all(projectId);
902
+ }
903
+ export function getPlannerItemById(id) {
904
+ const db = getDatabase();
905
+ return db.prepare('SELECT * FROM planner_items WHERE id = ?').get(id);
906
+ }
907
+ export function updatePlannerItem(id, updates) {
908
+ const db = getDatabase();
909
+ const fields = [];
910
+ const values = [];
911
+ if (updates.title !== undefined) {
912
+ fields.push('title = ?');
913
+ values.push(updates.title);
914
+ }
915
+ if (updates.description !== undefined) {
916
+ fields.push('description = ?');
917
+ values.push(updates.description);
918
+ }
919
+ if (updates.tags !== undefined) {
920
+ fields.push('tags = ?');
921
+ values.push(updates.tags);
922
+ }
923
+ if (updates.due_date !== undefined) {
924
+ fields.push('due_date = ?');
925
+ values.push(updates.due_date);
926
+ }
927
+ if (updates.status !== undefined) {
928
+ fields.push('status = ?');
929
+ values.push(updates.status);
930
+ }
931
+ if (updates.priority !== undefined) {
932
+ fields.push('priority = ?');
933
+ values.push(updates.priority);
934
+ }
935
+ if (updates.images !== undefined) {
936
+ fields.push('images = ?');
937
+ values.push(updates.images);
938
+ }
939
+ if (updates.converted_type !== undefined) {
940
+ fields.push('converted_type = ?');
941
+ values.push(updates.converted_type);
942
+ }
943
+ if (updates.converted_id !== undefined) {
944
+ fields.push('converted_id = ?');
945
+ values.push(updates.converted_id);
946
+ }
947
+ if (fields.length === 0)
948
+ return getPlannerItemById(id);
949
+ fields.push('updated_at = ?');
950
+ values.push(new Date().toISOString());
951
+ values.push(id);
952
+ db.prepare(`UPDATE planner_items SET ${fields.join(', ')} WHERE id = ?`).run(...values);
953
+ return getPlannerItemById(id);
954
+ }
955
+ export function deletePlannerItem(id) {
956
+ const db = getDatabase();
957
+ const result = db.prepare('DELETE FROM planner_items WHERE id = ?').run(id);
958
+ return result.changes > 0;
959
+ }
960
+ // Returns tag objects with colors. Merges planner_tags table with tags found in items.
961
+ export function getPlannerTagsByProjectId(projectId) {
962
+ const db = getDatabase();
963
+ // Get saved tag metadata
964
+ const savedTags = db.prepare('SELECT * FROM planner_tags WHERE project_id = ? ORDER BY name').all(projectId);
965
+ const savedMap = new Map(savedTags.map(t => [t.name, t]));
966
+ // Collect all tags used in items
967
+ let colorIndex = savedTags.length;
968
+ const items = getPlannerItemsByProjectId(projectId);
969
+ for (const item of items) {
970
+ if (item.tags) {
971
+ try {
972
+ const parsed = JSON.parse(item.tags);
973
+ if (Array.isArray(parsed)) {
974
+ for (const name of parsed) {
975
+ if (!savedMap.has(name)) {
976
+ const color = PLANNER_TAG_COLORS[colorIndex % PLANNER_TAG_COLORS.length];
977
+ colorIndex++;
978
+ const tag = upsertPlannerTag(projectId, name, color);
979
+ savedMap.set(name, tag);
980
+ }
981
+ }
982
+ }
983
+ }
984
+ catch { /* ignore */ }
985
+ }
986
+ }
987
+ return Array.from(savedMap.values()).sort((a, b) => a.name.localeCompare(b.name));
988
+ }
989
+ export function upsertPlannerTag(projectId, name, color) {
990
+ const db = getDatabase();
991
+ const existing = db.prepare('SELECT * FROM planner_tags WHERE project_id = ? AND name = ?').get(projectId, name);
992
+ if (existing) {
993
+ db.prepare('UPDATE planner_tags SET color = ? WHERE id = ?').run(color, existing.id);
994
+ return { ...existing, color };
995
+ }
996
+ const id = uuidv4();
997
+ db.prepare('INSERT INTO planner_tags (id, project_id, name, color) VALUES (?, ?, ?, ?)').run(id, projectId, name, color);
998
+ return { id, project_id: projectId, name, color };
999
+ }
1000
+ export function renamePlannerTag(projectId, oldName, newName) {
1001
+ const db = getDatabase();
1002
+ // Update tag table
1003
+ db.prepare('UPDATE planner_tags SET name = ? WHERE project_id = ? AND name = ?').run(newName, projectId, oldName);
1004
+ // Update all items' JSON arrays
1005
+ const items = getPlannerItemsByProjectId(projectId);
1006
+ for (const item of items) {
1007
+ if (!item.tags)
1008
+ continue;
1009
+ try {
1010
+ const parsed = JSON.parse(item.tags);
1011
+ const idx = parsed.indexOf(oldName);
1012
+ if (idx !== -1) {
1013
+ parsed[idx] = newName;
1014
+ db.prepare('UPDATE planner_items SET tags = ? WHERE id = ?').run(JSON.stringify(parsed), item.id);
1015
+ }
1016
+ }
1017
+ catch { /* ignore */ }
1018
+ }
1019
+ }
1020
+ export function deletePlannerTag(projectId, name) {
1021
+ const db = getDatabase();
1022
+ // Remove from tag table
1023
+ db.prepare('DELETE FROM planner_tags WHERE project_id = ? AND name = ?').run(projectId, name);
1024
+ // Remove from all items' JSON arrays
1025
+ const items = getPlannerItemsByProjectId(projectId);
1026
+ for (const item of items) {
1027
+ if (!item.tags)
1028
+ continue;
1029
+ try {
1030
+ const parsed = JSON.parse(item.tags);
1031
+ const filtered = parsed.filter(t => t !== name);
1032
+ const newTags = filtered.length > 0 ? JSON.stringify(filtered) : null;
1033
+ db.prepare('UPDATE planner_items SET tags = ? WHERE id = ?').run(newTags, item.id);
1034
+ }
1035
+ catch { /* ignore */ }
1036
+ }
1037
+ }
839
1038
  // ── Cleanup ──
840
1039
  export function cleanOldLogs(daysToKeep) {
841
1040
  const db = getDatabase();
842
1041
  const cutoff = new Date(Date.now() - daysToKeep * 24 * 60 * 60 * 1000).toISOString();
843
1042
  const taskResult = db.prepare('DELETE FROM task_logs WHERE created_at < ?').run(cutoff);
844
- const pipelineResult = db.prepare('DELETE FROM pipeline_logs WHERE created_at < ?').run(cutoff);
845
1043
  const discussionResult = db.prepare('DELETE FROM discussion_logs WHERE created_at < ?').run(cutoff);
846
- return taskResult.changes + pipelineResult.changes + discussionResult.changes;
1044
+ const sessionResult = db.prepare('DELETE FROM session_logs WHERE created_at < ?').run(cutoff);
1045
+ return taskResult.changes + discussionResult.changes + sessionResult.changes;
847
1046
  }
848
1047
  //# sourceMappingURL=queries.js.map