@assistkick/create 1.9.0 → 1.11.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 (206) hide show
  1. package/dist/src/scaffolder.d.ts +12 -1
  2. package/dist/src/scaffolder.js +40 -3
  3. package/dist/src/scaffolder.js.map +1 -1
  4. package/package.json +1 -1
  5. package/templates/assistkick-product-system/package.json +1 -1
  6. package/templates/assistkick-product-system/packages/backend/package.json +1 -0
  7. package/templates/assistkick-product-system/packages/backend/src/mcp/permission_mcp_server.ts +196 -0
  8. package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +31 -7
  9. package/templates/assistkick-product-system/packages/backend/src/routes/auth.ts +15 -12
  10. package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.test.ts +95 -0
  11. package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.ts +97 -0
  12. package/templates/assistkick-product-system/packages/backend/src/routes/chat_permission.ts +94 -0
  13. package/templates/assistkick-product-system/packages/backend/src/routes/chat_sessions.ts +189 -0
  14. package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.test.ts +131 -0
  15. package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.ts +94 -0
  16. package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +12 -3
  17. package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +2 -2
  18. package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +391 -23
  19. package/templates/assistkick-product-system/packages/backend/src/routes/git_branches.test.ts +306 -0
  20. package/templates/assistkick-product-system/packages/backend/src/routes/git_connect.test.ts +133 -0
  21. package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +66 -9
  22. package/templates/assistkick-product-system/packages/backend/src/routes/preview.ts +204 -0
  23. package/templates/assistkick-product-system/packages/backend/src/routes/projects.test.ts +205 -0
  24. package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +37 -9
  25. package/templates/assistkick-product-system/packages/backend/src/routes/skills.test.ts +139 -0
  26. package/templates/assistkick-product-system/packages/backend/src/routes/skills.ts +95 -0
  27. package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +5 -4
  28. package/templates/assistkick-product-system/packages/backend/src/routes/users.ts +4 -4
  29. package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +8 -8
  30. package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +5 -5
  31. package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +6 -6
  32. package/templates/assistkick-product-system/packages/backend/src/server.ts +107 -27
  33. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +105 -203
  34. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +76 -266
  35. package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.test.ts +427 -0
  36. package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.ts +345 -0
  37. package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.test.ts +170 -0
  38. package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.ts +106 -0
  39. package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.test.ts +217 -0
  40. package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.ts +188 -0
  41. package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.test.ts +1243 -0
  42. package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.ts +894 -0
  43. package/templates/assistkick-product-system/packages/backend/src/services/coherence-review.ts +3 -3
  44. package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.test.ts +85 -0
  45. package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.ts +54 -0
  46. package/templates/assistkick-product-system/packages/backend/src/services/email_service.ts +13 -10
  47. package/templates/assistkick-product-system/packages/backend/src/services/init.ts +11 -3
  48. package/templates/assistkick-product-system/packages/backend/src/services/invitation_service.ts +1 -1
  49. package/templates/assistkick-product-system/packages/backend/src/services/password_reset_service.ts +1 -1
  50. package/templates/assistkick-product-system/packages/backend/src/services/permission_service.test.ts +243 -0
  51. package/templates/assistkick-product-system/packages/backend/src/services/permission_service.ts +259 -0
  52. package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.test.ts +172 -0
  53. package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.ts +225 -0
  54. package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +29 -0
  55. package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +17 -0
  56. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +255 -0
  57. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +300 -25
  58. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +44 -0
  59. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +62 -7
  60. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +77 -6
  61. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +149 -14
  62. package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +2 -1
  63. package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.test.ts +45 -0
  64. package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.ts +157 -0
  65. package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +4 -3
  66. package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +3 -3
  67. package/templates/assistkick-product-system/packages/frontend/package.json +5 -0
  68. package/templates/assistkick-product-system/packages/frontend/src/App.tsx +2 -0
  69. package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +336 -5
  70. package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +192 -12
  71. package/templates/assistkick-product-system/packages/frontend/src/components/AttachmentPreviewList.tsx +98 -0
  72. package/templates/assistkick-product-system/packages/frontend/src/components/AutocompleteDropdown.tsx +65 -0
  73. package/templates/assistkick-product-system/packages/frontend/src/components/ChatAttachButton.tsx +56 -0
  74. package/templates/assistkick-product-system/packages/frontend/src/components/ChatDropZone.tsx +80 -0
  75. package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageBubble.tsx +155 -0
  76. package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageContent.tsx +182 -0
  77. package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageInput.tsx +233 -0
  78. package/templates/assistkick-product-system/packages/frontend/src/components/ChatSessionSidebar.tsx +218 -0
  79. package/templates/assistkick-product-system/packages/frontend/src/components/ChatStopButton.tsx +32 -0
  80. package/templates/assistkick-product-system/packages/frontend/src/components/ChatTodoSidebar.tsx +113 -0
  81. package/templates/assistkick-product-system/packages/frontend/src/components/ChatView.tsx +842 -0
  82. package/templates/assistkick-product-system/packages/frontend/src/components/CommitMessageModal.tsx +82 -0
  83. package/templates/assistkick-product-system/packages/frontend/src/components/DiagramOverlay.tsx +160 -0
  84. package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +5 -5
  85. package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +9 -10
  86. package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +5 -5
  87. package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +112 -41
  88. package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +2 -2
  89. package/templates/assistkick-product-system/packages/frontend/src/components/HighlightedText.tsx +87 -0
  90. package/templates/assistkick-product-system/packages/frontend/src/components/ImageLightbox.tsx +192 -0
  91. package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +2 -2
  92. package/templates/assistkick-product-system/packages/frontend/src/components/MentionPill.tsx +33 -0
  93. package/templates/assistkick-product-system/packages/frontend/src/components/MermaidBlock.tsx +148 -0
  94. package/templates/assistkick-product-system/packages/frontend/src/components/PermissionDialog.tsx +91 -0
  95. package/templates/assistkick-product-system/packages/frontend/src/components/PermissionModeSelector.tsx +229 -0
  96. package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +249 -83
  97. package/templates/assistkick-product-system/packages/frontend/src/components/QueuedMessageBubble.tsx +38 -0
  98. package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +212 -117
  99. package/templates/assistkick-product-system/packages/frontend/src/components/SystemPromptAccordion.tsx +48 -0
  100. package/templates/assistkick-product-system/packages/frontend/src/components/TaskIcon.tsx +11 -0
  101. package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +25 -9
  102. package/templates/assistkick-product-system/packages/frontend/src/components/ToolDiffView.tsx +114 -0
  103. package/templates/assistkick-product-system/packages/frontend/src/components/ToolResultCard.tsx +87 -0
  104. package/templates/assistkick-product-system/packages/frontend/src/components/ToolUseCard.tsx +149 -0
  105. package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +25 -8
  106. package/templates/assistkick-product-system/packages/frontend/src/components/UnifiedGitWidget.tsx +722 -0
  107. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +2 -0
  108. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +2 -1
  109. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/ProgrammableNode.tsx +178 -0
  110. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +3 -0
  111. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +103 -9
  112. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +26 -2
  113. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +42 -1
  114. package/templates/assistkick-product-system/packages/frontend/src/hooks/useDocumentTitle.ts +11 -0
  115. package/templates/assistkick-product-system/packages/frontend/src/hooks/useProjects.ts +1 -0
  116. package/templates/assistkick-product-system/packages/frontend/src/hooks/use_chat_stream.ts +826 -0
  117. package/templates/assistkick-product-system/packages/frontend/src/hooks/use_file_tree_cache.ts +69 -0
  118. package/templates/assistkick-product-system/packages/frontend/src/hooks/use_mention_autocomplete.ts +284 -0
  119. package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.test.ts +183 -0
  120. package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.ts +150 -0
  121. package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.test.ts +305 -0
  122. package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.ts +113 -0
  123. package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.test.ts +157 -0
  124. package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.ts +95 -0
  125. package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.test.ts +65 -0
  126. package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.ts +110 -0
  127. package/templates/assistkick-product-system/packages/frontend/src/lib/message_queue.ts +66 -0
  128. package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.test.ts +124 -0
  129. package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.ts +112 -0
  130. package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +2 -0
  131. package/templates/assistkick-product-system/packages/frontend/src/routes/ChatRoute.tsx +8 -0
  132. package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +2 -0
  133. package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +0 -4
  134. package/templates/assistkick-product-system/packages/frontend/src/routes/DesignSystemRoute.tsx +2 -0
  135. package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +2 -0
  136. package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +2 -0
  137. package/templates/assistkick-product-system/packages/frontend/src/routes/KanbanRoute.tsx +2 -0
  138. package/templates/assistkick-product-system/packages/frontend/src/routes/TerminalRoute.tsx +2 -0
  139. package/templates/assistkick-product-system/packages/frontend/src/routes/UsersRoute.tsx +2 -0
  140. package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +2 -0
  141. package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +2 -0
  142. package/templates/assistkick-product-system/packages/frontend/src/routes/accept_invitation.tsx +2 -0
  143. package/templates/assistkick-product-system/packages/frontend/src/routes/forgot_password.tsx +2 -0
  144. package/templates/assistkick-product-system/packages/frontend/src/routes/login.tsx +2 -0
  145. package/templates/assistkick-product-system/packages/frontend/src/routes/register.tsx +2 -0
  146. package/templates/assistkick-product-system/packages/frontend/src/routes/reset_password.tsx +2 -0
  147. package/templates/assistkick-product-system/packages/frontend/src/stores/useAttachmentStore.ts +66 -0
  148. package/templates/assistkick-product-system/packages/frontend/src/stores/useChatSessionStore.ts +107 -0
  149. package/templates/assistkick-product-system/packages/frontend/src/stores/useMessageQueueStore.ts +110 -0
  150. package/templates/assistkick-product-system/packages/frontend/src/stores/usePreviewStore.ts +78 -0
  151. package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +7 -0
  152. package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +6 -1
  153. package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +30 -357
  154. package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.test.ts +115 -0
  155. package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.ts +91 -0
  156. package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.test.ts +30 -0
  157. package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.ts +3 -0
  158. package/templates/assistkick-product-system/packages/shared/db/migrations/0015_magenta_jazinda.sql +1 -0
  159. package/templates/assistkick-product-system/packages/shared/db/migrations/0016_giant_xorn.sql +1 -0
  160. package/templates/assistkick-product-system/packages/shared/db/migrations/0017_sloppy_mentor.sql +6 -0
  161. package/templates/assistkick-product-system/packages/shared/db/migrations/0018_vengeful_kabuki.sql +9 -0
  162. package/templates/assistkick-product-system/packages/shared/db/migrations/0019_careful_sentinels.sql +8 -0
  163. package/templates/assistkick-product-system/packages/shared/db/migrations/0020_clever_spot.sql +27 -0
  164. package/templates/assistkick-product-system/packages/shared/db/migrations/0021_graceful_hex.sql +1 -0
  165. package/templates/assistkick-product-system/packages/shared/db/migrations/0022_short_kingpin.sql +1 -0
  166. package/templates/assistkick-product-system/packages/shared/db/migrations/0023_ambiguous_sharon_carter.sql +1 -0
  167. package/templates/assistkick-product-system/packages/shared/db/migrations/0024_fat_unus.sql +1 -0
  168. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0015_snapshot.json +1552 -0
  169. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0016_snapshot.json +1560 -0
  170. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0017_snapshot.json +1598 -0
  171. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0018_snapshot.json +1657 -0
  172. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0019_snapshot.json +1709 -0
  173. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0020_snapshot.json +1733 -0
  174. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0021_snapshot.json +1740 -0
  175. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0022_snapshot.json +1755 -0
  176. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0023_snapshot.json +1762 -0
  177. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0024_snapshot.json +1769 -0
  178. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +70 -0
  179. package/templates/assistkick-product-system/packages/shared/db/schema.ts +40 -1
  180. package/templates/assistkick-product-system/packages/shared/lib/claude-service.test.ts +236 -0
  181. package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +46 -5
  182. package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +65 -39
  183. package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.test.ts +173 -0
  184. package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.ts +213 -0
  185. package/templates/assistkick-product-system/packages/shared/lib/validator.test.ts +70 -0
  186. package/templates/assistkick-product-system/packages/shared/lib/validator.ts +17 -1
  187. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +803 -27
  188. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +502 -68
  189. package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +4 -4
  190. package/templates/assistkick-product-system/packages/shared/package.json +2 -1
  191. package/templates/assistkick-product-system/packages/shared/test_fixtures/hanging_stream.mjs +46 -0
  192. package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +44 -0
  193. package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +7 -0
  194. package/templates/assistkick-product-system/packages/shared/tools/remove_node.ts +2 -1
  195. package/templates/assistkick-product-system/packages/shared/tools/resolve_question.ts +2 -1
  196. package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -1
  197. package/templates/assistkick-product-system/tests/message_queue.test.ts +178 -0
  198. package/templates/assistkick-product-system/tests/message_queue_per_session.test.ts +143 -0
  199. package/templates/skills/assistkick-bootstrap/SKILL.md +26 -26
  200. package/templates/skills/assistkick-code-reviewer/SKILL.md +45 -46
  201. package/templates/skills/assistkick-db-explorer/SKILL.md +13 -13
  202. package/templates/skills/assistkick-debugger/SKILL.md +23 -23
  203. package/templates/skills/assistkick-developer/SKILL.md +59 -63
  204. package/templates/skills/assistkick-interview/SKILL.md +26 -26
  205. package/templates/skills/assistkick-video-composition-agent/SKILL.md +231 -0
  206. package/templates/skills/assistkick-video-script-writer/SKILL.md +136 -0
