profclaw 0.0.1-beta.1 → 0.0.1-beta.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 (151) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/openclaw.js +1 -1
  3. package/dist/agents/executor.js +38 -6
  4. package/dist/auth/auth-service.js +8 -6
  5. package/dist/auth/device-identity.js +7 -5
  6. package/dist/auth/github-oauth.js +3 -1
  7. package/dist/auth/pairing-codes.js +6 -4
  8. package/dist/browser/service.js +5 -3
  9. package/dist/chat/execution/guardrails.js +3 -1
  10. package/dist/chat/execution/workflows/executor.js +4 -2
  11. package/dist/chat/memory.js +3 -1
  12. package/dist/chat/proactive/index.js +13 -11
  13. package/dist/chat/tools.js +8 -7
  14. package/dist/cli/commands/auth.js +22 -13
  15. package/dist/cli/commands/onboard.js +248 -59
  16. package/dist/cli/commands/setup.js +180 -104
  17. package/dist/cron/issue-poller.js +1 -1
  18. package/dist/hooks/agent-webhook.js +10 -7
  19. package/dist/hooks/prompt-submit.js +5 -6
  20. package/dist/hooks/session-end.js +10 -6
  21. package/dist/hooks/tool-use.js +9 -6
  22. package/dist/integrations/github-ticket-sync.js +8 -6
  23. package/dist/integrations/github.js +8 -6
  24. package/dist/integrations/jira.js +5 -3
  25. package/dist/mcp/server.js +12 -9
  26. package/dist/memory/experience-store.js +15 -14
  27. package/dist/notifications/slack.js +4 -2
  28. package/dist/providers/types.d.ts +2 -2
  29. package/dist/queue/failure-handler.js +15 -13
  30. package/dist/queue/index.js +6 -4
  31. package/dist/queue/memory-queue.js +23 -27
  32. package/dist/queue/task-queue.js +18 -22
  33. package/dist/routes/agents.js +3 -1
  34. package/dist/routes/auth.js +11 -9
  35. package/dist/routes/devices.js +17 -15
  36. package/dist/routes/gateway.js +3 -1
  37. package/dist/routes/hooks.js +7 -5
  38. package/dist/routes/import.js +10 -8
  39. package/dist/routes/labels.js +11 -9
  40. package/dist/routes/oobe.js +8 -6
  41. package/dist/routes/openapi.js +1 -1
  42. package/dist/routes/projects.js +27 -25
  43. package/dist/routes/settings.js +7 -5
  44. package/dist/routes/setup.js +12 -11
  45. package/dist/routes/slack.js +28 -27
  46. package/dist/routes/stats.js +6 -4
  47. package/dist/routes/summaries.js +4 -3
  48. package/dist/routes/sync.js +7 -5
  49. package/dist/routes/tasks.js +10 -8
  50. package/dist/routes/tickets.js +26 -26
  51. package/dist/routes/tokens.js +5 -3
  52. package/dist/routes/users.js +14 -12
  53. package/dist/routes/webhooks.js +5 -3
  54. package/dist/settings/index.js +3 -1
  55. package/dist/storage/index.d.ts +2 -1
  56. package/dist/storage/index.js +9 -4
  57. package/dist/storage/libsql.js +29 -21
  58. package/dist/storage/schema.d.ts +107 -46
  59. package/dist/summaries/storage.js +3 -1
  60. package/dist/tickets/index.js +10 -8
  61. package/dist/utils/circuit-breaker.js +10 -5
  62. package/dist/utils/logger.d.ts +5 -1
  63. package/dist/utils/logger.js +23 -7
  64. package/package.json +4 -3
  65. package/ui/dist/assets/{ActivityView-CkPgKhwm.js → ActivityView-DIPQSJ_d.js} +1 -1
  66. package/ui/dist/assets/{AgentList-C3SVdeEz.js → AgentList-CqyaYrcq.js} +1 -1
  67. package/ui/dist/assets/{AnalyticsDashboard-DVU--vlP.js → AnalyticsDashboard-C-mjuGHT.js} +1 -1
  68. package/ui/dist/assets/{AreaChart-B5qMEGWj.js → AreaChart-CfYWmbtr.js} +1 -1
  69. package/ui/dist/assets/{CartesianChart-B50bcUJi.js → CartesianChart-BaQ3It0c.js} +1 -1
  70. package/ui/dist/assets/{ChatView-BZFJs7w_.js → ChatView-DxxQy6pl.js} +1 -1
  71. package/ui/dist/assets/CostsDashboard-CDBBcGkg.js +1 -0
  72. package/ui/dist/assets/{EstimateSelect-CLpB4NQO.js → EstimateSelect-CDjf5qKl.js} +1 -1
  73. package/ui/dist/assets/{FloatingChatbot-CBzBY9a0.js → FloatingChatbot-CZHjvJIe.js} +1 -1
  74. package/ui/dist/assets/{InviteCodeManagement-DsbdPa6W.js → InviteCodeManagement-DTm-IPTm.js} +1 -1
  75. package/ui/dist/assets/{ProjectDetail-BEM3tFXg.js → ProjectDetail-DlYUcOss.js} +1 -1
  76. package/ui/dist/assets/{ProjectIcon-CN1FmFAk.js → ProjectIcon-BMRpnM04.js} +1 -1
  77. package/ui/dist/assets/{ProjectList-DSDaNhxQ.js → ProjectList-D85TN0i0.js} +1 -1
  78. package/ui/dist/assets/{Settings-dPVcqC_d.js → Settings-CgPqzUvj.js} +3 -3
  79. package/ui/dist/assets/{StatusIndicator-DA3NAo_b.js → StatusIndicator-yig0uZEA.js} +1 -1
  80. package/ui/dist/assets/{SummaryDetail-Bjnf9lT8.js → SummaryDetail-CwLAfHgJ.js} +1 -1
  81. package/ui/dist/assets/{SummaryList-ENwKDBKW.js → SummaryList-BvS5Idnu.js} +1 -1
  82. package/ui/dist/assets/{TaskDetail-DnwG6MzB.js → TaskDetail-zarC1fOt.js} +1 -1
  83. package/ui/dist/assets/{TaskList-D9Ug_HiV.js → TaskList-CyJq3ANE.js} +1 -1
  84. package/ui/dist/assets/{TicketBoard-CviH1571.js → TicketBoard-BlWr3-iH.js} +1 -1
  85. package/ui/dist/assets/{TicketDetail-8Jk8O-33.js → TicketDetail-DmqWKj2W.js} +1 -1
  86. package/ui/dist/assets/{TicketList-B-iV4rRA.js → TicketList-Scj4pMWa.js} +1 -1
  87. package/ui/dist/assets/{UserManagement-CPZ8s7s2.js → UserManagement-BH7uG7dw.js} +1 -1
  88. package/ui/dist/assets/{ViewSwitcher-BUyOOWDI.js → ViewSwitcher-3HzZUdWn.js} +1 -1
  89. package/ui/dist/assets/{alert-dialog-BOmnTkN-.js → alert-dialog-DWPb2IfQ.js} +1 -1
  90. package/ui/dist/assets/{archive-D5my9zOG.js → archive-CGck7gxR.js} +1 -1
  91. package/ui/dist/assets/{badge-B4ov81_m.js → badge-DEmc3Z_l.js} +1 -1
  92. package/ui/dist/assets/{brain-C53ElFLD.js → brain-CfFdLVqb.js} +1 -1
  93. package/ui/dist/assets/{bug-D0TJoCYn.js → bug-DqSGPUUE.js} +1 -1
  94. package/ui/dist/assets/{calendar-BkWIhKa1.js → calendar-BuZ4zbPW.js} +1 -1
  95. package/ui/dist/assets/{chevron-up-BRTtndUZ.js → chevron-up-DcJ4LL_N.js} +1 -1
  96. package/ui/dist/assets/{circle-x-BN89YhbS.js → circle-x-C78PNZjF.js} +1 -1
  97. package/ui/dist/assets/{constants-fc7TFI7u.js → constants-DhDjZe4P.js} +1 -1
  98. package/ui/dist/assets/{cpu-B41x1-vV.js → cpu-Ck6AoG8c.js} +1 -1
  99. package/ui/dist/assets/{database-D9Cnfmzj.js → database-CA2w8Lvt.js} +1 -1
  100. package/ui/dist/assets/{dialog-DrWB4EYD.js → dialog-BOdGWhgE.js} +1 -1
  101. package/ui/dist/assets/{ellipsis-NuUWekvu.js → ellipsis-FhHKRbfl.js} +1 -1
  102. package/ui/dist/assets/{ellipsis-vertical-BueMfuCw.js → ellipsis-vertical-CO0UqE4-.js} +1 -1
  103. package/ui/dist/assets/{file-code-HR9829Jc.js → file-code-ChnhYYj1.js} +1 -1
  104. package/ui/dist/assets/{folder-open-C_7oYEqe.js → folder-open-CHwA1-ve.js} +1 -1
  105. package/ui/dist/assets/{funnel-B5gmNXGf.js → funnel-ByEjRFNB.js} +1 -1
  106. package/ui/dist/assets/{git-branch-BRMiJmV3.js → git-branch-GTOPQgU4.js} +1 -1
  107. package/ui/dist/assets/{git-commit-horizontal-CXOUQeJI.js → git-commit-horizontal-F5M84Kut.js} +1 -1
  108. package/ui/dist/assets/{globe-CCspjvus.js → globe-CQWfr7hT.js} +1 -1
  109. package/ui/dist/assets/{hash-g3102kPC.js → hash-nKC9gtLg.js} +1 -1
  110. package/ui/dist/assets/{history-CNqcBBrV.js → history-DfFSA9xJ.js} +1 -1
  111. package/ui/dist/assets/{index-kb4AJXUB.js → index--JkIxVXb.js} +3 -3
  112. package/ui/dist/assets/index-Ca3vk7Gq.js +1 -0
  113. package/ui/dist/assets/{index-C9jNQXzL.js → index-DHGvP9mp.js} +1 -1
  114. package/ui/dist/assets/index-DeI8lKRR.js +1 -0
  115. package/ui/dist/assets/{index-DURTouJI.js → index-Z4-RtZcs.js} +1 -1
  116. package/ui/dist/assets/{index-CEZ6R2Uw.js → index-a4Fxq0Hb.js} +1 -1
  117. package/ui/dist/assets/{layers-CLXiHN6o.js → layers-DFeLExSa.js} +1 -1
  118. package/ui/dist/assets/{layout-dashboard-B07MFhBs.js → layout-dashboard-WmgjMhWF.js} +1 -1
  119. package/ui/dist/assets/{lightbulb-B2dgG5ks.js → lightbulb-Bo8hEr7B.js} +1 -1
  120. package/ui/dist/assets/{link-2-BxNmr9hL.js → link-2-YqrpQXBH.js} +1 -1
  121. package/ui/dist/assets/{markdown-renderer-CjU6hBcW.js → markdown-renderer-Croje6Xe.js} +1 -1
  122. package/ui/dist/assets/{message-square-Bf2-CVbt.js → message-square-CD0H5hot.js} +1 -1
  123. package/ui/dist/assets/{pencil-D096Ey62.js → pencil-DpFnj5dn.js} +1 -1
  124. package/ui/dist/assets/{play-DfdcSI3x.js → play-DVgea_jT.js} +1 -1
  125. package/ui/dist/assets/{popover-BV0QJDQq.js → popover-JXecfWG5.js} +1 -1
  126. package/ui/dist/assets/{progress-DjPEDJfI.js → progress-C1ghf1Fu.js} +1 -1
  127. package/ui/dist/assets/{rocket-CPsTc-5G.js → rocket-BFxPYGx9.js} +1 -1
  128. package/ui/dist/assets/{select-LsO16slr.js → select-MADP8m6Q.js} +1 -1
  129. package/ui/dist/assets/{send-BDYBZDUZ.js → send-eYnW_7n-.js} +1 -1
  130. package/ui/dist/assets/{server-B3k6noce.js → server-CPMaysH8.js} +1 -1
  131. package/ui/dist/assets/{settings-2-Cu4xTjhG.js → settings-2-scXUOuE_.js} +1 -1
  132. package/ui/dist/assets/{sheet-BScLnPKX.js → sheet-r6NSOxi-.js} +1 -1
  133. package/ui/dist/assets/{shield-check-CQqkwufI.js → shield-check-PEr7nmVw.js} +1 -1
  134. package/ui/dist/assets/{shield-off-ZFruH9KO.js → shield-off-CLtXio62.js} +1 -1
  135. package/ui/dist/assets/{skeleton-CtkIA_MU.js → skeleton-C9oEzNlU.js} +1 -1
  136. package/ui/dist/assets/{smartphone-DnoksVkc.js → smartphone-DusFfY0U.js} +1 -1
  137. package/ui/dist/assets/{square-uD9ZHMfW.js → square-e1yxB2eR.js} +1 -1
  138. package/ui/dist/assets/{switch-MQPnwGJK.js → switch-tNs0n-kz.js} +1 -1
  139. package/ui/dist/assets/{table-B8cqlywA.js → table-CXxtLicg.js} +1 -1
  140. package/ui/dist/assets/{tag-wEJQRWlV.js → tag-tAwMmQ9G.js} +1 -1
  141. package/ui/dist/assets/{textarea-D5LJCOGl.js → textarea-BjiEeIWh.js} +1 -1
  142. package/ui/dist/assets/{timer-mbGHegmr.js → timer-Vel1N3RP.js} +1 -1
  143. package/ui/dist/assets/{tooltip-Df1CunSp.js → tooltip-ZMwtfr1J.js} +1 -1
  144. package/ui/dist/assets/{trash-2-B4oAXsX-.js → trash-2-eM-CNwsZ.js} +1 -1
  145. package/ui/dist/assets/{trending-up-BGWxvlmZ.js → trending-up-BGafmjRo.js} +1 -1
  146. package/ui/dist/assets/{wand-sparkles-CZy4xvL3.js → wand-sparkles-DPvcd9Pi.js} +1 -1
  147. package/ui/dist/assets/{wrench-ByZkjO6m.js → wrench-B8s3zYVV.js} +1 -1
  148. package/ui/dist/index.html +1 -1
  149. package/ui/dist/assets/CostsDashboard-ChfH8BlG.js +0 -1
  150. package/ui/dist/assets/index-27mTPKuh.js +0 -1
  151. package/ui/dist/assets/index-BMx3fH-e.js +0 -1
