@kb-labs/inbox-entry 2.107.0 → 2.110.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/mail-accounts.d.ts +1 -1
- package/dist/commands/mail-accounts.js +4 -4
- package/dist/commands/mail-accounts.js.map +1 -1
- package/dist/commands/mail-delete.js +5 -5
- package/dist/commands/mail-delete.js.map +1 -1
- package/dist/commands/mail-folders.d.ts +1 -1
- package/dist/commands/mail-folders.js +3 -3
- package/dist/commands/mail-folders.js.map +1 -1
- package/dist/commands/mail-get.d.ts +1 -1
- package/dist/commands/mail-get.js +5 -5
- package/dist/commands/mail-get.js.map +1 -1
- package/dist/commands/mail-list.d.ts +1 -1
- package/dist/commands/mail-list.js +4 -4
- package/dist/commands/mail-list.js.map +1 -1
- package/dist/commands/mail-mark.js +6 -6
- package/dist/commands/mail-mark.js.map +1 -1
- package/dist/commands/mail-move.js +6 -6
- package/dist/commands/mail-move.js.map +1 -1
- package/dist/commands/mail-reply.d.ts +1 -1
- package/dist/commands/mail-reply.js +6 -6
- package/dist/commands/mail-reply.js.map +1 -1
- package/dist/commands/mail-search.d.ts +1 -1
- package/dist/commands/mail-search.js +4 -4
- package/dist/commands/mail-search.js.map +1 -1
- package/dist/commands/mail-send.d.ts +1 -1
- package/dist/commands/mail-send.js +6 -6
- package/dist/commands/mail-send.js.map +1 -1
- package/dist/commands/mail-thread.d.ts +1 -1
- package/dist/commands/mail-thread.js +5 -5
- package/dist/commands/mail-thread.js.map +1 -1
- package/dist/rest/handlers/accounts-handler.js.map +1 -1
- package/dist/rest/handlers/delete-handler.js.map +1 -1
- package/dist/rest/handlers/folders-handler.js.map +1 -1
- package/dist/rest/handlers/get-handler.js.map +1 -1
- package/dist/rest/handlers/list-handler.js.map +1 -1
- package/dist/rest/handlers/mark-handler.js.map +1 -1
- package/dist/rest/handlers/move-handler.js.map +1 -1
- package/dist/rest/handlers/reply-handler.js.map +1 -1
- package/dist/rest/handlers/search-handler.js.map +1 -1
- package/dist/rest/handlers/send-handler.js.map +1 -1
- package/dist/rest/handlers/thread-handler.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/error.ts","../../src/commands/mail-move.ts"],"names":[],"mappings":";;;;AAoBA,SAAS,OAAA,CAAQ,MAAsB,OAAA,EAAqC;AAC1E,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,aAAA;AACH,MAAA,OAAO,4GAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,mFAAA,CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,qGAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,qFAAA,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,6DAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,gEAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,yDAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,sFAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,qDAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,0CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,SAAS;AAGP,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAUO,SAAS,WAAA,CAAY,GAAA,EAAsB,GAAA,EAAc,MAAA,EAAwB;AACtF,EAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,OAAO,CAAA;AAE1C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,QACb,EAAA,EAAI,KAAA;AAAA,QACJ,KAAA,EAAO;AAAA,UACL,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,GAAI,IAAA,IAAQ,EAAE,IAAA;AAAK;AACrB,OACD,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,GAAA,CAAI,EAAA,EAAI,KAAA,GAAQ,GAAA,CAAI,OAAA,EAAS;AAAA,QAC3B,GAAI,IAAA,IAAQ,EAAE,IAAA,EAAK;AAAA,QACnB,KAAA,EAAO,CAAA,YAAA,EAAe,GAAA,CAAI,IAAI,CAAA,CAAA;AAAA,OAC/B,CAAA;AAAA,IACH;AACA,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE/D,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,MACb,EAAA,EAAI,KAAA;AAAA,MACJ,KAAA,EAAO,EAAE,IAAA,EAAM,gBAAA,EAAkB,OAAA;AAAQ,KAC1C,CAAA;AAAA,EACH,CAAA,MAAO;AACL,IAAA,GAAA,CAAI,EAAA,EAAI,QAAQ,OAAO,CAAA;AAAA,EACzB;AACF;;;ACpFA,IAAO,oBAAQ,aAAA,CAAc;AAAA,EAC3B,EAAA,EAAI,iBAAA;AAAA,EACJ,WAAA,EAAa,2BAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA4B;AAC9D,MAAA,MAAM,CAAC,MAAM,CAAA,GAAI,KAAA,CAAM,IAAA;AACvB,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,eAAA,CAAgB,GAAA,EAAK,iBAAA,EAAmB,0CAAA,EAA4C,KAAA,CAAM,MAAM,IAAI,CAAA;AACpG,QAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"sources":["../../src/utils/error.ts","../../src/commands/mail-move.ts"],"names":[],"mappings":"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","file":"mail-move.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { ok: false, error: 'Command failed', result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import { defineCommand, validationError, type CLIInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { resolveAccount, moveMessage } from '@kb-labs/inbox-core';\nimport { handleError } from '../utils/error.js';\n\ntype MoveFlags = {\n folder?: string;\n from?: string;\n account?: string;\n json?: boolean;\n};\n\nexport default defineCommand({\n id: 'inbox:mail.move',\n description: 'Move an email to a folder',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<MoveFlags>) {\n const [rawUid] = input.argv;\n if (!rawUid) {\n validationError(ctx, 'uid is required', 'Usage: kb inbox move <uid> --folder Work', input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n if (!input.flags.folder) {\n validationError(ctx, '--folder is required', undefined, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n\n const uid = parseInt(rawUid, 10);\n if (isNaN(uid)) {\n validationError(ctx, `Invalid uid: \"${rawUid}\" — must be a number`, undefined, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n\n try {\n const account = resolveAccount(input.flags.account);\n await moveMessage(account, uid, input.flags.from ?? 'INBOX', input.flags.folder);\n\n if (input.flags.json) {\n ctx.ui?.json?.({ ok: true, result: { uid, folder: input.flags.folder } });\n return { ok: true, result: { uid, folder: input.flags.folder } };\n }\n\n ctx.ui?.success?.(`Moved uid=${uid} → ${input.flags.folder}`);\n return { ok: true, result: null };\n } catch (err) {\n handleError(ctx, err, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n },\n },\n});\n"]}
|
|
@@ -74,16 +74,16 @@ var mail_reply_default = defineCommand({
|
|
|
74
74
|
const [rawUid] = input.argv;
|
|
75
75
|
if (!rawUid) {
|
|
76
76
|
validationError(ctx, "uid is required", 'Usage: kb inbox reply <uid> --body "..."', input.flags.json);
|
|
77
|
-
return {
|
|
77
|
+
return { ok: false, error: "Command failed", result: null };
|
|
78
78
|
}
|
|
79
79
|
if (!input.flags.body) {
|
|
80
80
|
validationError(ctx, "--body is required", void 0, input.flags.json);
|
|
81
|
-
return {
|
|
81
|
+
return { ok: false, error: "Command failed", result: null };
|
|
82
82
|
}
|
|
83
83
|
const uid = parseInt(rawUid, 10);
|
|
84
84
|
if (isNaN(uid)) {
|
|
85
85
|
validationError(ctx, `Invalid uid: "${rawUid}" \u2014 must be a number`, void 0, input.flags.json);
|
|
86
|
-
return {
|
|
86
|
+
return { ok: false, error: "Command failed", result: null };
|
|
87
87
|
}
|
|
88
88
|
try {
|
|
89
89
|
const account = resolveAccount(input.flags.account);
|
|
@@ -97,13 +97,13 @@ var mail_reply_default = defineCommand({
|
|
|
97
97
|
}, input.flags.body);
|
|
98
98
|
if (input.flags.json) {
|
|
99
99
|
ctx.ui?.json?.({ ok: true, result });
|
|
100
|
-
return {
|
|
100
|
+
return { ok: true, result };
|
|
101
101
|
}
|
|
102
102
|
ctx.ui?.success?.(`Reply sent id: ${result.messageId}`);
|
|
103
|
-
return {
|
|
103
|
+
return { ok: true, result };
|
|
104
104
|
} catch (err) {
|
|
105
105
|
handleError(ctx, err, input.flags.json);
|
|
106
|
-
return {
|
|
106
|
+
return { ok: false, error: "Command failed", result: null };
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/error.ts","../../src/commands/mail-reply.ts"],"names":[],"mappings":";;;;AAoBA,SAAS,OAAA,CAAQ,MAAsB,OAAA,EAAqC;AAC1E,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,aAAA;AACH,MAAA,OAAO,4GAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,mFAAA,CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,qGAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,qFAAA,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,6DAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,gEAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,yDAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,sFAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,qDAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,0CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,SAAS;AAGP,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAUO,SAAS,WAAA,CAAY,GAAA,EAAsB,GAAA,EAAc,MAAA,EAAwB;AACtF,EAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,OAAO,CAAA;AAE1C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,QACb,EAAA,EAAI,KAAA;AAAA,QACJ,KAAA,EAAO;AAAA,UACL,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,GAAI,IAAA,IAAQ,EAAE,IAAA;AAAK;AACrB,OACD,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,GAAA,CAAI,EAAA,EAAI,KAAA,GAAQ,GAAA,CAAI,OAAA,EAAS;AAAA,QAC3B,GAAI,IAAA,IAAQ,EAAE,IAAA,EAAK;AAAA,QACnB,KAAA,EAAO,CAAA,YAAA,EAAe,GAAA,CAAI,IAAI,CAAA,CAAA;AAAA,OAC/B,CAAA;AAAA,IACH;AACA,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE/D,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,MACb,EAAA,EAAI,KAAA;AAAA,MACJ,KAAA,EAAO,EAAE,IAAA,EAAM,gBAAA,EAAkB,OAAA;AAAQ,KAC1C,CAAA;AAAA,EACH,CAAA,MAAO;AACL,IAAA,GAAA,CAAI,EAAA,EAAI,QAAQ,OAAO,CAAA;AAAA,EACzB;AACF;;;ACpFA,IAAO,qBAAQ,aAAA,CAAc;AAAA,EAC3B,EAAA,EAAI,kBAAA;AAAA,EACJ,WAAA,EAAa,6CAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA6B;AAC/D,MAAA,MAAM,CAAC,MAAM,CAAA,GAAI,KAAA,CAAM,IAAA;AACvB,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,eAAA,CAAgB,GAAA,EAAK,iBAAA,EAAmB,0CAAA,EAA4C,KAAA,CAAM,MAAM,IAAI,CAAA;AACpG,QAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"sources":["../../src/utils/error.ts","../../src/commands/mail-reply.ts"],"names":[],"mappings":"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","file":"mail-reply.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { ok: false, error: 'Command failed', result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import { defineCommand, validationError, type CLIInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { resolveAccount, getMessage, replyMessage } from '@kb-labs/inbox-core';\nimport { handleError } from '../utils/error.js';\n\ntype ReplyFlags = {\n body?: string;\n folder?: string;\n account?: string;\n json?: boolean;\n};\n\nexport default defineCommand({\n id: 'inbox:mail.reply',\n description: 'Reply to an email by uid (preserves thread)',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<ReplyFlags>) {\n const [rawUid] = input.argv;\n if (!rawUid) {\n validationError(ctx, 'uid is required', 'Usage: kb inbox reply <uid> --body \"...\"', input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n if (!input.flags.body) {\n validationError(ctx, '--body is required', undefined, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n\n const uid = parseInt(rawUid, 10);\n if (isNaN(uid)) {\n validationError(ctx, `Invalid uid: \"${rawUid}\" — must be a number`, undefined, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n\n try {\n const account = resolveAccount(input.flags.account);\n const folder = input.flags.folder ?? 'INBOX';\n\n const original = await getMessage(account, uid, { folder });\n const result = await replyMessage(account, {\n body: input.flags.body,\n originalMessageId: original.messageId,\n originalReferences: original.references,\n originalSubject: original.subject,\n }, input.flags.body);\n\n if (input.flags.json) {\n ctx.ui?.json?.({ ok: true, result });\n return { ok: true, result };\n }\n\n ctx.ui?.success?.(`Reply sent id: ${result.messageId}`);\n return { ok: true, result };\n } catch (err) {\n handleError(ctx, err, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n },\n },\n});\n"]}
|
|
@@ -14,6 +14,6 @@ type SearchFlags = {
|
|
|
14
14
|
json?: boolean;
|
|
15
15
|
full?: boolean;
|
|
16
16
|
};
|
|
17
|
-
declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<SearchFlags>, _kb_labs_inbox_contracts.EmailSlim[]
|
|
17
|
+
declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<SearchFlags>, _kb_labs_inbox_contracts.EmailSlim[]>;
|
|
18
18
|
|
|
19
19
|
export { _default as default };
|
|
@@ -108,11 +108,11 @@ var mail_search_default = defineCommand({
|
|
|
108
108
|
});
|
|
109
109
|
if (input.flags.json) {
|
|
110
110
|
ctx.ui?.json?.({ ok: true, result: messages });
|
|
111
|
-
return {
|
|
111
|
+
return { ok: true, result: messages };
|
|
112
112
|
}
|
|
113
113
|
if (!messages.length) {
|
|
114
114
|
ctx.ui?.info?.("No messages found.");
|
|
115
|
-
return {
|
|
115
|
+
return { ok: true, result: messages };
|
|
116
116
|
}
|
|
117
117
|
ctx.ui?.chain?.(messages.map((msg) => ({
|
|
118
118
|
title: `[${msg.uid}] ${msg.unread ? "\u25CF " : ""}${msg.subject}`,
|
|
@@ -122,10 +122,10 @@ var mail_search_default = defineCommand({
|
|
|
122
122
|
]
|
|
123
123
|
}]
|
|
124
124
|
})));
|
|
125
|
-
return {
|
|
125
|
+
return { ok: true, result: messages };
|
|
126
126
|
} catch (err) {
|
|
127
127
|
handleError(ctx, err, input.flags.json);
|
|
128
|
-
return {
|
|
128
|
+
return { ok: false, error: "Command failed", result: null };
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/error.ts","../../src/utils/slim.ts","../../src/commands/mail-search.ts"],"names":[],"mappings":"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","file":"mail-search.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { exitCode: 1, result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import type { Email, EmailSlim } from '@kb-labs/inbox-contracts';\n\nexport function slimEmail(email: Email): EmailSlim {\n return {\n uid: email.uid,\n subject: email.subject,\n from: email.from,\n date: email.date,\n folder: email.folder,\n unread: !email.flags.includes('\\\\Seen'),\n flagged: email.flags.includes('\\\\Flagged'),\n hasAttachments: (email.attachments?.length ?? 0) > 0,\n };\n}\n\nexport function formatDate(iso: string): string {\n const d = new Date(iso);\n const now = new Date();\n const diff = now.getTime() - d.getTime();\n\n if (diff < 60_000) { return 'just now'; }\n if (diff < 3_600_000) { return `${Math.floor(diff / 60_000)}m ago`; }\n if (diff < 86_400_000) { return `${Math.floor(diff / 3_600_000)}h ago`; }\n if (diff < 7 * 86_400_000) { return `${Math.floor(diff / 86_400_000)}d ago`; }\n\n return d.toLocaleDateString();\n}\n\nexport function formatFrom(from: { name?: string; address: string }): string {\n return from.name ? `${from.name} <${from.address}>` : from.address;\n}\n","import { defineCommand, type CLIInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { resolveAccount, searchMessages } from '@kb-labs/inbox-core';\nimport { handleError } from '../utils/error.js';\nimport { formatDate, formatFrom } from '../utils/slim.js';\n\ntype SearchFlags = {\n from?: string;\n subject?: string;\n body?: string;\n text?: string;\n folder?: string;\n since?: string;\n limit?: number;\n account?: string;\n json?: boolean;\n full?: boolean;\n};\n\nexport default defineCommand({\n id: 'inbox:mail.search',\n description: 'Search emails by from, subject, body, or text',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<SearchFlags>) {\n try {\n const account = resolveAccount(input.flags.account);\n const since = input.flags.since ? parseSince(input.flags.since) : undefined;\n\n const messages = await searchMessages(account, {\n from: input.flags.from,\n subject: input.flags.subject,\n body: input.flags.body,\n text: input.flags.text,\n folder: input.flags.folder,\n since,\n limit: input.flags.limit ?? 20,\n });\n\n if (input.flags.json) {\n ctx.ui?.json?.({ ok: true, result: messages });\n return { exitCode: 0, result: messages };\n }\n\n if (!messages.length) {\n ctx.ui?.info?.('No messages found.');\n return { exitCode: 0, result: messages };\n }\n\n ctx.ui?.chain?.(messages.map(msg => ({\n title: `[${msg.uid}] ${msg.unread ? '● ' : ''}${msg.subject}`,\n sections: [{\n items: [\n `from: ${formatFrom(msg.from)} ${formatDate(msg.date)} folder: ${msg.folder}`,\n ],\n }],\n })));\n\n return { exitCode: 0, result: messages };\n } catch (err) {\n handleError(ctx, err, input.flags.json);\n return { exitCode: 1, result: null };\n }\n },\n },\n});\n\nfunction parseSince(raw: string): Date {\n const match = raw.match(/^(\\d+)(h|d|w)$/i);\n if (match) {\n const n = parseInt(match[1] ?? '0', 10);\n const unit = (match[2] ?? 'h').toLowerCase();\n const ms = unit === 'h' ? n * 3_600_000 : unit === 'd' ? n * 86_400_000 : n * 7 * 86_400_000;\n return new Date(Date.now() - ms);\n }\n return new Date(raw);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/error.ts","../../src/utils/slim.ts","../../src/commands/mail-search.ts"],"names":[],"mappings":";;;;AAoBA,SAAS,OAAA,CAAQ,MAAsB,OAAA,EAAqC;AAC1E,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,aAAA;AACH,MAAA,OAAO,4GAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,mFAAA,CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,qGAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,qFAAA,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,6DAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,gEAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,yDAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,sFAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,qDAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,0CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,SAAS;AAGP,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAUO,SAAS,WAAA,CAAY,GAAA,EAAsB,GAAA,EAAc,MAAA,EAAwB;AACtF,EAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,OAAO,CAAA;AAE1C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,QACb,EAAA,EAAI,KAAA;AAAA,QACJ,KAAA,EAAO;AAAA,UACL,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,GAAI,IAAA,IAAQ,EAAE,IAAA;AAAK;AACrB,OACD,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,GAAA,CAAI,EAAA,EAAI,KAAA,GAAQ,GAAA,CAAI,OAAA,EAAS;AAAA,QAC3B,GAAI,IAAA,IAAQ,EAAE,IAAA,EAAK;AAAA,QACnB,KAAA,EAAO,CAAA,YAAA,EAAe,GAAA,CAAI,IAAI,CAAA,CAAA;AAAA,OAC/B,CAAA;AAAA,IACH;AACA,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE/D,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,MACb,EAAA,EAAI,KAAA;AAAA,MACJ,KAAA,EAAO,EAAE,IAAA,EAAM,gBAAA,EAAkB,OAAA;AAAQ,KAC1C,CAAA;AAAA,EACH,CAAA,MAAO;AACL,IAAA,GAAA,CAAI,EAAA,EAAI,QAAQ,OAAO,CAAA;AAAA,EACzB;AACF;;;AChFO,SAAS,WAAW,GAAA,EAAqB;AAC9C,EAAA,MAAM,CAAA,GAAI,IAAI,IAAA,CAAK,GAAG,CAAA;AACtB,EAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AACrB,EAAA,MAAM,IAAA,GAAO,GAAA,CAAI,OAAA,EAAQ,GAAI,EAAE,OAAA,EAAQ;AAEvC,EAAA,IAAI,OAAO,GAAA,EAAQ;AAAE,IAAA,OAAO,UAAA;AAAA,EAAY;AACxC,EAAA,IAAI,OAAO,IAAA,EAAW;AAAE,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,GAAM,CAAC,CAAA,KAAA,CAAA;AAAA,EAAS;AACpE,EAAA,IAAI,OAAO,KAAA,EAAY;AAAE,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,IAAS,CAAC,CAAA,KAAA,CAAA;AAAA,EAAS;AACxE,EAAA,IAAI,IAAA,GAAO,IAAI,KAAA,EAAY;AAAE,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,KAAU,CAAC,CAAA,KAAA,CAAA;AAAA,EAAS;AAE7E,EAAA,OAAO,EAAE,kBAAA,EAAmB;AAC9B;AAEO,SAAS,WAAW,IAAA,EAAkD;AAC3E,EAAA,OAAO,IAAA,CAAK,OAAO,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,EAAA,EAAK,IAAA,CAAK,OAAO,CAAA,CAAA,CAAA,GAAM,IAAA,CAAK,OAAA;AAC7D;;;ACZA,IAAO,sBAAQ,aAAA,CAAc;AAAA,EAC3B,EAAA,EAAI,mBAAA;AAAA,EACJ,WAAA,EAAa,+CAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA8B;AAChE,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,cAAA,CAAe,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA;AAClD,QAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,KAAA,GAAQ,WAAW,KAAA,CAAM,KAAA,CAAM,KAAK,CAAA,GAAI,KAAA,CAAA;AAElE,QAAA,MAAM,QAAA,GAAW,MAAM,cAAA,CAAe,OAAA,EAAS;AAAA,UAC7C,IAAA,EAAM,MAAM,KAAA,CAAM,IAAA;AAAA,UAClB,OAAA,EAAS,MAAM,KAAA,CAAM,OAAA;AAAA,UACrB,IAAA,EAAM,MAAM,KAAA,CAAM,IAAA;AAAA,UAClB,IAAA,EAAM,MAAM,KAAA,CAAM,IAAA;AAAA,UAClB,MAAA,EAAQ,MAAM,KAAA,CAAM,MAAA;AAAA,UACpB,KAAA;AAAA,UACA,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,KAAA,IAAS;AAAA,SAC7B,CAAA;AAED,QAAA,IAAI,KAAA,CAAM,MAAM,IAAA,EAAM;AACpB,UAAA,GAAA,CAAI,IAAI,IAAA,GAAO,EAAE,IAAI,IAAA,EAAM,MAAA,EAAQ,UAAU,CAAA;AAC7C,UAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAS;AAAA,QACtC;AAEA,QAAA,IAAI,CAAC,SAAS,MAAA,EAAQ;AACpB,UAAA,GAAA,CAAI,EAAA,EAAI,OAAO,oBAAoB,CAAA;AACnC,UAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAS;AAAA,QACtC;AAEA,QAAA,GAAA,CAAI,EAAA,EAAI,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,CAAA,GAAA,MAAQ;AAAA,UACnC,KAAA,EAAO,CAAA,CAAA,EAAI,GAAA,CAAI,GAAG,CAAA,EAAA,EAAK,GAAA,CAAI,MAAA,GAAS,SAAA,GAAO,EAAE,CAAA,EAAG,GAAA,CAAI,OAAO,CAAA,CAAA;AAAA,UAC3D,UAAU,CAAC;AAAA,YACT,KAAA,EAAO;AAAA,cACL,CAAA,MAAA,EAAS,UAAA,CAAW,GAAA,CAAI,IAAI,CAAC,CAAA,EAAA,EAAK,UAAA,CAAW,GAAA,CAAI,IAAI,CAAC,CAAA,UAAA,EAAa,GAAA,CAAI,MAAM,CAAA;AAAA;AAC/E,WACD;AAAA,UACD,CAAC,CAAA;AAEH,QAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAS;AAAA,MACtC,SAAS,GAAA,EAAK;AACZ,QAAA,WAAA,CAAY,GAAA,EAAK,GAAA,EAAK,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AACtC,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,gBAAA,EAAkB,QAAQ,IAAA,EAAK;AAAA,MAC5D;AAAA,IACF;AAAA;AAEJ,CAAC;AAED,SAAS,WAAW,GAAA,EAAmB;AACrC,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,iBAAiB,CAAA;AACzC,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,MAAM,IAAI,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,IAAK,KAAK,EAAE,CAAA;AACtC,IAAA,MAAM,IAAA,GAAA,CAAQ,KAAA,CAAM,CAAC,CAAA,IAAK,KAAK,WAAA,EAAY;AAC3C,IAAA,MAAM,EAAA,GAAK,IAAA,KAAS,GAAA,GAAM,CAAA,GAAI,IAAA,GAAY,SAAS,GAAA,GAAM,CAAA,GAAI,KAAA,GAAa,CAAA,GAAI,CAAA,GAAI,KAAA;AAClF,IAAA,OAAO,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,KAAQ,EAAE,CAAA;AAAA,EACjC;AACA,EAAA,OAAO,IAAI,KAAK,GAAG,CAAA;AACrB","file":"mail-search.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { ok: false, error: 'Command failed', result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import type { Email, EmailSlim } from '@kb-labs/inbox-contracts';\n\nexport function slimEmail(email: Email): EmailSlim {\n return {\n uid: email.uid,\n subject: email.subject,\n from: email.from,\n date: email.date,\n folder: email.folder,\n unread: !email.flags.includes('\\\\Seen'),\n flagged: email.flags.includes('\\\\Flagged'),\n hasAttachments: (email.attachments?.length ?? 0) > 0,\n };\n}\n\nexport function formatDate(iso: string): string {\n const d = new Date(iso);\n const now = new Date();\n const diff = now.getTime() - d.getTime();\n\n if (diff < 60_000) { return 'just now'; }\n if (diff < 3_600_000) { return `${Math.floor(diff / 60_000)}m ago`; }\n if (diff < 86_400_000) { return `${Math.floor(diff / 3_600_000)}h ago`; }\n if (diff < 7 * 86_400_000) { return `${Math.floor(diff / 86_400_000)}d ago`; }\n\n return d.toLocaleDateString();\n}\n\nexport function formatFrom(from: { name?: string; address: string }): string {\n return from.name ? `${from.name} <${from.address}>` : from.address;\n}\n","import { defineCommand, type CLIInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { resolveAccount, searchMessages } from '@kb-labs/inbox-core';\nimport { handleError } from '../utils/error.js';\nimport { formatDate, formatFrom } from '../utils/slim.js';\n\ntype SearchFlags = {\n from?: string;\n subject?: string;\n body?: string;\n text?: string;\n folder?: string;\n since?: string;\n limit?: number;\n account?: string;\n json?: boolean;\n full?: boolean;\n};\n\nexport default defineCommand({\n id: 'inbox:mail.search',\n description: 'Search emails by from, subject, body, or text',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<SearchFlags>) {\n try {\n const account = resolveAccount(input.flags.account);\n const since = input.flags.since ? parseSince(input.flags.since) : undefined;\n\n const messages = await searchMessages(account, {\n from: input.flags.from,\n subject: input.flags.subject,\n body: input.flags.body,\n text: input.flags.text,\n folder: input.flags.folder,\n since,\n limit: input.flags.limit ?? 20,\n });\n\n if (input.flags.json) {\n ctx.ui?.json?.({ ok: true, result: messages });\n return { ok: true, result: messages };\n }\n\n if (!messages.length) {\n ctx.ui?.info?.('No messages found.');\n return { ok: true, result: messages };\n }\n\n ctx.ui?.chain?.(messages.map(msg => ({\n title: `[${msg.uid}] ${msg.unread ? '● ' : ''}${msg.subject}`,\n sections: [{\n items: [\n `from: ${formatFrom(msg.from)} ${formatDate(msg.date)} folder: ${msg.folder}`,\n ],\n }],\n })));\n\n return { ok: true, result: messages };\n } catch (err) {\n handleError(ctx, err, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n },\n },\n});\n\nfunction parseSince(raw: string): Date {\n const match = raw.match(/^(\\d+)(h|d|w)$/i);\n if (match) {\n const n = parseInt(match[1] ?? '0', 10);\n const unit = (match[2] ?? 'h').toLowerCase();\n const ms = unit === 'h' ? n * 3_600_000 : unit === 'd' ? n * 86_400_000 : n * 7 * 86_400_000;\n return new Date(Date.now() - ms);\n }\n return new Date(raw);\n}\n"]}
|
|
@@ -73,15 +73,15 @@ var mail_send_default = defineCommand({
|
|
|
73
73
|
async execute(ctx, input) {
|
|
74
74
|
if (!input.flags.to) {
|
|
75
75
|
validationError(ctx, "--to is required", 'Usage: kb inbox send --to user@example.com --subject "..." --body "..."', input.flags.json);
|
|
76
|
-
return {
|
|
76
|
+
return { ok: false, error: "Command failed", result: null };
|
|
77
77
|
}
|
|
78
78
|
if (!input.flags.subject) {
|
|
79
79
|
validationError(ctx, "--subject is required", void 0, input.flags.json);
|
|
80
|
-
return {
|
|
80
|
+
return { ok: false, error: "Command failed", result: null };
|
|
81
81
|
}
|
|
82
82
|
if (!input.flags.body) {
|
|
83
83
|
validationError(ctx, "--body is required", void 0, input.flags.json);
|
|
84
|
-
return {
|
|
84
|
+
return { ok: false, error: "Command failed", result: null };
|
|
85
85
|
}
|
|
86
86
|
try {
|
|
87
87
|
const account = resolveAccount(input.flags.account);
|
|
@@ -94,13 +94,13 @@ var mail_send_default = defineCommand({
|
|
|
94
94
|
});
|
|
95
95
|
if (input.flags.json) {
|
|
96
96
|
ctx.ui?.json?.({ ok: true, result });
|
|
97
|
-
return {
|
|
97
|
+
return { ok: true, result };
|
|
98
98
|
}
|
|
99
99
|
ctx.ui?.success?.(`Message sent id: ${result.messageId}`);
|
|
100
|
-
return {
|
|
100
|
+
return { ok: true, result };
|
|
101
101
|
} catch (err) {
|
|
102
102
|
handleError(ctx, err, input.flags.json);
|
|
103
|
-
return {
|
|
103
|
+
return { ok: false, error: "Command failed", result: null };
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/error.ts","../../src/commands/mail-send.ts"],"names":[],"mappings":";;;;AAoBA,SAAS,OAAA,CAAQ,MAAsB,OAAA,EAAqC;AAC1E,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,aAAA;AACH,MAAA,OAAO,4GAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,mFAAA,CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,qGAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,qFAAA,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,6DAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,gEAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,yDAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,sFAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,qDAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,0CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,SAAS;AAGP,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAUO,SAAS,WAAA,CAAY,GAAA,EAAsB,GAAA,EAAc,MAAA,EAAwB;AACtF,EAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,OAAO,CAAA;AAE1C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,QACb,EAAA,EAAI,KAAA;AAAA,QACJ,KAAA,EAAO;AAAA,UACL,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,GAAI,IAAA,IAAQ,EAAE,IAAA;AAAK;AACrB,OACD,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,GAAA,CAAI,EAAA,EAAI,KAAA,GAAQ,GAAA,CAAI,OAAA,EAAS;AAAA,QAC3B,GAAI,IAAA,IAAQ,EAAE,IAAA,EAAK;AAAA,QACnB,KAAA,EAAO,CAAA,YAAA,EAAe,GAAA,CAAI,IAAI,CAAA,CAAA;AAAA,OAC/B,CAAA;AAAA,IACH;AACA,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE/D,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,MACb,EAAA,EAAI,KAAA;AAAA,MACJ,KAAA,EAAO,EAAE,IAAA,EAAM,gBAAA,EAAkB,OAAA;AAAQ,KAC1C,CAAA;AAAA,EACH,CAAA,MAAO;AACL,IAAA,GAAA,CAAI,EAAA,EAAI,QAAQ,OAAO,CAAA;AAAA,EACzB;AACF;;;ACjFA,IAAO,oBAAQ,aAAA,CAAc;AAAA,EAC3B,EAAA,EAAI,iBAAA;AAAA,EACJ,WAAA,EAAa,eAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA4B;AAC9D,MAAA,IAAI,CAAC,KAAA,CAAM,KAAA,CAAM,EAAA,EAAI;AACnB,QAAA,eAAA,CAAgB,GAAA,EAAK,kBAAA,EAAoB,yEAAA,EAA2E,KAAA,CAAM,MAAM,IAAI,CAAA;AACpI,QAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"sources":["../../src/utils/error.ts","../../src/commands/mail-send.ts"],"names":[],"mappings":";;;;AAoBA,SAAS,OAAA,CAAQ,MAAsB,OAAA,EAAqC;AAC1E,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,aAAA;AACH,MAAA,OAAO,4GAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,mFAAA,CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,qGAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,qFAAA,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,6DAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,gEAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,yDAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,sFAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,qDAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,0CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,SAAS;AAGP,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAUO,SAAS,WAAA,CAAY,GAAA,EAAsB,GAAA,EAAc,MAAA,EAAwB;AACtF,EAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,OAAO,CAAA;AAE1C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,QACb,EAAA,EAAI,KAAA;AAAA,QACJ,KAAA,EAAO;AAAA,UACL,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,GAAI,IAAA,IAAQ,EAAE,IAAA;AAAK;AACrB,OACD,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,GAAA,CAAI,EAAA,EAAI,KAAA,GAAQ,GAAA,CAAI,OAAA,EAAS;AAAA,QAC3B,GAAI,IAAA,IAAQ,EAAE,IAAA,EAAK;AAAA,QACnB,KAAA,EAAO,CAAA,YAAA,EAAe,GAAA,CAAI,IAAI,CAAA,CAAA;AAAA,OAC/B,CAAA;AAAA,IACH;AACA,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE/D,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,GAAA,CAAI,IAAI,IAAA,GAAO;AAAA,MACb,EAAA,EAAI,KAAA;AAAA,MACJ,KAAA,EAAO,EAAE,IAAA,EAAM,gBAAA,EAAkB,OAAA;AAAQ,KAC1C,CAAA;AAAA,EACH,CAAA,MAAO;AACL,IAAA,GAAA,CAAI,EAAA,EAAI,QAAQ,OAAO,CAAA;AAAA,EACzB;AACF;;;ACjFA,IAAO,oBAAQ,aAAA,CAAc;AAAA,EAC3B,EAAA,EAAI,iBAAA;AAAA,EACJ,WAAA,EAAa,eAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA4B;AAC9D,MAAA,IAAI,CAAC,KAAA,CAAM,KAAA,CAAM,EAAA,EAAI;AACnB,QAAA,eAAA,CAAgB,GAAA,EAAK,kBAAA,EAAoB,yEAAA,EAA2E,KAAA,CAAM,MAAM,IAAI,CAAA;AACpI,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,gBAAA,EAAkB,QAAQ,IAAA,EAAK;AAAA,MAC5D;AACA,MAAA,IAAI,CAAC,KAAA,CAAM,KAAA,CAAM,OAAA,EAAS;AACxB,QAAA,eAAA,CAAgB,GAAA,EAAK,uBAAA,EAAyB,MAAA,EAAW,KAAA,CAAM,MAAM,IAAI,CAAA;AACzE,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,gBAAA,EAAkB,QAAQ,IAAA,EAAK;AAAA,MAC5D;AACA,MAAA,IAAI,CAAC,KAAA,CAAM,KAAA,CAAM,IAAA,EAAM;AACrB,QAAA,eAAA,CAAgB,GAAA,EAAK,oBAAA,EAAsB,MAAA,EAAW,KAAA,CAAM,MAAM,IAAI,CAAA;AACtE,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,gBAAA,EAAkB,QAAQ,IAAA,EAAK;AAAA,MAC5D;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,cAAA,CAAe,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA;AAClD,QAAA,MAAM,MAAA,GAAS,MAAM,WAAA,CAAY,OAAA,EAAS;AAAA,UACxC,EAAA,EAAI,MAAM,KAAA,CAAM,EAAA;AAAA,UAChB,OAAA,EAAS,MAAM,KAAA,CAAM,OAAA;AAAA,UACrB,IAAA,EAAM,MAAM,KAAA,CAAM,IAAA;AAAA,UAClB,EAAA,EAAI,MAAM,KAAA,CAAM,EAAA;AAAA,UAChB,GAAA,EAAK,MAAM,KAAA,CAAM;AAAA,SAClB,CAAA;AAED,QAAA,IAAI,KAAA,CAAM,MAAM,IAAA,EAAM;AACpB,UAAA,GAAA,CAAI,IAAI,IAAA,GAAO,EAAE,EAAA,EAAI,IAAA,EAAM,QAAQ,CAAA;AACnC,UAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAO;AAAA,QAC5B;AAEA,QAAA,GAAA,CAAI,EAAA,EAAI,OAAA,GAAU,CAAA,kBAAA,EAAqB,MAAA,CAAO,SAAS,CAAA,CAAE,CAAA;AACvD,QAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAO;AAAA,MAC9B,SAAS,GAAA,EAAK;AACZ,QAAA,WAAA,CAAY,GAAA,EAAK,GAAA,EAAK,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AACtC,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,gBAAA,EAAkB,QAAQ,IAAA,EAAK;AAAA,MAC5D;AAAA,IACF;AAAA;AAEJ,CAAC","file":"mail-send.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { ok: false, error: 'Command failed', result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import { defineCommand, validationError, type CLIInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { resolveAccount, sendMessage } from '@kb-labs/inbox-core';\nimport { handleError } from '../utils/error.js';\n\ntype SendFlags = {\n to?: string;\n subject?: string;\n body?: string;\n cc?: string;\n bcc?: string;\n account?: string;\n json?: boolean;\n};\n\nexport default defineCommand({\n id: 'inbox:mail.send',\n description: 'Send an email',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<SendFlags>) {\n if (!input.flags.to) {\n validationError(ctx, '--to is required', 'Usage: kb inbox send --to user@example.com --subject \"...\" --body \"...\"', input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n if (!input.flags.subject) {\n validationError(ctx, '--subject is required', undefined, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n if (!input.flags.body) {\n validationError(ctx, '--body is required', undefined, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n\n try {\n const account = resolveAccount(input.flags.account);\n const result = await sendMessage(account, {\n to: input.flags.to,\n subject: input.flags.subject,\n body: input.flags.body,\n cc: input.flags.cc,\n bcc: input.flags.bcc,\n });\n\n if (input.flags.json) {\n ctx.ui?.json?.({ ok: true, result });\n return { ok: true, result };\n }\n\n ctx.ui?.success?.(`Message sent id: ${result.messageId}`);\n return { ok: true, result };\n } catch (err) {\n handleError(ctx, err, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n },\n },\n});\n"]}
|
|
@@ -8,6 +8,6 @@ type ThreadFlags = {
|
|
|
8
8
|
json?: boolean;
|
|
9
9
|
full?: boolean;
|
|
10
10
|
};
|
|
11
|
-
declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<ThreadFlags>, _kb_labs_inbox_contracts.Email[]
|
|
11
|
+
declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<ThreadFlags>, _kb_labs_inbox_contracts.Email[]>;
|
|
12
12
|
|
|
13
13
|
export { _default as default };
|
|
@@ -97,12 +97,12 @@ var mail_thread_default = defineCommand({
|
|
|
97
97
|
const [rawUid] = input.argv;
|
|
98
98
|
if (!rawUid) {
|
|
99
99
|
validationError(ctx, "uid is required", "Usage: kb inbox thread <uid>", input.flags.json);
|
|
100
|
-
return {
|
|
100
|
+
return { ok: false, error: "Command failed", result: null };
|
|
101
101
|
}
|
|
102
102
|
const uid = parseInt(rawUid, 10);
|
|
103
103
|
if (isNaN(uid)) {
|
|
104
104
|
validationError(ctx, `Invalid uid: "${rawUid}" \u2014 must be a number`, void 0, input.flags.json);
|
|
105
|
-
return {
|
|
105
|
+
return { ok: false, error: "Command failed", result: null };
|
|
106
106
|
}
|
|
107
107
|
try {
|
|
108
108
|
const account = resolveAccount(input.flags.account);
|
|
@@ -111,7 +111,7 @@ var mail_thread_default = defineCommand({
|
|
|
111
111
|
});
|
|
112
112
|
if (input.flags.json) {
|
|
113
113
|
ctx.ui?.json?.({ ok: true, result: thread });
|
|
114
|
-
return {
|
|
114
|
+
return { ok: true, result: thread };
|
|
115
115
|
}
|
|
116
116
|
ctx.ui?.info?.(`Thread: ${thread.length} message${thread.length !== 1 ? "s" : ""}`);
|
|
117
117
|
ctx.ui?.chain?.(thread.map((msg, i) => ({
|
|
@@ -123,10 +123,10 @@ var mail_thread_default = defineCommand({
|
|
|
123
123
|
]
|
|
124
124
|
}]
|
|
125
125
|
})));
|
|
126
|
-
return {
|
|
126
|
+
return { ok: true, result: thread };
|
|
127
127
|
} catch (err) {
|
|
128
128
|
handleError(ctx, err, input.flags.json);
|
|
129
|
-
return {
|
|
129
|
+
return { ok: false, error: "Command failed", result: null };
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/error.ts","../../src/utils/slim.ts","../../src/commands/mail-thread.ts"],"names":[],"mappings":"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","file":"mail-thread.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { exitCode: 1, result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import type { Email, EmailSlim } from '@kb-labs/inbox-contracts';\n\nexport function slimEmail(email: Email): EmailSlim {\n return {\n uid: email.uid,\n subject: email.subject,\n from: email.from,\n date: email.date,\n folder: email.folder,\n unread: !email.flags.includes('\\\\Seen'),\n flagged: email.flags.includes('\\\\Flagged'),\n hasAttachments: (email.attachments?.length ?? 0) > 0,\n };\n}\n\nexport function formatDate(iso: string): string {\n const d = new Date(iso);\n const now = new Date();\n const diff = now.getTime() - d.getTime();\n\n if (diff < 60_000) { return 'just now'; }\n if (diff < 3_600_000) { return `${Math.floor(diff / 60_000)}m ago`; }\n if (diff < 86_400_000) { return `${Math.floor(diff / 3_600_000)}h ago`; }\n if (diff < 7 * 86_400_000) { return `${Math.floor(diff / 86_400_000)}d ago`; }\n\n return d.toLocaleDateString();\n}\n\nexport function formatFrom(from: { name?: string; address: string }): string {\n return from.name ? `${from.name} <${from.address}>` : from.address;\n}\n","import { defineCommand, validationError, type CLIInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { resolveAccount, getThread } from '@kb-labs/inbox-core';\nimport { handleError } from '../utils/error.js';\nimport { formatDate, formatFrom } from '../utils/slim.js';\n\ntype ThreadFlags = {\n folder?: string;\n account?: string;\n json?: boolean;\n full?: boolean;\n};\n\nexport default defineCommand({\n id: 'inbox:mail.thread',\n description: 'Get full email thread by uid',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<ThreadFlags>) {\n const [rawUid] = input.argv;\n if (!rawUid) {\n validationError(ctx, 'uid is required', 'Usage: kb inbox thread <uid>', input.flags.json);\n return { exitCode: 1, result: null };\n }\n\n const uid = parseInt(rawUid, 10);\n if (isNaN(uid)) {\n validationError(ctx, `Invalid uid: \"${rawUid}\" — must be a number`, undefined, input.flags.json);\n return { exitCode: 1, result: null };\n }\n\n try {\n const account = resolveAccount(input.flags.account);\n const thread = await getThread(account, uid, {\n folder: input.flags.folder ?? 'INBOX',\n });\n\n if (input.flags.json) {\n ctx.ui?.json?.({ ok: true, result: thread });\n return { exitCode: 0, result: thread };\n }\n\n ctx.ui?.info?.(`Thread: ${thread.length} message${thread.length !== 1 ? 's' : ''}`);\n\n ctx.ui?.chain?.(thread.map((msg, i) => ({\n title: `[${i + 1}/${thread.length}] [uid:${msg.uid}] ${msg.subject}`,\n sections: [{\n items: [\n `from: ${formatFrom(msg.from)} ${formatDate(msg.date)}`,\n msg.text ? msg.text.slice(0, 500) : '(no text body)',\n ],\n }],\n })));\n\n return { exitCode: 0, result: thread };\n } catch (err) {\n handleError(ctx, err, input.flags.json);\n return { exitCode: 1, result: null };\n }\n },\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/error.ts","../../src/utils/slim.ts","../../src/commands/mail-thread.ts"],"names":[],"mappings":"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","file":"mail-thread.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { ok: false, error: 'Command failed', result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import type { Email, EmailSlim } from '@kb-labs/inbox-contracts';\n\nexport function slimEmail(email: Email): EmailSlim {\n return {\n uid: email.uid,\n subject: email.subject,\n from: email.from,\n date: email.date,\n folder: email.folder,\n unread: !email.flags.includes('\\\\Seen'),\n flagged: email.flags.includes('\\\\Flagged'),\n hasAttachments: (email.attachments?.length ?? 0) > 0,\n };\n}\n\nexport function formatDate(iso: string): string {\n const d = new Date(iso);\n const now = new Date();\n const diff = now.getTime() - d.getTime();\n\n if (diff < 60_000) { return 'just now'; }\n if (diff < 3_600_000) { return `${Math.floor(diff / 60_000)}m ago`; }\n if (diff < 86_400_000) { return `${Math.floor(diff / 3_600_000)}h ago`; }\n if (diff < 7 * 86_400_000) { return `${Math.floor(diff / 86_400_000)}d ago`; }\n\n return d.toLocaleDateString();\n}\n\nexport function formatFrom(from: { name?: string; address: string }): string {\n return from.name ? `${from.name} <${from.address}>` : from.address;\n}\n","import { defineCommand, validationError, type CLIInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { resolveAccount, getThread } from '@kb-labs/inbox-core';\nimport { handleError } from '../utils/error.js';\nimport { formatDate, formatFrom } from '../utils/slim.js';\n\ntype ThreadFlags = {\n folder?: string;\n account?: string;\n json?: boolean;\n full?: boolean;\n};\n\nexport default defineCommand({\n id: 'inbox:mail.thread',\n description: 'Get full email thread by uid',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<ThreadFlags>) {\n const [rawUid] = input.argv;\n if (!rawUid) {\n validationError(ctx, 'uid is required', 'Usage: kb inbox thread <uid>', input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n\n const uid = parseInt(rawUid, 10);\n if (isNaN(uid)) {\n validationError(ctx, `Invalid uid: \"${rawUid}\" — must be a number`, undefined, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n\n try {\n const account = resolveAccount(input.flags.account);\n const thread = await getThread(account, uid, {\n folder: input.flags.folder ?? 'INBOX',\n });\n\n if (input.flags.json) {\n ctx.ui?.json?.({ ok: true, result: thread });\n return { ok: true, result: thread };\n }\n\n ctx.ui?.info?.(`Thread: ${thread.length} message${thread.length !== 1 ? 's' : ''}`);\n\n ctx.ui?.chain?.(thread.map((msg, i) => ({\n title: `[${i + 1}/${thread.length}] [uid:${msg.uid}] ${msg.subject}`,\n sections: [{\n items: [\n `from: ${formatFrom(msg.from)} ${formatDate(msg.date)}`,\n msg.text ? msg.text.slice(0, 500) : '(no text body)',\n ],\n }],\n })));\n\n return { ok: true, result: thread };\n } catch (err) {\n handleError(ctx, err, input.flags.json);\n return { ok: false, error: 'Command failed', result: null };\n }\n },\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/accounts-handler.ts"],"names":[],"mappings":";;;;AAIA,IAAM,WAAA,GAA8C;AAAA,EAClD,WAAA,EAAwB,GAAA;AAAA,EACxB,iBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,mBAAA,EAAwB,GAAA;AAAA,EACxB,YAAA,EAAwB,GAAA;AAAA,EACxB,sBAAA,EAAwB,GAAA;AAAA,EACxB,iBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,mBAAA,EAAwB,GAAA;AAAA,EACxB,sBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,cAAA,EAAwB;AAC1B,CAAA;AAGA,SAAS,OAAA,CAAQ,MAAsB,OAAA,EAAqC;AAC1E,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,aAAA;AACH,MAAA,OAAO,4GAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,mFAAA,CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,qGAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,qFAAA,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,6DAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,gEAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,yDAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,sFAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,qDAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,0CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,SAAS;AAGP,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAiDO,SAAS,eAAe,GAAA,EAAqB;AAClD,EAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,OAAO,CAAA;AAC1C,IAAA,MAAM,OAAO,MAAA,CAAO,IAAI,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA,EAAG;AAAA,MAC1C,UAAA,EAAY,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA,IAAK,GAAA;AAAA,MACrC,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,OAAA,EAAS,IAAA,GAAO,EAAE,IAAA,EAAK,GAAI;AAAA,KAC5B,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,EAAA,MAAM,MAAA,CAAO,MAAA,CAAO,IAAI,KAAA,CAAM,OAAO,CAAA,EAAG;AAAA,IACtC,UAAA,EAAY,GAAA;AAAA,IACZ,IAAA,EAAM;AAAA,GACP,CAAA;AACH;;;AChHA,IAAO,2BAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CAAQ,IAAA,EAAuB,MAAA,EAAwC;AAC3E,IAAA,IAAI;AACF,MAAA,MAAM,WAAW,YAAA,EAAa;AAC9B,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAS;AAAA,IACtC,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"accounts-handler.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return {
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/accounts-handler.ts"],"names":[],"mappings":";;;;AAIA,IAAM,WAAA,GAA8C;AAAA,EAClD,WAAA,EAAwB,GAAA;AAAA,EACxB,iBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,mBAAA,EAAwB,GAAA;AAAA,EACxB,YAAA,EAAwB,GAAA;AAAA,EACxB,sBAAA,EAAwB,GAAA;AAAA,EACxB,iBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,mBAAA,EAAwB,GAAA;AAAA,EACxB,sBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,cAAA,EAAwB;AAC1B,CAAA;AAGA,SAAS,OAAA,CAAQ,MAAsB,OAAA,EAAqC;AAC1E,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,aAAA;AACH,MAAA,OAAO,4GAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,mFAAA,CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,qGAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,qFAAA,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,6DAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,gEAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,yDAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,sFAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,qDAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,0CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,SAAS;AAGP,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAiDO,SAAS,eAAe,GAAA,EAAqB;AAClD,EAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,OAAO,CAAA;AAC1C,IAAA,MAAM,OAAO,MAAA,CAAO,IAAI,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA,EAAG;AAAA,MAC1C,UAAA,EAAY,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA,IAAK,GAAA;AAAA,MACrC,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,OAAA,EAAS,IAAA,GAAO,EAAE,IAAA,EAAK,GAAI;AAAA,KAC5B,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,EAAA,MAAM,MAAA,CAAO,MAAA,CAAO,IAAI,KAAA,CAAM,OAAO,CAAA,EAAG;AAAA,IACtC,UAAA,EAAY,GAAA;AAAA,IACZ,IAAA,EAAM;AAAA,GACP,CAAA;AACH;;;AChHA,IAAO,2BAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CAAQ,IAAA,EAAuB,MAAA,EAAwC;AAC3E,IAAA,IAAI;AACF,MAAA,MAAM,WAAW,YAAA,EAAa;AAC9B,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAS;AAAA,IACtC,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"accounts-handler.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { ok: false, error: 'Command failed', result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { listAccounts } from '@kb-labs/inbox-core';\nimport { rethrowForRest } from '../../utils/error.js';\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, _input: RestInput<never, never, never>) {\n try {\n const accounts = listAccounts();\n return { ok: true, result: accounts };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/delete-handler.ts"],"names":[],"mappings":"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","file":"delete-handler.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return {
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/delete-handler.ts"],"names":[],"mappings":"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","file":"delete-handler.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { ok: false, error: 'Command failed', result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, deleteMessage } from '@kb-labs/inbox-core';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Query = { folder?: string; account?: string };\ntype Params = { uid: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<Query, never, Params>) {\n try {\n const uid = parseInt(input.params?.uid ?? '', 10);\n if (isNaN(uid)) { throw Object.assign(new Error('uid must be a number'), { statusCode: 400, code: 'VALIDATION_ERROR' }); }\n\n const q = input.query ?? {};\n const account = resolveAccount(q.account);\n await deleteMessage(account, uid, q.folder ?? 'INBOX');\n\n return { ok: true, result: { uid, deleted: true } };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/folders-handler.ts"],"names":[],"mappings":";;;;AAIA,IAAM,WAAA,GAA8C;AAAA,EAClD,WAAA,EAAwB,GAAA;AAAA,EACxB,iBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,mBAAA,EAAwB,GAAA;AAAA,EACxB,YAAA,EAAwB,GAAA;AAAA,EACxB,sBAAA,EAAwB,GAAA;AAAA,EACxB,iBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,mBAAA,EAAwB,GAAA;AAAA,EACxB,sBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,cAAA,EAAwB;AAC1B,CAAA;AAGA,SAAS,OAAA,CAAQ,MAAsB,OAAA,EAAqC;AAC1E,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,aAAA;AACH,MAAA,OAAO,4GAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,mFAAA,CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,qGAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,qFAAA,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,6DAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,gEAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,yDAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,sFAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,qDAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,0CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,SAAS;AAGP,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAiDO,SAAS,eAAe,GAAA,EAAqB;AAClD,EAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,OAAO,CAAA;AAC1C,IAAA,MAAM,OAAO,MAAA,CAAO,IAAI,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA,EAAG;AAAA,MAC1C,UAAA,EAAY,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA,IAAK,GAAA;AAAA,MACrC,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,OAAA,EAAS,IAAA,GAAO,EAAE,IAAA,EAAK,GAAI;AAAA,KAC5B,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,EAAA,MAAM,MAAA,CAAO,MAAA,CAAO,IAAI,KAAA,CAAM,OAAO,CAAA,EAAG;AAAA,IACtC,UAAA,EAAY,GAAA;AAAA,IACZ,IAAA,EAAM;AAAA,GACP,CAAA;AACH;;;AC9GA,IAAO,0BAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CAAQ,IAAA,EAAuB,KAAA,EAAuC;AAC1E,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,cAAA,CAAe,KAAA,CAAM,KAAA,EAAO,OAAO,CAAA;AACnD,MAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,OAAO,CAAA;AACzC,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAQ;AAAA,IACrC,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"folders-handler.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return {
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/folders-handler.ts"],"names":[],"mappings":";;;;AAIA,IAAM,WAAA,GAA8C;AAAA,EAClD,WAAA,EAAwB,GAAA;AAAA,EACxB,iBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,mBAAA,EAAwB,GAAA;AAAA,EACxB,YAAA,EAAwB,GAAA;AAAA,EACxB,sBAAA,EAAwB,GAAA;AAAA,EACxB,iBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,mBAAA,EAAwB,GAAA;AAAA,EACxB,sBAAA,EAAwB,GAAA;AAAA,EACxB,gBAAA,EAAwB,GAAA;AAAA,EACxB,cAAA,EAAwB;AAC1B,CAAA;AAGA,SAAS,OAAA,CAAQ,MAAsB,OAAA,EAAqC;AAC1E,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,aAAA;AACH,MAAA,OAAO,4GAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,mFAAA,CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,qGAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,qFAAA,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,6DAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,gEAAA;AAAA,IACT,KAAK,mBAAA;AACH,MAAA,OAAO,yDAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,sFAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,qDAAA;AAAA,IACT,KAAK,wBAAA;AACH,MAAA,OAAO,0CAAA;AAAA,IACT,KAAK,kBAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,SAAS;AAGP,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ;AAiDO,SAAS,eAAe,GAAA,EAAqB;AAClD,EAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,OAAO,CAAA;AAC1C,IAAA,MAAM,OAAO,MAAA,CAAO,IAAI,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA,EAAG;AAAA,MAC1C,UAAA,EAAY,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA,IAAK,GAAA;AAAA,MACrC,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,OAAA,EAAS,IAAA,GAAO,EAAE,IAAA,EAAK,GAAI;AAAA,KAC5B,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,EAAA,MAAM,MAAA,CAAO,MAAA,CAAO,IAAI,KAAA,CAAM,OAAO,CAAA,EAAG;AAAA,IACtC,UAAA,EAAY,GAAA;AAAA,IACZ,IAAA,EAAM;AAAA,GACP,CAAA;AACH;;;AC9GA,IAAO,0BAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CAAQ,IAAA,EAAuB,KAAA,EAAuC;AAC1E,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,cAAA,CAAe,KAAA,CAAM,KAAA,EAAO,OAAO,CAAA;AACnD,MAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,OAAO,CAAA;AACzC,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAQ;AAAA,IACrC,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"folders-handler.js","sourcesContent":["import type { PluginContextV3 } from '@kb-labs/sdk';\nimport { InboxError, type InboxErrorCode } from '@kb-labs/inbox-core';\n\n// HTTP status codes for REST layer\nconst REST_STATUS: Record<InboxErrorCode, number> = {\n ENV_MISSING: 400,\n ACCOUNT_NOT_FOUND: 400,\n IMAP_AUTH_FAILED: 401,\n IMAP_CONNECT_FAILED: 503,\n IMAP_TIMEOUT: 504,\n IMAP_MAILBOX_NOT_FOUND: 404,\n MESSAGE_NOT_FOUND: 404,\n SMTP_AUTH_FAILED: 401,\n SMTP_CONNECT_FAILED: 503,\n SMTP_INVALID_RECIPIENT: 400,\n VALIDATION_ERROR: 400,\n INTERNAL_ERROR: 500,\n};\n\n// Human-readable hints per error code\nfunction getHint(code: InboxErrorCode, message: string): string | undefined {\n switch (code) {\n case 'ENV_MISSING':\n return 'Set INBOX_ACCOUNTS=work,personal and account vars (INBOX_ACCOUNT_WORK_USER, _PASS, _IMAP_HOST, _SMTP_HOST)';\n case 'ACCOUNT_NOT_FOUND':\n return `Use kb inbox accounts to see configured accounts, then pass the name with --account`;\n case 'IMAP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings (yandex.ru/id) and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'IMAP_CONNECT_FAILED':\n return `Check INBOX_ACCOUNT_<NAME>_IMAP_HOST and _IMAP_PORT, and that the server is reachable`;\n case 'IMAP_TIMEOUT':\n return 'Server did not respond in time — try again in a moment';\n case 'IMAP_MAILBOX_NOT_FOUND':\n return 'Run kb inbox folders --account <name> to see available folders';\n case 'MESSAGE_NOT_FOUND':\n return 'The uid may be stale — refresh with: kb inbox list';\n case 'SMTP_AUTH_FAILED':\n return 'Create an app-password in Yandex ID settings and set it as INBOX_ACCOUNT_<NAME>_PASS';\n case 'SMTP_CONNECT_FAILED':\n return 'Check INBOX_ACCOUNT_<NAME>_SMTP_HOST and _SMTP_PORT';\n case 'SMTP_INVALID_RECIPIENT':\n return 'Verify the --to address is a valid email';\n case 'VALIDATION_ERROR':\n return undefined; // message itself is descriptive enough\n case 'INTERNAL_ERROR':\n return undefined;\n default: {\n const _: never = code;\n void _;\n return undefined;\n }\n }\n}\n\n/**\n * Output a structured error for CLI commands.\n *\n * JSON mode → { ok: false, error: { code, message, hint? } } — agent-parseable\n * Human mode → ctx.ui.error() with hint and cause fields\n *\n * Call right before `return { ok: false, error: 'Command failed', result: null }`.\n */\nexport function handleError(ctx: PluginContextV3, err: unknown, isJson?: boolean): void {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(hint && { hint }),\n },\n });\n } else {\n ctx.ui?.error?.(err.message, {\n ...(hint && { hint }),\n cause: `InboxError [${err.code}]`,\n });\n }\n return;\n }\n\n // Unknown error\n const message = err instanceof Error ? err.message : String(err);\n\n if (isJson) {\n ctx.ui?.json?.({\n ok: false,\n error: { code: 'INTERNAL_ERROR', message },\n });\n } else {\n ctx.ui?.error?.(message);\n }\n}\n\n/**\n * Re-throws err as an HTTP-aware error for REST handlers.\n * InboxError → preserves HTTP status; others → 500.\n */\nexport function rethrowForRest(err: unknown): never {\n if (err instanceof InboxError) {\n const hint = getHint(err.code, err.message);\n throw Object.assign(new Error(err.message), {\n statusCode: REST_STATUS[err.code] ?? 500,\n code: err.code,\n details: hint ? { hint } : undefined,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(message), {\n statusCode: 500,\n code: 'INTERNAL_ERROR',\n });\n}\n","import { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, listFolders } from '@kb-labs/inbox-core';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Query = { account?: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<Query, never, never>) {\n try {\n const account = resolveAccount(input.query?.account);\n const folders = await listFolders(account);\n return { ok: true, result: folders };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|