@winspan/claude-forge 8.30.0 → 8.33.2

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 (207) hide show
  1. package/README.md +4 -4
  2. package/dist/capability/execution-manager.d.ts +38 -1
  3. package/dist/capability/execution-manager.d.ts.map +1 -1
  4. package/dist/capability/execution-manager.js +93 -1
  5. package/dist/capability/execution-manager.js.map +1 -1
  6. package/dist/capability/executor/background-executor.d.ts +1 -0
  7. package/dist/capability/executor/background-executor.d.ts.map +1 -1
  8. package/dist/capability/executor/background-executor.js +27 -4
  9. package/dist/capability/executor/background-executor.js.map +1 -1
  10. package/dist/capability/executor/orchestrator.d.ts +15 -2
  11. package/dist/capability/executor/orchestrator.d.ts.map +1 -1
  12. package/dist/capability/executor/orchestrator.js +82 -3
  13. package/dist/capability/executor/orchestrator.js.map +1 -1
  14. package/dist/capability/executor/worker-auth-probe.d.ts.map +1 -1
  15. package/dist/capability/executor/worker-auth-probe.js +11 -2
  16. package/dist/capability/executor/worker-auth-probe.js.map +1 -1
  17. package/dist/capability/methodologies/bmad.yaml +17 -5
  18. package/dist/capability/methodologies/code-quality-audit.yaml +26 -0
  19. package/dist/capability/methodologies/harness-engineering.yaml +12 -6
  20. package/dist/capability/methodologies/test-coverage-scan.yaml +26 -0
  21. package/dist/capability/methodology-planner.d.ts +17 -1
  22. package/dist/capability/methodology-planner.d.ts.map +1 -1
  23. package/dist/capability/methodology-planner.js +125 -0
  24. package/dist/capability/methodology-planner.js.map +1 -1
  25. package/dist/capability/methodology-registry.d.ts.map +1 -1
  26. package/dist/capability/methodology-registry.js +21 -5
  27. package/dist/capability/methodology-registry.js.map +1 -1
  28. package/dist/capability/types.d.ts +2 -0
  29. package/dist/capability/types.d.ts.map +1 -1
  30. package/dist/cli/commands/init.d.ts.map +1 -1
  31. package/dist/cli/commands/init.js +82 -2
  32. package/dist/cli/commands/init.js.map +1 -1
  33. package/dist/core/ai/provider.d.ts +17 -9
  34. package/dist/core/ai/provider.d.ts.map +1 -1
  35. package/dist/core/ai/provider.js +130 -23
  36. package/dist/core/ai/provider.js.map +1 -1
  37. package/dist/core/ai/types.d.ts +26 -5
  38. package/dist/core/ai/types.d.ts.map +1 -1
  39. package/dist/core/storage/rows.d.ts +153 -0
  40. package/dist/core/storage/rows.d.ts.map +1 -0
  41. package/dist/core/storage/rows.js +14 -0
  42. package/dist/core/storage/rows.js.map +1 -0
  43. package/dist/core/storage/schema.sql +26 -2
  44. package/dist/core/storage/sqlite.d.ts +95 -7
  45. package/dist/core/storage/sqlite.d.ts.map +1 -1
  46. package/dist/core/storage/sqlite.js +409 -22
  47. package/dist/core/storage/sqlite.js.map +1 -1
  48. package/dist/core/utils/token-tracker.d.ts +40 -0
  49. package/dist/core/utils/token-tracker.d.ts.map +1 -0
  50. package/dist/core/utils/token-tracker.js +70 -0
  51. package/dist/core/utils/token-tracker.js.map +1 -0
  52. package/dist/daemon/handlers/post-tool-use.d.ts +1 -0
  53. package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
  54. package/dist/daemon/handlers/post-tool-use.js +7 -0
  55. package/dist/daemon/handlers/post-tool-use.js.map +1 -1
  56. package/dist/daemon/handlers/stop.d.ts +11 -0
  57. package/dist/daemon/handlers/stop.d.ts.map +1 -1
  58. package/dist/daemon/handlers/stop.js +52 -0
  59. package/dist/daemon/handlers/stop.js.map +1 -1
  60. package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
  61. package/dist/daemon/handlers/user-prompt.js +63 -4
  62. package/dist/daemon/handlers/user-prompt.js.map +1 -1
  63. package/dist/daemon/idle-detector.d.ts +35 -0
  64. package/dist/daemon/idle-detector.d.ts.map +1 -0
  65. package/dist/daemon/idle-detector.js +56 -0
  66. package/dist/daemon/idle-detector.js.map +1 -0
  67. package/dist/daemon/idle-trigger.d.ts +53 -0
  68. package/dist/daemon/idle-trigger.d.ts.map +1 -0
  69. package/dist/daemon/idle-trigger.js +153 -0
  70. package/dist/daemon/idle-trigger.js.map +1 -0
  71. package/dist/daemon/index.d.ts.map +1 -1
  72. package/dist/daemon/index.js +30 -2
  73. package/dist/daemon/index.js.map +1 -1
  74. package/dist/daemon/routing-observer.d.ts +2 -1
  75. package/dist/daemon/routing-observer.d.ts.map +1 -1
  76. package/dist/daemon/routing-observer.js +117 -39
  77. package/dist/daemon/routing-observer.js.map +1 -1
  78. package/dist/engine/agent-router.d.ts +6 -0
  79. package/dist/engine/agent-router.d.ts.map +1 -1
  80. package/dist/engine/agent-router.js +13 -1
  81. package/dist/engine/agent-router.js.map +1 -1
  82. package/dist/engine/conventions/routing.yaml +15 -0
  83. package/dist/engine/dsl/compiler.d.ts.map +1 -1
  84. package/dist/engine/dsl/compiler.js +85 -3
  85. package/dist/engine/dsl/compiler.js.map +1 -1
  86. package/dist/engine/recommender.d.ts.map +1 -1
  87. package/dist/engine/recommender.js +10 -1
  88. package/dist/engine/recommender.js.map +1 -1
  89. package/dist/intelligence/classifier.d.ts +6 -0
  90. package/dist/intelligence/classifier.d.ts.map +1 -1
  91. package/dist/intelligence/classifier.js +57 -0
  92. package/dist/intelligence/classifier.js.map +1 -1
  93. package/dist/skills/registry.d.ts +6 -0
  94. package/dist/skills/registry.d.ts.map +1 -1
  95. package/dist/skills/registry.js +49 -14
  96. package/dist/skills/registry.js.map +1 -1
  97. package/dist/skills/semantic-matcher.d.ts +1 -0
  98. package/dist/skills/semantic-matcher.d.ts.map +1 -1
  99. package/dist/skills/semantic-matcher.js +6 -1
  100. package/dist/skills/semantic-matcher.js.map +1 -1
  101. package/dist/web/auth-middleware.d.ts +22 -0
  102. package/dist/web/auth-middleware.d.ts.map +1 -0
  103. package/dist/web/auth-middleware.js +51 -0
  104. package/dist/web/auth-middleware.js.map +1 -0
  105. package/dist/web/routes/agents.d.ts +7 -0
  106. package/dist/web/routes/agents.d.ts.map +1 -0
  107. package/dist/web/routes/agents.js +192 -0
  108. package/dist/web/routes/agents.js.map +1 -0
  109. package/dist/web/routes/ai.d.ts +10 -0
  110. package/dist/web/routes/ai.d.ts.map +1 -0
  111. package/dist/web/routes/ai.js +197 -0
  112. package/dist/web/routes/ai.js.map +1 -0
  113. package/dist/web/routes/auth.d.ts +12 -0
  114. package/dist/web/routes/auth.d.ts.map +1 -0
  115. package/dist/web/routes/auth.js +20 -0
  116. package/dist/web/routes/auth.js.map +1 -0
  117. package/dist/web/routes/events.d.ts +11 -0
  118. package/dist/web/routes/events.d.ts.map +1 -0
  119. package/dist/web/routes/events.js +43 -0
  120. package/dist/web/routes/events.js.map +1 -0
  121. package/dist/web/routes/execution-trace.d.ts +13 -0
  122. package/dist/web/routes/execution-trace.d.ts.map +1 -0
  123. package/dist/web/routes/execution-trace.js +308 -0
  124. package/dist/web/routes/execution-trace.js.map +1 -0
  125. package/dist/web/routes/experiments.d.ts +15 -0
  126. package/dist/web/routes/experiments.d.ts.map +1 -0
  127. package/dist/web/routes/experiments.js +187 -0
  128. package/dist/web/routes/experiments.js.map +1 -0
  129. package/dist/web/routes/methodology.d.ts +12 -0
  130. package/dist/web/routes/methodology.d.ts.map +1 -0
  131. package/dist/web/routes/methodology.js +228 -0
  132. package/dist/web/routes/methodology.js.map +1 -0
  133. package/dist/web/routes/patch.d.ts +7 -0
  134. package/dist/web/routes/patch.d.ts.map +1 -0
  135. package/dist/web/routes/patch.js +106 -0
  136. package/dist/web/routes/patch.js.map +1 -0
  137. package/dist/web/routes/routing.d.ts +17 -0
  138. package/dist/web/routes/routing.d.ts.map +1 -0
  139. package/dist/web/routes/routing.js +582 -0
  140. package/dist/web/routes/routing.js.map +1 -0
  141. package/dist/web/routes/rules.d.ts +7 -0
  142. package/dist/web/routes/rules.d.ts.map +1 -0
  143. package/dist/web/routes/rules.js +105 -0
  144. package/dist/web/routes/rules.js.map +1 -0
  145. package/dist/web/routes/sessions.d.ts +10 -0
  146. package/dist/web/routes/sessions.d.ts.map +1 -0
  147. package/dist/web/routes/sessions.js +234 -0
  148. package/dist/web/routes/sessions.js.map +1 -0
  149. package/dist/web/routes/skills.d.ts +10 -0
  150. package/dist/web/routes/skills.d.ts.map +1 -0
  151. package/dist/web/routes/skills.js +272 -0
  152. package/dist/web/routes/skills.js.map +1 -0
  153. package/dist/web/routes/static.d.ts +19 -0
  154. package/dist/web/routes/static.d.ts.map +1 -0
  155. package/dist/web/routes/static.js +61 -0
  156. package/dist/web/routes/static.js.map +1 -0
  157. package/dist/web/routes/status.d.ts +7 -0
  158. package/dist/web/routes/status.d.ts.map +1 -0
  159. package/dist/web/routes/status.js +28 -0
  160. package/dist/web/routes/status.js.map +1 -0
  161. package/dist/web/routes/token-usage.d.ts +7 -0
  162. package/dist/web/routes/token-usage.d.ts.map +1 -0
  163. package/dist/web/routes/token-usage.js +33 -0
  164. package/dist/web/routes/token-usage.js.map +1 -0
  165. package/dist/web/routes/types.d.ts +40 -0
  166. package/dist/web/routes/types.d.ts.map +1 -0
  167. package/dist/web/routes/types.js +52 -0
  168. package/dist/web/routes/types.js.map +1 -0
  169. package/dist/web/server.d.ts +7 -4
  170. package/dist/web/server.d.ts.map +1 -1
  171. package/dist/web/server.js +60 -2330
  172. package/dist/web/server.js.map +1 -1
  173. package/dist/web/ssrf-guard.d.ts +35 -0
  174. package/dist/web/ssrf-guard.d.ts.map +1 -0
  175. package/dist/web/ssrf-guard.js +93 -0
  176. package/dist/web/ssrf-guard.js.map +1 -0
  177. package/dist/web/static/assets/AIConfig-Dw13rVtT.js +2 -0
  178. package/dist/web/static/assets/AIConfig-Dw13rVtT.js.map +1 -0
  179. package/dist/web/static/assets/Agents-D1p3JhQs.js +2 -0
  180. package/dist/web/static/assets/Agents-D1p3JhQs.js.map +1 -0
  181. package/dist/web/static/assets/{Events-CnA3f740.js → Events-DqzBTrly.js} +2 -2
  182. package/dist/web/static/assets/{Events-CnA3f740.js.map → Events-DqzBTrly.js.map} +1 -1
  183. package/dist/web/static/assets/{ExecutionTrace-ClPfFIQa.js → ExecutionTrace-Z-zlH0KH.js} +2 -2
  184. package/dist/web/static/assets/{ExecutionTrace-ClPfFIQa.js.map → ExecutionTrace-Z-zlH0KH.js.map} +1 -1
  185. package/dist/web/static/assets/Methodologies-Br5KOWuF.js +5 -0
  186. package/dist/web/static/assets/Methodologies-Br5KOWuF.js.map +1 -0
  187. package/dist/web/static/assets/{Sessions-DwWOKgnl.js → Sessions-DOd65EkN.js} +2 -2
  188. package/dist/web/static/assets/{Sessions-DwWOKgnl.js.map → Sessions-DOd65EkN.js.map} +1 -1
  189. package/dist/web/static/assets/Skills-zacj_uSW.js +2 -0
  190. package/dist/web/static/assets/Skills-zacj_uSW.js.map +1 -0
  191. package/dist/web/static/assets/auth-Bnf8ZcqN.js +2 -0
  192. package/dist/web/static/assets/auth-Bnf8ZcqN.js.map +1 -0
  193. package/dist/web/static/assets/index-BVpUTHdp.js +3 -0
  194. package/dist/web/static/assets/{index-DUYj2ek1.js.map → index-BVpUTHdp.js.map} +1 -1
  195. package/dist/web/static/assets/index-Drpf7sLl.css +1 -0
  196. package/dist/web/static/index.html +2 -2
  197. package/package.json +4 -3
  198. package/dist/web/static/assets/AIConfig-nZgwaowr.js +0 -2
  199. package/dist/web/static/assets/AIConfig-nZgwaowr.js.map +0 -1
  200. package/dist/web/static/assets/Agents-BZGXKWC7.js +0 -2
  201. package/dist/web/static/assets/Agents-BZGXKWC7.js.map +0 -1
  202. package/dist/web/static/assets/Methodologies-CAXUXeox.js +0 -2
  203. package/dist/web/static/assets/Methodologies-CAXUXeox.js.map +0 -1
  204. package/dist/web/static/assets/Skills-DhM6ALhr.js +0 -2
  205. package/dist/web/static/assets/Skills-DhM6ALhr.js.map +0 -1
  206. package/dist/web/static/assets/index-CVWult53.css +0 -1
  207. package/dist/web/static/assets/index-DUYj2ek1.js +0 -3
