@lovelybunch/api 1.0.75-alpha.9 → 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.
- package/dist/lib/jobs/job-runner.js +10 -2
- package/dist/lib/jobs/job-scheduler.js +21 -0
- package/dist/lib/mail/mail-runner.d.ts +51 -0
- package/dist/lib/mail/mail-runner.js +342 -0
- package/dist/lib/slack/slack-service.d.ts +2 -0
- package/dist/lib/slack/slack-service.js +3 -0
- package/dist/lib/storage/file-storage.d.ts +16 -16
- package/dist/lib/storage/file-storage.js +59 -64
- package/dist/lib/terminal/terminal-manager.d.ts +3 -3
- package/dist/lib/terminal/terminal-manager.js +10 -10
- package/dist/routes/api/v1/ai/route.js +39 -19
- package/dist/routes/api/v1/git/index.js +23 -0
- package/dist/routes/api/v1/mail/index.d.ts +3 -0
- package/dist/routes/api/v1/mail/index.js +23 -0
- package/dist/routes/api/v1/mail/route.d.ts +294 -0
- package/dist/routes/api/v1/mail/route.js +344 -0
- package/dist/routes/api/v1/mcp/index.js +32 -32
- package/dist/routes/api/v1/slack/index.d.ts +3 -0
- package/dist/routes/api/v1/slack/index.js +15 -0
- package/dist/routes/api/v1/slack/route.d.ts +124 -0
- package/dist/routes/api/v1/slack/route.js +192 -0
- package/dist/routes/api/v1/tasks/[id]/route.d.ts +117 -0
- package/dist/routes/api/v1/tasks/[id]/route.js +166 -0
- package/dist/routes/api/v1/tasks/index.d.ts +3 -0
- package/dist/routes/api/v1/tasks/index.js +10 -0
- package/dist/routes/api/v1/tasks/route.d.ts +96 -0
- package/dist/routes/api/v1/tasks/route.js +136 -0
- package/dist/routes/api/v1/terminal/[taskId]/create/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/[taskId]/create/index.js +5 -0
- package/dist/routes/api/v1/terminal/[taskId]/create/route.d.ts +10 -0
- package/dist/routes/api/v1/terminal/[taskId]/create/route.js +27 -0
- package/dist/routes/api/v1/terminal/[taskId]/destroy/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/[taskId]/destroy/index.js +5 -0
- package/dist/routes/api/v1/terminal/[taskId]/destroy/route.d.ts +10 -0
- package/dist/routes/api/v1/terminal/[taskId]/destroy/route.js +21 -0
- package/dist/routes/api/v1/terminal/[taskId]/resize/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/[taskId]/resize/index.js +5 -0
- package/dist/routes/api/v1/terminal/[taskId]/resize/route.d.ts +10 -0
- package/dist/routes/api/v1/terminal/[taskId]/resize/route.js +21 -0
- package/dist/routes/api/v1/terminal/sessions/route.js +4 -4
- package/dist/server-with-static.js +12 -8
- package/dist/server.js +12 -8
- package/package.json +4 -4
- package/static/assets/{ActivityPage-OxRci_V2.js → ActivityPage-k4I7Q53O.js} +1 -1
- package/static/assets/ApiKeysSettingsPage-B1YvVdmg.js +2 -0
- package/static/assets/{ArchitectureEditPage-D7xcH6dY.js → ArchitectureEditPage-CpowsIx2.js} +4 -4
- package/static/assets/{ArchitecturePage-pvnlX-NW.js → ArchitecturePage-DYxC_aMR.js} +1 -1
- package/static/assets/{AuthSettingsPage-Bu0CZ1rY.js → AuthSettingsPage-DtSo78Y_.js} +2 -2
- package/static/assets/{CallbackPage-D0lkjxCT.js → CallbackPage-bROCGapx.js} +1 -1
- package/static/assets/CodePage-CPCj64rX.js +2 -0
- package/static/assets/{CollapsibleSection-Bt_ZLnJc.js → CollapsibleSection-M5cXbl92.js} +1 -1
- package/static/assets/DashboardPage-B9BZZfw6.js +51 -0
- package/static/assets/{GitPage-TrTxZ27J.js → GitPage-BiDtdSK1.js} +2 -2
- package/static/assets/GitSettingsPage-THm6wDjs.js +6 -0
- package/static/assets/IdentityPage-BC16skg6.js +6 -0
- package/static/assets/{ImplementationStepsEditor-Ctx0CvbU.js → ImplementationStepsEditor-HliLQav5.js} +2 -2
- package/static/assets/{IntegrationsSettingsPage-C2wJVdM7.js → IntegrationsSettingsPage-CC_VKIQa.js} +1 -1
- package/static/assets/JobDetailPage-z1QQYvmU.js +1 -0
- package/static/assets/{KnowledgeDetailPage-BdTUfWqj.js → KnowledgeDetailPage-DzHXBS7Q.js} +1 -1
- package/static/assets/{KnowledgeEditPage-D8XK4IUf.js → KnowledgeEditPage-BwGnUH_m.js} +1 -1
- package/static/assets/KnowledgePage-CGIVMS02.js +3 -0
- package/static/assets/{LoginPage-Dqxd7cTa.js → LoginPage-VQ3lcfLV.js} +1 -1
- package/static/assets/MailInboxPage-DiZKqwdU.js +1 -0
- package/static/assets/MailProcessingModal-DIeSQBoR.js +6 -0
- package/static/assets/MailReadPage-C8AACmZQ.js +1 -0
- package/static/assets/MailSentPage-C_5yFly_.js +1 -0
- package/static/assets/{McpSettingsPage-10n35zXi.js → McpSettingsPage-i9YHcu1s.js} +1 -1
- package/static/assets/{NewKnowledgePage-BlJzzuh7.js → NewKnowledgePage-BnVY7WUD.js} +1 -1
- package/static/assets/{NewSkillPage-ByqN--mH.js → NewSkillPage-DwniHD6D.js} +1 -1
- package/static/assets/NewTaskPage-F5UX2WMc.js +90 -0
- package/static/assets/NotFoundPage-BbSZX_4L.js +6 -0
- package/static/assets/NotificationsSettingsPage-C8kjcift.js +1 -0
- package/static/assets/{ProjectEditPage-DKJTY2uc.js → ProjectEditPage-DUUlIEqI.js} +1 -1
- package/static/assets/{ProjectPage-2VblKCWz.js → ProjectPage-Unz9PQpA.js} +1 -1
- package/static/assets/{PromptsSettingsPage-B4mOhXuo.js → PromptsSettingsPage-DVpIuRKI.js} +1 -1
- package/static/assets/ResourceDetailPage-DqHZ2KYD.js +1 -0
- package/static/assets/{ResourcesPage-2BbjIWfF.js → ResourcesPage-BP5tuAi-.js} +1 -1
- package/static/assets/RoleEditPage-BgKu8S0-.js +13 -0
- package/static/assets/{RolePage-qXWXZ2FZ.js → RolePage-Fed52Ov5.js} +1 -1
- package/static/assets/{RulesSettingsPage-BtM7p8F6.js → RulesSettingsPage-BQ2O0u66.js} +3 -3
- package/static/assets/SchedulePage-jkxjuzBx.js +4 -0
- package/static/assets/SkillDetailPage-k3Q2-NFd.js +1 -0
- package/static/assets/{SkillEditPage-Czlo8WWT.js → SkillEditPage-urF4snjo.js} +1 -1
- package/static/assets/SkillsPage-DlWDhEjR.js +8 -0
- package/static/assets/{SkillsSettingsPage-DKtpy7qk.js → SkillsSettingsPage-BViFgckG.js} +1 -1
- package/static/assets/{SourceInput-BITn1Y15.js → SourceInput-CAFKTHw-.js} +1 -1
- package/static/assets/{TagInput-BK91_M1N.js → TagInput-C6lI-ePr.js} +1 -1
- package/static/assets/TaskDetailPage-DpbRHnW_.js +16 -0
- package/static/assets/TaskEditPage-DssRbW0h.js +1 -0
- package/static/assets/TasksPage-CD_eo0Bj.js +17 -0
- package/static/assets/TerminalPage-BG_wlccr.js +1 -0
- package/static/assets/TerminalSessionPage-CsK-LznK.js +8 -0
- package/static/assets/{UserPreferencesPage-DrgYEcxO.js → UserPreferencesPage-CWUq3efu.js} +1 -1
- package/static/assets/UserSettingsPage-CduI_MGS.js +1 -0
- package/static/assets/{UtilitiesPage-Djr4qT5L.js → UtilitiesPage-BAxokhLh.js} +1 -1
- package/static/assets/{alert-CsMvyYoX.js → alert-BXsc6_qu.js} +1 -1
- package/static/assets/{arrow-down-BZnfbld8.js → arrow-down-DmW_3gE8.js} +1 -1
- package/static/assets/{arrow-left-WGBYWq3h.js → arrow-left-1S-835kP.js} +1 -1
- package/static/assets/{arrow-up-BByVUPE7.js → arrow-up-BYism_o1.js} +1 -1
- package/static/assets/arrow-up-down-Dw3J0a4i.js +6 -0
- package/static/assets/{badge-AwLOflf5.js → badge-BUEY53dV.js} +1 -1
- package/static/assets/{browser-modal-BzGNFfTG.js → browser-modal-DCNdI4NT.js} +2 -2
- package/static/assets/{card-SN5gKnu7.js → card-BcPlIAH5.js} +1 -1
- package/static/assets/{chevron-left-C7uNq9l_.js → chevron-left-FMmNe7yP.js} +1 -1
- package/static/assets/{chevron-up-CHdIiLxL.js → chevron-up-CqM3won3.js} +1 -1
- package/static/assets/{chevrons-up-TXwQuoUN.js → chevrons-up-DTvCkIHc.js} +1 -1
- package/static/assets/{circle-alert-37E5gU9K.js → circle-alert-dseM-Ib7.js} +1 -1
- package/static/assets/{circle-check-big-nY4PntB5.js → circle-check-big-jKg34xC-.js} +1 -1
- package/static/assets/{circle-check-D02pWDME.js → circle-check-eyo6pBP1.js} +1 -1
- package/static/assets/{circle-play-7EXFLo4F.js → circle-play-BrY_lNiH.js} +1 -1
- package/static/assets/{circle-x-By4JoTHB.js → circle-x-uqmzEce1.js} +1 -1
- package/static/assets/{clipboard-BdymjxLO.js → clipboard-tzPFoieb.js} +1 -1
- package/static/assets/{clock-HDu44KTo.js → clock-Bjc06QBM.js} +1 -1
- package/static/assets/code-DrYqPukx.js +6 -0
- package/static/assets/{download-Cv2G2Eg9.js → download-Bg__QCLT.js} +1 -1
- package/static/assets/{external-link-DwMXcCCj.js → external-link-CNDy2UUo.js} +1 -1
- package/static/assets/{eye-DYnjJzdb.js → eye-DLFBnC8t.js} +1 -1
- package/static/assets/{folder-git-2-COeWFPHS.js → folder-git-2-DUqd0WRi.js} +1 -1
- package/static/assets/index-CHdBxVyk.css +2 -0
- package/static/assets/{index-9Tv-j_Ga.js → index-DFcWlnzl.js} +118 -103
- package/static/assets/{info-BmtuPMhv.js → info-D6jxZC5X.js} +1 -1
- package/static/assets/kiro-CX1mOsRO.js +17 -0
- package/static/assets/{label-TGqbNfMO.js → label-DBuh-ke5.js} +1 -1
- package/static/assets/{markdown-editor-ls1JPK_e.js → markdown-editor-B4YNQFT2.js} +1 -1
- package/static/assets/message-square-B5RWz_ff.js +6 -0
- package/static/assets/paperclip-4A_3MaPx.js +6 -0
- package/static/assets/{pause-CAWbvTiL.js → pause-BzhKXHtR.js} +1 -1
- package/static/assets/{play-DF_Qeu0H.js → play-CHIf-Rcz.js} +1 -1
- package/static/assets/{radio-group-DYTbywtK.js → radio-group-C1ct-VsJ.js} +1 -1
- package/static/assets/{refresh-cw-BFZxHqbC.js → refresh-cw-B3OwrDUf.js} +1 -1
- package/static/assets/{search-Dr90tbch.js → search-Cq1ksEdp.js} +1 -1
- package/static/assets/{select-Cs5qtMYV.js → select-44mcS2_G.js} +1 -1
- package/static/assets/{status-utils-BDOyevaX.js → status-utils-CDkPeVfP.js} +1 -1
- package/static/assets/{switch-4TDb6YiQ.js → switch-CIwjYvCt.js} +1 -1
- package/static/assets/{tabs-BrbEvF4V.js → tabs-DTV6Su-h.js} +1 -1
- package/static/assets/{tag-DrQkepeD.js → tag-p6yeowCW.js} +1 -1
- package/static/assets/{terminal-preview-uuKF9_x4.js → terminal-preview-DN38x9Jm.js} +1 -1
- package/static/assets/use-terminal-BXJqOeJe.js +1 -0
- package/static/assets/{video-DYA2WfbA.js → video-BH5ChaoS.js} +1 -1
- package/static/index.html +2 -2
- package/static/assets/ApiKeysSettingsPage-C0evI19e.js +0 -2
- package/static/assets/CodePage-BJ4PC5nb.js +0 -2
- package/static/assets/DashboardPage-BiffPdmj.js +0 -41
- package/static/assets/GitSettingsPage-D7q5xQd_.js +0 -6
- package/static/assets/IdentityPage-CY0Ak2j0.js +0 -11
- package/static/assets/JobDetailPage-Phx_IlKX.js +0 -1
- package/static/assets/KnowledgePage-Ci9G7Br-.js +0 -8
- package/static/assets/NewProposalPage-BP7Ttoxk.js +0 -90
- package/static/assets/ProposalDetailPage-m3ysyzpj.js +0 -1
- package/static/assets/ProposalEditPage-3XVg_paW.js +0 -1
- package/static/assets/ProposalsPage-B3u0aFFz.js +0 -17
- package/static/assets/ResourceDetailPage-somBLUpC.js +0 -1
- package/static/assets/RoleEditPage-CLzX7Xhi.js +0 -13
- package/static/assets/SchedulePage-4tFcIBSs.js +0 -4
- package/static/assets/SkillDetailPage-CroSdaju.js +0 -1
- package/static/assets/SkillsPage-CgULbcI-.js +0 -8
- package/static/assets/TerminalPage-8fwvnOo2.js +0 -1
- package/static/assets/TerminalSessionPage-BhO5U48p.js +0 -13
- package/static/assets/UserSettingsPage-Dj6lKLi8.js +0 -1
- package/static/assets/droid-CPteN3f9.js +0 -17
- package/static/assets/index-GFQ5RqVh.css +0 -2
- package/static/assets/use-terminal-BG5UXuVE.js +0 -1
- package/static/assets/zap-h9QOsasv.js +0 -6
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { Context } from 'hono';
|
|
2
|
+
import type { MailFolder } from '@lovelybunch/types';
|
|
3
|
+
/**
|
|
4
|
+
* GET /api/v1/mail/:folder
|
|
5
|
+
* List emails in a folder
|
|
6
|
+
*/
|
|
7
|
+
export declare function listMailHandler(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
8
|
+
success: false;
|
|
9
|
+
error: string;
|
|
10
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
11
|
+
success: true;
|
|
12
|
+
data: {
|
|
13
|
+
messages: {
|
|
14
|
+
id: string;
|
|
15
|
+
emailId: string;
|
|
16
|
+
from: string;
|
|
17
|
+
to: string[];
|
|
18
|
+
cc: string[];
|
|
19
|
+
bcc: string[];
|
|
20
|
+
subject: string;
|
|
21
|
+
messageId: string;
|
|
22
|
+
attachments: {
|
|
23
|
+
id: string;
|
|
24
|
+
filename: string;
|
|
25
|
+
contentType: string;
|
|
26
|
+
contentDisposition?: string;
|
|
27
|
+
contentId?: string;
|
|
28
|
+
}[];
|
|
29
|
+
receivedAt: string;
|
|
30
|
+
content: string;
|
|
31
|
+
folder: MailFolder;
|
|
32
|
+
action?: string;
|
|
33
|
+
processing?: boolean;
|
|
34
|
+
processingStartedAt?: string;
|
|
35
|
+
}[];
|
|
36
|
+
};
|
|
37
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
38
|
+
success: false;
|
|
39
|
+
error: any;
|
|
40
|
+
}, 500, "json">)>;
|
|
41
|
+
/**
|
|
42
|
+
* GET /api/v1/mail/:folder/:id
|
|
43
|
+
* Get a specific email
|
|
44
|
+
*/
|
|
45
|
+
export declare function getMailHandler(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
46
|
+
success: false;
|
|
47
|
+
error: string;
|
|
48
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
49
|
+
success: false;
|
|
50
|
+
error: string;
|
|
51
|
+
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
52
|
+
success: true;
|
|
53
|
+
data: {
|
|
54
|
+
message: {
|
|
55
|
+
id: string;
|
|
56
|
+
emailId: string;
|
|
57
|
+
from: string;
|
|
58
|
+
to: string[];
|
|
59
|
+
cc: string[];
|
|
60
|
+
bcc: string[];
|
|
61
|
+
subject: string;
|
|
62
|
+
messageId: string;
|
|
63
|
+
attachments: {
|
|
64
|
+
id: string;
|
|
65
|
+
filename: string;
|
|
66
|
+
contentType: string;
|
|
67
|
+
contentDisposition?: string;
|
|
68
|
+
contentId?: string;
|
|
69
|
+
}[];
|
|
70
|
+
receivedAt: string;
|
|
71
|
+
content: string;
|
|
72
|
+
folder: MailFolder;
|
|
73
|
+
action?: string;
|
|
74
|
+
processing?: boolean;
|
|
75
|
+
processingStartedAt?: string;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
79
|
+
success: false;
|
|
80
|
+
error: any;
|
|
81
|
+
}, 500, "json">)>;
|
|
82
|
+
/**
|
|
83
|
+
* PUT /api/v1/mail/:id/status
|
|
84
|
+
* Set email read/unread status
|
|
85
|
+
*/
|
|
86
|
+
export declare function setMailStatusHandler(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
87
|
+
success: false;
|
|
88
|
+
error: string;
|
|
89
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
90
|
+
success: true;
|
|
91
|
+
data: {
|
|
92
|
+
message: {
|
|
93
|
+
id: string;
|
|
94
|
+
emailId: string;
|
|
95
|
+
from: string;
|
|
96
|
+
to: string[];
|
|
97
|
+
cc: string[];
|
|
98
|
+
bcc: string[];
|
|
99
|
+
subject: string;
|
|
100
|
+
messageId: string;
|
|
101
|
+
attachments: {
|
|
102
|
+
id: string;
|
|
103
|
+
filename: string;
|
|
104
|
+
contentType: string;
|
|
105
|
+
contentDisposition?: string;
|
|
106
|
+
contentId?: string;
|
|
107
|
+
}[];
|
|
108
|
+
receivedAt: string;
|
|
109
|
+
content: string;
|
|
110
|
+
folder: MailFolder;
|
|
111
|
+
action?: string;
|
|
112
|
+
processing?: boolean;
|
|
113
|
+
processingStartedAt?: string;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
117
|
+
success: false;
|
|
118
|
+
error: any;
|
|
119
|
+
}, 404 | 500, "json">)>;
|
|
120
|
+
/**
|
|
121
|
+
* POST /api/v1/mail/:id/reply
|
|
122
|
+
* Reply to an email
|
|
123
|
+
*/
|
|
124
|
+
export declare function replyMailHandler(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
125
|
+
success: false;
|
|
126
|
+
error: string;
|
|
127
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
128
|
+
success: true;
|
|
129
|
+
data: {
|
|
130
|
+
message: {
|
|
131
|
+
id: string;
|
|
132
|
+
emailId: string;
|
|
133
|
+
from: string;
|
|
134
|
+
to: string[];
|
|
135
|
+
cc: string[];
|
|
136
|
+
bcc: string[];
|
|
137
|
+
subject: string;
|
|
138
|
+
messageId: string;
|
|
139
|
+
attachments: {
|
|
140
|
+
id: string;
|
|
141
|
+
filename: string;
|
|
142
|
+
contentType: string;
|
|
143
|
+
contentDisposition?: string;
|
|
144
|
+
contentId?: string;
|
|
145
|
+
}[];
|
|
146
|
+
receivedAt: string;
|
|
147
|
+
content: string;
|
|
148
|
+
folder: MailFolder;
|
|
149
|
+
action?: string;
|
|
150
|
+
processing?: boolean;
|
|
151
|
+
processingStartedAt?: string;
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
155
|
+
success: false;
|
|
156
|
+
error: any;
|
|
157
|
+
}, 404 | 500, "json">)>;
|
|
158
|
+
/**
|
|
159
|
+
* POST /api/v1/mail/send
|
|
160
|
+
* Send an email (coming soon)
|
|
161
|
+
*/
|
|
162
|
+
export declare function sendMailHandler(c: Context): Promise<Response & import("hono").TypedResponse<{
|
|
163
|
+
success: false;
|
|
164
|
+
error: string;
|
|
165
|
+
}, 501, "json">>;
|
|
166
|
+
/**
|
|
167
|
+
* DELETE /api/v1/mail/:folder/:id
|
|
168
|
+
* Delete an email
|
|
169
|
+
*/
|
|
170
|
+
export declare function deleteMailHandler(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
171
|
+
success: false;
|
|
172
|
+
error: string;
|
|
173
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
174
|
+
success: false;
|
|
175
|
+
error: string;
|
|
176
|
+
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
177
|
+
success: true;
|
|
178
|
+
message: string;
|
|
179
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
180
|
+
success: false;
|
|
181
|
+
error: any;
|
|
182
|
+
}, 500, "json">)>;
|
|
183
|
+
/**
|
|
184
|
+
* PUT /api/v1/mail/:id/action
|
|
185
|
+
* Set agent action summary on an email
|
|
186
|
+
*/
|
|
187
|
+
export declare function setMailActionHandler(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
188
|
+
success: false;
|
|
189
|
+
error: string;
|
|
190
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
191
|
+
success: true;
|
|
192
|
+
data: {
|
|
193
|
+
message: {
|
|
194
|
+
id: string;
|
|
195
|
+
emailId: string;
|
|
196
|
+
from: string;
|
|
197
|
+
to: string[];
|
|
198
|
+
cc: string[];
|
|
199
|
+
bcc: string[];
|
|
200
|
+
subject: string;
|
|
201
|
+
messageId: string;
|
|
202
|
+
attachments: {
|
|
203
|
+
id: string;
|
|
204
|
+
filename: string;
|
|
205
|
+
contentType: string;
|
|
206
|
+
contentDisposition?: string;
|
|
207
|
+
contentId?: string;
|
|
208
|
+
}[];
|
|
209
|
+
receivedAt: string;
|
|
210
|
+
content: string;
|
|
211
|
+
folder: MailFolder;
|
|
212
|
+
action?: string;
|
|
213
|
+
processing?: boolean;
|
|
214
|
+
processingStartedAt?: string;
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
218
|
+
success: false;
|
|
219
|
+
error: any;
|
|
220
|
+
}, 404 | 500, "json">)>;
|
|
221
|
+
/**
|
|
222
|
+
* GET /api/v1/mail/:id/processing
|
|
223
|
+
* Get processing status and log tail for an email
|
|
224
|
+
*/
|
|
225
|
+
export declare function getMailProcessingHandler(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
226
|
+
success: false;
|
|
227
|
+
error: string;
|
|
228
|
+
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
229
|
+
success: true;
|
|
230
|
+
data: {
|
|
231
|
+
mailId: string;
|
|
232
|
+
processing: boolean;
|
|
233
|
+
processingStartedAt: string;
|
|
234
|
+
active: {
|
|
235
|
+
pid: number;
|
|
236
|
+
agent: string;
|
|
237
|
+
startedAt: string;
|
|
238
|
+
};
|
|
239
|
+
log: string;
|
|
240
|
+
logPath: string;
|
|
241
|
+
};
|
|
242
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
243
|
+
success: false;
|
|
244
|
+
error: any;
|
|
245
|
+
}, 500, "json">)>;
|
|
246
|
+
/**
|
|
247
|
+
* POST /api/v1/mail/:id/processing/stop
|
|
248
|
+
* Stop an active mail processing job
|
|
249
|
+
*/
|
|
250
|
+
export declare function stopMailProcessingHandler(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
251
|
+
success: true;
|
|
252
|
+
message: string;
|
|
253
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
254
|
+
success: false;
|
|
255
|
+
error: any;
|
|
256
|
+
}, 500, "json">)>;
|
|
257
|
+
/**
|
|
258
|
+
* POST /api/v1/mail/inbound
|
|
259
|
+
* Receive email via Resend webhook
|
|
260
|
+
*/
|
|
261
|
+
export declare function inboundWebhookHandler(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
262
|
+
success: false;
|
|
263
|
+
error: string;
|
|
264
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
265
|
+
success: true;
|
|
266
|
+
data: {
|
|
267
|
+
message: {
|
|
268
|
+
id: string;
|
|
269
|
+
emailId: string;
|
|
270
|
+
from: string;
|
|
271
|
+
to: string[];
|
|
272
|
+
cc: string[];
|
|
273
|
+
bcc: string[];
|
|
274
|
+
subject: string;
|
|
275
|
+
messageId: string;
|
|
276
|
+
attachments: {
|
|
277
|
+
id: string;
|
|
278
|
+
filename: string;
|
|
279
|
+
contentType: string;
|
|
280
|
+
contentDisposition?: string;
|
|
281
|
+
contentId?: string;
|
|
282
|
+
}[];
|
|
283
|
+
receivedAt: string;
|
|
284
|
+
content: string;
|
|
285
|
+
folder: MailFolder;
|
|
286
|
+
action?: string;
|
|
287
|
+
processing?: boolean;
|
|
288
|
+
processingStartedAt?: string;
|
|
289
|
+
};
|
|
290
|
+
};
|
|
291
|
+
}, 201, "json">) | (Response & import("hono").TypedResponse<{
|
|
292
|
+
success: false;
|
|
293
|
+
error: any;
|
|
294
|
+
}, 500, "json">)>;
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { listMail, getMail, saveMail, setMailStatus, deleteMail, replyToMail, addMailAction, setMailProcessing, } from '@lovelybunch/core';
|
|
2
|
+
import { getMailRunner } from '../../../../lib/mail/mail-runner.js';
|
|
3
|
+
const VALID_FOLDERS = ['inbox', 'read', 'sent'];
|
|
4
|
+
function isValidFolder(folder) {
|
|
5
|
+
return VALID_FOLDERS.includes(folder);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* GET /api/v1/mail/:folder
|
|
9
|
+
* List emails in a folder
|
|
10
|
+
*/
|
|
11
|
+
export async function listMailHandler(c) {
|
|
12
|
+
try {
|
|
13
|
+
const folder = c.req.param('folder');
|
|
14
|
+
if (!isValidFolder(folder)) {
|
|
15
|
+
return c.json({
|
|
16
|
+
success: false,
|
|
17
|
+
error: `Invalid folder "${folder}". Must be one of: ${VALID_FOLDERS.join(', ')}`,
|
|
18
|
+
}, 400);
|
|
19
|
+
}
|
|
20
|
+
const messages = await listMail(folder);
|
|
21
|
+
return c.json({
|
|
22
|
+
success: true,
|
|
23
|
+
data: { messages },
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error('[mail] list error:', error);
|
|
28
|
+
return c.json({
|
|
29
|
+
success: false,
|
|
30
|
+
error: error.message || 'Failed to list mail',
|
|
31
|
+
}, 500);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* GET /api/v1/mail/:folder/:id
|
|
36
|
+
* Get a specific email
|
|
37
|
+
*/
|
|
38
|
+
export async function getMailHandler(c) {
|
|
39
|
+
try {
|
|
40
|
+
const folder = c.req.param('folder');
|
|
41
|
+
const id = c.req.param('id');
|
|
42
|
+
if (!isValidFolder(folder)) {
|
|
43
|
+
return c.json({
|
|
44
|
+
success: false,
|
|
45
|
+
error: `Invalid folder "${folder}". Must be one of: ${VALID_FOLDERS.join(', ')}`,
|
|
46
|
+
}, 400);
|
|
47
|
+
}
|
|
48
|
+
const message = await getMail(id, folder);
|
|
49
|
+
if (!message) {
|
|
50
|
+
return c.json({
|
|
51
|
+
success: false,
|
|
52
|
+
error: `Email "${id}" not found in ${folder}`,
|
|
53
|
+
}, 404);
|
|
54
|
+
}
|
|
55
|
+
return c.json({
|
|
56
|
+
success: true,
|
|
57
|
+
data: { message },
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error('[mail] get error:', error);
|
|
62
|
+
return c.json({
|
|
63
|
+
success: false,
|
|
64
|
+
error: error.message || 'Failed to get mail',
|
|
65
|
+
}, 500);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* PUT /api/v1/mail/:id/status
|
|
70
|
+
* Set email read/unread status
|
|
71
|
+
*/
|
|
72
|
+
export async function setMailStatusHandler(c) {
|
|
73
|
+
try {
|
|
74
|
+
const id = c.req.param('id');
|
|
75
|
+
const body = await c.req.json();
|
|
76
|
+
const status = body.status;
|
|
77
|
+
if (status !== 'read' && status !== 'unread') {
|
|
78
|
+
return c.json({
|
|
79
|
+
success: false,
|
|
80
|
+
error: 'Status must be "read" or "unread"',
|
|
81
|
+
}, 400);
|
|
82
|
+
}
|
|
83
|
+
const message = await setMailStatus(id, status);
|
|
84
|
+
return c.json({
|
|
85
|
+
success: true,
|
|
86
|
+
data: { message },
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error('[mail] setStatus error:', error);
|
|
91
|
+
const status = error.message?.includes('not found') ? 404 : 500;
|
|
92
|
+
return c.json({
|
|
93
|
+
success: false,
|
|
94
|
+
error: error.message || 'Failed to set mail status',
|
|
95
|
+
}, status);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* POST /api/v1/mail/:id/reply
|
|
100
|
+
* Reply to an email
|
|
101
|
+
*/
|
|
102
|
+
export async function replyMailHandler(c) {
|
|
103
|
+
try {
|
|
104
|
+
const id = c.req.param('id');
|
|
105
|
+
const body = await c.req.json();
|
|
106
|
+
if (!body.content || typeof body.content !== 'string') {
|
|
107
|
+
return c.json({
|
|
108
|
+
success: false,
|
|
109
|
+
error: 'Reply content is required',
|
|
110
|
+
}, 400);
|
|
111
|
+
}
|
|
112
|
+
const reply = await replyToMail(id, { content: body.content });
|
|
113
|
+
return c.json({
|
|
114
|
+
success: true,
|
|
115
|
+
data: { message: reply },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
console.error('[mail] reply error:', error);
|
|
120
|
+
const status = error.message?.includes('not found') ? 404 : 500;
|
|
121
|
+
return c.json({
|
|
122
|
+
success: false,
|
|
123
|
+
error: error.message || 'Failed to reply to mail',
|
|
124
|
+
}, status);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* POST /api/v1/mail/send
|
|
129
|
+
* Send an email (coming soon)
|
|
130
|
+
*/
|
|
131
|
+
export async function sendMailHandler(c) {
|
|
132
|
+
return c.json({
|
|
133
|
+
success: false,
|
|
134
|
+
error: 'Send email is coming soon',
|
|
135
|
+
}, 501);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* DELETE /api/v1/mail/:folder/:id
|
|
139
|
+
* Delete an email
|
|
140
|
+
*/
|
|
141
|
+
export async function deleteMailHandler(c) {
|
|
142
|
+
try {
|
|
143
|
+
const folder = c.req.param('folder');
|
|
144
|
+
const id = c.req.param('id');
|
|
145
|
+
if (!isValidFolder(folder)) {
|
|
146
|
+
return c.json({
|
|
147
|
+
success: false,
|
|
148
|
+
error: `Invalid folder "${folder}". Must be one of: ${VALID_FOLDERS.join(', ')}`,
|
|
149
|
+
}, 400);
|
|
150
|
+
}
|
|
151
|
+
const deleted = await deleteMail(id, folder);
|
|
152
|
+
if (!deleted) {
|
|
153
|
+
return c.json({
|
|
154
|
+
success: false,
|
|
155
|
+
error: `Email "${id}" not found in ${folder}`,
|
|
156
|
+
}, 404);
|
|
157
|
+
}
|
|
158
|
+
return c.json({
|
|
159
|
+
success: true,
|
|
160
|
+
message: `Email "${id}" deleted from ${folder}`,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
console.error('[mail] delete error:', error);
|
|
165
|
+
return c.json({
|
|
166
|
+
success: false,
|
|
167
|
+
error: error.message || 'Failed to delete mail',
|
|
168
|
+
}, 500);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* PUT /api/v1/mail/:id/action
|
|
173
|
+
* Set agent action summary on an email
|
|
174
|
+
*/
|
|
175
|
+
export async function setMailActionHandler(c) {
|
|
176
|
+
try {
|
|
177
|
+
const id = c.req.param('id');
|
|
178
|
+
const body = await c.req.json();
|
|
179
|
+
if (!body.action || typeof body.action !== 'string') {
|
|
180
|
+
return c.json({
|
|
181
|
+
success: false,
|
|
182
|
+
error: 'Action message is required and must be a string',
|
|
183
|
+
}, 400);
|
|
184
|
+
}
|
|
185
|
+
const message = await addMailAction(id, body.action);
|
|
186
|
+
return c.json({
|
|
187
|
+
success: true,
|
|
188
|
+
data: { message },
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
console.error('[mail] setAction error:', error);
|
|
193
|
+
const status = error.message?.includes('not found') ? 404 : 500;
|
|
194
|
+
return c.json({
|
|
195
|
+
success: false,
|
|
196
|
+
error: error.message || 'Failed to set mail action',
|
|
197
|
+
}, status);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* GET /api/v1/mail/:id/processing
|
|
202
|
+
* Get processing status and log tail for an email
|
|
203
|
+
*/
|
|
204
|
+
export async function getMailProcessingHandler(c) {
|
|
205
|
+
try {
|
|
206
|
+
const id = c.req.param('id');
|
|
207
|
+
const runner = getMailRunner();
|
|
208
|
+
const mail = await getMail(id);
|
|
209
|
+
if (!mail) {
|
|
210
|
+
return c.json({
|
|
211
|
+
success: false,
|
|
212
|
+
error: `Email "${id}" not found`,
|
|
213
|
+
}, 404);
|
|
214
|
+
}
|
|
215
|
+
const active = runner.getActiveProcess(id);
|
|
216
|
+
const logData = await runner.readLog(id);
|
|
217
|
+
return c.json({
|
|
218
|
+
success: true,
|
|
219
|
+
data: {
|
|
220
|
+
mailId: id,
|
|
221
|
+
processing: mail.processing || false,
|
|
222
|
+
processingStartedAt: mail.processingStartedAt || null,
|
|
223
|
+
active: active ? {
|
|
224
|
+
pid: active.pid,
|
|
225
|
+
agent: active.agent,
|
|
226
|
+
startedAt: active.startedAt,
|
|
227
|
+
} : null,
|
|
228
|
+
log: logData?.log || null,
|
|
229
|
+
logPath: logData?.logPath || null,
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
console.error('[mail] getProcessing error:', error);
|
|
235
|
+
return c.json({
|
|
236
|
+
success: false,
|
|
237
|
+
error: error.message || 'Failed to get processing status',
|
|
238
|
+
}, 500);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* POST /api/v1/mail/:id/processing/stop
|
|
243
|
+
* Stop an active mail processing job
|
|
244
|
+
*/
|
|
245
|
+
export async function stopMailProcessingHandler(c) {
|
|
246
|
+
try {
|
|
247
|
+
const id = c.req.param('id');
|
|
248
|
+
const runner = getMailRunner();
|
|
249
|
+
const active = runner.getActiveProcess(id);
|
|
250
|
+
if (!active) {
|
|
251
|
+
// No active process — clear the processing flag if still set
|
|
252
|
+
await setMailProcessing(id, false);
|
|
253
|
+
return c.json({
|
|
254
|
+
success: true,
|
|
255
|
+
message: `No active process found for "${id}". Processing flag cleared.`,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
const stopped = await runner.stop(id);
|
|
259
|
+
if (!stopped) {
|
|
260
|
+
return c.json({
|
|
261
|
+
success: false,
|
|
262
|
+
error: `Failed to stop processing for "${id}"`,
|
|
263
|
+
}, 500);
|
|
264
|
+
}
|
|
265
|
+
return c.json({
|
|
266
|
+
success: true,
|
|
267
|
+
message: `Processing for "${id}" has been stopped (PID: ${active.pid}).`,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
console.error('[mail] stopProcessing error:', error);
|
|
272
|
+
return c.json({
|
|
273
|
+
success: false,
|
|
274
|
+
error: error.message || 'Failed to stop processing',
|
|
275
|
+
}, 500);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* POST /api/v1/mail/inbound
|
|
280
|
+
* Receive email via Resend webhook
|
|
281
|
+
*/
|
|
282
|
+
export async function inboundWebhookHandler(c) {
|
|
283
|
+
try {
|
|
284
|
+
const body = await c.req.json();
|
|
285
|
+
if (body.type !== 'email.received') {
|
|
286
|
+
return c.json({
|
|
287
|
+
success: false,
|
|
288
|
+
error: `Unsupported webhook type: ${body.type}`,
|
|
289
|
+
}, 400);
|
|
290
|
+
}
|
|
291
|
+
const data = body.data;
|
|
292
|
+
if (!data || !data.email_id) {
|
|
293
|
+
return c.json({
|
|
294
|
+
success: false,
|
|
295
|
+
error: 'Missing email data in webhook payload',
|
|
296
|
+
}, 400);
|
|
297
|
+
}
|
|
298
|
+
const attachments = Array.isArray(data.attachments)
|
|
299
|
+
? data.attachments.map((a) => ({
|
|
300
|
+
id: a.id,
|
|
301
|
+
filename: a.filename,
|
|
302
|
+
contentType: a.content_type,
|
|
303
|
+
contentDisposition: a.content_disposition,
|
|
304
|
+
contentId: a.content_id,
|
|
305
|
+
}))
|
|
306
|
+
: [];
|
|
307
|
+
const message = await saveMail('inbox', {
|
|
308
|
+
emailId: data.email_id,
|
|
309
|
+
from: data.from || '',
|
|
310
|
+
to: Array.isArray(data.to) ? data.to : [],
|
|
311
|
+
cc: Array.isArray(data.cc) ? data.cc : [],
|
|
312
|
+
bcc: Array.isArray(data.bcc) ? data.bcc : [],
|
|
313
|
+
subject: data.subject || '(no subject)',
|
|
314
|
+
messageId: data.message_id || '',
|
|
315
|
+
attachments,
|
|
316
|
+
receivedAt: data.created_at || body.created_at || new Date().toISOString(),
|
|
317
|
+
content: data.body || data.text || data.html || '',
|
|
318
|
+
});
|
|
319
|
+
const runner = getMailRunner();
|
|
320
|
+
const mailEnabled = await runner.isMailProcessingEnabled();
|
|
321
|
+
if (mailEnabled) {
|
|
322
|
+
setMailProcessing(message.id, true).catch(err => {
|
|
323
|
+
console.warn('[mail] failed to set processing state:', err);
|
|
324
|
+
});
|
|
325
|
+
runner.run(message.id, `.nut/mail/inbox/${message.id}.md`).catch(err => {
|
|
326
|
+
console.error('[mail] agent processing failed:', err);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
console.log('[mail] processing disabled via config, skipping agent for', message.id);
|
|
331
|
+
}
|
|
332
|
+
return c.json({
|
|
333
|
+
success: true,
|
|
334
|
+
data: { message },
|
|
335
|
+
}, 201);
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
console.error('[mail] inbound webhook error:', error);
|
|
339
|
+
return c.json({
|
|
340
|
+
success: false,
|
|
341
|
+
error: error.message || 'Failed to process inbound email',
|
|
342
|
+
}, 500);
|
|
343
|
+
}
|
|
344
|
+
}
|