@@ -1,54 +1,50 @@
1
1
  /**
2
- * Agent service — CRUD operations for agents.
2
+ * Agent service — CRUD operations for agents and skill discovery.
3
3
  * Handles listing, creating, updating, deleting agents with deletion protection,
4
- * and resetting default agents to original prompts.
4
+ * resetting default agents to original grounding, and listing available skills.
5
5
  */
6
6
 
7
7
  import { eq, isNull } from 'drizzle-orm';
8
8
  import { agents, workflows } from '@assistkick/shared/db/schema.js';
9
9
  import { randomUUID } from 'node:crypto';
10
- import { readFile } from 'node:fs/promises';
10
+ import { readdir, readFile } from 'node:fs/promises';
11
+ import { join } from 'node:path';
12
+ import { existsSync } from 'node:fs';
11
13
 
12
14
  interface AgentServiceDeps {
13
15
  getDb: () => any;
14
16
  log: (tag: string, ...args: any[]) => void;
15
- skillPaths: {
16
- developer: string;
17
- reviewer: string;
18
- debugger: string;
19
- videoScriptWriter?: string;
20
- videoCompositionAgent?: string;
21
- };
17
+ skillsDir: string;
22
18
  }
23
19
 
24
20
  export interface AgentRecord {
25
21
  id: string;
26
22
  name: string;
27
- promptTemplate: string;
23
+ model: string;
24
+ skills: string;
25
+ grounding: string;
26
+ defaultGrounding: string | null;
28
27
  projectId: string | null;
29
28
  isDefault: number;
30
29
  createdAt: string;
31
30
  updatedAt: string;
32
31
  }
