@lovelybunch/api 1.0.75-alpha.8 → 1.0.75

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 (188) hide show
  1. package/dist/lib/jobs/job-runner.js +10 -2
  2. package/dist/lib/jobs/job-scheduler.js +21 -0
  3. package/dist/lib/mail/mail-runner.d.ts +51 -0
  4. package/dist/lib/mail/mail-runner.js +342 -0
  5. package/dist/lib/slack/slack-service.d.ts +2 -0
  6. package/dist/lib/slack/slack-service.js +3 -0
  7. package/dist/lib/storage/file-storage.d.ts +16 -16
  8. package/dist/lib/storage/file-storage.js +59 -64
  9. package/dist/lib/terminal/terminal-manager.d.ts +3 -5
  10. package/dist/lib/terminal/terminal-manager.js +10 -61
  11. package/dist/routes/api/v1/ai/route.js +361 -20
  12. package/dist/routes/api/v1/chats/[id]/index.js +2 -1
  13. package/dist/routes/api/v1/chats/[id]/route.d.ts +7 -0
  14. package/dist/routes/api/v1/chats/[id]/route.js +30 -1
  15. package/dist/routes/api/v1/context/index.js +0 -2
  16. package/dist/routes/api/v1/git/index.js +23 -0
  17. package/dist/routes/api/v1/knowledge/[filename]/index.d.ts +1 -0
  18. package/dist/routes/api/v1/knowledge/[filename]/index.js +1 -0
  19. package/dist/routes/api/v1/knowledge/[filename]/route.d.ts +3 -0
  20. package/dist/routes/api/v1/knowledge/[filename]/route.js +254 -0
  21. package/dist/routes/api/v1/knowledge/index.d.ts +1 -0
  22. package/dist/routes/api/v1/knowledge/index.js +1 -0
  23. package/dist/routes/api/v1/knowledge/route.d.ts +3 -0
  24. package/dist/routes/api/v1/knowledge/route.js +176 -0
  25. package/dist/routes/api/v1/mail/index.d.ts +3 -0
  26. package/dist/routes/api/v1/mail/index.js +23 -0
  27. package/dist/routes/api/v1/mail/route.d.ts +294 -0
  28. package/dist/routes/api/v1/mail/route.js +344 -0
  29. package/dist/routes/api/v1/mcp/index.js +109 -34
  30. package/dist/routes/api/v1/slack/index.d.ts +3 -0
  31. package/dist/routes/api/v1/slack/index.js +15 -0
  32. package/dist/routes/api/v1/slack/route.d.ts +124 -0
  33. package/dist/routes/api/v1/slack/route.js +192 -0
  34. package/dist/routes/api/v1/tasks/[id]/route.d.ts +117 -0
  35. package/dist/routes/api/v1/tasks/[id]/route.js +166 -0
  36. package/dist/routes/api/v1/tasks/index.d.ts +3 -0
  37. package/dist/routes/api/v1/tasks/index.js +10 -0
  38. package/dist/routes/api/v1/tasks/route.d.ts +96 -0
  39. package/dist/routes/api/v1/tasks/route.js +136 -0
  40. package/dist/routes/api/v1/terminal/[proposalId]/create/route.js +2 -2
  41. package/dist/routes/api/v1/terminal/[taskId]/create/index.d.ts +3 -0
  42. package/dist/routes/api/v1/terminal/[taskId]/create/index.js +5 -0
  43. package/dist/routes/api/v1/terminal/[taskId]/create/route.d.ts +10 -0
  44. package/dist/routes/api/v1/terminal/[taskId]/create/route.js +27 -0
  45. package/dist/routes/api/v1/terminal/[taskId]/destroy/index.d.ts +3 -0
  46. package/dist/routes/api/v1/terminal/[taskId]/destroy/index.js +5 -0
  47. package/dist/routes/api/v1/terminal/[taskId]/destroy/route.d.ts +10 -0
  48. package/dist/routes/api/v1/terminal/[taskId]/destroy/route.js +21 -0
  49. package/dist/routes/api/v1/terminal/[taskId]/resize/index.d.ts +3 -0
  50. package/dist/routes/api/v1/terminal/[taskId]/resize/index.js +5 -0
  51. package/dist/routes/api/v1/terminal/[taskId]/resize/route.d.ts +10 -0
  52. package/dist/routes/api/v1/terminal/[taskId]/resize/route.js +21 -0
  53. package/dist/routes/api/v1/terminal/sessions/route.js +4 -4
  54. package/dist/server-with-static.js +14 -8
  55. package/dist/server.js +14 -8
  56. package/package.json +4 -4
  57. package/static/assets/{ActivityPage-DSSML9J-.js → ActivityPage-k4I7Q53O.js} +1 -1
  58. package/static/assets/ApiKeysSettingsPage-B1YvVdmg.js +2 -0
  59. package/static/assets/{ArchitectureEditPage-CIjqkpMz.js → ArchitectureEditPage-CpowsIx2.js} +1 -1
  60. package/static/assets/{ArchitecturePage-Db__w054.js → ArchitecturePage-DYxC_aMR.js} +1 -1
  61. package/static/assets/{AuthSettingsPage-Bpooi8Z0.js → AuthSettingsPage-DtSo78Y_.js} +2 -2
  62. package/static/assets/{CallbackPage-BGLKeyjv.js → CallbackPage-bROCGapx.js} +1 -1
  63. package/static/assets/CodePage-CPCj64rX.js +2 -0
  64. package/static/assets/{CollapsibleSection-B6RO5o5R.js → CollapsibleSection-M5cXbl92.js} +1 -1
  65. package/static/assets/DashboardPage-B9BZZfw6.js +51 -0
  66. package/static/assets/{GitPage-DxjLaRWe.js → GitPage-BiDtdSK1.js} +2 -2
  67. package/static/assets/GitSettingsPage-THm6wDjs.js +6 -0
  68. package/static/assets/IdentityPage-BC16skg6.js +6 -0
  69. package/static/assets/{ImplementationStepsEditor-DWjDyZzP.js → ImplementationStepsEditor-HliLQav5.js} +2 -2
  70. package/static/assets/IntegrationsSettingsPage-CC_VKIQa.js +1 -0
  71. package/static/assets/JobDetailPage-z1QQYvmU.js +1 -0
  72. package/static/assets/KnowledgeDetailPage-DzHXBS7Q.js +1 -0
  73. package/static/assets/KnowledgeEditPage-BwGnUH_m.js +1 -0
  74. package/static/assets/KnowledgePage-CGIVMS02.js +3 -0
  75. package/static/assets/{LoginPage-DptfKsWo.js → LoginPage-VQ3lcfLV.js} +1 -1
  76. package/static/assets/MailInboxPage-DiZKqwdU.js +1 -0
  77. package/static/assets/MailProcessingModal-DIeSQBoR.js +6 -0
  78. package/static/assets/MailReadPage-C8AACmZQ.js +1 -0
  79. package/static/assets/MailSentPage-C_5yFly_.js +1 -0
  80. package/static/assets/McpSettingsPage-i9YHcu1s.js +1 -0
  81. package/static/assets/NewKnowledgePage-BnVY7WUD.js +9 -0
  82. package/static/assets/{NewSkillPage-Cwy2MSr9.js → NewSkillPage-DwniHD6D.js} +1 -1
  83. package/static/assets/NewTaskPage-F5UX2WMc.js +90 -0
  84. package/static/assets/NotFoundPage-BbSZX_4L.js +6 -0
  85. package/static/assets/NotificationsSettingsPage-C8kjcift.js +1 -0
  86. package/static/assets/ProjectEditPage-DUUlIEqI.js +11 -0
  87. package/static/assets/{ProjectPage-DgUr4bVU.js → ProjectPage-Unz9PQpA.js} +1 -1
  88. package/static/assets/PromptsSettingsPage-DVpIuRKI.js +1 -0
  89. package/static/assets/ResourceDetailPage-DqHZ2KYD.js +1 -0
  90. package/static/assets/ResourcesPage-BP5tuAi-.js +41 -0
  91. package/static/assets/RoleEditPage-BgKu8S0-.js +13 -0
  92. package/static/assets/{RolePage-Sc-GFiL2.js → RolePage-Fed52Ov5.js} +1 -1
  93. package/static/assets/{RulesSettingsPage-DdMCzh9j.js → RulesSettingsPage-BQ2O0u66.js} +2 -2
  94. package/static/assets/SchedulePage-jkxjuzBx.js +4 -0
  95. package/static/assets/SkillDetailPage-k3Q2-NFd.js +1 -0
  96. package/static/assets/{SkillEditPage-BDd2CtAS.js → SkillEditPage-urF4snjo.js} +1 -1
  97. package/static/assets/SkillsPage-DlWDhEjR.js +8 -0
  98. package/static/assets/{SkillsSettingsPage-1N0JQOYc.js → SkillsSettingsPage-BViFgckG.js} +1 -1
  99. package/static/assets/SourceInput-CAFKTHw-.js +1 -0
  100. package/static/assets/{TagInput-D_SdcypZ.js → TagInput-C6lI-ePr.js} +1 -1
  101. package/static/assets/TaskDetailPage-DpbRHnW_.js +16 -0
  102. package/static/assets/TaskEditPage-DssRbW0h.js +1 -0
  103. package/static/assets/TasksPage-CD_eo0Bj.js +17 -0
  104. package/static/assets/TerminalPage-BG_wlccr.js +1 -0
  105. package/static/assets/TerminalSessionPage-CsK-LznK.js +8 -0
  106. package/static/assets/UserPreferencesPage-CWUq3efu.js +1 -0
  107. package/static/assets/UserSettingsPage-CduI_MGS.js +1 -0
  108. package/static/assets/UtilitiesPage-BAxokhLh.js +1 -0
  109. package/static/assets/{alert-BD5jo3SI.js → alert-BXsc6_qu.js} +1 -1
  110. package/static/assets/{arrow-down-BxcoVp6S.js → arrow-down-DmW_3gE8.js} +1 -1
  111. package/static/assets/{arrow-left-CdM_IPng.js → arrow-left-1S-835kP.js} +1 -1
  112. package/static/assets/{arrow-up-BOJ6ob9X.js → arrow-up-BYism_o1.js} +1 -1
  113. package/static/assets/arrow-up-down-Dw3J0a4i.js +6 -0
  114. package/static/assets/{badge-DEiQk9C9.js → badge-BUEY53dV.js} +1 -1
  115. package/static/assets/{browser-modal-Dp1eMxt6.js → browser-modal-DCNdI4NT.js} +2 -2
  116. package/static/assets/{card-BCFxXzRk.js → card-BcPlIAH5.js} +1 -1
  117. package/static/assets/{chevron-left-C25izNzZ.js → chevron-left-FMmNe7yP.js} +1 -1
  118. package/static/assets/{plus-iamYJu5V.js → chevron-up-CqM3won3.js} +2 -2
  119. package/static/assets/{chevrons-up-DqbWMOjv.js → chevrons-up-DTvCkIHc.js} +1 -1
  120. package/static/assets/{circle-alert-CMRMPnbY.js → circle-alert-dseM-Ib7.js} +1 -1
  121. package/static/assets/{circle-check-big-NI18oHuP.js → circle-check-big-jKg34xC-.js} +1 -1
  122. package/static/assets/{circle-check-D5wZZPvj.js → circle-check-eyo6pBP1.js} +1 -1
  123. package/static/assets/{circle-play-BhVU869u.js → circle-play-BrY_lNiH.js} +1 -1
  124. package/static/assets/{circle-x-BXDB-G_q.js → circle-x-uqmzEce1.js} +1 -1
  125. package/static/assets/{clipboard-DC2xmNVx.js → clipboard-tzPFoieb.js} +1 -1
  126. package/static/assets/{clock-CeCp7Pz1.js → clock-Bjc06QBM.js} +1 -1
  127. package/static/assets/code-DrYqPukx.js +6 -0
  128. package/static/assets/{download-ZF_XbTIA.js → download-Bg__QCLT.js} +1 -1
  129. package/static/assets/{external-link-CYBz87-P.js → external-link-CNDy2UUo.js} +1 -1
  130. package/static/assets/{eye-BT8MAvKY.js → eye-DLFBnC8t.js} +1 -1
  131. package/static/assets/{folder-git-2-BE9AIPnj.js → folder-git-2-DUqd0WRi.js} +1 -1
  132. package/static/assets/index-CHdBxVyk.css +2 -0
  133. package/static/assets/index-DFcWlnzl.js +487 -0
  134. package/static/assets/{info-DunFSp-x.js → info-D6jxZC5X.js} +1 -1
  135. package/static/assets/kiro-CX1mOsRO.js +17 -0
  136. package/static/assets/{label-vYhfrPMD.js → label-DBuh-ke5.js} +1 -1
  137. package/static/assets/{markdown-editor-BzZ8tCto.js → markdown-editor-B4YNQFT2.js} +1 -1
  138. package/static/assets/message-square-B5RWz_ff.js +6 -0
  139. package/static/assets/paperclip-4A_3MaPx.js +6 -0
  140. package/static/assets/{pause-BHonpdnw.js → pause-BzhKXHtR.js} +1 -1
  141. package/static/assets/{play-CCo7tau2.js → play-CHIf-Rcz.js} +1 -1
  142. package/static/assets/{radio-group-Db-pBuyW.js → radio-group-C1ct-VsJ.js} +1 -1
  143. package/static/assets/{refresh-cw-Bg7vQzOw.js → refresh-cw-B3OwrDUf.js} +1 -1
  144. package/static/assets/{search-CH2zaibZ.js → search-Cq1ksEdp.js} +1 -1
  145. package/static/assets/select-44mcS2_G.js +1 -0
  146. package/static/assets/{status-utils-BDOyevaX.js → status-utils-CDkPeVfP.js} +1 -1
  147. package/static/assets/{switch-CH-VOgPo.js → switch-CIwjYvCt.js} +1 -1
  148. package/static/assets/{tabs-XeRAjZYR.js → tabs-DTV6Su-h.js} +1 -1
  149. package/static/assets/{tag-CRP5nL5-.js → tag-p6yeowCW.js} +1 -1
  150. package/static/assets/{terminal-preview-DMJMuORo.js → terminal-preview-DN38x9Jm.js} +1 -1
  151. package/static/assets/use-terminal-BXJqOeJe.js +1 -0
  152. package/static/assets/video-BH5ChaoS.js +36 -0
  153. package/static/index.html +2 -2
  154. package/static/assets/ApiKeysSettingsPage-Chw9PNL5.js +0 -2
  155. package/static/assets/CodePage-CrokcH-S.js +0 -2
  156. package/static/assets/DashboardPage-BaSQQ8Nv.js +0 -41
  157. package/static/assets/GitSettingsPage-tKBXYAFm.js +0 -6
  158. package/static/assets/IdentityPage-D2yBjeYn.js +0 -11
  159. package/static/assets/IntegrationsSettingsPage-Bx8-0Ig4.js +0 -1
  160. package/static/assets/JobDetailPage-BQmTHled.js +0 -1
  161. package/static/assets/KnowledgeDetailPage-QMU2bC3L.js +0 -1
  162. package/static/assets/KnowledgeEditPage-DbMJVcLc.js +0 -1
  163. package/static/assets/KnowledgePage-aU1GxZSZ.js +0 -8
  164. package/static/assets/McpSettingsPage-C3WxFwRB.js +0 -1
  165. package/static/assets/NewKnowledgePage-Cbiswrw_.js +0 -9
  166. package/static/assets/NewProposalPage-B_sDMBTK.js +0 -90
  167. package/static/assets/ProjectEditPage-BznWiBBc.js +0 -11
  168. package/static/assets/PromptsSettingsPage-CY0-870a.js +0 -1
  169. package/static/assets/ProposalDetailPage-K4iMXHEg.js +0 -1
  170. package/static/assets/ProposalEditPage-jZOtCMqP.js +0 -1
  171. package/static/assets/ProposalsPage-C7n4-G05.js +0 -17
  172. package/static/assets/ResourcesPage-vB5-XkUv.js +0 -71
  173. package/static/assets/RoleEditPage-Cu7ZB3yj.js +0 -13
  174. package/static/assets/SchedulePage-Bkkf2wA0.js +0 -4
  175. package/static/assets/SkillDetailPage-5sDxf3Of.js +0 -1
  176. package/static/assets/SkillsPage-D2G7EfK8.js +0 -8
  177. package/static/assets/SourceInput-DlC0zwva.js +0 -1
  178. package/static/assets/TerminalPage--KZ7azvP.js +0 -1
  179. package/static/assets/TerminalSessionPage-ClvxK9ia.js +0 -13
  180. package/static/assets/UserPreferencesPage-CheOH7jZ.js +0 -1
  181. package/static/assets/UserSettingsPage-C8STDvfQ.js +0 -1
  182. package/static/assets/UtilitiesPage-9rTxR2md.js +0 -1
  183. package/static/assets/calendar-Cx5r9R7A.js +0 -6
  184. package/static/assets/droid-DqWsM2dp.js +0 -17
  185. package/static/assets/index-DVTgTsDa.css +0 -2
  186. package/static/assets/index-hqVgTgRB.js +0 -462
  187. package/static/assets/use-terminal-DuGZuvd2.js +0 -1
  188. package/static/assets/zap-BlzMp7dY.js +0 -6
