@kb-labs/inbox-entry 2.109.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.
Files changed (42) hide show
  1. package/dist/commands/mail-accounts.d.ts +1 -1
  2. package/dist/commands/mail-accounts.js +4 -4
  3. package/dist/commands/mail-accounts.js.map +1 -1
  4. package/dist/commands/mail-delete.js +5 -5
  5. package/dist/commands/mail-delete.js.map +1 -1
  6. package/dist/commands/mail-folders.d.ts +1 -1
  7. package/dist/commands/mail-folders.js +3 -3
  8. package/dist/commands/mail-folders.js.map +1 -1
  9. package/dist/commands/mail-get.d.ts +1 -1
  10. package/dist/commands/mail-get.js +5 -5
  11. package/dist/commands/mail-get.js.map +1 -1
  12. package/dist/commands/mail-list.d.ts +1 -1
  13. package/dist/commands/mail-list.js +4 -4
  14. package/dist/commands/mail-list.js.map +1 -1
  15. package/dist/commands/mail-mark.js +6 -6
  16. package/dist/commands/mail-mark.js.map +1 -1
  17. package/dist/commands/mail-move.js +6 -6
  18. package/dist/commands/mail-move.js.map +1 -1
  19. package/dist/commands/mail-reply.d.ts +1 -1
  20. package/dist/commands/mail-reply.js +6 -6
  21. package/dist/commands/mail-reply.js.map +1 -1
  22. package/dist/commands/mail-search.d.ts +1 -1
  23. package/dist/commands/mail-search.js +4 -4
  24. package/dist/commands/mail-search.js.map +1 -1
  25. package/dist/commands/mail-send.d.ts +1 -1
  26. package/dist/commands/mail-send.js +6 -6
  27. package/dist/commands/mail-send.js.map +1 -1
  28. package/dist/commands/mail-thread.d.ts +1 -1
  29. package/dist/commands/mail-thread.js +5 -5
  30. package/dist/commands/mail-thread.js.map +1 -1
  31. package/dist/rest/handlers/accounts-handler.js.map +1 -1
  32. package/dist/rest/handlers/delete-handler.js.map +1 -1
  33. package/dist/rest/handlers/folders-handler.js.map +1 -1
  34. package/dist/rest/handlers/get-handler.js.map +1 -1
  35. package/dist/rest/handlers/list-handler.js.map +1 -1
  36. package/dist/rest/handlers/mark-handler.js.map +1 -1
  37. package/dist/rest/handlers/move-handler.js.map +1 -1
  38. package/dist/rest/handlers/reply-handler.js.map +1 -1
  39. package/dist/rest/handlers/search-handler.js.map +1 -1
  40. package/dist/rest/handlers/send-handler.js.map +1 -1
  41. package/dist/rest/handlers/thread-handler.js.map +1 -1
  42. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/get-handler.ts"],"names":[],"mappings":"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","file":"get-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 { 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 { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, getMessage } from '@kb-labs/inbox-core';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Query = { folder?: string; attachments?: 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 const email = await getMessage(account, uid, {\n folder: q.folder ?? 'INBOX',\n withAttachments: q.attachments === 'true',\n });\n\n return { ok: true, result: email };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/get-handler.ts"],"names":[],"mappings":"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","file":"get-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, getMessage } from '@kb-labs/inbox-core';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Query = { folder?: string; attachments?: 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 const email = await getMessage(account, uid, {\n folder: q.folder ?? 'INBOX',\n withAttachments: q.attachments === 'true',\n });\n\n return { ok: true, result: email };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/list-handler.ts"],"names":[],"mappings":"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","file":"list-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 { 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 { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, listMessages } from '@kb-labs/inbox-core';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Query = { folder?: string; unread?: string; since?: string; limit?: string; account?: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<Query, never, never>) {\n try {\n const q = input.query ?? {};\n const account = resolveAccount(q.account);\n const since = q.since ? new Date(q.since) : undefined;\n\n const messages = await listMessages(account, {\n folder: q.folder ?? 'INBOX',\n unreadOnly: q.unread === 'true',\n since,\n limit: q.limit ? parseInt(q.limit, 10) : 50,\n });\n\n return { ok: true, result: messages };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/list-handler.ts"],"names":[],"mappings":"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","file":"list-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, listMessages } from '@kb-labs/inbox-core';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Query = { folder?: string; unread?: string; since?: string; limit?: string; account?: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<Query, never, never>) {\n try {\n const q = input.query ?? {};\n const account = resolveAccount(q.account);\n const since = q.since ? new Date(q.since) : undefined;\n\n const messages = await listMessages(account, {\n folder: q.folder ?? 'INBOX',\n unreadOnly: q.unread === 'true',\n since,\n limit: q.limit ? parseInt(q.limit, 10) : 50,\n });\n\n return { ok: true, result: messages };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/mark-handler.ts"],"names":[],"mappings":"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","file":"mark-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 { 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 { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, markMessage } from '@kb-labs/inbox-core';\nimport type { MarkMessageInput } from '@kb-labs/inbox-contracts';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Params = { uid: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<never, MarkMessageInput, 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 body = input.body!;\n const account = resolveAccount(body.account);\n await markMessage(account, uid, 'INBOX', body.mark);\n\n return { ok: true, result: { uid, action: body.mark } };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/mark-handler.ts"],"names":[],"mappings":"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","file":"mark-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, markMessage } from '@kb-labs/inbox-core';\nimport type { MarkMessageInput } from '@kb-labs/inbox-contracts';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Params = { uid: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<never, MarkMessageInput, 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 body = input.body!;\n const account = resolveAccount(body.account);\n await markMessage(account, uid, 'INBOX', body.mark);\n\n return { ok: true, result: { uid, action: body.mark } };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/move-handler.ts"],"names":[],"mappings":"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","file":"move-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 { 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 { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, moveMessage } from '@kb-labs/inbox-core';\nimport type { MoveMessageInput } from '@kb-labs/inbox-contracts';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Params = { uid: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<never, MoveMessageInput, 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 body = input.body!;\n const account = resolveAccount(body.account);\n await moveMessage(account, uid, 'INBOX', body.folder);\n\n return { ok: true, result: { uid, folder: body.folder } };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/move-handler.ts"],"names":[],"mappings":"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","file":"move-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, moveMessage } from '@kb-labs/inbox-core';\nimport type { MoveMessageInput } from '@kb-labs/inbox-contracts';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Params = { uid: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<never, MoveMessageInput, 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 body = input.body!;\n const account = resolveAccount(body.account);\n await moveMessage(account, uid, 'INBOX', body.folder);\n\n return { ok: true, result: { uid, folder: body.folder } };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/reply-handler.ts"],"names":[],"mappings":"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","file":"reply-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 { 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 { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, getMessage, replyMessage } from '@kb-labs/inbox-core';\nimport type { ReplyMessageInput } from '@kb-labs/inbox-contracts';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Params = { uid: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<never, ReplyMessageInput, 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 body = input.body!;\n const account = resolveAccount(body.account);\n const original = await getMessage(account, uid, { folder: 'INBOX' });\n\n const result = await replyMessage(account, {\n body: body.body,\n originalMessageId: original.messageId,\n originalReferences: original.references,\n originalSubject: original.subject,\n }, body.body);\n\n return { ok: true, result };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/reply-handler.ts"],"names":[],"mappings":"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","file":"reply-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, getMessage, replyMessage } from '@kb-labs/inbox-core';\nimport type { ReplyMessageInput } from '@kb-labs/inbox-contracts';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Params = { uid: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<never, ReplyMessageInput, 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 body = input.body!;\n const account = resolveAccount(body.account);\n const original = await getMessage(account, uid, { folder: 'INBOX' });\n\n const result = await replyMessage(account, {\n body: body.body,\n originalMessageId: original.messageId,\n originalReferences: original.references,\n originalSubject: original.subject,\n }, body.body);\n\n return { ok: true, result };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/search-handler.ts"],"names":[],"mappings":"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","file":"search-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 { 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 { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, searchMessages } from '@kb-labs/inbox-core';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Query = { from?: string; subject?: string; body?: string; text?: string; folder?: string; since?: string; limit?: string; account?: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<Query, never, never>) {\n try {\n const q = input.query ?? {};\n const account = resolveAccount(q.account);\n const since = q.since ? new Date(q.since) : undefined;\n\n const messages = await searchMessages(account, {\n from: q.from,\n subject: q.subject,\n body: q.body,\n text: q.text,\n folder: q.folder,\n since,\n limit: q.limit ? parseInt(q.limit, 10) : 20,\n });\n\n return { ok: true, result: messages };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/search-handler.ts"],"names":[],"mappings":"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","file":"search-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, searchMessages } from '@kb-labs/inbox-core';\nimport { rethrowForRest } from '../../utils/error.js';\n\ntype Query = { from?: string; subject?: string; body?: string; text?: string; folder?: string; since?: string; limit?: string; account?: string };\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<Query, never, never>) {\n try {\n const q = input.query ?? {};\n const account = resolveAccount(q.account);\n const since = q.since ? new Date(q.since) : undefined;\n\n const messages = await searchMessages(account, {\n from: q.from,\n subject: q.subject,\n body: q.body,\n text: q.text,\n folder: q.folder,\n since,\n limit: q.limit ? parseInt(q.limit, 10) : 20,\n });\n\n return { ok: true, result: messages };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/send-handler.ts"],"names":[],"mappings":"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","file":"send-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 { 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 { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, sendMessage } from '@kb-labs/inbox-core';\nimport type { SendMessageInput } from '@kb-labs/inbox-contracts';\nimport { rethrowForRest } from '../../utils/error.js';\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<never, SendMessageInput, never>) {\n try {\n const body = input.body!;\n const account = resolveAccount(body.account);\n const result = await sendMessage(account, {\n to: body.to,\n subject: body.subject,\n body: body.body,\n cc: body.cc,\n bcc: body.bcc,\n });\n\n return { ok: true, result };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/send-handler.ts"],"names":[],"mappings":"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","file":"send-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, sendMessage } from '@kb-labs/inbox-core';\nimport type { SendMessageInput } from '@kb-labs/inbox-contracts';\nimport { rethrowForRest } from '../../utils/error.js';\n\nexport default defineHandler({\n async execute(_ctx: PluginContextV3, input: RestInput<never, SendMessageInput, never>) {\n try {\n const body = input.body!;\n const account = resolveAccount(body.account);\n const result = await sendMessage(account, {\n to: body.to,\n subject: body.subject,\n body: body.body,\n cc: body.cc,\n bcc: body.bcc,\n });\n\n return { ok: true, result };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/thread-handler.ts"],"names":[],"mappings":"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","file":"thread-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 { 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 { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { resolveAccount, getThread } 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 const thread = await getThread(account, uid, { folder: q.folder ?? 'INBOX' });\n\n return { ok: true, result: thread };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/utils/error.ts","../../../src/rest/handlers/thread-handler.ts"],"names":[],"mappings":"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","file":"thread-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, getThread } 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 const thread = await getThread(account, uid, { folder: q.folder ?? 'INBOX' });\n\n return { ok: true, result: thread };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kb-labs/inbox-entry",
3
- "version": "2.109.0",
3
+ "version": "2.110.0",
4
4
  "type": "module",
5
5
  "description": "V3 manifest + CLI commands + REST handlers for inbox plugin",
6
6
  "main": "./dist/index.js",
@@ -33,10 +33,10 @@
33
33
  "test:cli": "vitest run --config vitest.cli.config.ts --passWithNoTests"
34
34
  },
35
35
  "dependencies": {
36
- "@kb-labs/inbox-contracts": "^2.109.0",
37
- "@kb-labs/inbox-core": "^2.109.0",
36
+ "@kb-labs/inbox-contracts": "^2.110.0",
37
+ "@kb-labs/inbox-core": "^2.110.0",
38
38
  "@kb-labs/sdk": "workspace:*",
39
- "@kb-labs/shared-command-kit": "^2.109.0"
39
+ "@kb-labs/shared-command-kit": "^2.110.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@kb-labs/devkit": "workspace:*",