33
32
 
34
- /** Maps stage identifiers to default agent display names. */
35
- const DEFAULT_AGENT_NAMES: Record<string, string> = {
36
- developer: 'Default Developer',
37
- reviewer: 'Default Reviewer',
38
- debugger: 'Default Debugger',
39
- videoScriptWriter: 'Default Video Script Writer',
40
- videoCompositionAgent: 'Default Video Composition Agent',
41
- };
33
+ export interface SkillInfo {
34
+ id: string;
35
+ name: string;
36
+ preview: string;
37
+ }
42
38
 
43
39
  export class AgentService {
44
40
  private readonly getDb: () => any;
45
41
  private readonly log: (tag: string, ...args: any[]) => void;
46
- private readonly skillPaths: AgentServiceDeps['skillPaths'];
42
+ private readonly skillsDir: string;
47
43
 
48
- constructor({ getDb, log, skillPaths }: AgentServiceDeps) {
44
+ constructor({ getDb, log, skillsDir }: AgentServiceDeps) {
49
45
  this.getDb = getDb;
50
46
  this.log = log;
51
- this.skillPaths = skillPaths;
47
+ this.skillsDir = skillsDir;
52
48
  }
53
49
 
54
50
  /** List agents filtered by scope. */
@@ -74,7 +70,7 @@ export class AgentService {
74
70
  };
75
71
 
76
72
  /** Create a new agent. */
77
- create = async (data: { name: string; promptTemplate: string; projectId?: string | null }): Promise<AgentRecord> => {
73
+ create = async (data: { name: string; grounding: string; model?: string; skills?: string; projectId?: string | null }): Promise<AgentRecord> => {
78
74
  const db = this.getDb();
79
75
  const now = new Date().toISOString();
80
76
  const id = randomUUID();
@@ -82,7 +78,10 @@ export class AgentService {
82
78
  const record: AgentRecord = {
83
79
  id,
84
80
  name: data.name,
85
- promptTemplate: data.promptTemplate,
81
+ model: data.model || 'claude-opus-4-6',
82
+ skills: data.skills || '[]',
83
+ grounding: data.grounding,
84
+ defaultGrounding: null,
86
85
  projectId: data.projectId || null,
87
86
  isDefault: 0,
88
87
  createdAt: now,
@@ -94,8 +93,8 @@ export class AgentService {
94
93
  return record;
95
94
  };
96
95
 
97
- /** Update an agent's name and/or prompt_template. */
98
- update = async (id: string, data: { name?: string; promptTemplate?: string }): Promise<AgentRecord> => {
96
+ /** Update an agent's name, grounding, model, and/or skills. */
97
+ update = async (id: string, data: { name?: string; grounding?: string; model?: string; skills?: string }): Promise<AgentRecord> => {
99
98
  const db = this.getDb();
100
99
  const existing = await this.getById(id);
101
100
 
@@ -107,7 +106,9 @@ export class AgentService {
107
106
  const updates: Record<string, any> = { updatedAt: now };
108
107
 
109
108
  if (data.name !== undefined) updates.name = data.name;
110
- if (data.promptTemplate !== undefined) updates.promptTemplate = data.promptTemplate;
109
+ if (data.grounding !== undefined) updates.grounding = data.grounding;
110
+ if (data.model !== undefined) updates.model = data.model;
111
+ if (data.skills !== undefined) updates.skills = data.skills;
111
112
 
112
113
  await db.update(agents).set(updates).where(eq(agents.id, id));
113
114
 
@@ -139,7 +140,7 @@ export class AgentService {
139
140
  this.log('AGENTS', `Deleted agent: ${existing.name} (${id})`);
140
141
  };
141
142
 
142
- /** Reset a default agent's prompt_template to the original system prompt. */
143
+ /** Reset a default agent's grounding to the original default_grounding value. */
143
144
  resetToDefault = async (id: string): Promise<AgentRecord> => {
144
145
  const db = this.getDb();
145
146
  const existing = await this.getById(id);
@@ -152,265 +153,74 @@ export class AgentService {
152
153
  throw new Error('Only default agents can be reset');
153
154
  }
154
155
 
155
- // Determine the stage from the agent's name (e.g. "Default Developer" → "developer")
156
- const stage = this.inferStageFromName(existing.name);
157
- if (!stage) {
158
- throw new Error('Cannot determine stage for this default agent');
156
+ if (!existing.defaultGrounding) {
157
+ throw new Error('No default grounding available for this agent');
159
158
  }
160
159
 
161
- const template = await this.buildDefaultTemplate(stage);
162
160
  const now = new Date().toISOString();
163
161
 
164
162
  await db
165
163
  .update(agents)
166
- .set({ promptTemplate: template, updatedAt: now })
164
+ .set({ grounding: existing.defaultGrounding, updatedAt: now })
167
165
  .where(eq(agents.id, id));
168
166
 
169
- this.log('AGENTS', `Reset default agent to original prompt: ${existing.name} (${id})`);
170
- return { ...existing, promptTemplate: template, updatedAt: now };
167
+ this.log('AGENTS', `Reset default agent to original grounding: ${existing.name} (${id})`);
168
+ return { ...existing, grounding: existing.defaultGrounding, updatedAt: now };
171
169
  };
172
170
 
173
- /** Refresh all default agent prompt templates from SKILL.md + template sections.
174
- * Called on server startup to keep stored prompts in sync with code changes.
175
- * Also creates any missing default agents that have a skill path configured. */
176
- syncDefaults = async (): Promise<void> => {
177
- const db = this.getDb();
178
- const allAgents = await db.select().from(agents).where(eq(agents.isDefault, 1));
179
- const now = new Date().toISOString();
180
-
181
- // Update existing default agents
182
- for (const agent of allAgents) {
183
- const stage = this.inferStageFromName(agent.name);
184
- if (!stage) continue;
185
- try {
186
- const template = await this.buildDefaultTemplate(stage);
187
- if (template !== agent.promptTemplate) {
188
- await db.update(agents).set({ promptTemplate: template, updatedAt: now }).where(eq(agents.id, agent.id));
189
- this.log('AGENTS', `Synced default agent prompt: ${agent.name} (${agent.id})`);
190
- }
191
- } catch { /* skip if skill file missing */ }
171
+ /** List available skills by scanning the skills directory on disk. */
172
+ listSkills = async (): Promise<SkillInfo[]> => {
173
+ if (!existsSync(this.skillsDir)) {
174
+ return [];
192
175
  }
193
176
 
194
- // Create missing default agents
195
- for (const [stage, name] of Object.entries(DEFAULT_AGENT_NAMES)) {
196
- const skillPath = this.skillPaths[stage as keyof typeof this.skillPaths];
197
- if (!skillPath) continue;
198
- const exists = allAgents.some((a: AgentRecord) => this.inferStageFromName(a.name) === stage);
199
- if (exists) continue;
200
- try {
201
- const template = await this.buildDefaultTemplate(stage);
202
- const id = randomUUID();
203
- await db.insert(agents).values({
204
- id,
205
- name,
206
- promptTemplate: template,
207
- projectId: null,
208
- isDefault: 1,
209
- createdAt: now,
210
- updatedAt: now,
211
- });
212
- this.log('AGENTS', `Created missing default agent: ${name} (${id})`);
213
- } catch { /* skip if skill file missing or read error */ }
214
- }
215
- };
177
+ const entries = await readdir(this.skillsDir, { withFileTypes: true });
178
+ const skills: SkillInfo[] = [];
216
179
 
217
- /** Infer the stage from a default agent's name. */
218
- private inferStageFromName = (name: string): string | null => {
219
- const lower = name.toLowerCase();
220
- if (lower.includes('developer')) return 'developer';
221
- if (lower.includes('reviewer')) return 'reviewer';
222
- if (lower.includes('debugger')) return 'debugger';
223
- if (lower.includes('video script')) return 'videoScriptWriter';
224
- if (lower.includes('video composition')) return 'videoCompositionAgent';
225
- return null;
226
- };
180
+ for (const entry of entries) {
181
+ if (!entry.isDirectory()) continue;
227
182
 
228
- /** Build the default prompt template for a stage by reading the SKILL.md file. */
229
- private buildDefaultTemplate = async (stage: string): Promise<string> => {
230
- const pathMap: Record<string, string | undefined> = {
231
- developer: this.skillPaths.developer,
232
- reviewer: this.skillPaths.reviewer,
233
- debugger: this.skillPaths.debugger,
234
- videoScriptWriter: this.skillPaths.videoScriptWriter,
235
- videoCompositionAgent: this.skillPaths.videoCompositionAgent,
236
- };
183
+ const skillMdPath = join(this.skillsDir, entry.name, 'SKILL.md');
184
+ let name = entry.name;
185
+ let preview = '';
237
186
 
238
- const skillPath = pathMap[stage];
239
- if (!skillPath) {
240
- throw new Error(`Unknown stage: ${stage}`);
241
- }
187
+ if (existsSync(skillMdPath)) {
188
+ try {
189
+ const content = await readFile(skillMdPath, 'utf-8');
190
+ const parsed = this.parseSkillMd(content);
191
+ if (parsed.name) name = parsed.name;
192
+ preview = parsed.preview;
193
+ } catch {
194
+ // Use folder name as fallback
195
+ }
196
+ }
242
197
 
243
- const skillContent = await readFile(skillPath, 'utf-8');
244
-
245
- // Append the dynamic template sections with {{placeholder}} syntax
246
- // These match the format used in the seed data
247
- let template = skillContent + '\n\n';
248
-
249
- if (stage === 'developer') {
250
- template += this.buildDeveloperTemplateSections();
251
- } else if (stage === 'reviewer') {
252
- template += this.buildReviewerTemplateSections();
253
- } else if (stage === 'debugger') {
254
- template += this.buildDebuggerTemplateSections();
255
- } else if (stage === 'videoScriptWriter') {
256
- template += this.buildVideoScriptWriterTemplateSections();
257
- } else if (stage === 'videoCompositionAgent') {
258
- template += this.buildVideoCompositionAgentTemplateSections();
198
+ skills.push({ id: entry.name, name, preview });
259
199
  }
260
200
 
261
- return template;
262
- };
263
-
264
- private buildDeveloperTemplateSections = (): string => {
265
- let s = '';
266
- s += `## CRITICAL: Data Isolation\n`;
267
- s += `You are working in a git worktree. The worktree is ONLY for code changes.\n`;
268
- s += `All kanban, graph, and spec data lives in the MAIN REPO — never use the worktree copy.\n\n`;
269
- s += `**All tool commands MUST use absolute paths to the main repo's tools:**\n`;
270
- s += `- Tools directory: {{mainToolsDir}}\n`;
271
- s += `- All tool commands MUST be run from: {{mainSkillDir}}\n`;
272
- s += `- Example: cd {{mainSkillDir}} && npx tsx packages/shared/tools/get_node.ts {{featureId}}{{pidFlag}}\n`;
273
- s += `- Example: cd {{mainSkillDir}} && npx tsx packages/shared/tools/move_card.ts {{featureId}} in_review{{pidFlag}}\n\n`;
274
- s += `NEVER run tools from the worktree directory. NEVER use relative paths like \`assistkick-product-system/tools/\`.\n`;
275
- s += `ALWAYS \`cd {{mainSkillDir}}\` before running any tool command.\n`;
276
- s += `ALWAYS include --project-id {{projectId}} when running any tool command.\n\n`;
277
- s += `## Development Guidelines\n`;
278
- s += `Before writing any code, load the development guidelines:\n`;
279
- s += ` cd {{mainSkillDir}} && npx tsx packages/shared/tools/get_node.ts nfr_001{{pidFlag}}\n`;
280
- s += `These guidelines define mandatory coding standards (class-based architecture, arrow functions, constructor DI, naming conventions). All code you write MUST follow them.\n\n`;
281
- s += `## Current Task\n`;
282
- s += `Implement feature {{featureId}}. Read the feature spec using get_node, understand all related nodes, and implement it.\n\n`;
283
- s += `{{debuggerFindings}}\n\n`;
284
- s += `{{previousReviewNotes}}\n\n`;
285
- s += `When done implementing, do NOT move the card yourself — the pipeline will handle card transitions.\n\n`;
286
- s += `## REQUIRED: Work Summary Output\n`;
287
- s += `After completing your implementation, you MUST output a structured work summary block as your final text output.\n`;
288
- s += `The pipeline will parse this block to record what was done. Use this exact format:\n\n`;
289
- s += '```\n';
290
- s += `## Work Summary\n`;
291
- s += `### Approach\n`;
292
- s += `<A short paragraph explaining what you implemented and why you chose this approach.>\n`;
293
- s += `### Decisions\n`;
294
- s += `- <Key decision 1 you made during implementation>\n`;
295
- s += `- <Key decision 2>\n`;
296
- s += '```\n\n';
297
- s += `This block MUST appear in your final output. Do not skip it.\n`;
298
- return s;
201
+ return skills;
299
202
  };
300
203
 
301
- private buildReviewerTemplateSections = (): string => {
302
- let s = '';
303
- s += `## CRITICAL: Data Isolation\n`;
304
- s += `You are reviewing code in a git worktree. The worktree is ONLY for code changes.\n`;
305
- s += `All kanban, graph, and spec data lives in the MAIN REPO — never use the worktree copy.\n\n`;
306
- s += `**All tool commands MUST use absolute paths to the main repo's tools:**\n`;
307
- s += `- Tools directory: {{mainToolsDir}}\n`;
308
- s += `- All tool commands MUST be run from: {{mainSkillDir}}\n`;
309
- s += `- Example: cd {{mainSkillDir}} && npx tsx packages/shared/tools/get_node.ts {{featureId}}{{pidFlag}}\n`;
310
- s += `- Example: cd {{mainSkillDir}} && npx tsx packages/shared/tools/move_card.ts {{featureId}} qa{{pidFlag}}\n\n`;
311
- s += `NEVER run tools from the worktree directory. NEVER use relative paths like \`assistkick-product-system/tools/\`.\n`;
312
- s += `ALWAYS \`cd {{mainSkillDir}}\` before running any tool command.\n`;
313
- s += `ALWAYS include --project-id {{projectId}} when running any tool command.\n\n`;
314
- s += `## Current Task\n`;
315
- s += `Review feature {{featureId}}. Read the feature spec using get_node, understand all related nodes, and review the implementation.\n`;
316
- s += `If the implementation passes review, approve it by running: cd {{mainSkillDir}} && npx tsx packages/shared/tools/move_card.ts {{featureId}} qa{{pidFlag}}\n`;
317
- s += `If it fails, reject it with a note: cd {{mainSkillDir}} && npx tsx packages/shared/tools/move_card.ts {{featureId}} todo{{pidFlag}} --note "description of issues"\n`;
318
- return s;
319
- };
320
-
321
- private buildVideoScriptWriterTemplateSections = (): string => {
322
- let s = '';
323
- s += `## CRITICAL: Data Isolation\n`;
324
- s += `You are working in a git worktree. The worktree is ONLY for code changes.\n`;
325
- s += `All kanban, graph, and spec data lives in the MAIN REPO — never use the worktree copy.\n\n`;
326
- s += `## Current Task\n`;
327
- s += `Write a video script for the following feature brief:\n\n`;
328
- s += `{{featureDescription}}\n\n`;
329
- s += `Write the script to: {{worktreePath}}/assistkick-product-system/packages/video/scripts/{{compositionName}}-script.md\n\n`;
330
- s += `The composition name is: {{compositionName}}\n\n`;
331
- s += `## Iteration Handling\n`;
332
- s += `When re-running on a feature that was moved back to TODO, you receive iteration\n`;
333
- s += `comments from the previous review. Address all feedback in your revised script.\n\n`;
334
- s += `{{iterationComments}}\n\n`;
335
- s += `When done, do NOT move the card yourself — the pipeline will handle card transitions.\n\n`;
336
- s += `## REQUIRED: Work Summary Output\n`;
337
- s += `After completing your script, you MUST output a structured work summary block as your final text output.\n`;
338
- s += `The pipeline will parse this block to record what was done. Use this exact format:\n\n`;
339
- s += '```\n';
340
- s += `## Work Summary\n`;
341
- s += `### Approach\n`;
342
- s += `<A short paragraph explaining the script structure and creative choices.>\n`;
343
- s += `### Decisions\n`;
344
- s += `- <Key decision 1 about scene structure or content>\n`;
345
- s += `- <Key decision 2>\n`;
346
- s += '```\n\n';
347
- s += `This block MUST appear in your final output. Do not skip it.\n`;
348
- return s;
349
- };
204
+ /** Parse a SKILL.md file to extract name and a content preview. */
205
+ private parseSkillMd = (content: string): { name: string; preview: string } => {
206
+ const lines = content.split('\n');
207
+ let name = '';
208
+ const PREVIEW_LENGTH = 200;
209
+
210
+ for (const line of lines) {
211
+ const trimmed = line.trim();
212
+ if (!name && trimmed.startsWith('# ')) {
213
+ name = trimmed.slice(2).trim();
214
+ break;
215
+ }
216
+ }
350
217
 
351
- private buildVideoCompositionAgentTemplateSections = (): string => {
352
- let s = '';
353
- s += `## CRITICAL: Data Isolation\n`;
354
- s += `You are working in a git worktree. The worktree is ONLY for code changes.\n`;
355
- s += `All kanban, graph, and spec data lives in the MAIN REPO — never use the worktree copy.\n\n`;
356
- s += `## Current Task\n`;
357
- s += `Read the video script and generate the Remotion composition code for the following feature:\n\n`;
358
- s += `{{featureDescription}}\n\n`;
359
- s += `Script file: {{worktreePath}}/assistkick-product-system/packages/video/scripts/{{compositionName}}-script.md\n\n`;
360
- s += `The composition name is: {{compositionName}}\n`;
361
- s += `Write the composition to: {{worktreePath}}/assistkick-product-system/packages/video/compositions/{{compositionName}}/index.tsx\n`;
362
- s += `Register it in: {{worktreePath}}/assistkick-product-system/packages/video/Root.tsx\n\n`;
363
- s += `## Component Reuse\n`;
364
- s += `Before creating new components, list existing files in packages/video/components/ within the worktree.\n`;
365
- s += `Import and reuse shared components (TitleScene, Scene, OutroScene, PartDivider, EmailScene, VideoSplitLayout, theme) rather than duplicating.\n`;
366
- s += `Only create new components in packages/video/components/ when the script describes a scene type not covered by existing components.\n\n`;
367
- s += `## Iteration Handling\n`;
368
- s += `When re-running on a feature that was moved back to TODO, you receive iteration\n`;
369
- s += `comments from the previous review. Address all feedback in your revised composition.\n\n`;
370
- s += `{{iterationComments}}\n\n`;
371
- s += `When done, do NOT move the card yourself — the pipeline will handle card transitions.\n\n`;
372
- s += `## REQUIRED: Work Summary Output\n`;
373
- s += `After completing your composition, you MUST output a structured work summary block as your final text output.\n`;
374
- s += `The pipeline will parse this block to record what was done. Use this exact format:\n\n`;
375
- s += '```\n';
376
- s += `## Work Summary\n`;
377
- s += `### Approach\n`;
378
- s += `<A short paragraph explaining the composition structure and component choices.>\n`;
379
- s += `### Decisions\n`;
380
- s += `- <Key decision 1 about component reuse or scene implementation>\n`;
381
- s += `- <Key decision 2>\n`;
382
- s += '```\n\n';
383
- s += `This block MUST appear in your final output. Do not skip it.\n`;
384
- return s;
385
- };
218
+ // Preview: first N characters of content after the heading
219
+ const headingEnd = content.indexOf('\n', content.indexOf('# '));
220
+ const bodyStart = headingEnd >= 0 ? headingEnd + 1 : 0;
221
+ const body = content.slice(bodyStart).trim();
222
+ const preview = body.length > PREVIEW_LENGTH ? body.slice(0, PREVIEW_LENGTH) + '…' : body;
386
223
 
387
- private buildDebuggerTemplateSections = (): string => {
388
- let s = '';
389
- s += `## CRITICAL: Data Isolation\n`;
390
- s += `You are investigating bugs in a git worktree. The worktree is ONLY for code changes.\n`;
391
- s += `All kanban, graph, and spec data lives in the MAIN REPO — never use the worktree copy.\n\n`;
392
- s += `**All tool commands MUST use absolute paths to the main repo's tools:**\n`;
393
- s += `- Tools directory: {{mainToolsDir}}\n`;
394
- s += `- All tool commands MUST be run from: {{mainSkillDir}}\n`;
395
- s += `- Example: cd {{mainSkillDir}} && npx tsx packages/shared/tools/get_node.ts {{featureId}}{{pidFlag}}\n\n`;
396
- s += `NEVER run tools from the worktree directory. NEVER use relative paths.\n`;
397
- s += `ALWAYS \`cd {{mainSkillDir}}\` before running any tool command.\n`;
398
- s += `ALWAYS include --project-id {{projectId}} when running any tool command.\n\n`;
399
- s += `## Current Task\n`;
400
- s += `You are running as part of an automated pipeline. Do NOT create bugfix features or move kanban cards.\n`;
401
- s += `Instead, investigate the QA rejection notes below and output your findings as a structured report.\n\n`;
402
- s += `Feature: {{featureId}}\n\n`;
403
- s += `{{unaddressedNotes}}\n\n`;
404
- s += `## Instructions\n`;
405
- s += `1. Read the feature spec using get_node to understand what the feature should do\n`;
406
- s += `2. Read all related nodes to understand the full context\n`;
407
- s += `3. Trace through the code to find the root cause of each reported issue\n`;
408
- s += `4. Output a structured report with your findings. For each issue:\n`;
409
- s += ` - The original QA note text\n`;
410
- s += ` - Root cause analysis with specific file paths and line numbers\n`;
411
- s += ` - Why the current code fails\n`;
412
- s += ` - Specific guidance on what needs to change to fix it\n`;
413
- s += `5. Do NOT create bugfix features, do NOT move kanban cards, do NOT write code fixes\n`;
414
- return s;
224
+ return { name, preview };
415
225
  };
416
226
  }