@@ -13,7 +13,9 @@ import { validateGitHubToken, listGitHubProjects, listGitHubRepos, getGitHubProj
13
13
  import { getCookie } from 'hono/cookie';
14
14
  import { validateSession } from '../auth/auth-service.js';
15
15
  import { createProject, createProjectExternalLink, createSprint } from '../projects/index.js';
16
+ import { createContextualLogger } from '../utils/logger.js';
16
17
  export const importRoutes = new Hono();
18
+ const log = createContextualLogger('ImportRoutes');
17
19
  // Token storage helpers
18
20
  async function storeGitHubToken(token, tokenType, username, scopes) {
19
21
  const db = getDb();
@@ -119,7 +121,7 @@ importRoutes.post('/github/validate-token', async (c) => {
119
121
  });
120
122
  }
121
123
  catch (error) {
122
- console.error('[Import] Token validation error:', error);
124
+ log.error('Token validation error', error instanceof Error ? error : new Error(String(error)));
123
125
  return c.json({
124
126
  valid: false,
125
127
  error: error instanceof Error ? error.message : 'Validation failed',
@@ -149,7 +151,7 @@ importRoutes.get('/github/status', async (c) => {
149
151
  });
150
152
  }
151
153
  catch (error) {
152
- console.error('[Import] Status check error:', error);
154
+ log.error('Status check error', error instanceof Error ? error : new Error(String(error)));
153
155
  return c.json({
154
156
  connected: false,
155
157
  error: error instanceof Error ? error.message : 'Status check failed',
@@ -176,7 +178,7 @@ importRoutes.get('/github/projects', async (c) => {
176
178
  });
177
179
  }
178
180
  catch (error) {
179
- console.error('[Import] List projects error:', error);
181
+ log.error('List projects error', error instanceof Error ? error : new Error(String(error)));
180
182
  return c.json({
181
183
  error: error instanceof Error ? error.message : 'Failed to list projects',
182
184
  }, 500);
@@ -199,7 +201,7 @@ importRoutes.get('/github/projects/:projectId/preview', async (c) => {
199
201
  return c.json(preview);
200
202
  }
201
203
  catch (error) {
202
- console.error('[Import] Project preview error:', error);
204
+ log.error('Project preview error', error instanceof Error ? error : new Error(String(error)));
203
205
  return c.json({
204
206
  error: error instanceof Error ? error.message : 'Failed to get project preview',
205
207
  }, 500);
@@ -322,7 +324,7 @@ importRoutes.post('/github/projects/:projectId/dry-run', async (c) => {
322
324
  });
323
325
  }
324
326
  catch (error) {
325
- console.error('[Import] Dry run error:', error);
327
+ log.error('Dry run error', error instanceof Error ? error : new Error(String(error)));
326
328
  return c.json({
327
329
  error: error instanceof Error ? error.message : 'Dry run failed',
328
330
  }, 500);
@@ -463,7 +465,7 @@ importRoutes.post('/github/projects/:projectId/execute', async (c) => {
463
465
  });
464
466
  }
465
467
  catch (error) {
466
- console.error('[Import] Execute error:', error);
468
+ log.error('Execute error', error instanceof Error ? error : new Error(String(error)));
467
469
  // Check for unique constraint violation
468
470
  if (error instanceof Error && error.message.includes('UNIQUE constraint failed')) {
469
471
  return c.json({
@@ -498,7 +500,7 @@ importRoutes.get('/github/repos', async (c) => {
498
500
  });
499
501
  }
500
502
  catch (error) {
501
- console.error('[Import] List repos error:', error);
503
+ log.error('List repos error', error instanceof Error ? error : new Error(String(error)));
502
504
  return c.json({
503
505
  error: error instanceof Error ? error.message : 'Failed to list repositories',
504
506
  }, 500);
@@ -520,7 +522,7 @@ importRoutes.delete('/github/disconnect', async (c) => {
520
522
  });
521
523
  }
522
524
  catch (error) {
523
- console.error('[Import] Disconnect error:', error);
525
+ log.error('Disconnect error', error instanceof Error ? error : new Error(String(error)));
524
526
  return c.json({
525
527
  error: error instanceof Error ? error.message : 'Disconnect failed',
526
528
  }, 500);
@@ -6,7 +6,9 @@
6
6
  import { Hono } from 'hono';
7
7
  import { z } from 'zod';
8
8
  import { createLabel, getLabel, listLabels, updateLabel, deleteLabel, getTicketLabels, addLabelToTicket, removeLabelFromTicket, setTicketLabels, } from '../labels/index.js';
9
+ import { createContextualLogger } from '../utils/logger.js';
9
10
  export const labelsRoutes = new Hono();
11
+ const log = createContextualLogger('LabelsRoutes');
10
12
  function getErrorMessage(error) {
11
13
  return error instanceof Error ? error.message : undefined;
12
14
  }
@@ -56,7 +58,7 @@ labelsRoutes.get('/projects/:projectId/labels', async (c) => {
56
58
  });
57
59
  }
58
60
  catch (error) {
59
- console.error('[Labels] List error:', error);
61
+ log.error('List error', error instanceof Error ? error : new Error(String(error)));
60
62
  return c.json({ error: error instanceof Error ? error.message : 'Failed to list labels' }, 500);
61
63
  }
62
64
  });
@@ -86,7 +88,7 @@ labelsRoutes.post('/projects/:projectId/labels', async (c) => {
86
88
  return c.json(label, 201);
87
89
  }
88
90
  catch (error) {
89
- console.error('[Labels] Create error:', error);
91
+ log.error('Create error', error instanceof Error ? error : new Error(String(error)));
90
92
  if (getErrorMessage(error)?.includes('UNIQUE constraint')) {
91
93
  return c.json({ error: 'A label with this name already exists' }, 409);
92
94
  }
@@ -107,7 +109,7 @@ labelsRoutes.get('/labels/:id', async (c) => {
107
109
  return c.json(label);
108
110
  }
109
111
  catch (error) {
110
- console.error('[Labels] Get error:', error);
112
+ log.error('Get error', error instanceof Error ? error : new Error(String(error)));
111
113
  return c.json({ error: error instanceof Error ? error.message : 'Failed to get label' }, 500);
112
114
  }
113
115
  });
@@ -137,7 +139,7 @@ labelsRoutes.patch('/labels/:id', async (c) => {
137
139
  return c.json(label);
138
140
  }
139
141
  catch (error) {
140
- console.error('[Labels] Update error:', error);
142
+ log.error('Update error', error instanceof Error ? error : new Error(String(error)));
141
143
  if (getErrorMessage(error)?.includes('not found')) {
142
144
  return c.json({ error: 'Label not found' }, 404);
143
145
  }
@@ -155,7 +157,7 @@ labelsRoutes.delete('/labels/:id', async (c) => {
155
157
  return c.json({ success: true });
156
158
  }
157
159
  catch (error) {
158
- console.error('[Labels] Delete error:', error);
160
+ log.error('Delete error', error instanceof Error ? error : new Error(String(error)));
159
161
  return c.json({ error: error instanceof Error ? error.message : 'Failed to delete label' }, 500);
160
162
  }
161
163
  });
@@ -174,7 +176,7 @@ labelsRoutes.get('/tickets/:ticketId/labels', async (c) => {
174
176
  });
175
177
  }
176
178
  catch (error) {
177
- console.error('[Labels] Get ticket labels error:', error);
179
+ log.error('Get ticket labels error', error instanceof Error ? error : new Error(String(error)));
178
180
  return c.json({ error: error instanceof Error ? error.message : 'Failed to get ticket labels' }, 500);
179
181
  }
180
182
  });
@@ -201,7 +203,7 @@ labelsRoutes.put('/tickets/:ticketId/labels', async (c) => {
201
203
  });
202
204
  }
203
205
  catch (error) {
204
- console.error('[Labels] Set ticket labels error:', error);
206
+ log.error('Set ticket labels error', error instanceof Error ? error : new Error(String(error)));
205
207
  return c.json({ error: error instanceof Error ? error.message : 'Failed to set ticket labels' }, 500);
206
208
  }
207
209
  });
@@ -217,7 +219,7 @@ labelsRoutes.post('/tickets/:ticketId/labels/:labelId', async (c) => {
217
219
  return c.json({ success: true });
218
220
  }
219
221
  catch (error) {
220
- console.error('[Labels] Add label to ticket error:', error);
222
+ log.error('Add label to ticket error', error instanceof Error ? error : new Error(String(error)));
221
223
  return c.json({ error: error instanceof Error ? error.message : 'Failed to add label' }, 500);
222
224
  }
223
225
  });
@@ -233,7 +235,7 @@ labelsRoutes.delete('/tickets/:ticketId/labels/:labelId', async (c) => {
233
235
  return c.json({ success: true });
234
236
  }
235
237
  catch (error) {
236
- console.error('[Labels] Remove label from ticket error:', error);
238
+ log.error('Remove label from ticket error', error instanceof Error ? error : new Error(String(error)));
237
239
  return c.json({ error: error instanceof Error ? error.message : 'Failed to remove label' }, 500);
238
240
  }
239
241
  });
@@ -15,7 +15,9 @@ import { createSession } from '../auth/auth-service.js';
15
15
  import { setCookie } from 'hono/cookie';
16
16
  import { hashPassword, validatePasswordStrength } from '../auth/password.js';
17
17
  import { invalidateLocalAdminCache } from '../auth/middleware.js';
18
+ import { createContextualLogger } from '../utils/logger.js';
18
19
  const oobe = new Hono();
20
+ const log = createContextualLogger('OOBE');
19
21
  const COOKIE_OPTIONS = {
20
22
  httpOnly: true,
21
23
  secure: process.env.NODE_ENV === 'production',
@@ -90,7 +92,7 @@ oobe.get('/status', async (c) => {
90
92
  });
91
93
  }
92
94
  catch (error) {
93
- console.error('[OOBE] Status check error:', error);
95
+ log.error('Status check error', error instanceof Error ? error : new Error(String(error)));
94
96
  return c.json({ needsSetup: true, authMode: 'local' });
95
97
  }
96
98
  });