@@ -0,0 +1,272 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { homedir } from 'os';
4
+ import { logger } from '../../core/utils/logger.js';
5
+ /**
6
+ * /api/skills/* — list, read, update, version, rollback.
7
+ *
8
+ * Supports both flat `<name>.md` and directory-style `<name>/SKILL.md` layouts.
9
+ * Prefers the registry when available so built-in skills resolve correctly.
10
+ */
11
+ export function registerSkillsRoutes(app, ctx) {
12
+ const skillRegistry = ctx.skillRegistry;
13
+ // GET /api/skills — list all skills (official + user; supports flat & directory formats)
14
+ app.get('/api/skills', (_req, res) => {
15
+ try {
16
+ if (skillRegistry) {
17
+ // Preferred path: reuse SkillRegistry (handles flat .md and <name>/SKILL.md)
18
+ const skills = skillRegistry.getAll().map(s => ({
19
+ name: s.name,
20
+ id: s.id,
21
+ description: s.description ?? '',
22
+ keywords: s.keywords,
23
+ path: s.path,
24
+ isOfficial: s.isOfficial === true,
25
+ source: s.isOfficial ? 'official' : 'user',
26
+ }));
27
+ res.json({ skills });
28
+ return;
29
+ }
30
+ // Fallback: scan directly if registry not injected
31
+ const skillsDir = path.join(homedir(), '.claude', 'skills');
32
+ const skills = [];
33
+ if (fs.existsSync(skillsDir)) {
34
+ const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
35
+ for (const entry of entries) {
36
+ let filePath = null;
37
+ let id;
38
+ if (entry.isFile() && entry.name.endsWith('.md')) {
39
+ filePath = path.join(skillsDir, entry.name);
40
+ id = entry.name.replace(/\.md$/, '');
41
+ }
42
+ else if (entry.isDirectory() || entry.isSymbolicLink()) {
43
+ const skillMd = path.join(skillsDir, entry.name, 'SKILL.md');
44
+ if (!fs.existsSync(skillMd))
45
+ continue;
46
+ filePath = skillMd;
47
+ id = entry.name;
48
+ }
49
+ else {
50
+ continue;
51
+ }
52
+ try {
53
+ const content = fs.readFileSync(filePath, 'utf-8');
54
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
55
+ let description = '';
56
+ const keywords = [];
57
+ if (match) {
58
+ const fm = match[1];
59
+ const descMatch = fm.match(/description:\s*["']?([^"'\n]+)["']?/);
60
+ description = descMatch?.[1]?.trim() || '';
61
+ }
62
+ skills.push({
63
+ name: id,
64
+ id,
65
+ description,
66
+ keywords,
67
+ path: filePath,
68
+ isOfficial: false,
69
+ source: 'user',
70
+ });
71
+ }
72
+ catch (err) {
73
+ logger.warn(`[Web] Failed to read skill ${id}: ${err}`);
74
+ }
75
+ }
76
+ }
77
+ res.json({ skills });
78
+ }
79
+ catch (err) {
80
+ logger.warn(`[Web] Failed to list skills: ${err}`);
81
+ res.status(500).json({ error: String(err) });
82
+ }
83
+ });
84
+ // GET /api/skills/:name — get skill details (supports flat & directory formats)
85
+ app.get('/api/skills/:name', (req, res) => {
86
+ try {
87
+ const { name } = req.params;
88
+ if (skillRegistry) {
89
+ const skill = skillRegistry.getAll().find(s => s.id === name || s.name === name);
90
+ if (skill) {
91
+ if (skill.path === '<built-in>') {
92
+ res.json({
93
+ name: skill.name,
94
+ id: skill.id,
95
+ description: skill.description ?? '',
96
+ keywords: skill.keywords,
97
+ isOfficial: true,
98
+ source: 'official',
99
+ content: skill.content,
100
+ });
101
+ return;
102
+ }
103
+ // For user skills, fall through to disk read so edits show latest content
104
+ if (fs.existsSync(skill.path)) {
105
+ const content = fs.readFileSync(skill.path, 'utf-8');
106
+ res.json({
107
+ name: skill.name,
108
+ id: skill.id,
109
+ description: skill.description ?? '',
110
+ keywords: skill.keywords,
111
+ isOfficial: false,
112
+ source: 'user',
113
+ path: skill.path,
114
+ content,
115
+ });
116
+ return;
117
+ }
118
+ }
119
+ }
120
+ // Fallback: try flat .md then <name>/SKILL.md
121
+ const skillsDir = path.join(homedir(), '.claude', 'skills');
122
+ const flatPath = path.join(skillsDir, `${name}.md`);
123
+ const dirPath = path.join(skillsDir, name, 'SKILL.md');
124
+ const filePath = fs.existsSync(flatPath)
125
+ ? flatPath
126
+ : fs.existsSync(dirPath)
127
+ ? dirPath
128
+ : null;
129
+ if (!filePath) {
130
+ res.status(404).json({ error: 'Skill not found' });
131
+ return;
132
+ }
133
+ const content = fs.readFileSync(filePath, 'utf-8');
134
+ const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
135
+ if (!match) {
136
+ res.json({ name, id: name, content, path: filePath });
137
+ return;
138
+ }
139
+ const fm = match[1];
140
+ const descMatch = fm.match(/description:\s*["']?([^"'\n]+)["']?/);
141
+ const verMatch = fm.match(/version:\s*["']?([^"'\n]+)["']?/);
142
+ const sourceMatch = fm.match(/source:\s*["']?([^"'\n]+)["']?/);
143
+ res.json({
144
+ name,
145
+ id: name,
146
+ description: descMatch?.[1]?.trim() || '',
147
+ version: verMatch?.[1],
148
+ source: sourceMatch?.[1] || 'user',
149
+ path: filePath,
150
+ content,
151
+ });
152
+ }
153
+ catch (err) {
154
+ logger.warn(`[Web] Failed to get skill ${req.params.name}: ${err}`);
155
+ res.status(500).json({ error: String(err) });
156
+ }
157
+ });
158
+ // PUT /api/skills/:name — update skill content
159
+ app.put('/api/skills/:name', (req, res) => {
160
+ try {
161
+ const { name } = req.params;
162
+ const { content } = req.body;
163
+ if (!content || typeof content !== 'string') {
164
+ res.status(400).json({ error: 'Missing content' });
165
+ return;
166
+ }
167
+ const skillsDir = path.join(homedir(), '.claude', 'skills');
168
+ const filePath = path.join(skillsDir, `${name}.md`);
169
+ if (!fs.existsSync(filePath)) {
170
+ res.status(404).json({ error: 'Skill not found' });
171
+ return;
172
+ }
173
+ const backupDir = path.join(homedir(), '.claude-forge', 'backups', 'skills');
174
+ fs.mkdirSync(backupDir, { recursive: true });
175
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
176
+ const backupPath = path.join(backupDir, `${name}-${timestamp}.md`);
177
+ fs.copyFileSync(filePath, backupPath);
178
+ fs.writeFileSync(filePath, content, 'utf-8');
179
+ logger.info(`[Web] Updated skill ${name} (backup: ${backupPath})`);
180
+ res.json({ success: true, backup: backupPath });
181
+ }
182
+ catch (err) {
183
+ logger.warn(`[Web] Failed to update skill ${req.params.name}: ${err}`);
184
+ res.status(500).json({ error: String(err) });
185
+ }
186
+ });
187
+ // GET /api/skills/:name/versions — list backup versions
188
+ app.get('/api/skills/:name/versions', (req, res) => {
189
+ try {
190
+ const { name } = req.params;
191
+ const backupDir = path.join(homedir(), '.claude-forge', 'backups', 'skills');
192
+ if (!fs.existsSync(backupDir)) {
193
+ res.json({ versions: [] });
194
+ return;
195
+ }
196
+ const files = fs.readdirSync(backupDir)
197
+ .filter(f => f.startsWith(`${name}-`) && f.endsWith('.md'))
198
+ .map(f => {
199
+ const filePath = path.join(backupDir, f);
200
+ const stats = fs.statSync(filePath);
201
+ const timestampMatch = f.match(/-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z)\.md$/);
202
+ return {
203
+ filename: f,
204
+ timestamp: timestampMatch ? timestampMatch[1].replace(/-/g, ':').replace(/T(\d{2}):(\d{2}):(\d{2})/, 'T$1:$2:$3') : '',
205
+ size: stats.size,
206
+ mtime: stats.mtime.toISOString(),
207
+ };
208
+ })
209
+ .sort((a, b) => new Date(b.mtime).getTime() - new Date(a.mtime).getTime());
210
+ res.json({ versions: files });
211
+ }
212
+ catch (err) {
213
+ logger.warn(`[Web] Failed to list skill versions: ${err}`);
214
+ res.status(500).json({ error: String(err) });
215
+ }
216
+ });
217
+ // GET /api/skills/:name/versions/:timestamp — get specific version content
218
+ app.get('/api/skills/:name/versions/:timestamp', (req, res) => {
219
+ try {
220
+ const { name, timestamp } = req.params;
221
+ const backupDir = path.join(homedir(), '.claude-forge', 'backups', 'skills');
222
+ const filename = `${name}-${timestamp}.md`;
223
+ const filePath = path.join(backupDir, filename);
224
+ if (!fs.existsSync(filePath)) {
225
+ res.status(404).json({ error: 'Version not found' });
226
+ return;
227
+ }
228
+ const content = fs.readFileSync(filePath, 'utf-8');
229
+ res.json({ content });
230
+ }
231
+ catch (err) {
232
+ logger.warn(`[Web] Failed to get skill version: ${err}`);
233
+ res.status(500).json({ error: String(err) });
234
+ }
235
+ });
236
+ // POST /api/skills/:name/rollback — rollback to a specific version
237
+ app.post('/api/skills/:name/rollback', (req, res) => {
238
+ try {
239
+ const { name } = req.params;
240
+ const { timestamp } = req.body;
241
+ if (!timestamp) {
242
+ res.status(400).json({ error: 'Missing timestamp' });
243
+ return;
244
+ }
245
+ const skillsDir = path.join(homedir(), '.claude', 'skills');
246
+ const currentPath = path.join(skillsDir, `${name}.md`);
247
+ const backupDir = path.join(homedir(), '.claude-forge', 'backups', 'skills');
248
+ const versionPath = path.join(backupDir, `${name}-${timestamp}.md`);
249
+ if (!fs.existsSync(currentPath)) {
250
+ res.status(404).json({ error: 'Skill not found' });
251
+ return;
252
+ }
253
+ if (!fs.existsSync(versionPath)) {
254
+ res.status(404).json({ error: 'Version not found' });
255
+ return;
256
+ }
257
+ fs.mkdirSync(backupDir, { recursive: true });
258
+ const rollbackTimestamp = new Date().toISOString().replace(/[:.]/g, '-');
259
+ const rollbackBackupPath = path.join(backupDir, `${name}-${rollbackTimestamp}.md`);
260
+ fs.copyFileSync(currentPath, rollbackBackupPath);
261
+ const versionContent = fs.readFileSync(versionPath, 'utf-8');
262
+ fs.writeFileSync(currentPath, versionContent, 'utf-8');
263
+ logger.info(`[Web] Rolled back skill ${name} to ${timestamp} (backup: ${rollbackBackupPath})`);
264
+ res.json({ success: true, backup: rollbackBackupPath });
265
+ }
266
+ catch (err) {
267
+ logger.warn(`[Web] Failed to rollback skill: ${err}`);
268
+ res.status(500).json({ error: String(err) });
269
+ }
270
+ });
271
+ }
272
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../../src/web/routes/skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Application } from 'express';
2
+ import type { RouteContext } from './types.js';
3
+ /**
4
+ * Static assets — Vite-built UI + cache headers + SPA fallback.
5
+ *
6
+ * index.html: no-cache (always fetch latest, avoids stale UI after deploy)
7
+ * /assets/*: immutable, content-hashed, safe to cache for a year.
8
+ *
9
+ * SPA fallback MUST be registered last so it doesn't shadow any API route;
10
+ * that constraint is enforced by splitting into `registerStaticAssets` (runs
11
+ * early, sets up express.static) and `registerStaticFallback` (runs last).
12
+ */
13
+ export declare function registerStaticAssets(app: Application, _ctx: RouteContext): void;
14
+ /**
15
+ * SPA catch-all — must be registered last. Routes any non-/api path to
16
+ * index.html so the frontend router handles deep links on refresh.
17
+ */
18
+ export declare function registerStaticFallback(app: Application, _ctx: RouteContext): void;
19
+ //# sourceMappingURL=static.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../../src/web/routes/static.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAK3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAY/C;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAyB/E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAOjF"}
@@ -0,0 +1,61 @@
1
+ import express from 'express';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { logger } from '../../core/utils/logger.js';
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ function findStaticDir() {
8
+ const candidates = [
9
+ path.join(__dirname, '..', 'static'), // dist/web/routes -> dist/web/static
10
+ path.join(__dirname, '../../..', 'src/web/static'), // dev: src/web/routes -> src/web/static
11
+ ];
12
+ return candidates.find(d => fs.existsSync(d)) ?? null;
13
+ }
14
+ /**
15
+ * Static assets — Vite-built UI + cache headers + SPA fallback.
16
+ *
17
+ * index.html: no-cache (always fetch latest, avoids stale UI after deploy)
18
+ * /assets/*: immutable, content-hashed, safe to cache for a year.
19
+ *
20
+ * SPA fallback MUST be registered last so it doesn't shadow any API route;
21
+ * that constraint is enforced by splitting into `registerStaticAssets` (runs
22
+ * early, sets up express.static) and `registerStaticFallback` (runs last).
23
+ */
24
+ export function registerStaticAssets(app, _ctx) {
25
+ const staticDir = findStaticDir();
26
+ if (!staticDir) {
27
+ logger.warn('[Web] Static directory not found; UI will not be served.');
28
+ return;
29
+ }
30
+ app.use(express.static(staticDir, {
31
+ setHeaders: (res, filePath) => {
32
+ if (filePath.endsWith('index.html')) {
33
+ res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
34
+ res.setHeader('Pragma', 'no-cache');
35
+ res.setHeader('Expires', '0');
36
+ }
37
+ else if (filePath.includes('/assets/')) {
38
+ res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
39
+ }
40
+ },
41
+ }));
42
+ app.get('/', (_req, res) => {
43
+ res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
44
+ res.sendFile('index.html', { root: staticDir });
45
+ });
46
+ logger.info(`[Web] Serving static files from ${staticDir}`);
47
+ }
48
+ /**
49
+ * SPA catch-all — must be registered last. Routes any non-/api path to
50
+ * index.html so the frontend router handles deep links on refresh.
51
+ */
52
+ export function registerStaticFallback(app, _ctx) {
53
+ const staticDir = findStaticDir();
54
+ if (!staticDir)
55
+ return;
56
+ app.get(/^(?!\/api).*$/, (_req, res) => {
57
+ res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
58
+ res.sendFile('index.html', { root: staticDir });
59
+ });
60
+ }
61
+ //# sourceMappingURL=static.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static.js","sourceRoot":"","sources":["../../../src/web/routes/static.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAGpD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE/D,SAAS,aAAa;IACpB,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAY,qCAAqC;QACrF,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,gBAAgB,CAAC,EAAE,wCAAwC;KAC7F,CAAC;IACF,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACxD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAgB,EAAE,IAAkB;IACvE,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;IAClC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE;QAChC,UAAU,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;YAC5B,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACpC,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;gBACtE,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;gBACpC,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAChC,CAAC;iBAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACzC,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;KACF,CAAC,CAAC,CAAC;IAEJ,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACzB,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;QACtE,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,mCAAmC,SAAS,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAgB,EAAE,IAAkB;IACzE,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;IAClC,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACrC,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;QACtE,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Application } from 'express';
2
+ import type { RouteContext } from './types.js';
3
+ /**
4
+ * Status / health endpoints for the daemon and background worker.
5
+ */
6
+ export declare function registerStatusRoutes(app: Application, ctx: RouteContext): void;
7
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/web/routes/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI,CAuB9E"}
@@ -0,0 +1,28 @@
1
+ import { probeWorkerAuth } from '../../capability/executor/worker-auth-probe.js';
2
+ /**
3
+ * Status / health endpoints for the daemon and background worker.
4
+ */
5
+ export function registerStatusRoutes(app, ctx) {
6
+ const { storage } = ctx;
7
+ // Worker auth probe: used by frontend to warn before attempting background mode
8
+ app.get('/api/worker-auth-status', (_req, res) => {
9
+ try {
10
+ const probe = probeWorkerAuth();
11
+ res.json(probe);
12
+ }
13
+ catch (err) {
14
+ const message = err instanceof Error ? err.message : String(err);
15
+ res.status(500).json({ error: message });
16
+ }
17
+ });
18
+ // Dashboard: daemon status
19
+ app.get('/api/status', (_req, res) => {
20
+ res.json({
21
+ pid: process.pid,
22
+ uptime: process.uptime(),
23
+ memory: process.memoryUsage(),
24
+ eventCount: storage.countEvents({}),
25
+ });
26
+ });
27
+ }
28
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/web/routes/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAGjF;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAgB,EAAE,GAAiB;IACtE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC;IAExB,gFAAgF;IAChF,GAAG,CAAC,GAAG,CAAC,yBAAyB,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAC/C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;YAChC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,2BAA2B;IAC3B,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACnC,GAAG,CAAC,IAAI,CAAC;YACP,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;YACxB,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE;YAC7B,UAAU,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;SACpC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Application } from 'express';
2
+ import type { RouteContext } from './types.js';
3
+ /**
4
+ * /api/token-usage/* — token usage queries by session or methodology.
5
+ */
6
+ export declare function registerTokenUsageRoutes(app: Application, ctx: RouteContext): void;
7
+ //# sourceMappingURL=token-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-usage.d.ts","sourceRoot":"","sources":["../../../src/web/routes/token-usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI,CA4BlF"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * /api/token-usage/* — token usage queries by session or methodology.
3
+ */
4
+ export function registerTokenUsageRoutes(app, ctx) {
5
+ const { storage } = ctx;
6
+ app.get('/api/token-usage/session/:sessionId', (req, res) => {
7
+ const sessionId = req.params.sessionId;
8
+ try {
9
+ const usage = storage.getTokenUsageBySession(sessionId);
10
+ const details = storage.listTokenUsage({ session_id: sessionId, limit: 100 });
11
+ res.json({ ...usage, details });
12
+ }
13
+ catch (err) {
14
+ res.status(500).json({ error: String(err) });
15
+ }
16
+ });
17
+ app.get('/api/token-usage/methodology/:executionId', (req, res) => {
18
+ const executionId = parseInt(req.params.executionId);
19
+ if (isNaN(executionId)) {
20
+ res.status(400).json({ error: 'Invalid execution ID' });
21
+ return;
22
+ }
23
+ try {
24
+ const usage = storage.getTokenUsageByMethodology(executionId);
25
+ const details = storage.listTokenUsage({ methodology_execution_id: executionId, limit: 100 });
26
+ res.json({ ...usage, details });
27
+ }
28
+ catch (err) {
29
+ res.status(500).json({ error: String(err) });
30
+ }
31
+ });
32
+ }
33
+ //# sourceMappingURL=token-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-usage.js","sourceRoot":"","sources":["../../../src/web/routes/token-usage.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAgB,EAAE,GAAiB;IAC1E,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC;IAExB,GAAG,CAAC,GAAG,CAAC,qCAAqC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC1D,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,OAAO,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;YACxD,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9E,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,2CAA2C,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAChE,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YACvB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;YACxD,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,OAAO,CAAC,0BAA0B,CAAC,WAAW,CAAC,CAAC;YAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,EAAE,wBAAwB,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9F,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Shared types & helpers for route modules.
3
+ *
4
+ * Each route module exports a `register(app, ctx)` function that attaches its
5
+ * endpoints onto the Express app. The context carries all the service
6
+ * dependencies the routes need — this keeps the modules decoupled from the
7
+ * WebServer class while preserving behaviour.
8
+ */
9
+ import type { SQLiteStorage } from '../../core/storage/sqlite.js';
10
+ import type { RuleEngine } from '../../engine/rule-engine.js';
11
+ import type { AgentRouter } from '../../engine/agent-router.js';
12
+ import type { AgentRegistry } from '../../agents/registry.js';
13
+ import type { ExecutionManager } from '../../capability/execution-manager.js';
14
+ import type { MethodologyRegistry } from '../../capability/methodology-registry.js';
15
+ import type { MethodologyPlanner } from '../../capability/methodology-planner.js';
16
+ import type { SkillRegistry } from '../../skills/registry.js';
17
+ export interface RouteContext {
18
+ storage: SQLiteStorage;
19
+ ruleEngine: RuleEngine;
20
+ router?: AgentRouter;
21
+ agents?: AgentRegistry;
22
+ skillRegistry?: SkillRegistry;
23
+ executionManager?: ExecutionManager;
24
+ methodologyRegistry?: MethodologyRegistry;
25
+ methodologyPlanner?: MethodologyPlanner;
26
+ }
27
+ /**
28
+ * Resolve the concrete on-disk path + backup dir for a patchable target.
29
+ * Shared by /api/patch/* and AI optimization flows.
30
+ */
31
+ export declare function resolvePatchTarget(targetType: string, targetName: string): {
32
+ filePath: string;
33
+ backupDir: string;
34
+ };
35
+ /**
36
+ * Locate the static assets directory. Supports both dist/ and src/ layouts so
37
+ * dev & prod builds both work without configuration.
38
+ */
39
+ export declare function resolveStaticDir(moduleUrl: string): string | null;
40
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/web/routes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AACpF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAoBzC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Shared types & helpers for route modules.
3
+ *
4
+ * Each route module exports a `register(app, ctx)` function that attaches its
5
+ * endpoints onto the Express app. The context carries all the service
6
+ * dependencies the routes need — this keeps the modules decoupled from the
7
+ * WebServer class while preserving behaviour.
8
+ */
9
+ import path from 'path';
10
+ import fs from 'fs';
11
+ import { fileURLToPath } from 'url';
12
+ import { homedir } from 'os';
13
+ /**
14
+ * Resolve the concrete on-disk path + backup dir for a patchable target.
15
+ * Shared by /api/patch/* and AI optimization flows.
16
+ */
17
+ export function resolvePatchTarget(targetType, targetName) {
18
+ if (targetType === 'agent') {
19
+ return {
20
+ filePath: path.join(homedir(), '.claude', 'agents', `${targetName}.md`),
21
+ backupDir: path.join(homedir(), '.claude-forge', 'backups', 'agents'),
22
+ };
23
+ }
24
+ if (targetType === 'skill') {
25
+ return {
26
+ filePath: path.join(homedir(), '.claude', 'skills', `${targetName}.md`),
27
+ backupDir: path.join(homedir(), '.claude-forge', 'backups', 'skills'),
28
+ };
29
+ }
30
+ if (targetType === 'routing_rule') {
31
+ return {
32
+ filePath: path.join(homedir(), '.claude-forge', 'routing.yaml'),
33
+ backupDir: path.join(homedir(), '.claude-forge', 'backups', 'routing'),
34
+ };
35
+ }
36
+ throw new Error(`Unsupported targetType: ${targetType}`);
37
+ }
38
+ /**
39
+ * Locate the static assets directory. Supports both dist/ and src/ layouts so
40
+ * dev & prod builds both work without configuration.
41
+ */
42
+ export function resolveStaticDir(moduleUrl) {
43
+ const dir = path.dirname(fileURLToPath(moduleUrl));
44
+ const candidates = [
45
+ path.join(dir, '..', 'static'), // dist/web/static (from dist/web/routes/*.js)
46
+ path.join(dir, '../../../src/web/static'), // dev: src/web/static (from dist/web/routes/*.js)
47
+ path.join(dir, '../static'), // legacy: dist/web/static (from dist/web/*.js)
48
+ path.join(dir, '../../src/web/static'), // legacy dev
49
+ ];
50
+ return candidates.find(d => fs.existsSync(d)) ?? null;
51
+ }
52
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/web/routes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAqB7B;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAkB,EAClB,UAAkB;IAElB,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,UAAU,KAAK,CAAC;YACvE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,CAAC;SACtE,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,UAAU,KAAK,CAAC;YACvE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,CAAC;SACtE,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;QAClC,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,cAAc,CAAC;YAC/D,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,CAAC;SACvE,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2BAA2B,UAAU,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAe,8CAA8C;QAC3F,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,yBAAyB,CAAC,EAAI,kDAAkD;QAC/F,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,EAAkB,+CAA+C;QAC5F,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAsB,CAAC,EAAO,aAAa;KAC3D,CAAC;IACF,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACxD,CAAC"}
@@ -1,7 +1,10 @@
1
1
  /**
2
- * Web API server — lightweight Express server for Forge dashboard
2
+ * Web API server — Express entry for the Forge dashboard.
3
3
  *
4
- * 3 pages: Dashboard, Events, Rules
4
+ * server.ts is intentionally thin: it wires middleware, composes the route
5
+ * modules under src/web/routes/, and owns lifecycle (start/stop). Each route
6
+ * module is responsible for its own domain; see src/web/routes/types.ts for
7
+ * the shared RouteContext.
5
8
  */
