@archznn/crewloop-skills 0.6.0 → 0.7.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 (245) hide show
  1. package/README.md +4 -16
  2. package/package.json +1 -2
  3. package/packages/cli/dist/agents.js +1 -1
  4. package/packages/cli/dist/agents.js.map +1 -1
  5. package/packages/cli/dist/cli.d.ts.map +1 -1
  6. package/packages/cli/dist/cli.js +2 -30
  7. package/packages/cli/dist/cli.js.map +1 -1
  8. package/packages/cli/dist/hooks.d.ts +6 -4
  9. package/packages/cli/dist/hooks.d.ts.map +1 -1
  10. package/packages/cli/dist/hooks.js +250 -98
  11. package/packages/cli/dist/hooks.js.map +1 -1
  12. package/packages/cli/dist/tests/hooks.test.js +245 -33
  13. package/packages/cli/dist/tests/hooks.test.js.map +1 -1
  14. package/references/conventions.md +1 -10
  15. package/references/workflow.md +1 -1
  16. package/servers/dashboard/README.md +55 -1
  17. package/servers/dashboard/dist/adapters/agy.d.ts +19 -0
  18. package/servers/dashboard/dist/adapters/agy.d.ts.map +1 -0
  19. package/servers/dashboard/dist/adapters/agy.js +108 -0
  20. package/servers/dashboard/dist/adapters/agy.js.map +1 -0
  21. package/servers/dashboard/dist/adapters/codex.d.ts.map +1 -1
  22. package/servers/dashboard/dist/adapters/codex.js +2 -0
  23. package/servers/dashboard/dist/adapters/codex.js.map +1 -1
  24. package/servers/dashboard/dist/adapters/kimi.d.ts +1 -1
  25. package/servers/dashboard/dist/adapters/kimi.d.ts.map +1 -1
  26. package/servers/dashboard/dist/adapters/kimi.js +9 -0
  27. package/servers/dashboard/dist/adapters/kimi.js.map +1 -1
  28. package/servers/dashboard/dist/adapters/shim.d.ts +1 -1
  29. package/servers/dashboard/dist/adapters/shim.d.ts.map +1 -1
  30. package/servers/dashboard/dist/adapters/shim.js +32 -11
  31. package/servers/dashboard/dist/adapters/shim.js.map +1 -1
  32. package/servers/dashboard/dist/adapters/shim.test.js +46 -4
  33. package/servers/dashboard/dist/adapters/shim.test.js.map +1 -1
  34. package/servers/dashboard/dist/lib/constants.d.ts +5 -0
  35. package/servers/dashboard/dist/lib/constants.d.ts.map +1 -0
  36. package/servers/dashboard/dist/lib/constants.js +46 -0
  37. package/servers/dashboard/dist/lib/constants.js.map +1 -0
  38. package/servers/dashboard/dist/lib/format.d.ts +6 -0
  39. package/servers/dashboard/dist/lib/format.d.ts.map +1 -0
  40. package/servers/dashboard/dist/lib/format.js +52 -0
  41. package/servers/dashboard/dist/lib/format.js.map +1 -0
  42. package/servers/dashboard/dist/lib/graph.d.ts +22 -0
  43. package/servers/dashboard/dist/lib/graph.d.ts.map +1 -0
  44. package/servers/dashboard/dist/lib/graph.js +45 -0
  45. package/servers/dashboard/dist/lib/graph.js.map +1 -0
  46. package/servers/dashboard/dist/lib/invocations.d.ts +32 -0
  47. package/servers/dashboard/dist/lib/invocations.d.ts.map +1 -0
  48. package/servers/dashboard/dist/lib/invocations.js +135 -0
  49. package/servers/dashboard/dist/lib/invocations.js.map +1 -0
  50. package/servers/dashboard/dist/lib/invocations.test.d.ts +2 -0
  51. package/servers/dashboard/dist/lib/invocations.test.d.ts.map +1 -0
  52. package/servers/dashboard/dist/lib/invocations.test.js +68 -0
  53. package/servers/dashboard/dist/lib/invocations.test.js.map +1 -0
  54. package/servers/dashboard/dist/lib/paths.d.ts +2 -0
  55. package/servers/dashboard/dist/lib/paths.d.ts.map +1 -0
  56. package/servers/dashboard/dist/lib/paths.js +40 -0
  57. package/servers/dashboard/dist/lib/paths.js.map +1 -0
  58. package/servers/dashboard/dist/presenter.d.ts.map +1 -1
  59. package/servers/dashboard/dist/presenter.js +2 -0
  60. package/servers/dashboard/dist/presenter.js.map +1 -1
  61. package/servers/dashboard/dist/public/assets/index-DjmMKbPN.css +1 -0
  62. package/servers/dashboard/dist/public/assets/index-DzOqMleZ.js +5323 -0
  63. package/servers/dashboard/dist/public/assets/index-DzOqMleZ.js.map +1 -0
  64. package/servers/dashboard/dist/public/index.html +16 -0
  65. package/servers/dashboard/dist/server.d.ts.map +1 -1
  66. package/servers/dashboard/dist/server.js +5 -1
  67. package/servers/dashboard/dist/server.js.map +1 -1
  68. package/servers/dashboard/dist/skills/infer.d.ts.map +1 -1
  69. package/servers/dashboard/dist/skills/infer.js +0 -6
  70. package/servers/dashboard/dist/skills/infer.js.map +1 -1
  71. package/servers/dashboard/dist/skills/infer.test.js +10 -3
  72. package/servers/dashboard/dist/skills/infer.test.js.map +1 -1
  73. package/servers/dashboard/dist/skills/mapping.d.ts +0 -3
  74. package/servers/dashboard/dist/skills/mapping.d.ts.map +1 -1
  75. package/servers/dashboard/dist/skills/mapping.js +0 -18
  76. package/servers/dashboard/dist/skills/mapping.js.map +1 -1
  77. package/servers/dashboard/dist/skills/registry.d.ts.map +1 -1
  78. package/servers/dashboard/dist/skills/registry.js +0 -1
  79. package/servers/dashboard/dist/skills/registry.js.map +1 -1
  80. package/servers/dashboard/dist/tests/adapters.test.d.ts +2 -0
  81. package/servers/dashboard/dist/tests/adapters.test.d.ts.map +1 -0
  82. package/servers/dashboard/dist/tests/adapters.test.js +180 -0
  83. package/servers/dashboard/dist/tests/adapters.test.js.map +1 -0
  84. package/servers/dashboard/dist/tests/lib-helpers.test.d.ts +2 -0
  85. package/servers/dashboard/dist/tests/lib-helpers.test.d.ts.map +1 -0
  86. package/servers/dashboard/dist/tests/lib-helpers.test.js +123 -0
  87. package/servers/dashboard/dist/tests/lib-helpers.test.js.map +1 -0
  88. package/servers/dashboard/dist/tests/shim.test.js +88 -2
  89. package/servers/dashboard/dist/tests/shim.test.js.map +1 -1
  90. package/servers/dashboard/dist/types.d.ts +5 -2
  91. package/servers/dashboard/dist/types.d.ts.map +1 -1
  92. package/servers/dashboard/package.json +22 -5
  93. package/servers/dashboard/src/adapters/agy.ts +136 -0
  94. package/servers/dashboard/src/adapters/codex.ts +2 -0
  95. package/servers/dashboard/src/adapters/kimi.ts +11 -1
  96. package/servers/dashboard/src/adapters/shim.test.ts +57 -4
  97. package/servers/dashboard/src/adapters/shim.ts +31 -11
  98. package/servers/dashboard/src/lib/constants.ts +44 -0
  99. package/servers/dashboard/src/lib/format.ts +44 -0
  100. package/servers/dashboard/src/lib/graph.ts +69 -0
  101. package/servers/dashboard/src/lib/invocations.test.ts +70 -0
  102. package/servers/dashboard/src/lib/invocations.ts +172 -0
  103. package/servers/dashboard/src/lib/paths.ts +35 -0
  104. package/servers/dashboard/src/presenter.ts +2 -0
  105. package/servers/dashboard/src/server.ts +5 -1
  106. package/servers/dashboard/src/skills/infer.test.ts +11 -3
  107. package/servers/dashboard/src/skills/infer.ts +1 -8
  108. package/servers/dashboard/src/skills/mapping.ts +0 -20
  109. package/servers/dashboard/src/skills/registry.ts +0 -1
  110. package/servers/dashboard/src/tests/adapters.test.ts +198 -0
  111. package/servers/dashboard/src/tests/lib-helpers.test.ts +133 -0
  112. package/servers/dashboard/src/tests/shim.test.ts +110 -2
  113. package/servers/dashboard/src/types.ts +5 -3
  114. package/servers/dashboard/ui/index.html +15 -0
  115. package/servers/dashboard/ui/postcss.config.js +6 -0
  116. package/servers/dashboard/ui/src/App.tsx +360 -0
  117. package/servers/dashboard/ui/src/components/ActiveSkillPanel.tsx +69 -0
  118. package/servers/dashboard/ui/src/components/ActivityGraph.tsx +74 -0
  119. package/servers/dashboard/ui/src/components/CommandPalette.tsx +200 -0
  120. package/servers/dashboard/ui/src/components/FileActivity.tsx +20 -0
  121. package/servers/dashboard/ui/src/components/FileDiff.tsx +68 -0
  122. package/servers/dashboard/ui/src/components/FileList.tsx +64 -0
  123. package/servers/dashboard/ui/src/components/FilterBar.tsx +208 -0
  124. package/servers/dashboard/ui/src/components/Network3D.tsx +178 -0
  125. package/servers/dashboard/ui/src/components/SessionSelector.tsx +95 -0
  126. package/servers/dashboard/ui/src/components/Sidebar.tsx +110 -0
  127. package/servers/dashboard/ui/src/components/TelemetryPanel.tsx +57 -0
  128. package/servers/dashboard/ui/src/components/Timeline.tsx +57 -0
  129. package/servers/dashboard/ui/src/components/TimelineRow.tsx +112 -0
  130. package/servers/dashboard/ui/src/components/TopBar.tsx +116 -0
  131. package/servers/dashboard/ui/src/components/ViewHeader.tsx +19 -0
  132. package/servers/dashboard/ui/src/components/ui/Icon.tsx +105 -0
  133. package/servers/dashboard/ui/src/components/ui/StatusBadge.tsx +19 -0
  134. package/servers/dashboard/ui/src/components/views/FilesView.tsx +23 -0
  135. package/servers/dashboard/ui/src/components/views/NetworkView.tsx +20 -0
  136. package/servers/dashboard/ui/src/components/views/Overview.tsx +135 -0
  137. package/servers/dashboard/ui/src/components/views/SessionsView.tsx +84 -0
  138. package/servers/dashboard/ui/src/components/views/SettingsView.tsx +138 -0
  139. package/servers/dashboard/ui/src/components/views/SkillsView.tsx +92 -0
  140. package/servers/dashboard/ui/src/components/views/TimelineView.tsx +46 -0
  141. package/servers/dashboard/ui/src/contexts/FilterContext.tsx +41 -0
  142. package/servers/dashboard/ui/src/contexts/PinnedSessionsContext.tsx +80 -0
  143. package/servers/dashboard/ui/src/contexts/SettingsContext.tsx +60 -0
  144. package/servers/dashboard/ui/src/hooks/useCommandPalette.ts +36 -0
  145. package/servers/dashboard/ui/src/hooks/useKeyboardShortcut.ts +38 -0
  146. package/servers/dashboard/ui/src/hooks/useNow.ts +12 -0
  147. package/servers/dashboard/ui/src/hooks/useReducedMotion.ts +15 -0
  148. package/servers/dashboard/ui/src/hooks/useSessions.ts +64 -0
  149. package/servers/dashboard/ui/src/hooks/useTheme.ts +30 -0
  150. package/servers/dashboard/ui/src/hooks/useViewport.ts +19 -0
  151. package/servers/dashboard/ui/src/hooks/useWebSocket.ts +118 -0
  152. package/servers/dashboard/ui/src/lib/export.test.ts +33 -0
  153. package/servers/dashboard/ui/src/lib/export.ts +39 -0
  154. package/servers/dashboard/ui/src/lib/filter.test.ts +95 -0
  155. package/servers/dashboard/ui/src/lib/filter.ts +178 -0
  156. package/servers/dashboard/ui/src/lib/format.test.ts +25 -0
  157. package/servers/dashboard/ui/src/lib/search.test.ts +52 -0
  158. package/servers/dashboard/ui/src/lib/search.ts +60 -0
  159. package/servers/dashboard/ui/src/lib/settings.test.ts +50 -0
  160. package/servers/dashboard/ui/src/lib/settings.ts +56 -0
  161. package/servers/dashboard/ui/src/lib/types.ts +124 -0
  162. package/servers/dashboard/ui/src/main.tsx +19 -0
  163. package/servers/dashboard/ui/src/styles/index.css +155 -0
  164. package/servers/dashboard/ui/tailwind.config.js +45 -0
  165. package/servers/dashboard/ui/tsconfig.json +33 -0
  166. package/servers/dashboard/ui/tsconfig.node.json +10 -0
  167. package/servers/dashboard/ui/vite.config.ts +37 -0
  168. package/servers/dashboard/ui/vitest.config.ts +8 -0
  169. package/skills/accessibility-auditor/SKILL.md +0 -20
  170. package/skills/architect/SKILL.md +0 -45
  171. package/skills/designer/SKILL.md +0 -30
  172. package/skills/docs-writer/SKILL.md +0 -13
  173. package/skills/engineer/SKILL.md +0 -30
  174. package/skills/maintainer/SKILL.md +0 -20
  175. package/skills/orchestrator/SKILL.md +0 -13
  176. package/skills/product-manager/SKILL.md +0 -20
  177. package/skills/researcher/SKILL.md +0 -20
  178. package/skills/reviewer/SKILL.md +0 -30
  179. package/skills/security-guard/SKILL.md +0 -20
  180. package/skills/shipper/SKILL.md +0 -33
  181. package/skills/tester/SKILL.md +0 -20
  182. package/packages/cli/dist/mcp.d.ts +0 -28
  183. package/packages/cli/dist/mcp.d.ts.map +0 -1
  184. package/packages/cli/dist/mcp.js +0 -148
  185. package/packages/cli/dist/mcp.js.map +0 -1
  186. package/packages/cli/dist/tests/mcp.test.d.ts +0 -2
  187. package/packages/cli/dist/tests/mcp.test.d.ts.map +0 -1
  188. package/packages/cli/dist/tests/mcp.test.js +0 -232
  189. package/packages/cli/dist/tests/mcp.test.js.map +0 -1
  190. package/references/obsidian-mcp-usage.md +0 -190
  191. package/servers/dashboard/public/app.js +0 -516
  192. package/servers/dashboard/public/index.html +0 -96
  193. package/servers/dashboard/public/styles.css +0 -819
  194. package/servers/obsidian-mcp/README.md +0 -82
  195. package/servers/obsidian-mcp/pyproject.toml +0 -32
  196. package/servers/obsidian-mcp/src/obsidian_mcp/__init__.py +0 -0
  197. package/servers/obsidian-mcp/src/obsidian_mcp/config.py +0 -47
  198. package/servers/obsidian-mcp/src/obsidian_mcp/indexer/__init__.py +0 -0
  199. package/servers/obsidian-mcp/src/obsidian_mcp/indexer/embeddings.py +0 -105
  200. package/servers/obsidian-mcp/src/obsidian_mcp/indexer/indexer.py +0 -79
  201. package/servers/obsidian-mcp/src/obsidian_mcp/indexer/store.py +0 -141
  202. package/servers/obsidian-mcp/src/obsidian_mcp/indexer/sync.py +0 -37
  203. package/servers/obsidian-mcp/src/obsidian_mcp/learning/__init__.py +0 -0
  204. package/servers/obsidian-mcp/src/obsidian_mcp/learning/detector.py +0 -66
  205. package/servers/obsidian-mcp/src/obsidian_mcp/learning/note_generator.py +0 -40
  206. package/servers/obsidian-mcp/src/obsidian_mcp/main.py +0 -4
  207. package/servers/obsidian-mcp/src/obsidian_mcp/models.py +0 -42
  208. package/servers/obsidian-mcp/src/obsidian_mcp/privacy/__init__.py +0 -0
  209. package/servers/obsidian-mcp/src/obsidian_mcp/privacy/filter.py +0 -68
  210. package/servers/obsidian-mcp/src/obsidian_mcp/rag/__init__.py +0 -0
  211. package/servers/obsidian-mcp/src/obsidian_mcp/rag/engine.py +0 -50
  212. package/servers/obsidian-mcp/src/obsidian_mcp/rag/graph_search.py +0 -55
  213. package/servers/obsidian-mcp/src/obsidian_mcp/rag/text_search.py +0 -37
  214. package/servers/obsidian-mcp/src/obsidian_mcp/rag/vector_search.py +0 -118
  215. package/servers/obsidian-mcp/src/obsidian_mcp/server.py +0 -61
  216. package/servers/obsidian-mcp/src/obsidian_mcp/tools/__init__.py +0 -0
  217. package/servers/obsidian-mcp/src/obsidian_mcp/tools/create.py +0 -43
  218. package/servers/obsidian-mcp/src/obsidian_mcp/tools/delete.py +0 -16
  219. package/servers/obsidian-mcp/src/obsidian_mcp/tools/learn.py +0 -42
  220. package/servers/obsidian-mcp/src/obsidian_mcp/tools/list.py +0 -16
  221. package/servers/obsidian-mcp/src/obsidian_mcp/tools/read.py +0 -15
  222. package/servers/obsidian-mcp/src/obsidian_mcp/tools/registry.py +0 -130
  223. package/servers/obsidian-mcp/src/obsidian_mcp/tools/related.py +0 -20
  224. package/servers/obsidian-mcp/src/obsidian_mcp/tools/search.py +0 -26
  225. package/servers/obsidian-mcp/src/obsidian_mcp/tools/sync.py +0 -22
  226. package/servers/obsidian-mcp/src/obsidian_mcp/tools/update.py +0 -34
  227. package/servers/obsidian-mcp/src/obsidian_mcp/vault/__init__.py +0 -0
  228. package/servers/obsidian-mcp/src/obsidian_mcp/vault/parser.py +0 -82
  229. package/servers/obsidian-mcp/src/obsidian_mcp/vault/repository.py +0 -68
  230. package/servers/obsidian-mcp/src/obsidian_mcp/vault/writer.py +0 -61
  231. package/servers/obsidian-mcp/tests/conftest.py +0 -39
  232. package/servers/obsidian-mcp/tests/test_async_tools.py +0 -87
  233. package/servers/obsidian-mcp/tests/test_edge_cases.py +0 -59
  234. package/servers/obsidian-mcp/tests/test_indexer.py +0 -27
  235. package/servers/obsidian-mcp/tests/test_integration.py +0 -90
  236. package/servers/obsidian-mcp/tests/test_learning.py +0 -34
  237. package/servers/obsidian-mcp/tests/test_privacy.py +0 -31
  238. package/servers/obsidian-mcp/tests/test_privacy_config.py +0 -44
  239. package/servers/obsidian-mcp/tests/test_rag.py +0 -64
  240. package/servers/obsidian-mcp/tests/test_read_raw.py +0 -37
  241. package/servers/obsidian-mcp/tests/test_tfidf_fallback.py +0 -54
  242. package/servers/obsidian-mcp/tests/test_tools.py +0 -108
  243. package/servers/obsidian-mcp/tests/test_vault.py +0 -103
  244. package/servers/obsidian-mcp/tests/test_writer.py +0 -139
  245. package/skills/obsidian-second-brain/SKILL.md +0 -298