@@ -172,7 +174,7 @@ oobe.post('/setup', async (c) => {
172
174
  setCookie(c, 'profclaw_session', session.token, COOKIE_OPTIONS);
173
175
  // Invalidate cached admin in middleware
174
176
  invalidateLocalAdminCache();
175
- console.log(`[OOBE] Local admin created: ${name}`);
177
+ log.info(`Local admin created: ${name}`);
176
178
  return c.json({
177
179
  success: true,
178
180
  user: {
@@ -184,7 +186,7 @@ oobe.post('/setup', async (c) => {
184
186
  });
185
187
  }
186
188
  catch (error) {
187
- console.error('[OOBE] Setup error:', error);
189
+ log.error('Setup error', error instanceof Error ? error : new Error(String(error)));
188
190
  return c.json({
189
191
  error: 'Setup failed',
190
192
  details: error instanceof Error ? error.message : 'Unknown',
@@ -325,7 +327,7 @@ oobe.post('/validate-ai', async (c) => {
325
327
  return c.json({ valid: false, error: 'API key is required' }, 400);
326
328
  }
327
329
  catch (error) {
328
- console.error('[OOBE] AI validation error:', error);
330
+ log.error('AI validation error', error instanceof Error ? error : new Error(String(error)));
329
331
  return c.json({ valid: false, error: 'Validation failed' }, 500);
330
332
  }
331
333
  });
@@ -390,14 +392,14 @@ oobe.post('/enable-multiuser', async (c) => {
390
392
  });
391
393
  // Invalidate cached admin
392
394
  invalidateLocalAdminCache();
393
- console.log(`[OOBE] Multi-user mode enabled for: ${email}`);
395
+ log.info(`Multi-user mode enabled for: ${email}`);
394
396
  return c.json({
395
397
  success: true,
396
398
  message: 'Multi-user authentication enabled',
397
399
  });
398
400
  }
399
401
  catch (error) {
400
- console.error('[OOBE] Enable multi-user error:', error);
402
+ log.error('Enable multi-user error', error instanceof Error ? error : new Error(String(error)));
401
403
  return c.json({ error: 'Failed to enable multi-user mode' }, 500);
402
404
  }
403
405
  });
@@ -12,7 +12,7 @@ const spec = {
12
12
  title: 'profClaw API',
13
13
  version: '0.1.0',
14
14
  description: 'AI-powered task orchestration, ticket management, and chat system. Supports multi-provider AI (Anthropic, OpenAI, Google, Ollama) with agentic tool execution.',
15
- contact: { name: 'profClaw', url: 'https://profclaw.dev' },
15
+ contact: { name: 'profClaw', url: 'https://profclaw.ai' },
16
16
  license: { name: 'MIT' },
17
17
  },
18
18
  servers: [
@@ -4,6 +4,8 @@
4
4
  * Multi-project support with custom ticket prefixes and sprint management.
5
5
  */
6
6
  import { Hono } from 'hono';
7
+ import { createContextualLogger } from '../utils/logger.js';
8
+ const log = createContextualLogger('Projects');
7
9
  import {
8
10
  // Projects
9
11
  createProject, getProject, getProjectByKey, getProjectWithRelations, updateProject, archiveProject, deleteProject, queryProjects, createProjectExternalLink, getProjectExternalLinks, findProjectByExternalId, getOrCreateDefaultProject, migrateTicketsToDefaultProject,
@@ -67,7 +69,7 @@ projectsRouter.get('/', async (c) => {
67
69
  });
68
70
  }
69
71
  catch (error) {
70
- console.error('[API] Error querying projects:', error);
72
+ log.error('Error querying projects', error instanceof Error ? error : new Error(String(error)));
71
73
  return c.json({ error: 'Failed to query projects' }, 500);
72
74
  }
73
75
  });
@@ -91,7 +93,7 @@ projectsRouter.post('/', async (c) => {
91
93
  }, 201);
92
94
  }
93
95
  catch (error) {
94
- console.error('[API] Error creating project:', error);
96
+ log.error('Error creating project', error instanceof Error ? error : new Error(String(error)));
95
97
  // Check for unique constraint violation
96
98
  if (errorMessageIncludes(error, 'UNIQUE constraint failed') || getErrorCode(error) === 'SQLITE_CONSTRAINT') {
97
99
  return c.json({
@@ -114,7 +116,7 @@ projectsRouter.get('/default', async (c) => {
114
116
  return c.json({ project });
115
117
  }
116
118
  catch (error) {
117
- console.error('[API] Error getting default project:', error);
119
+ log.error('Error getting default project', error instanceof Error ? error : new Error(String(error)));
118
120
  return c.json({ error: 'Failed to get default project' }, 500);
119
121
  }
120
122
  });
@@ -130,7 +132,7 @@ projectsRouter.post('/migrate', async (c) => {
130
132
  });
131
133
  }
132
134
  catch (error) {
133
- console.error('[API] Error migrating tickets:', error);
135
+ log.error('Error migrating tickets', error instanceof Error ? error : new Error(String(error)));
134
136
  return c.json({ error: 'Failed to migrate tickets' }, 500);
135
137
  }
136
138
  });
@@ -147,7 +149,7 @@ projectsRouter.get('/by-key/:key', async (c) => {
147
149
  return c.json({ project });
148
150
  }
149
151
  catch (error) {
150
- console.error('[API] Error getting project by key:', error);
152
+ log.error('Error getting project by key', error instanceof Error ? error : new Error(String(error)));
151
153
  return c.json({ error: 'Failed to get project' }, 500);
152
154
  }
153
155
  });
