@assistkick/create 1.10.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 +390 -22
  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 +129 -8
  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,14 +1,17 @@
1
1
  import { describe, it, mock, beforeEach } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { writeFileSync, mkdirSync, rmSync } from 'node:fs';
3
+ import { AgentService } from './agent_service.js';
4
+ import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises';
4
5
  import { join } from 'node:path';
5
6
  import { tmpdir } from 'node:os';
6
- import { AgentService } from './agent_service.ts';
7
7
 
8
8
  const MOCK_AGENT = {
9
9
  id: 'agent-1',
10
10
  name: 'Test Agent',
11
- promptTemplate: 'You are a test agent.',
11
+ model: 'claude-opus-4-6',
12
+ skills: '[]',
13
+ grounding: 'You are a test agent.',
14
+ defaultGrounding: null,
12
15
  projectId: null,
13
16
  isDefault: 0,
14
17
  createdAt: '2024-01-01T00:00:00Z',
@@ -18,27 +21,10 @@ const MOCK_AGENT = {
18
21
  const MOCK_DEFAULT_AGENT = {
19
22
  id: 'default-dev',
20
23
  name: 'Default Developer',
21
- promptTemplate: 'Original prompt template',
22
- projectId: null,
23
- isDefault: 1,
24
- createdAt: '2024-01-01T00:00:00Z',
25
- updatedAt: '2024-01-01T00:00:00Z',
26
- };
27
-
28
- const MOCK_VIDEO_SCRIPT_AGENT = {
29
- id: 'default-vsw',
30
- name: 'Default Video Script Writer',
31
- promptTemplate: 'Original video script prompt',
32
- projectId: null,
33
- isDefault: 1,
34
- createdAt: '2024-01-01T00:00:00Z',
35
- updatedAt: '2024-01-01T00:00:00Z',
36
- };
37
-
38
- const MOCK_VIDEO_COMPOSITION_AGENT = {
39
- id: 'default-vca',
40
- name: 'Default Video Composition Agent',
41
- promptTemplate: 'Original video composition prompt',
24
+ model: 'claude-opus-4-6',
25
+ skills: '["assistkick-developer"]',
26
+ grounding: '## CRITICAL: Data Isolation\nDeveloper grounding content',
27
+ defaultGrounding: '## CRITICAL: Data Isolation\nDeveloper grounding content',
42
28
  projectId: null,
43
29
  isDefault: 1,
44
30
  createdAt: '2024-01-01T00:00:00Z',
@@ -59,8 +45,6 @@ const createMockDb = () => {
59
45
  select: mock.fn(() => {
60
46
  const selectObj = {
61
47
  from: mock.fn(() => {
62
- // Make from() return a thenable (for direct await without .where())
63
- // that also has .where() and .leftJoin() for chaining
64
48
  const result = getNextResult();
65
49
  const fromObj = Object.assign(Promise.resolve(result), {
66
50
  where: mock.fn(() => {
@@ -97,43 +81,11 @@ const createMockDb = () => {
97
81
  return db;
98
82
  };
99
83
 
100
- const createService = (db: any) => {
101
- return new AgentService({
102
- getDb: () => db,
103
- log: mock.fn(),
104
- skillPaths: {
105
- developer: '/fake/developer/SKILL.md',
106
- reviewer: '/fake/reviewer/SKILL.md',
107
- debugger: '/fake/debugger/SKILL.md',
108
- },
109
- });
110
- };
111
-
112
- /** Create a service with a real skill file for the video script writer. */
113
- const createServiceWithVideoSkill = (db: any, skillDir: string) => {
84
+ const createService = (db: any, skillsDir = '/fake/skills') => {
114
85
  return new AgentService({
115
86
  getDb: () => db,
116
87
  log: mock.fn(),
117
- skillPaths: {
118
- developer: '/fake/developer/SKILL.md',
119
- reviewer: '/fake/reviewer/SKILL.md',
120
- debugger: '/fake/debugger/SKILL.md',
121
- videoScriptWriter: join(skillDir, 'SKILL.md'),
122
- },
123
- });
124
- };
125
-
126
- /** Create a service with a real skill file for the video composition agent. */
127
- const createServiceWithCompositionSkill = (db: any, skillDir: string) => {
128
- return new AgentService({
129
- getDb: () => db,
130
- log: mock.fn(),
131
- skillPaths: {
132
- developer: '/fake/developer/SKILL.md',
133
- reviewer: '/fake/reviewer/SKILL.md',
134
- debugger: '/fake/debugger/SKILL.md',
135
- videoCompositionAgent: join(skillDir, 'SKILL.md'),
136
- },
88
+ skillsDir,
137
89
  });
138
90
  };
139
91
 
@@ -197,12 +149,15 @@ describe('AgentService', () => {
197
149
  it('creates an agent with correct fields', async () => {
198
150
  const result = await service.create({
199
151
  name: 'New Agent',
200
- promptTemplate: 'You are a new agent.',
152
+ grounding: 'You are a new agent.',
201
153
  });
202
154
 
203
155
  assert.ok(result.id);
204
156
  assert.equal(result.name, 'New Agent');
205
- assert.equal(result.promptTemplate, 'You are a new agent.');
157
+ assert.equal(result.grounding, 'You are a new agent.');
158
+ assert.equal(result.model, 'claude-opus-4-6');
159
+ assert.equal(result.skills, '[]');
160
+ assert.equal(result.defaultGrounding, null);
206
161
  assert.equal(result.projectId, null);
207
162
  assert.equal(result.isDefault, 0);
208
163
  assert.ok(result.createdAt);
@@ -212,12 +167,24 @@ describe('AgentService', () => {
212
167
  it('creates a project-scoped agent', async () => {
213
168
  const result = await service.create({
214
169
  name: 'Project Agent',
215
- promptTemplate: 'Prompt',
170
+ grounding: 'Grounding content',
216
171
  projectId: 'proj_001',
217
172
  });
218
173
 
219
174
  assert.equal(result.projectId, 'proj_001');
220
175
  });
176
+
177
+ it('creates an agent with custom model and skills', async () => {
178
+ const result = await service.create({
179
+ name: 'Custom Agent',
180
+ grounding: 'Custom grounding',
181
+ model: 'claude-sonnet-4-6',
182
+ skills: '["assistkick-developer"]',
183
+ });
184
+
185
+ assert.equal(result.model, 'claude-sonnet-4-6');
186
+ assert.equal(result.skills, '["assistkick-developer"]');
187
+ });
221
188
  });
222
189
 
223
190
  describe('update', () => {
@@ -230,12 +197,24 @@ describe('AgentService', () => {
230
197
  assert.equal(db.update.mock.calls.length, 1);
231
198
  });
232
199
 
233
- it('updates agent promptTemplate', async () => {
200
+ it('updates agent grounding', async () => {
234
201
  db._setSelectResults([[MOCK_AGENT]]);
235
202
 
236
- const result = await service.update('agent-1', { promptTemplate: 'New prompt' });
203
+ const result = await service.update('agent-1', { grounding: 'New grounding' });
237
204
 
238
- assert.equal(result.promptTemplate, 'New prompt');
205
+ assert.equal(result.grounding, 'New grounding');
206
+ });
207
+
208
+ it('updates agent model and skills', async () => {
209
+ db._setSelectResults([[MOCK_AGENT]]);
210
+
211
+ const result = await service.update('agent-1', {
212
+ model: 'claude-sonnet-4-6',
213
+ skills: '["assistkick-developer"]',
214
+ });
215
+
216
+ assert.equal(result.model, 'claude-sonnet-4-6');
217
+ assert.equal(result.skills, '["assistkick-developer"]');
239
218
  });
240
219
 
241
220
  it('allows editing default agents', async () => {
@@ -314,176 +293,99 @@ describe('AgentService', () => {
314
293
  );
315
294
  });
316
295
 
317
- it('throws when stage cannot be inferred from name', async () => {
318
- const unknownDefault = { ...MOCK_DEFAULT_AGENT, name: 'Unknown Agent' };
319
- db._setSelectResults([[unknownDefault]]);
296
+ it('throws when default agent has no defaultGrounding', async () => {
297
+ const noDefaultGrounding = { ...MOCK_DEFAULT_AGENT, defaultGrounding: null };
298
+ db._setSelectResults([[noDefaultGrounding]]);
320
299
 
321
300
  await assert.rejects(
322
301
  () => service.resetToDefault('default-dev'),
323
- { message: 'Cannot determine stage for this default agent' },
302
+ { message: 'No default grounding available for this agent' },
324
303
  );
325
304
  });
326
- });
327
305
 
328
- describe('video script writer support', () => {
329
- let skillDir: string;
306
+ it('resets grounding to defaultGrounding value', async () => {
307
+ const modifiedAgent = { ...MOCK_DEFAULT_AGENT, grounding: 'User modified grounding' };
308
+ db._setSelectResults([[modifiedAgent]]);
330
309
 
331
- beforeEach(() => {
332
- skillDir = join(tmpdir(), `agent-test-${Date.now()}`);
333
- mkdirSync(skillDir, { recursive: true });
334
- writeFileSync(join(skillDir, 'SKILL.md'), '# Video Script Writer\nTest skill content.');
335
- });
336
-
337
- it('syncDefaults creates missing video script writer agent', async () => {
338
- const vsDb = createMockDb();
339
- const vsService = createServiceWithVideoSkill(vsDb, skillDir);
340
-
341
- // syncDefaults queries isDefault=1 agents — return empty (no existing defaults)
342
- vsDb._setSelectResults([[]]);
343
-
344
- await vsService.syncDefaults();
345
-
346
- // Should have called insert for all 4 default agents whose skill path exists
347
- // developer/reviewer/debugger will fail because /fake/ doesn't exist
348
- // only videoScriptWriter should succeed
349
- assert.equal(vsDb.insert.mock.calls.length, 1);
350
-
351
- rmSync(skillDir, { recursive: true, force: true });
352
- });
353
-
354
- it('syncDefaults skips video script writer when it already exists', async () => {
355
- const vsDb = createMockDb();
356
- const vsService = createServiceWithVideoSkill(vsDb, skillDir);
357
-
358
- // syncDefaults finds the video script writer already in DB
359
- vsDb._setSelectResults([[MOCK_VIDEO_SCRIPT_AGENT]]);
360
-
361
- await vsService.syncDefaults();
362
-
363
- // Should not insert any new agents (video script writer exists, others fail due to /fake/ path)
364
- assert.equal(vsDb.insert.mock.calls.length, 0);
365
-
366
- rmSync(skillDir, { recursive: true, force: true });
367
- });
368
-
369
- it('resetToDefault works for video script writer agent', async () => {
370
- const vsDb = createMockDb();
371
- const vsService = createServiceWithVideoSkill(vsDb, skillDir);
372
-
373
- vsDb._setSelectResults([[MOCK_VIDEO_SCRIPT_AGENT]]);
374
-
375
- const result = await vsService.resetToDefault('default-vsw');
376
-
377
- assert.ok(result.promptTemplate.includes('Video Script Writer'));
378
- assert.ok(result.promptTemplate.includes('{{featureDescription}}'));
379
- assert.ok(result.promptTemplate.includes('{{compositionName}}'));
380
- assert.ok(result.promptTemplate.includes('{{worktreePath}}'));
381
- assert.ok(result.promptTemplate.includes('{{iterationComments}}'));
382
-
383
- rmSync(skillDir, { recursive: true, force: true });
384
- });
310
+ const result = await service.resetToDefault('default-dev');
385
311
 
386
- it('template includes fenced directive format documentation', async () => {
387
- const vsDb = createMockDb();
388
- const vsService = createServiceWithVideoSkill(vsDb, skillDir);
389
-
390
- vsDb._setSelectResults([[MOCK_VIDEO_SCRIPT_AGENT]]);
391
-
392
- const result = await vsService.resetToDefault('default-vsw');
393
-
394
- // The SKILL.md mentions fenced directives; template sections add task context
395
- assert.ok(result.promptTemplate.includes('Data Isolation'));
396
- assert.ok(result.promptTemplate.includes('Work Summary'));
397
-
398
- rmSync(skillDir, { recursive: true, force: true });
312
+ assert.equal(result.grounding, MOCK_DEFAULT_AGENT.defaultGrounding);
313
+ assert.equal(db.update.mock.calls.length, 1);
399
314
  });
400
315
  });
401
316
 
402
- describe('video composition agent support', () => {
403
- let skillDir: string;
317
+ describe('listSkills', () => {
318
+ let tmpDir: string;
404
319
 
405
- beforeEach(() => {
406
- skillDir = join(tmpdir(), `agent-composition-test-${Date.now()}`);
407
- mkdirSync(skillDir, { recursive: true });
408
- writeFileSync(join(skillDir, 'SKILL.md'), '# Video Composition Agent\nTest composition skill content.');
320
+ beforeEach(async () => {
321
+ tmpDir = await mkdtemp(join(tmpdir(), 'skills-test-'));
409
322
  });
410
323
 
411
- it('syncDefaults creates missing video composition agent', async () => {
412
- const vcDb = createMockDb();
413
- const vcService = createServiceWithCompositionSkill(vcDb, skillDir);
324
+ it('returns empty array when skills directory does not exist', async () => {
325
+ const svc = createService(db, '/nonexistent/path');
414
326
 
415
- // No existing default agents
416
- vcDb._setSelectResults([[]]);
327
+ const result = await svc.listSkills();
417
328
 
418
- await vcService.syncDefaults();
419
-
420
- // Only videoCompositionAgent should succeed (others have /fake/ paths)
421
- assert.equal(vcDb.insert.mock.calls.length, 1);
422
-
423
- rmSync(skillDir, { recursive: true, force: true });
329
+ assert.deepEqual(result, []);
424
330
  });
425
331
 
426
- it('syncDefaults skips video composition agent when it already exists', async () => {
427
- const vcDb = createMockDb();
428
- const vcService = createServiceWithCompositionSkill(vcDb, skillDir);
429
-
430
- // Video composition agent already in DB
431
- vcDb._setSelectResults([[MOCK_VIDEO_COMPOSITION_AGENT]]);
332
+ it('lists skills from directory with SKILL.md files', async () => {
333
+ const skillDir = join(tmpDir, 'my-skill');
334
+ await mkdir(skillDir, { recursive: true });
335
+ await writeFile(join(skillDir, 'SKILL.md'), '# My Skill\nDoes something useful.\nMore details here.');
432
336
 
433
- await vcService.syncDefaults();
337
+ const svc = createService(db, tmpDir);
338
+ const result = await svc.listSkills();
434
339
 
435
- // Should not insert any new agents
436
- assert.equal(vcDb.insert.mock.calls.length, 0);
437
-
438
- rmSync(skillDir, { recursive: true, force: true });
340
+ assert.equal(result.length, 1);
341
+ assert.equal(result[0].id, 'my-skill');
342
+ assert.equal(result[0].name, 'My Skill');
343
+ assert.ok(result[0].preview.includes('Does something useful.'));
439
344
  });
440
345
 
441
- it('resetToDefault works for video composition agent', async () => {
442
- const vcDb = createMockDb();
443
- const vcService = createServiceWithCompositionSkill(vcDb, skillDir);
346
+ it('uses folder name when SKILL.md is missing', async () => {
347
+ const skillDir = join(tmpDir, 'bare-skill');
348
+ await mkdir(skillDir, { recursive: true });
444
349
 
445
- vcDb._setSelectResults([[MOCK_VIDEO_COMPOSITION_AGENT]]);
350
+ const svc = createService(db, tmpDir);
351
+ const result = await svc.listSkills();
446
352
 
447
- const result = await vcService.resetToDefault('default-vca');
448
-
449
- assert.ok(result.promptTemplate.includes('Video Composition Agent'));
450
- assert.ok(result.promptTemplate.includes('{{featureDescription}}'));
451
- assert.ok(result.promptTemplate.includes('{{compositionName}}'));
452
- assert.ok(result.promptTemplate.includes('{{worktreePath}}'));
453
- assert.ok(result.promptTemplate.includes('{{iterationComments}}'));
454
-
455
- rmSync(skillDir, { recursive: true, force: true });
353
+ assert.equal(result.length, 1);
354
+ assert.equal(result[0].id, 'bare-skill');
355
+ assert.equal(result[0].name, 'bare-skill');
356
+ assert.equal(result[0].preview, '');
456
357
  });
457
358
 
458
- it('template includes composition-specific sections', async () => {
459
- const vcDb = createMockDb();
460
- const vcService = createServiceWithCompositionSkill(vcDb, skillDir);
461
-
462
- vcDb._setSelectResults([[MOCK_VIDEO_COMPOSITION_AGENT]]);
463
-
464
- const result = await vcService.resetToDefault('default-vca');
359
+ it('skips non-directory entries', async () => {
360
+ await writeFile(join(tmpDir, 'not-a-skill.txt'), 'ignored');
361
+ const skillDir = join(tmpDir, 'real-skill');
362
+ await mkdir(skillDir, { recursive: true });
363
+ await writeFile(join(skillDir, 'SKILL.md'), '# Real Skill\nA real skill.');
465
364
 
466
- assert.ok(result.promptTemplate.includes('Data Isolation'));
467
- assert.ok(result.promptTemplate.includes('Component Reuse'));
468
- assert.ok(result.promptTemplate.includes('Work Summary'));
365
+ const svc = createService(db, tmpDir);
366
+ const result = await svc.listSkills();
469
367
 
470
- rmSync(skillDir, { recursive: true, force: true });
368
+ assert.equal(result.length, 1);
369
+ assert.equal(result[0].id, 'real-skill');
471
370
  });
472
371
 
473
- it('inferStageFromName correctly identifies video composition agent', async () => {
474
- const vcDb = createMockDb();
475
- const vcService = createServiceWithCompositionSkill(vcDb, skillDir);
476
-
477
- // Test with a custom-named agent that includes "video composition"
478
- const customAgent = { ...MOCK_VIDEO_COMPOSITION_AGENT, name: 'Custom Video Composition Bot' };
479
- vcDb._setSelectResults([[customAgent]]);
372
+ it('truncates long previews', async () => {
373
+ const skillDir = join(tmpDir, 'verbose-skill');
374
+ await mkdir(skillDir, { recursive: true });
375
+ const longContent = '# Verbose Skill\n' + 'A'.repeat(300);
376
+ await writeFile(join(skillDir, 'SKILL.md'), longContent);
480
377
 
481
- const result = await vcService.resetToDefault('default-vca');
378
+ const svc = createService(db, tmpDir);
379
+ const result = await svc.listSkills();
482
380
 
483
- // Should resolve to videoCompositionAgent stage and build from skill
484
- assert.ok(result.promptTemplate.includes('Video Composition Agent'));
381
+ assert.equal(result.length, 1);
382
+ assert.ok(result[0].preview.length <= 201); // 200 + ellipsis char
383
+ assert.ok(result[0].preview.endsWith('…'));
384
+ });
485
385
 
486
- rmSync(skillDir, { recursive: true, force: true });
386
+ // Clean up temp directory after all tests in this suite
387
+ it('cleanup', async () => {
388
+ await rm(tmpDir, { recursive: true, force: true });
487
389
  });
488
390
  });
489
391
  });