@@ -0,0 +1,117 @@
1
+ import { Context } from 'hono';
2
+ export declare function GET(c: Context): Promise<(Response & import("hono").TypedResponse<{
3
+ success: false;
4
+ error: {
5
+ code: string;
6
+ message: string;
7
+ };
8
+ }, 404, "json">) | (Response & import("hono").TypedResponse<{
9
+ success: true;
10
+ data: {
11
+ id: string;
12
+ title: string;
13
+ intent?: string;
14
+ content?: string;
15
+ author: {
16
+ type: import("@lovelybunch/core").AuthorType;
17
+ id: string;
18
+ name: string;
19
+ email?: string;
20
+ };
21
+ productSpecRef?: string;
22
+ planSteps: {
23
+ id: string;
24
+ description: string;
25
+ command?: string;
26
+ expectedOutcome?: string;
27
+ status: "pending" | "in-progress" | "completed" | "failed";
28
+ output?: string;
29
+ error?: string;
30
+ executedAt?: string;
31
+ }[];
32
+ status: import("@lovelybunch/core").TaskStatus;
33
+ comments?: {
34
+ id: string;
35
+ author: string;
36
+ content: string;
37
+ createdAt: string;
38
+ }[];
39
+ metadata: {
40
+ createdAt: string;
41
+ updatedAt: string;
42
+ reviewers: string[];
43
+ tags?: string[];
44
+ priority?: "low" | "medium" | "high" | "critical";
45
+ readiness?: number;
46
+ };
47
+ };
48
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
49
+ success: false;
50
+ error: {
51
+ code: string;
52
+ message: any;
53
+ };
54
+ }, 500, "json">)>;
55
+ export declare function PATCH(c: Context): Promise<(Response & import("hono").TypedResponse<{
56
+ success: true;
57
+ data: {
58
+ id: string;
59
+ title: string;
60
+ intent?: string;
61
+ content?: string;
62
+ author: {
63
+ type: import("@lovelybunch/core").AuthorType;
64
+ id: string;
65
+ name: string;
66
+ email?: string;
67
+ };
68
+ productSpecRef?: string;
69
+ planSteps: {
70
+ id: string;
71
+ description: string;
72
+ command?: string;
73
+ expectedOutcome?: string;
74
+ status: "pending" | "in-progress" | "completed" | "failed";
75
+ output?: string;
76
+ error?: string;
77
+ executedAt?: string;
78
+ }[];
79
+ status: import("@lovelybunch/core").TaskStatus;
80
+ comments?: {
81
+ id: string;
82
+ author: string;
83
+ content: string;
84
+ createdAt: string;
85
+ }[];
86
+ metadata: {
87
+ createdAt: string;
88
+ updatedAt: string;
89
+ reviewers: string[];
90
+ tags?: string[];
91
+ priority?: "low" | "medium" | "high" | "critical";
92
+ readiness?: number;
93
+ };
94
+ };
95
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
96
+ success: false;
97
+ error: {
98
+ code: string;
99
+ message: any;
100
+ };
101
+ }, 404, "json">) | (Response & import("hono").TypedResponse<{
102
+ success: false;
103
+ error: {
104
+ code: string;
105
+ message: any;
106
+ };
107
+ }, 500, "json">)>;
108
+ export declare function DELETE(c: Context): Promise<(Response & import("hono").TypedResponse<{
109
+ success: true;
110
+ message: string;
111
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
112
+ success: false;
113
+ error: {
114
+ code: string;
115
+ message: any;
116
+ };
117
+ }, 500, "json">)>;
@@ -0,0 +1,166 @@
1
+ import { FileStorageAdapter } from '../../../../../lib/storage/file-storage.js';
2
+ import { getLogger } from '@lovelybunch/core/logging';
3
+ const storage = new FileStorageAdapter();
4
+ // Logger is lazily initialized inside handlers to use server config
5
+ export async function GET(c) {
6
+ try {
7
+ const id = c.req.param('id');
8
+ const task = await storage.getTask(id);
9
+ if (!task) {
10
+ return c.json({
11
+ success: false,
12
+ error: {
13
+ code: 'TASK_NOT_FOUND',
14
+ message: `Task with id ${id} not found`
15
+ }
16
+ }, 404);
17
+ }
18
+ return c.json({
19
+ success: true,
20
+ data: task
21
+ });
22
+ }
23
+ catch (error) {
24
+ console.error('Error getting task:', error);
25
+ return c.json({
26
+ success: false,
27
+ error: {
28
+ code: 'GET_TASK_ERROR',
29
+ message: error.message
30
+ }
31
+ }, 500);
32
+ }
33
+ }
34
+ export async function PATCH(c) {
35
+ try {
36
+ const id = c.req.param('id');
37
+ const updates = await c.req.json();
38
+ // Get existing task to merge updates properly
39
+ const existing = await storage.getTask(id);
40
+ if (!existing) {
41
+ return c.json({
42
+ success: false,
43
+ error: {
44
+ code: 'TASK_NOT_FOUND',
45
+ message: `Task with id ${id} not found`
46
+ }
47
+ }, 404);
48
+ }
49
+ // Handle special fields like comments
50
+ let finalUpdates = { ...updates };
51
+ if (updates.comments) {
52
+ finalUpdates = { ...finalUpdates, comments: updates.comments };
53
+ }
54
+ await storage.updateTask(id, finalUpdates);
55
+ // Fetch the updated task
56
+ const updatedTask = await storage.getTask(id);
57
+ // Determine what changed
58
+ const changedFields = Object.keys(updates);
59
+ const oldStatus = existing.status;
60
+ const newStatus = updatedTask?.status || existing.status;
61
+ // Log task.update event
62
+ const logger = getLogger();
63
+ logger.log({
64
+ kind: 'task.update',
65
+ actor: updatedTask?.author.type === 'agent'
66
+ ? `agent:${updatedTask.author.name}`
67
+ : `human:${updatedTask?.author.email || 'unknown'}`,
68
+ subject: `task:${id}`,
69
+ tags: ['task'],
70
+ payload: {
71
+ id,
72
+ changes: changedFields,
73
+ oldStatus,
74
+ newStatus
75
+ }
76
+ });
77
+ // If status changed, also log a status.change event
78
+ if (oldStatus !== newStatus) {
79
+ logger.log({
80
+ kind: 'task.status.change',
81
+ actor: updatedTask?.author.type === 'agent'
82
+ ? `agent:${updatedTask.author.name}`
83
+ : `human:${updatedTask?.author.email || 'unknown'}`,
84
+ subject: `task:${id}`,
85
+ tags: ['task', 'status'],
86
+ payload: {
87
+ id,
88
+ from: oldStatus,
89
+ to: newStatus,
90
+ reason: null
91
+ }
92
+ });
93
+ // Send Slack notification for status change (non-blocking)
94
+ import('../../../../../lib/slack/slack-service.js').then(({ getSlackService }) => {
95
+ getSlackService().sendNotification({
96
+ type: 'proposal.statusChange',
97
+ proposalId: id,
98
+ intent: updatedTask?.title || existing.title || '',
99
+ status: newStatus,
100
+ previousStatus: oldStatus,
101
+ }).catch(err => console.warn('[tasks] Slack notification failed:', err));
102
+ }).catch(() => { });
103
+ }
104
+ return c.json({
105
+ success: true,
106
+ data: updatedTask
107
+ });
108
+ }
109
+ catch (error) {
110
+ console.error('Error updating task:', error);
111
+ if (error.message.includes('not found')) {
112
+ return c.json({
113
+ success: false,
114
+ error: {
115
+ code: 'TASK_NOT_FOUND',
116
+ message: error.message
117
+ }
118
+ }, 404);
119
+ }
120
+ return c.json({
121
+ success: false,
122
+ error: {
123
+ code: 'UPDATE_TASK_ERROR',
124
+ message: error.message
125
+ }
126
+ }, 500);
127
+ }
128
+ }
129
+ export async function DELETE(c) {
130
+ try {
131
+ const id = c.req.param('id');
132
+ // Get task info before deleting
133
+ const task = await storage.getTask(id);
134
+ await storage.deleteTask(id);
135
+ // Log the deletion event
136
+ if (task) {
137
+ const logger = getLogger();
138
+ logger.log({
139
+ kind: 'task.delete',
140
+ actor: task.author.type === 'agent'
141
+ ? `agent:${task.author.name}`
142
+ : `human:${task.author.email || 'unknown'}`,
143
+ subject: `task:${id}`,
144
+ tags: ['task'],
145
+ payload: {
146
+ id,
147
+ title: task.title
148
+ }
149
+ });
150
+ }
151
+ return c.json({
152
+ success: true,
153
+ message: `Task ${id} deleted successfully`
154
+ });
155
+ }
156
+ catch (error) {
157
+ console.error('Error deleting task:', error);
158
+ return c.json({
159
+ success: false,
160
+ error: {
161
+ code: 'DELETE_TASK_ERROR',
162
+ message: error.message
163
+ }
164
+ }, 500);
165
+ }
166
+ }
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ declare const tasks: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export default tasks;
@@ -0,0 +1,10 @@
1
+ import { Hono } from 'hono';
2
+ import { GET, POST } from './route.js';
3
+ import { GET as getTask, PATCH as patchTask, DELETE as deleteTask } from './[id]/route.js';
4
+ const tasks = new Hono();
5
+ tasks.get('/', GET);
6
+ tasks.post('/', POST);
7
+ tasks.get('/:id', getTask);
8
+ tasks.patch('/:id', patchTask);
9
+ tasks.delete('/:id', deleteTask);
10
+ export default tasks;
@@ -0,0 +1,96 @@
1
+ import { Context } from 'hono';
2
+ export declare function GET(c: Context): Promise<(Response & import("hono").TypedResponse<{
3
+ totalCount: number;
4
+ success: true;
5
+ data: {
6
+ id: string;
7
+ title: string;
8
+ intent?: string;
9
+ content?: string;
10
+ author: {
11
+ type: import("@lovelybunch/types").AuthorType;
12
+ id: string;
13
+ name: string;
14
+ email?: string;
15
+ };
16
+ productSpecRef?: string;
17
+ planSteps: {
18
+ id: string;
19
+ description: string;
20
+ command?: string;
21
+ expectedOutcome?: string;
22
+ status: "pending" | "in-progress" | "completed" | "failed";
23
+ output?: string;
24
+ error?: string;
25
+ executedAt?: string;
26
+ }[];
27
+ status: import("@lovelybunch/types").TaskStatus;
28
+ comments?: {
29
+ id: string;
30
+ author: string;
31
+ content: string;
32
+ createdAt: string;
33
+ }[];
34
+ metadata: {
35
+ createdAt: string;
36
+ updatedAt: string;
37
+ reviewers: string[];
38
+ tags?: string[];
39
+ priority?: "low" | "medium" | "high" | "critical";
40
+ readiness?: number;
41
+ };
42
+ }[];
43
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
44
+ success: false;
45
+ error: {
46
+ code: string;
47
+ message: any;
48
+ };
49
+ }, 500, "json">)>;
50
+ export declare function POST(c: Context): Promise<(Response & import("hono").TypedResponse<{
51
+ success: true;
52
+ data: {
53
+ id: string;
54
+ title: string;
55
+ intent?: string;
56
+ content?: string;
57
+ author: {
58
+ type: import("@lovelybunch/types").AuthorType;
59
+ id: string;
60
+ name: string;
61
+ email?: string;
62
+ };
63
+ productSpecRef?: string;
64
+ planSteps: {
65
+ id: string;
66
+ description: string;
67
+ command?: string;
68
+ expectedOutcome?: string;
69
+ status: "pending" | "in-progress" | "completed" | "failed";
70
+ output?: string;
71
+ error?: string;
72
+ executedAt?: string;
73
+ }[];
74
+ status: import("@lovelybunch/types").TaskStatus;
75
+ comments?: {
76
+ id: string;
77
+ author: string;
78
+ content: string;
79
+ createdAt: string;
80
+ }[];
81
+ metadata: {
82
+ createdAt: string;
83
+ updatedAt: string;
84
+ reviewers: string[];
85
+ tags?: string[];
86
+ priority?: "low" | "medium" | "high" | "critical";
87
+ readiness?: number;
88
+ };
89
+ };
90
+ }, 201, "json">) | (Response & import("hono").TypedResponse<{
91
+ success: false;
92
+ error: {
93
+ code: string;
94
+ message: any;
95
+ };
96
+ }, 500, "json">)>;
@@ -0,0 +1,136 @@
1
+ import { FileStorageAdapter } from '../../../../lib/storage/file-storage.js';
2
+ import { getAuthorInfo } from '../../../../lib/user-preferences.js';
3
+ import Fuse from 'fuse.js';
4
+ import { getLogger } from '@lovelybunch/core/logging';
5
+ const storage = new FileStorageAdapter();
6
+ // Logger is lazily initialized inside handlers to use server config
7
+ export async function GET(c) {
8
+ try {
9
+ const url = new URL(c.req.url);
10
+ const searchParams = url.searchParams;
11
+ const status = searchParams.get('status');
12
+ const author = searchParams.get('author');
13
+ const priority = searchParams.get('priority');
14
+ const tags = searchParams.get('tags')?.split(',');
15
+ const searchQuery = searchParams.get('q');
16
+ const limitParam = searchParams.get('limit');
17
+ const limit = limitParam ? Math.min(Math.max(1, parseInt(limitParam, 10) || 20), 100) : undefined;
18
+ let tasks = await storage.listTasks({
19
+ status,
20
+ author: author || undefined,
21
+ priority: priority || undefined,
22
+ tags
23
+ });
24
+ // Apply search filter if provided
25
+ if (searchQuery?.trim()) {
26
+ const fuse = new Fuse(tasks, {
27
+ keys: [
28
+ { name: 'title', weight: 0.4 },
29
+ { name: 'intent', weight: 0.4 }, // Deprecated fallback
30
+ { name: 'id', weight: 0.3 },
31
+ { name: 'author.name', weight: 0.2 },
32
+ { name: 'metadata.tags', weight: 0.1 }
33
+ ],
34
+ threshold: 0.3,
35
+ includeScore: true
36
+ });
37
+ const searchResults = fuse.search(searchQuery);
38
+ tasks = searchResults.map(result => result.item);
39
+ }
40
+ const totalCount = tasks.length;
41
+ if (limit !== undefined) {
42
+ tasks = tasks.slice(0, limit);
43
+ }
44
+ return c.json({
45
+ success: true,
46
+ data: tasks,
47
+ ...(limit !== undefined && { totalCount })
48
+ });
49
+ }
50
+ catch (error) {
51
+ console.error('Error listing tasks:', error);
52
+ return c.json({
53
+ success: false,
54
+ error: {
55
+ code: 'LIST_TASKS_ERROR',
56
+ message: error.message
57
+ }
58
+ }, 500);
59
+ }
60
+ }
61
+ export async function POST(c) {
62
+ try {
63
+ const body = await c.req.json();
64
+ // Get author info from saved preferences if not provided
65
+ const authorInfo = await getAuthorInfo();
66
+ // Create a new task with required fields
67
+ const now = new Date();
68
+ // Use title as primary, fall back to deprecated intent for backward compatibility
69
+ const titleValue = body.title || body.intent || '';
70
+ const task = {
71
+ id: body.id || `cp-${Date.now()}`,
72
+ title: titleValue,
73
+ // Keep intent for backward compatibility (deprecated)
74
+ ...(body.intent && { intent: body.intent }),
75
+ content: body.content,
76
+ author: body.author || {
77
+ id: 'current-user',
78
+ name: authorInfo.name,
79
+ email: authorInfo.email,
80
+ role: 'engineer',
81
+ type: 'human'
82
+ },
83
+ planSteps: body.planSteps || [],
84
+ status: body.status || 'draft',
85
+ metadata: {
86
+ createdAt: now,
87
+ updatedAt: now,
88
+ reviewers: body.metadata?.reviewers || [],
89
+ tags: body.metadata?.tags || [],
90
+ priority: body.metadata?.priority || 'medium',
91
+ ...(body.metadata?.readiness != null && { readiness: body.metadata.readiness }),
92
+ },
93
+ productSpecRef: body.productSpecRef
94
+ };
95
+ await storage.createTask(task);
96
+ // Log the task creation event
97
+ const logger = getLogger();
98
+ logger.log({
99
+ kind: 'task.create',
100
+ actor: task.author.type === 'agent'
101
+ ? `agent:${task.author.name}`
102
+ : `human:${task.author.email}`,
103
+ subject: `task:${task.id}`,
104
+ tags: ['task'],
105
+ payload: {
106
+ id: task.id,
107
+ title: task.title,
108
+ priority: task.metadata.priority,
109
+ author: task.author
110
+ }
111
+ });
112
+ // Send Slack notification (non-blocking)
113
+ import('../../../../lib/slack/slack-service.js').then(({ getSlackService }) => {
114
+ getSlackService().sendNotification({
115
+ type: 'proposal.created',
116
+ proposalId: task.id,
117
+ intent: task.title,
118
+ author: task.author.name,
119
+ }).catch(err => console.warn('[tasks] Slack notification failed:', err));
120
+ }).catch(() => { });
121
+ return c.json({
122
+ success: true,
123
+ data: task
124
+ }, 201);
125
+ }
126
+ catch (error) {
127
+ console.error('Error creating task:', error);
128
+ return c.json({
129
+ success: false,
130
+ error: {
131
+ code: 'CREATE_TASK_ERROR',
132
+ message: error.message
133
+ }
134
+ }, 500);
135
+ }
136
+ }
@@ -4,7 +4,7 @@ export async function POST(c) {
4
4
  try {
5
5
  const proposalId = c.req.param('proposalId');
6
6
  const body = await c.req.json().catch(() => ({}));
7
- const { enableLogging = false, startupCommand } = body;
7
+ const { startupCommand } = body;
8
8
  if (!proposalId) {
9
9
  return c.json({ error: 'Proposal ID is required' }, 400);
10
10
  }
@@ -13,7 +13,7 @@ export async function POST(c) {
13
13
  const shellPreference = (userSettings.preferences.terminalShell || 'bash');
14
14
  // Create a new terminal session for this proposal
15
15
  const terminalManager = getGlobalTerminalManager();
16
- const session = await terminalManager.createSession(proposalId, enableLogging, shellPreference, startupCommand);
16
+ const session = await terminalManager.createSession(proposalId, shellPreference, startupCommand);
17
17
  return c.json({
18
18
  sessionId: session.id,
19
19
  proposalId: session.proposalId,
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ declare const create: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export default create;
@@ -0,0 +1,5 @@
1
+ import { Hono } from 'hono';
2
+ import { POST } from './route.js';
3
+ const create = new Hono();
4
+ create.post('/', POST);
5
+ export default create;
@@ -0,0 +1,10 @@
1
+ import { Context } from 'hono';
2
+ export declare function POST(c: Context): Promise<(Response & import("hono").TypedResponse<{
3
+ error: string;
4
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
5
+ sessionId: string;
6
+ taskId: string;
7
+ createdAt: string;
8
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
9
+ error: string;
10
+ }, 500, "json">)>;
@@ -0,0 +1,27 @@
1
+ import { getGlobalTerminalManager } from '../../../../../../lib/terminal/global-manager.js';
2
+ import { loadUserSettings } from '../../../../../../lib/user-preferences.js';
3
+ export async function POST(c) {
4
+ try {
5
+ const taskId = c.req.param('taskId');
6
+ const body = await c.req.json().catch(() => ({}));
7
+ const { startupCommand } = body;
8
+ if (!taskId) {
9
+ return c.json({ error: 'Task ID is required' }, 400);
10
+ }
11
+ // Load user settings to get shell preference
12
+ const userSettings = await loadUserSettings();
13
+ const shellPreference = (userSettings.preferences.terminalShell || 'bash');
14
+ // Create a new terminal session for this task
15
+ const terminalManager = getGlobalTerminalManager();
16
+ const session = await terminalManager.createSession(taskId, shellPreference, startupCommand);
17
+ return c.json({
18
+ sessionId: session.id,
19
+ taskId: session.taskId,
20
+ createdAt: session.createdAt,
21
+ });
22
+ }
23
+ catch (error) {
24
+ console.error('Error creating terminal session:', error);
25
+ return c.json({ error: 'Failed to create terminal session' }, 500);
26
+ }
27
+ }
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export default app;
@@ -0,0 +1,5 @@
1
+ import { Hono } from 'hono';
2
+ import { POST } from './route.js';
3
+ const app = new Hono();
4
+ app.post('/', POST);
5
+ export default app;
@@ -0,0 +1,10 @@
1
+ import { Context } from 'hono';
2
+ export declare function POST(c: Context): Promise<(Response & import("hono").TypedResponse<{
3
+ error: string;
4
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
5
+ error: string;
6
+ }, 404, "json">) | (Response & import("hono").TypedResponse<{
7
+ success: true;
8
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
9
+ error: string;
10
+ }, 500, "json">)>;
@@ -0,0 +1,21 @@
1
+ import { getGlobalTerminalManager } from '../../../../../../lib/terminal/global-manager.js';
2
+ export async function POST(c) {
3
+ try {
4
+ const taskId = c.req.param('taskId');
5
+ const body = await c.req.json();
6
+ const { sessionId } = body;
7
+ if (!sessionId) {
8
+ return c.json({ error: 'Session ID is required' }, 400);
9
+ }
10
+ const terminalManager = getGlobalTerminalManager();
11
+ const success = terminalManager.destroySession(sessionId);
12
+ if (!success) {
13
+ return c.json({ error: 'Session not found' }, 404);
14
+ }
15
+ return c.json({ success: true });
16
+ }
17
+ catch (error) {
18
+ console.error('Error destroying terminal session:', error);
19
+ return c.json({ error: 'Failed to destroy terminal session' }, 500);
20
+ }
21
+ }
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export default app;
@@ -0,0 +1,5 @@
1
+ import { Hono } from 'hono';
2
+ import { POST } from './route.js';
3
+ const app = new Hono();
4
+ app.post('/', POST);
5
+ export default app;
@@ -0,0 +1,10 @@
1
+ import { Context } from 'hono';
2
+ export declare function POST(c: Context): Promise<(Response & import("hono").TypedResponse<{
3
+ error: string;
4
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
5
+ error: string;
6
+ }, 404, "json">) | (Response & import("hono").TypedResponse<{
7
+ success: true;
8
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
9
+ error: string;
10
+ }, 500, "json">)>;