@@ -165,7 +167,7 @@ projectsRouter.get('/by-external/:platform/:externalId', async (c) => {
165
167
  return c.json({ project });
166
168
  }
167
169
  catch (error) {
168
- console.error('[API] Error finding project by external ID:', error);
170
+ log.error('Error finding project by external ID', error instanceof Error ? error : new Error(String(error)));
169
171
  return c.json({ error: 'Failed to find project' }, 500);
170
172
  }
171
173
  });
@@ -185,7 +187,7 @@ projectsRouter.get('/:id', async (c) => {
185
187
  return c.json({ project });
186
188
  }
187
189
  catch (error) {
188
- console.error('[API] Error getting project:', error);
190
+ log.error('Error getting project', error instanceof Error ? error : new Error(String(error)));
189
191
  return c.json({ error: 'Failed to get project' }, 500);
190
192
  }
191
193
  });
@@ -210,7 +212,7 @@ projectsRouter.patch('/:id', async (c) => {
210
212
  });
211
213
  }
212
214
  catch (error) {
213
- console.error('[API] Error updating project:', error);
215
+ log.error('Error updating project', error instanceof Error ? error : new Error(String(error)));
214
216
  if (errorMessageIncludes(error, 'not found')) {
215
217
  return c.json({ error: 'Project not found' }, 404);
216
218
  }
@@ -233,7 +235,7 @@ projectsRouter.post('/:id/archive', async (c) => {
233
235
  });
234
236
  }