@@ -7,12 +7,14 @@ const node_test_1 = require("node:test");
7
7
  const node_assert_1 = __importDefault(require("node:assert"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const node_child_process_1 = require("node:child_process");
10
+ const node_http_1 = __importDefault(require("node:http"));
10
11
  const shim_1 = require("../adapters/shim");
11
- function runBin(args, input) {
12
+ function runBin(args, input, env) {
12
13
  const binPath = node_path_1.default.join(__dirname, '..', '..', 'bin', 'crewloop-shim.js');
13
14
  return new Promise((resolve, reject) => {
14
15
  const child = (0, node_child_process_1.spawn)(process.execPath, [binPath, ...args], {
15
16
  stdio: ['pipe', 'pipe', 'pipe'],
17
+ env: env ? { ...process.env, ...env } : process.env,
16
18
  });
17
19
  let stderr = '';
18
20
  child.stderr.on('data', (chunk) => {
@@ -41,7 +43,91 @@ function runBin(args, input) {
41
43
  const { exitCode, stderr } = await runBin(['unknown']);
42
44
  node_assert_1.default.strictEqual(exitCode, 1);
43
45
  node_assert_1.default.ok(stderr.includes('unknown source'));
44
- node_assert_1.default.ok(stderr.includes('crewloop-shim <kimi|codex>'));
46
+ node_assert_1.default.ok(stderr.includes('crewloop-shim <kimi|codex|agy>'));
47
+ });
48
+ (0, node_test_1.it)('exits 0 for agy source with empty stdin', async () => {
49
+ const { exitCode, stderr } = await runBin(['agy']);
50
+ node_assert_1.default.strictEqual(exitCode, 0);
51
+ node_assert_1.default.strictEqual(stderr, '');
52
+ });
53
+ (0, node_test_1.it)('delivers a POST /event before exiting', async () => {
54
+ let receivedBody;
55
+ const server = node_http_1.default.createServer((req, res) => {
56
+ if (req.method === 'POST' && req.url === '/event') {
57
+ let body = '';
58
+ req.on('data', (chunk) => {
59
+ body += chunk.toString();
60
+ });
61
+ req.on('end', () => {
62
+ receivedBody = body;
63
+ res.writeHead(200, { 'Content-Type': 'application/json' });
64
+ res.end(JSON.stringify({ ok: true }));
65
+ });
66
+ }
67
+ });
68
+ await new Promise((resolve) => server.listen(0, resolve));
69
+ const { port } = server.address();
70
+ const input = JSON.stringify({
71
+ hook_event_name: 'PostToolUse',
72
+ session_id: 'test-session',
73
+ cwd: '/tmp',
74
+ tool_name: 'TestTool',
75
+ tool_input: { command: 'echo hello' },
76
+ tool_output: 'hello\n',
77
+ });
78
+ try {
79
+ const { exitCode } = await runBin(['kimi', '--default-skill', 'orchestrator'], input, { CREWLOOP_DASHBOARD_URL: `http://127.0.0.1:${port}` });
80
+ node_assert_1.default.strictEqual(exitCode, 0);
81
+ node_assert_1.default.ok(receivedBody, 'shim should have sent a request body');
82
+ const parsed = JSON.parse(receivedBody);
83
+ node_assert_1.default.strictEqual(parsed.event_type, 'tool_end');
84
+ node_assert_1.default.strictEqual(parsed.source, 'kimi');
85
+ node_assert_1.default.strictEqual(parsed.session_id, 'test-session');
86
+ node_assert_1.default.deepStrictEqual(parsed.input, { command: 'echo hello' });
87
+ node_assert_1.default.deepStrictEqual(parsed.output, { output: 'hello\n' });
88
+ }
89
+ finally {
90
+ server.close();
91
+ }
92
+ });
93
+ (0, node_test_1.it)('delivers AGY event with default skill fallback', async () => {
94
+ let receivedBody;
95
+ const server = node_http_1.default.createServer((req, res) => {
96
+ if (req.method === 'POST' && req.url === '/event') {
97
+ let body = '';
98
+ req.on('data', (chunk) => {
99
+ body += chunk.toString();
100
+ });
101
+ req.on('end', () => {
102
+ receivedBody = body;
103
+ res.writeHead(200, { 'Content-Type': 'application/json' });
104
+ res.end(JSON.stringify({ ok: true }));
105
+ });
106
+ }
107
+ });
108
+ await new Promise((resolve) => server.listen(0, resolve));
109
+ const { port } = server.address();
110
+ const input = JSON.stringify({
111
+ hook_event_name: 'PreToolUse',
112
+ conversationId: 'agy-session',
113
+ stepIdx: 0,
114
+ toolCall: {
115
+ name: 'run_command',
116
+ args: { CommandLine: 'git status' },
117
+ },
118
+ });
119
+ try {
120
+ const { exitCode } = await runBin(['agy', '--default-skill', 'orchestrator'], input, { CREWLOOP_DASHBOARD_URL: `http://127.0.0.1:${port}` });
121
+ node_assert_1.default.strictEqual(exitCode, 0);
122
+ node_assert_1.default.ok(receivedBody, 'shim should have sent a request body');
123
+ const parsed = JSON.parse(receivedBody);
124
+ node_assert_1.default.strictEqual(parsed.event_type, 'tool_start');
125
+ node_assert_1.default.strictEqual(parsed.source, 'agy');
126
+ node_assert_1.default.strictEqual(parsed.skill, 'orchestrator');
127
+ }
128
+ finally {
129
+ server.close();
130
+ }
45
131
  });
46
132
  });
47
133
  //# sourceMappingURL=shim.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shim.test.js","sourceRoot":"","sources":["../../src/tests/shim.test.ts"],"names":[],"mappings":";;;;;AAAA,yCAAyC;AACzC,8DAAiC;AACjC,0DAA6B;AAC7B,2DAA2C;AAC3C,2CAA2C;AAE3C,SAAS,MAAM,CAAC,IAAc,EAAE,KAAc;IAC5C,MAAM,OAAO,GAAG,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAC5E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,IAAA,0BAAK,EAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,EAAE;YACxD,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,CAAC,MAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC7B,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,KAAK,CAAC,KAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,KAAK,CAAC,KAAM,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAA,oBAAQ,EAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,IAAA,cAAE,EAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,qBAAM,CAAC,WAAW,CAAC,OAAO,cAAO,EAAE,UAAU,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACpD,qBAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAChC,qBAAM,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QACvD,qBAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAChC,qBAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAC7C,qBAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"shim.test.js","sourceRoot":"","sources":["../../src/tests/shim.test.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export type AgentSource = 'kimi' | 'codex' | 'opencode' | 'log-watcher';
1
+ export type AgentSource = 'kimi' | 'codex' | 'opencode' | 'log-watcher' | 'agy';
2
2
  export type EventType = 'session_start' | 'session_end' | 'tool_start' | 'tool_end' | 'skill_change';
3
3
  export type EventStatus = 'running' | 'success' | 'error';
4
4
  export interface DashboardEvent {
@@ -12,6 +12,8 @@ export interface DashboardEvent {
12
12
  detail?: string;
13
13
  status?: EventStatus;
14
14
  duration_ms?: number;
15
+ input?: Record<string, unknown>;
16
+ output?: Record<string, unknown>;
15
17
  }
16
18
  export interface Session {
17
19
  id: string;
@@ -42,6 +44,8 @@ export interface ClientEvent {
42
44
  status?: EventStatus;
43
45
  duration_ms?: number;
44
46
  skill?: string;
47
+ input?: Record<string, unknown>;
48
+ output?: Record<string, unknown>;
45
49
  }
46
50
  export interface ClientSession {
47
51
  id: string;
@@ -74,7 +78,6 @@ export interface SkillMeta {
74
78
  description: string;
75
79
  icon: string;
76
80
  }
77
- export type ToolToSkillMap = Record<string, string | undefined>;
78
81
  export interface SkillInferenceResult {
79
82
  skill: string | undefined;
80
83
  confidence: 'explicit' | 'heuristic' | 'unknown';
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archznn/crewloop-dashboard",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Real-time CrewLoop skill dashboard server and UI",
5
5
  "license": "MIT",
6
6
  "author": "leorsousa05",
@@ -22,21 +22,38 @@
22
22
  ],
23
23
  "scripts": {
24
24
  "start": "node dist/index.js",
25
- "build": "tsc",
26
- "typecheck": "tsc --noEmit",
27
- "test": "node --test dist/**/*.test.js",
25
+ "build": "npm run build:server && npm run build:ui",
26
+ "build:server": "tsc",
27
+ "build:ui": "cd ui && vite build",
28
+ "dev": "cd ui && vite",
29
+ "typecheck": "tsc --noEmit && tsc --noEmit -p ui/tsconfig.json",
30
+ "test": "npm run test:server && npm run test:ui",
31
+ "test:server": "node --test dist/**/*.test.js",
32
+ "test:ui": "vitest run --root ui --config vitest.config.ts",
28
33
  "prepublishOnly": "npm run build"
29
34
  },
30
35
  "engines": {
31
36
  "node": ">=18"
32
37
  },
33
38
  "dependencies": {
39
+ "@phosphor-icons/react": "^2.1.7",
40
+ "react": "^18.3.1",
41
+ "react-dom": "^18.3.1",
42
+ "react-force-graph-3d": "^1.26.0",
34
43
  "ws": "^8.18.0"
35
44
  },
36
45
  "devDependencies": {
37
46
  "@types/node": "^20.0.0",
47
+ "@types/react": "^18.3.12",
48
+ "@types/react-dom": "^18.3.1",
38
49
  "@types/ws": "^8.5.0",
39
- "typescript": "^5.4.0"
50
+ "@vitejs/plugin-react": "^4.3.4",
51
+ "autoprefixer": "^10.4.20",
52
+ "postcss": "^8.4.49",
53
+ "tailwindcss": "^3.4.17",
54
+ "typescript": "^5.4.0",
55
+ "vite": "^6.0.3",
56
+ "vitest": "^2.1.8"
40
57
  },
41
58
  "keywords": [
42
59
  "ai-agent",
@@ -0,0 +1,136 @@
1
+ import type { AgentSource, DashboardEvent, EventType } from '../types';
2
+
3
+ export interface AgyHookPayload {
4
+ hook_event_name?: string;
5
+ conversationId?: string;
6
+ sessionId?: string;
7
+ session_id?: string;
8
+ toolCall?: {
9
+ name?: string;
10
+ args?: Record<string, unknown>;
11
+ };
12
+ toolName?: string;
13
+ stepIdx?: number;
14
+ error?: string;
15
+ workspacePaths?: string[];
16
+ transcriptPath?: string;
17
+ artifactDirectoryPath?: string;
18
+ }
19
+
20
+ const EVENT_MAP: Record<string, EventType> = {
21
+ PreToolUse: 'tool_start',
22
+ PostToolUse: 'tool_end',
23
+ };
24
+
25
+ const TOOL_NAME_MAP: Record<string, string> = {
26
+ run_command: 'Bash',
27
+ view_file: 'Read',
28
+ write_to_file: 'Write',
29
+ replace_file_content: 'Edit',
30
+ multi_replace_file_content: 'Edit',
31
+ list_dir: 'Glob',
32
+ find_by_name: 'Glob',
33
+ grep_search: 'Grep',
34
+ search_web: 'WebSearch',
35
+ read_url_content: 'FetchURL',
36
+ ask_question: 'AskUserQuestion',
37
+ generate_image: 'ReadMediaFile',
38
+ manage_task: 'Task',
39
+ invoke_subagent: 'Agent',
40
+ define_subagent: 'Agent',
41
+ manage_subagents: 'Agent',
42
+ send_message: 'Agent',
43
+ schedule: 'CronCreate',
44
+ list_permissions: 'Bash',
45
+ ask_permission: 'AskUserQuestion',
46
+ };
47
+
48
+ const DETAIL_FIELDS: Record<string, string[]> = {
49
+ Bash: ['CommandLine'],
50
+ Read: ['AbsolutePath'],
51
+ Write: ['TargetFile'],
52
+ Edit: ['TargetFile'],
53
+ Glob: ['DirectoryPath', 'Pattern'],
54
+ Grep: ['Query'],
55
+ WebSearch: ['query'],
56
+ FetchURL: ['Url'],
57
+ AskUserQuestion: [],
58
+ ReadMediaFile: [],
59
+ Task: [],
60
+ Agent: [],
61
+ CronCreate: [],
62
+ };
63
+
64
+ function normalizeToolName(name: string | undefined): string | undefined {
65
+ if (!name) return undefined;
66
+ return TOOL_NAME_MAP[name] || name;
67
+ }
68
+
69
+ function extractDetail(tool: string | undefined, args: Record<string, unknown> | undefined): string | undefined {
70
+ if (!args || typeof args !== 'object') return undefined;
71
+
72
+ const fields = tool ? DETAIL_FIELDS[tool] || [] : [];
73
+ for (const field of fields) {
74
+ const value = args[field];
75
+ if (typeof value === 'string' && value.length > 0) {
76
+ return value;
77
+ }
78
+ }
79
+
80
+ if (tool && fields.length > 0) {
81
+ return undefined;
82
+ }
83
+
84
+ const serialized = JSON.stringify(args);
85
+ if (serialized === '{}') return undefined;
86
+ return serialized.length > 200 ? `${serialized.slice(0, 197)}...` : serialized;
87
+ }
88
+
89
+ const SKILL_PATH_RE = /[\\/]skills[\\/]([^\\/]+)[\\/]SKILL\.md$/i;
90
+
91
+ function inferSkillFromReadPath(
92
+ tool: string | undefined,
93
+ args: Record<string, unknown> | undefined
94
+ ): string | undefined {
95
+ if (tool !== 'Read' || !args || typeof args !== 'object') return undefined;
96
+
97
+ const rawPath = args.AbsolutePath || args.path || args.filePath || args.file_path;
98
+ if (typeof rawPath !== 'string') return undefined;
99
+
100
+ const match = rawPath.match(SKILL_PATH_RE);
101
+ return match ? match[1] : undefined;
102
+ }
103
+
104
+ function generateId(sessionId: string, stepIdx: number | undefined): string {
105
+ const suffix = stepIdx !== undefined ? String(stepIdx) : `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
106
+ return `agy:${sessionId}:${suffix}`;
107
+ }
108
+
109
+ export function normalizeAgy(payload: AgyHookPayload): DashboardEvent | undefined {
110
+ const eventName = payload.hook_event_name || 'PostToolUse';
111
+ const event_type = EVENT_MAP[eventName];
112
+ if (!event_type) {
113
+ return undefined;
114
+ }
115
+
116
+ const session_id = payload.conversationId || payload.sessionId || payload.session_id || 'unknown';
117
+ const stepIdx = typeof payload.stepIdx === 'number' ? payload.stepIdx : undefined;
118
+ const toolCall = payload.toolCall;
119
+ const rawToolName = toolCall?.name || payload.toolName;
120
+ const tool = normalizeToolName(rawToolName);
121
+ const args = toolCall?.args;
122
+ const skill = inferSkillFromReadPath(tool, args);
123
+
124
+ return {
125
+ id: generateId(session_id, stepIdx),
126
+ timestamp: Date.now(),
127
+ source: 'agy' as AgentSource,
128
+ session_id,
129
+ event_type,
130
+ tool,
131
+ skill,
132
+ detail: extractDetail(tool, args),
133
+ input: args,
134
+ output: payload.error !== undefined ? { error: payload.error } : undefined,
135
+ };
136
+ }
@@ -44,6 +44,8 @@ export function normalizeCodex(payload: CodexHookPayload): DashboardEvent | unde
44
44
  event_type,
45
45
  tool: payload.toolName,
46
46
  skill: payload.skill,
47
+ input: payload.toolInput,
48
+ output: payload.toolResponse,
47
49
  };
48
50
  }
49
51
 
@@ -6,7 +6,7 @@ export interface KimiHookPayload {
6
6
  cwd: string;
7
7
  tool_name?: string;
8
8
  tool_input?: Record<string, unknown>;
9
- tool_response?: Record<string, unknown>;
9
+ tool_output?: string | Record<string, unknown>;
10
10
  stop_reason?: string;
11
11
  usage?: unknown;
12
12
  skill?: string;
@@ -34,9 +34,19 @@ export function normalizeKimi(payload: KimiHookPayload): DashboardEvent | undefi
34
34
  event_type,
35
35
  tool: payload.tool_name,
36
36
  skill: payload.skill,
37
+ input: payload.tool_input,
38
+ output: normalizeOutput(payload.tool_output),
37
39
  };
38
40
  }
39
41
 
42
+ function normalizeOutput(
43
+ output: string | Record<string, unknown> | undefined
44
+ ): Record<string, unknown> | undefined {
45
+ if (output === undefined) return undefined;
46
+ if (typeof output === 'string') return { output };
47
+ return output;
48
+ }
49
+
40
50
  function generateId(): string {
41
51
  return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
42
52
  }
@@ -51,18 +51,18 @@ describe('buildEvent', () => {
51
51
  assert.equal(event?.status, 'running');
52
52
  });
53
53
 
54
- it('builds Kimi PostToolUse event with status', () => {
54
+ it('builds Kimi PostToolUse event with input and wrapped output', () => {
55
55
  const event = buildEvent('kimi' as AgentSource, {
56
56
  hook_event_name: 'PostToolUse',
57
57
  session_id: 'sess-1',
58
58
  cwd: '/project',
59
59
  tool_name: 'Read',
60
60
  tool_input: { path: 'README.md' },
61
- tool_response: { success: true, duration_ms: 12 },
61
+ tool_output: 'README content',
62
62
  });
63
63
  assert.equal(event?.event_type, 'tool_end');
64
- assert.equal(event?.status, 'success');
65
- assert.equal(event?.duration_ms, 12);
64
+ assert.deepEqual(event?.input, { path: 'README.md' });
65
+ assert.deepEqual(event?.output, { output: 'README content' });
66
66
  });
67
67
 
68
68
  it('builds Codex event', () => {
@@ -134,4 +134,57 @@ describe('buildEvent', () => {
134
134
  });
135
135
  assert.equal(event?.skill, 'engineer');
136
136
  });
137
+
138
+ it('preserves AGY detail extracted by the adapter', () => {
139
+ const event = buildEvent('agy' as AgentSource, {
140
+ hook_event_name: 'PreToolUse',
141
+ conversationId: 'sess-agy',
142
+ stepIdx: 0,
143
+ toolCall: {
144
+ name: 'run_command',
145
+ args: { CommandLine: 'git status', Cwd: '/project' },
146
+ },
147
+ });
148
+ assert.equal(event?.source, 'agy');
149
+ assert.equal(event?.tool, 'Bash');
150
+ assert.equal(event?.detail, 'git status');
151
+ assert.equal(event?.status, 'running');
152
+ });
153
+
154
+ it('applies default skill fallback to AGY tool events', () => {
155
+ const event = buildEvent(
156
+ 'agy' as AgentSource,
157
+ {
158
+ hook_event_name: 'PreToolUse',
159
+ conversationId: 'sess-agy-default',
160
+ stepIdx: 0,
161
+ toolCall: {
162
+ name: 'run_command',
163
+ args: { CommandLine: 'git status', Cwd: '/project' },
164
+ },
165
+ },
166
+ 'orchestrator'
167
+ );
168
+ assert.equal(event?.event_type, 'tool_start');
169
+ assert.equal(event?.skill, 'orchestrator');
170
+ });
171
+
172
+ it('prefers AGY inferred skill over default skill fallback', () => {
173
+ const event = buildEvent(
174
+ 'agy' as AgentSource,
175
+ {
176
+ hook_event_name: 'PreToolUse',
177
+ conversationId: 'sess-agy-inferred',
178
+ stepIdx: 0,
179
+ toolCall: {
180
+ name: 'view_file',
181
+ args: { AbsolutePath: '/home/arch/.agents/skills/engineer/SKILL.md' },
182
+ },
183
+ },
184
+ 'orchestrator'
185
+ );
186
+ assert.equal(event?.event_type, 'tool_start');
187
+ assert.equal(event?.tool, 'Read');
188
+ assert.equal(event?.skill, 'engineer');
189
+ });
137
190
  });
@@ -2,6 +2,7 @@ import http from 'node:http';
2
2
  import type { AgentSource, DashboardEvent } from '../types';
3
3
  import { normalizeKimi, type KimiHookPayload } from './kimi';
4
4
  import { normalizeCodex, type CodexHookPayload } from './codex';
5
+ import { normalizeAgy, type AgyHookPayload } from './agy';
5
6
  import { sanitize } from '../filters/sanitize';
6
7
 
7
8
  const DEFAULT_SERVER_URL = 'http://127.0.0.1:7890';
@@ -17,7 +18,7 @@ export function getDefaultSkill(argv: string[]): string | undefined {
17
18
 
18
19
  export function detectSource(argv: string[]): AgentSource | undefined {
19
20
  const arg = argv[2];
20
- if (arg === 'kimi' || arg === 'codex' || arg === 'opencode' || arg === 'log-watcher') {
21
+ if (arg === 'kimi' || arg === 'codex' || arg === 'opencode' || arg === 'log-watcher' || arg === 'agy') {
21
22
  return arg;
22
23
  }
23
24
  const env = process.env.CREWLOOP_DASHBOARD_SOURCE;
@@ -25,7 +26,8 @@ export function detectSource(argv: string[]): AgentSource | undefined {
25
26
  env === 'kimi' ||
26
27
  env === 'codex' ||
27
28
  env === 'opencode' ||
28
- env === 'log-watcher'
29
+ env === 'log-watcher' ||
30
+ env === 'agy'
29
31
  ) {
30
32
  return env;
31
33
  }
@@ -44,6 +46,8 @@ export function normalizePayload(source: AgentSource, raw: unknown): DashboardEv
44
46
  return normalizeKimi(payload as unknown as KimiHookPayload);
45
47
  case 'codex':
46
48
  return normalizeCodex(payload as unknown as CodexHookPayload);
49
+ case 'agy':
50
+ return normalizeAgy(payload as unknown as AgyHookPayload);
47
51
  default:
48
52
  return undefined;
49
53
  }
@@ -61,31 +65,40 @@ export function buildEvent(
61
65
 
62
66
  if (base.event_type === 'session_start' && defaultSkill) {
63
67
  base.skill = defaultSkill;
68
+ } else if (source === 'agy' && defaultSkill && !base.skill) {
69
+ base.skill = defaultSkill;
64
70
  }
65
71
 
66
72
  const isPost = base.event_type === 'tool_end';
67
73
  const sanitized = sanitize(
68
74
  {
69
75
  tool_name: base.tool || '',
70
- tool_input: (raw.tool_input || raw.toolInput) as Record<string, unknown> | undefined,
71
- tool_response: (raw.tool_response || raw.toolResponse) as Record<string, unknown> | undefined,
76
+ tool_input: (base.input || raw.tool_input || raw.toolInput) as Record<string, unknown> | undefined,
77
+ tool_response: (base.output || raw.tool_response || raw.toolResponse) as Record<string, unknown> | undefined,
72
78
  },
73
79
  isPost ? 'post' : 'pre'
74
80
  );
75
81
 
76
82
  return {
77
83
  ...base,
78
- detail: sanitized.detail,
84
+ detail: sanitized.detail ?? base.detail,
79
85
  status: sanitized.status,
80
86
  duration_ms: sanitized.duration_ms,
81
87
  };
82
88
  }
83
89
 
84
- export function postEvent(event: DashboardEvent): void {
90
+ export function postEvent(event: DashboardEvent, onDone?: () => void): void {
85
91
  const serverUrl = process.env.CREWLOOP_DASHBOARD_URL || DEFAULT_SERVER_URL;
86
92
  const body = JSON.stringify(event);
87
93
 
88
94
  const url = new URL('/event', serverUrl);
95
+ let done = false;
96
+ function finish(): void {
97
+ if (done) return;
98
+ done = true;
99
+ onDone?.();
100
+ }
101
+
89
102
  const req = http.request(
90
103
  {
91
104
  hostname: url.hostname,
@@ -98,11 +111,17 @@ export function postEvent(event: DashboardEvent): void {
98
111
  },
99
112
  timeout: 300,
100
113
  },
101
- () => {}
114
+ (res) => {
115
+ res.resume();
116
+ finish();
117
+ }
102
118
  );
103
119
 
104
- req.on('error', () => {});
105
- req.on('timeout', () => req.destroy());
120
+ req.on('error', finish);
121
+ req.on('timeout', () => {
122
+ req.destroy();
123
+ finish();
124
+ });
106
125
  req.write(body);
107
126
  req.end();
108
127
  }
@@ -110,7 +129,7 @@ export function postEvent(event: DashboardEvent): void {
110
129
  export function runShim(): void {
111
130
  const source = detectSource(process.argv);
112
131
  if (!source) {
113
- process.stderr.write('crewloop-shim: unknown source. Use: crewloop-shim <kimi|codex>\n');
132
+ process.stderr.write('crewloop-shim: unknown source. Use: crewloop-shim <kimi|codex|agy>\n');
114
133
  process.exit(1);
115
134
  }
116
135
 
@@ -126,7 +145,8 @@ export function runShim(): void {
126
145
  const payload = JSON.parse(raw);
127
146
  const event = buildEvent(source, payload, defaultSkill);
128
147
  if (event) {
129
- postEvent(event);
148
+ postEvent(event, () => process.exit(0));
149
+ return;
130
150
  }
131
151
  } catch {
132
152
  // Fail silently so the agent is never blocked.
@@ -0,0 +1,44 @@
1
+ export const SKILL_ICONS: Record<string, string> = {
2
+ orchestrator: 'Target',
3
+ architect: 'Blueprint',
4
+ designer: 'Palette',
5
+ engineer: 'Wrench',
6
+ reviewer: 'MagnifyingGlass',
7
+ shipper: 'RocketLaunch',
8
+ 'docs-writer': 'Article',
9
+ tester: 'Flask',
10
+ 'product-manager': 'ChartBar',
11
+ maintainer: 'Toolbox',
12
+ researcher: 'Microscope',
13
+ 'security-guard': 'Shield',
14
+ 'accessibility-auditor': 'Person',
15
+ 'project-mapper': 'TreeStructure',
16
+ default: 'Circle',
17
+ };
18
+
19
+ export function skillIcon(skillName: string | undefined): string {
20
+ const key = String(skillName || '').toLowerCase().replace(/\s+/g, '-');
21
+ return SKILL_ICONS[key] || SKILL_ICONS.default;
22
+ }
23
+
24
+ export function sourceIcon(source: string | undefined): string {
25
+ switch (source) {
26
+ case 'kimi':
27
+ return 'ChatTeardropText';
28
+ case 'codex':
29
+ return 'Terminal';
30
+ case 'opencode':
31
+ return 'CodeBlock';
32
+ case 'log-watcher':
33
+ return 'FileText';
34
+ default:
35
+ return 'Monitor';
36
+ }
37
+ }
38
+
39
+ export const TYPE_COLORS: Record<string, string> = {
40
+ skill: 'var(--accent)',
41
+ tool: 'var(--running)',
42
+ file: 'var(--text-secondary)',
43
+ };
44
+