6
9
  import type { SQLiteStorage } from '../core/storage/sqlite.js';
7
10
  import type { RuleEngine } from '../engine/rule-engine.js';
@@ -10,6 +13,7 @@ import type { AgentRegistry } from '../agents/registry.js';
10
13
  import type { ExecutionManager } from '../capability/execution-manager.js';
11
14
  import type { MethodologyRegistry } from '../capability/methodology-registry.js';
12
15
  import type { MethodologyPlanner } from '../capability/methodology-planner.js';
16
+ import type { SkillRegistry } from '../skills/registry.js';
13
17
  export interface WebServerOptions {
14
18
  port: number;
15
19
  storage: SQLiteStorage;
@@ -19,13 +23,12 @@ export interface WebServerOptions {
19
23
  executionManager?: ExecutionManager;
20
24
  methodologyRegistry?: MethodologyRegistry;
21
25
  methodologyPlanner?: MethodologyPlanner;
26
+ skillRegistry?: SkillRegistry;
22
27
  }
23
28
  export declare class WebServer {
24
29
  private options;
25
30
  private app;
26
31
  private server;
27
- private agents?;
28
- private router?;
29
32
  constructor(options: WebServerOptions);
30
33
  private setupRoutes;
31
34
  start(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAW/E,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED,qBAAa,SAAS;IAMR,OAAO,CAAC,OAAO;IAL3B,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,MAAM,CAA0D;IACxE,OAAO,CAAC,MAAM,CAAC,CAAgB;IAC/B,OAAO,CAAC,MAAM,CAAC,CAAc;gBAET,OAAO,EAAE,gBAAgB;IAQ7C,OAAO,CAAC,WAAW;IAiiFb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAO5B"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAsB3D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,qBAAa,SAAS;IAIR,OAAO,CAAC,OAAO;IAH3B,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,MAAM,CAA0D;gBAEpD,OAAO,EAAE,gBAAgB;IAM7C,OAAO,CAAC,WAAW;IA8Cb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAO5B"}