235
237
  catch (error) {
236
- console.error('[API] Error archiving project:', error);
238
+ log.error('Error archiving project', error instanceof Error ? error : new Error(String(error)));
237
239
  if (errorMessageIncludes(error, 'not found')) {
238
240
  return c.json({ error: 'Project not found' }, 404);
239
241
  }
@@ -250,7 +252,7 @@ projectsRouter.delete('/:id', async (c) => {
250
252
  return c.json({ message: 'Project deleted' });
251
253
  }
252
254
  catch (error) {
253
- console.error('[API] Error deleting project:', error);
255
+ log.error('Error deleting project', error instanceof Error ? error : new Error(String(error)));
254
256
  return c.json({ error: 'Failed to delete project' }, 500);
255
257
  }
256
258
  });
@@ -265,7 +267,7 @@ projectsRouter.get('/:id/external-links', async (c) => {
265
267
  return c.json({ externalLinks: links });
266
268
  }
267
269
  catch (error) {
268
- console.error('[API] Error getting external links:', error);
270
+ log.error('Error getting external links', error instanceof Error ? error : new Error(String(error)));
269
271
  return c.json({ error: 'Failed to get external links' }, 500);
270
272
  }
271
273
  });
@@ -290,7 +292,7 @@ projectsRouter.post('/:id/external-links', async (c) => {
290
292
  }, 201);
291
293
  }
292
294
  catch (error) {
293
- console.error('[API] Error creating external link:', error);
295
+ log.error('Error creating external link', error instanceof Error ? error : new Error(String(error)));
294
296
  return c.json({ error: 'Failed to create external link' }, 500);
295
297
  }
296
298
  });
@@ -329,7 +331,7 @@ projectsRouter.get('/:projectId/sprints', async (c) => {
329
331
  });
330
332
  }
331
333
  catch (error) {
332
- console.error('[API] Error querying sprints:', error);
334
+ log.error('Error querying sprints', error instanceof Error ? error : new Error(String(error)));
333
335
  return c.json({ error: 'Failed to query sprints' }, 500);
334
336
  }
335
337
  });
@@ -354,7 +356,7 @@ projectsRouter.post('/:projectId/sprints', async (c) => {
354
356
  }, 201);
355
357
  }
356
358
  catch (error) {
357
- console.error('[API] Error creating sprint:', error);
359
+ log.error('Error creating sprint', error instanceof Error ? error : new Error(String(error)));
358
360
  if (errorMessageIncludes(error, 'not found')) {
359
361
  return c.json({ error: 'Project not found' }, 404);
360
362
  }
@@ -377,7 +379,7 @@ projectsRouter.get('/:projectId/sprints/active', async (c) => {
377
379
  return c.json({ sprint });
378
380
  }
379
381
  catch (error) {
380
- console.error('[API] Error getting active sprint:', error);
382
+ log.error('Error getting active sprint', error instanceof Error ? error : new Error(String(error)));
381
383
  return c.json({ error: 'Failed to get active sprint' }, 500);
382
384
  }
383
385
  });
@@ -397,7 +399,7 @@ projectsRouter.get('/:projectId/sprints/:sprintId', async (c) => {
397
399
  return c.json({ sprint });
398
400
  }
399
401
  catch (error) {
400
- console.error('[API] Error getting sprint:', error);
402
+ log.error('Error getting sprint', error instanceof Error ? error : new Error(String(error)));
401
403
  return c.json({ error: 'Failed to get sprint' }, 500);
402
404
  }
403
405
  });
@@ -422,7 +424,7 @@ projectsRouter.patch('/:projectId/sprints/:sprintId', async (c) => {
422
424
  });
423
425
  }
424
426
  catch (error) {
425
- console.error('[API] Error updating sprint:', error);
427
+ log.error('Error updating sprint', error instanceof Error ? error : new Error(String(error)));
426
428
  if (errorMessageIncludes(error, 'not found')) {
427
429
  return c.json({ error: 'Sprint not found' }, 404);
428
430
  }
@@ -445,7 +447,7 @@ projectsRouter.post('/:projectId/sprints/:sprintId/start', async (c) => {
445
447
  });
446
448
  }
447
449
  catch (error) {
448
- console.error('[API] Error starting sprint:', error);
450
+ log.error('Error starting sprint', error instanceof Error ? error : new Error(String(error)));
449
451
  if (errorMessageIncludes(error, 'not found')) {
450
452
  return c.json({ error: 'Sprint not found' }, 404);
451
453
  }
@@ -468,7 +470,7 @@ projectsRouter.post('/:projectId/sprints/:sprintId/complete', async (c) => {
468
470
  });
469
471
  }
470
472
  catch (error) {
471
- console.error('[API] Error completing sprint:', error);
473
+ log.error('Error completing sprint', error instanceof Error ? error : new Error(String(error)));
472
474
  if (errorMessageIncludes(error, 'not found')) {
473
475
  return c.json({ error: 'Sprint not found' }, 404);
474
476
  }
@@ -491,7 +493,7 @@ projectsRouter.post('/:projectId/sprints/:sprintId/cancel', async (c) => {
491
493
  });
492
494
  }
493
495
  catch (error) {
494
- console.error('[API] Error cancelling sprint:', error);
496
+ log.error('Error cancelling sprint', error instanceof Error ? error : new Error(String(error)));
495
497
  if (errorMessageIncludes(error, 'not found')) {
496
498
  return c.json({ error: 'Sprint not found' }, 404);
497
499
  }
@@ -508,7 +510,7 @@ projectsRouter.delete('/:projectId/sprints/:sprintId', async (c) => {
508
510
  return c.json({ message: 'Sprint deleted' });
509
511
  }
510
512
  catch (error) {
511
- console.error('[API] Error deleting sprint:', error);
513
+ log.error('Error deleting sprint', error instanceof Error ? error : new Error(String(error)));
512
514
  return c.json({ error: 'Failed to delete sprint' }, 500);
513
515
  }
514
516
  });
@@ -523,7 +525,7 @@ projectsRouter.get('/:projectId/sprints/:sprintId/tickets', async (c) => {
523
525
  return c.json({ ticketIds });
524
526
  }
525
527
  catch (error) {
526
- console.error('[API] Error getting sprint tickets:', error);
528
+ log.error('Error getting sprint tickets', error instanceof Error ? error : new Error(String(error)));
527
529
  return c.json({ error: 'Failed to get sprint tickets' }, 500);
528
530
  }
529
531
  });
@@ -548,7 +550,7 @@ projectsRouter.post('/:projectId/sprints/:sprintId/tickets', async (c) => {
548
550
  }, 201);
549
551
  }
550
552
  catch (error) {
551
- console.error('[API] Error adding tickets to sprint:', error);
553
+ log.error('Error adding tickets to sprint', error instanceof Error ? error : new Error(String(error)));
552
554
  if (errorMessageIncludes(error, 'not found')) {
553
555
  return c.json({ error: 'Sprint not found' }, 404);
554
556
  }
@@ -566,7 +568,7 @@ projectsRouter.delete('/:projectId/sprints/:sprintId/tickets/:ticketId', async (
566
568
  return c.json({ message: 'Ticket removed from sprint' });
567
569
  }
568
570
  catch (error) {
569
- console.error('[API] Error removing ticket from sprint:', error);
571
+ log.error('Error removing ticket from sprint', error instanceof Error ? error : new Error(String(error)));
570
572
  return c.json({ error: 'Failed to remove ticket from sprint' }, 500);
571
573
  }
572
574
  });
@@ -584,7 +586,7 @@ projectsRouter.put('/:projectId/sprints/:sprintId/tickets/reorder', async (c) =>
584
586
  return c.json({ message: 'Tickets reordered' });
585
587
  }
586
588
  catch (error) {
587
- console.error('[API] Error reordering sprint tickets:', error);
589
+ log.error('Error reordering sprint tickets', error instanceof Error ? error : new Error(String(error)));
588
590
  return c.json({ error: 'Failed to reorder tickets' }, 500);
589
591
  }
590
592
  });
@@ -1,4 +1,6 @@
1
1
  import { Hono } from 'hono';
2
+ import { createContextualLogger } from '../utils/logger.js';
3
+ const log = createContextualLogger('Settings');
2
4
  import { getSettings, updateSettings, resetSettings, UpdateSettingsSchema, getPluginHealth, togglePlugin, } from '../settings/index.js';
3
5
  const settings = new Hono();
4
6
  async function parseJsonBody(c) {
@@ -26,7 +28,7 @@ settings.get('/', async (c) => {
26
28
  return c.json({ settings: currentSettings });
27
29
  }
28
30
  catch (error) {
29
- console.error('[API] Error fetching settings:', error);
31
+ log.error('Error fetching settings', error instanceof Error ? error : new Error(String(error)));
30
32
  return c.json({
31
33
  error: 'Failed to fetch settings',
32
34
  message: error instanceof Error ? error.message : 'Unknown error',
@@ -54,7 +56,7 @@ settings.patch('/', async (c) => {
54
56
  });
55
57
  }
56
58
  catch (error) {
57
- console.error('[API] Error updating settings:', error);
59
+ log.error('Error updating settings', error instanceof Error ? error : new Error(String(error)));
58
60
  return c.json({
59
61
  error: 'Failed to update settings',
60
62
  message: error instanceof Error ? error.message : 'Unknown error',
@@ -71,7 +73,7 @@ settings.post('/reset', async (c) => {
71
73
  });
72
74
  }
73
75
  catch (error) {
74
- console.error('[API] Error resetting settings:', error);
76
+ log.error('Error resetting settings', error instanceof Error ? error : new Error(String(error)));
75
77
  return c.json({
76
78
  error: 'Failed to reset settings',
77
79
  message: error instanceof Error ? error.message : 'Unknown error',
@@ -85,7 +87,7 @@ settings.get('/plugins/health', async (c) => {
85
87
  return c.json({ plugins: health });
86
88
  }
87
89
  catch (error) {
88
- console.error('[API] Error checking plugin health:', error);
90
+ log.error('Error checking plugin health', error instanceof Error ? error : new Error(String(error)));
89
91
  return c.json({
90
92
  error: 'Failed to check plugin health',
91
93
  message: error instanceof Error ? error.message : 'Unknown error',
@@ -108,7 +110,7 @@ settings.post('/plugins/:id/toggle', async (c) => {
108
110
  });
109
111
  }
110
112
  catch (error) {
111
- console.error('[API] Error toggling plugin:', error);
113
+ log.error('Error toggling plugin', error instanceof Error ? error : new Error(String(error)));
112
114
  return c.json({
113
115
  error: 'Failed to toggle plugin',
114
116
  message: error instanceof Error ? error.message : 'Unknown error',
@@ -6,6 +6,8 @@
6
6
  * first-time setup and configuration checks.
7
7
  */
8
8
  import { Hono } from 'hono';
9
+ import { createContextualLogger } from '../utils/logger.js';
10
+ const log = createContextualLogger('Setup');
9
11
  import { randomUUID, randomBytes } from 'crypto';
10
12
  import { eq } from 'drizzle-orm';
11
13
  import { z } from 'zod';
@@ -103,7 +105,7 @@ setup.get('/status', async (c) => {
103
105
  });
104
106
  }
105
107
  catch (error) {
106
- console.error('[Setup] Status check error:', error);
108
+ log.error('Status check error', error instanceof Error ? error : new Error(String(error)));
107
109
  return c.json({
108
110
  configured: false,
109
111
  isFirstTimeSetup: true,
@@ -202,7 +204,7 @@ setup.post('/github-oauth/validate', async (c) => {
202
204
  }
203
205
  catch (fetchError) {
204
206
  // If GitHub API is unreachable, fall back to format validation only
205
- console.warn('[Setup] Could not verify credentials with GitHub API:', fetchError);
207
+ log.warn('Could not verify credentials with GitHub API', { error: fetchError instanceof Error ? fetchError.message : String(fetchError) });
206
208
  return c.json({
207
209
  valid: true,
208
210
  message: 'Credentials format is valid. Could not verify with GitHub API.',
@@ -212,7 +214,7 @@ setup.post('/github-oauth/validate', async (c) => {
212
214
  }
213
215
  }
214
216
  catch (error) {
215
- console.error('[Setup] GitHub OAuth validation error:', error);
217
+ log.error('GitHub OAuth validation error', error instanceof Error ? error : new Error(String(error)));
216
218
  return c.json({
217
219
  valid: false,
218
220
  error: 'Validation failed',
@@ -252,14 +254,14 @@ setup.post('/github-oauth', async (c) => {
252
254
  },
253
255
  },
254
256
  });
255
- console.log('[Setup] GitHub OAuth credentials saved to database');
257
+ log.info('GitHub OAuth credentials saved to database');
256
258
  return c.json({
257
259
  success: true,
258
260
  message: 'GitHub OAuth configured successfully.',
259
261
  });
260
262
  }
261
263
  catch (error) {
262
- console.error('[Setup] GitHub OAuth setup error:', error);
264
+ log.error('GitHub OAuth setup error', error instanceof Error ? error : new Error(String(error)));
263
265
  return c.json({ error: 'Failed to configure GitHub OAuth' }, 500);
264
266
  }
265
267
  });
@@ -328,7 +330,7 @@ setup.post('/admin', adminCreateLimiter, async (c) => {
328
330
  });
329
331
  // Create session
330
332
  const session = await createSession(userId);
331
- console.log(`[Setup] Admin user created: ${email}`);
333
+ log.info('Admin user created', { email });
332
334
  return c.json({
333
335
  success: true,
334
336
  user: {
@@ -347,8 +349,7 @@ setup.post('/admin', adminCreateLimiter, async (c) => {
347
349
  });
348
350
  }
349
351
  catch (error) {
350
- console.error('[Setup] Admin creation error:', error);
351
- console.error('[Setup] Error stack:', error instanceof Error ? error.stack : 'No stack');
352
+ log.error('Admin creation error', error instanceof Error ? error : new Error(String(error)));
352
353
  return c.json({
353
354
  error: 'Failed to create admin user',
354
355
  details: error instanceof Error ? error.message : String(error)
@@ -419,7 +420,7 @@ setup.post('/verify-recovery-code', recoveryLimiter, async (c) => {
419
420
  });
420
421
  }
421
422
  catch (error) {
422
- console.error('[Setup] Recovery code verification error:', error);
423
+ log.error('Recovery code verification error', error instanceof Error ? error : new Error(String(error)));
423
424
  return c.json({ error: 'Failed to verify recovery code' }, 500);
424
425
  }
425
426
  });
@@ -472,14 +473,14 @@ setup.post('/reset-password', resetLimiter, async (c) => {
472
473
  updatedAt: new Date(),
473
474
  })
474
475
  .where(eq(users.id, user.id));
475
- console.log(`[Setup] Password reset for user: ${user.email}`);
476
+ log.info('Password reset for user', { email: user.email });
476
477
  return c.json({
477
478
  success: true,
478
479
  message: 'Password has been reset successfully. You can now sign in.',
479
480
  });
480
481
  }
481
482
  catch (error) {
482
- console.error('[Setup] Password reset error:', error);
483
+ log.error('Password reset error', error instanceof Error ? error : new Error(String(error)));
483
484
  return c.json({ error: 'Failed to reset password' }, 500);
484
485
  }
485
486
  });