@microfox/ai-worker 1.0.1

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.
@@ -0,0 +1,50 @@
1
+ // src/config.ts
2
+ var cachedConfig = null;
3
+ var cacheExpiry = 0;
4
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
5
+ async function getWorkersConfig(apiUrl, apiKey) {
6
+ const now = Date.now();
7
+ if (cachedConfig && now < cacheExpiry) {
8
+ return cachedConfig;
9
+ }
10
+ const headers = {
11
+ "Content-Type": "application/json"
12
+ };
13
+ if (apiKey) {
14
+ headers["x-workers-config-key"] = apiKey;
15
+ }
16
+ const response = await fetch(apiUrl, {
17
+ method: "GET",
18
+ headers
19
+ });
20
+ if (!response.ok) {
21
+ throw new Error(
22
+ `Failed to fetch workers config: ${response.status} ${response.statusText}`
23
+ );
24
+ }
25
+ const config = await response.json();
26
+ cachedConfig = config;
27
+ cacheExpiry = now + CACHE_TTL_MS;
28
+ return config;
29
+ }
30
+ async function resolveQueueUrl(workerId, apiUrl, apiKey) {
31
+ const config = await getWorkersConfig(apiUrl, apiKey);
32
+ const worker = config.workers[workerId];
33
+ if (!worker) {
34
+ throw new Error(
35
+ `Worker "${workerId}" not found in workers config. Available workers: ${Object.keys(config.workers).join(", ")}`
36
+ );
37
+ }
38
+ return worker.queueUrl;
39
+ }
40
+ function clearWorkersConfigCache() {
41
+ cachedConfig = null;
42
+ cacheExpiry = 0;
43
+ }
44
+
45
+ export {
46
+ getWorkersConfig,
47
+ resolveQueueUrl,
48
+ clearWorkersConfigCache
49
+ };
50
+ //# sourceMappingURL=chunk-ZYYWZ3PR.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts"],"sourcesContent":["/**\n * Workers-config client for resolving queue URLs from the workers-config API Lambda.\n */\n\nexport interface WorkersConfig {\n version: string;\n stage: string;\n region: string;\n workers: Record<\n string,\n {\n queueUrl: string;\n region: string;\n }\n >;\n}\n\nlet cachedConfig: WorkersConfig | null = null;\nlet cacheExpiry: number = 0;\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Fetches the workers configuration from the workers-config API.\n * Results are cached for 5 minutes to reduce API calls.\n *\n * @param apiUrl - The URL of the workers-config API endpoint\n * @param apiKey - Optional API key for authentication (sent as x-workers-config-key header)\n * @returns The workers configuration mapping worker IDs to queue URLs\n */\nexport async function getWorkersConfig(\n apiUrl: string,\n apiKey?: string\n): Promise<WorkersConfig> {\n const now = Date.now();\n\n // Return cached config if still valid\n if (cachedConfig && now < cacheExpiry) {\n return cachedConfig;\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['x-workers-config-key'] = apiKey;\n }\n\n const response = await fetch(apiUrl, {\n method: 'GET',\n headers,\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch workers config: ${response.status} ${response.statusText}`\n );\n }\n\n const config = (await response.json()) as WorkersConfig;\n cachedConfig = config;\n cacheExpiry = now + CACHE_TTL_MS;\n\n return config;\n}\n\n/**\n * Resolves the queue URL for a specific worker ID.\n * Throws an error if the worker ID is not found in the configuration.\n *\n * @param workerId - The ID of the worker\n * @param apiUrl - The URL of the workers-config API endpoint\n * @param apiKey - Optional API key for authentication\n * @returns The queue URL for the worker\n */\nexport async function resolveQueueUrl(\n workerId: string,\n apiUrl: string,\n apiKey?: string\n): Promise<string> {\n const config = await getWorkersConfig(apiUrl, apiKey);\n const worker = config.workers[workerId];\n\n if (!worker) {\n throw new Error(\n `Worker \"${workerId}\" not found in workers config. Available workers: ${Object.keys(config.workers).join(', ')}`\n );\n }\n\n return worker.queueUrl;\n}\n\n/**\n * Clears the cached workers configuration.\n * Useful for testing or when you need to force a refresh.\n */\nexport function clearWorkersConfigCache(): void {\n cachedConfig = null;\n cacheExpiry = 0;\n}\n"],"mappings":";AAiBA,IAAI,eAAqC;AACzC,IAAI,cAAsB;AAC1B,IAAM,eAAe,IAAI,KAAK;AAU9B,eAAsB,iBACpB,QACA,QACwB;AACxB,QAAM,MAAM,KAAK,IAAI;AAGrB,MAAI,gBAAgB,MAAM,aAAa;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,EAClB;AAEA,MAAI,QAAQ;AACV,YAAQ,sBAAsB,IAAI;AAAA,EACpC;AAEA,QAAM,WAAW,MAAM,MAAM,QAAQ;AAAA,IACnC,QAAQ;AAAA,IACR;AAAA,EACF,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,mCAAmC,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,IAC3E;AAAA,EACF;AAEA,QAAM,SAAU,MAAM,SAAS,KAAK;AACpC,iBAAe;AACf,gBAAc,MAAM;AAEpB,SAAO;AACT;AAWA,eAAsB,gBACpB,UACA,QACA,QACiB;AACjB,QAAM,SAAS,MAAM,iBAAiB,QAAQ,MAAM;AACpD,QAAM,SAAS,OAAO,QAAQ,QAAQ;AAEtC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR,WAAW,QAAQ,qDAAqD,OAAO,KAAK,OAAO,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IAChH;AAAA,EACF;AAEA,SAAO,OAAO;AAChB;AAMO,SAAS,0BAAgC;AAC9C,iBAAe;AACf,gBAAc;AAChB;","names":[]}
@@ -0,0 +1,64 @@
1
+ import { ZodType, z } from 'zod';
2
+
3
+ /**
4
+ * Client for dispatching background worker jobs.
5
+ *
6
+ * In production, dispatching happens via the workers HTTP API:
7
+ * POST /workers/trigger -> enqueues message to SQS on the workers service side
8
+ *
9
+ * This avoids requiring AWS credentials in your Next.js app.
10
+ */
11
+
12
+ interface DispatchOptions {
13
+ /**
14
+ * Optional webhook callback URL to notify when the job finishes.
15
+ * Only called when provided. Default: no webhook (use job store / MongoDB only).
16
+ */
17
+ webhookUrl?: string;
18
+ /**
19
+ * Controls how dispatch executes.
20
+ * - "auto" (default): local inline execution in development unless WORKERS_LOCAL_MODE=false.
21
+ * - "local": force inline execution (no SQS).
22
+ * - "remote": force SQS/Lambda dispatch even in development.
23
+ */
24
+ mode?: 'auto' | 'local' | 'remote';
25
+ jobId?: string;
26
+ metadata?: Record<string, any>;
27
+ }
28
+ interface DispatchResult {
29
+ messageId: string;
30
+ status: 'queued';
31
+ jobId: string;
32
+ }
33
+ interface SerializedContext {
34
+ requestId?: string;
35
+ userId?: string;
36
+ traceId?: string;
37
+ [key: string]: any;
38
+ }
39
+ /**
40
+ * Dispatches a background worker job to SQS.
41
+ *
42
+ * @param workerId - The ID of the worker to dispatch
43
+ * @param input - The input data for the worker (will be validated against inputSchema)
44
+ * @param inputSchema - Zod schema for input validation
45
+ * @param options - Dispatch options including webhook URL
46
+ * @param ctx - Optional context object (only serializable parts will be sent)
47
+ * @returns Promise resolving to dispatch result with messageId and jobId
48
+ */
49
+ declare function dispatch<INPUT_SCHEMA extends ZodType<any>>(workerId: string, input: z.input<INPUT_SCHEMA>, inputSchema: INPUT_SCHEMA, options: DispatchOptions, ctx?: any): Promise<DispatchResult>;
50
+ /**
51
+ * Local development mode: runs the handler immediately in the same process.
52
+ * This bypasses SQS and Lambda for faster iteration during development.
53
+ *
54
+ * @param handler - The worker handler function
55
+ * @param input - The input data
56
+ * @param ctx - The context object
57
+ * @returns The handler result
58
+ */
59
+ declare function dispatchLocal<INPUT, OUTPUT>(handler: (params: {
60
+ input: INPUT;
61
+ ctx: any;
62
+ }) => Promise<OUTPUT>, input: INPUT, ctx?: any): Promise<OUTPUT>;
63
+
64
+ export { type DispatchOptions, type DispatchResult, type SerializedContext, dispatch, dispatchLocal };
@@ -0,0 +1,64 @@
1
+ import { ZodType, z } from 'zod';
2
+
3
+ /**
4
+ * Client for dispatching background worker jobs.
5
+ *
6
+ * In production, dispatching happens via the workers HTTP API:
7
+ * POST /workers/trigger -> enqueues message to SQS on the workers service side
8
+ *
9
+ * This avoids requiring AWS credentials in your Next.js app.
10
+ */
11
+
12
+ interface DispatchOptions {
13
+ /**
14
+ * Optional webhook callback URL to notify when the job finishes.
15
+ * Only called when provided. Default: no webhook (use job store / MongoDB only).
16
+ */
17
+ webhookUrl?: string;
18
+ /**
19
+ * Controls how dispatch executes.
20
+ * - "auto" (default): local inline execution in development unless WORKERS_LOCAL_MODE=false.
21
+ * - "local": force inline execution (no SQS).
22
+ * - "remote": force SQS/Lambda dispatch even in development.
23
+ */
24
+ mode?: 'auto' | 'local' | 'remote';
25
+ jobId?: string;
26
+ metadata?: Record<string, any>;
27
+ }
28
+ interface DispatchResult {
29
+ messageId: string;
30
+ status: 'queued';
31
+ jobId: string;
32
+ }
33
+ interface SerializedContext {
34
+ requestId?: string;
35
+ userId?: string;
36
+ traceId?: string;
37
+ [key: string]: any;
38
+ }
39
+ /**
40
+ * Dispatches a background worker job to SQS.
41
+ *
42
+ * @param workerId - The ID of the worker to dispatch
43
+ * @param input - The input data for the worker (will be validated against inputSchema)
44
+ * @param inputSchema - Zod schema for input validation
45
+ * @param options - Dispatch options including webhook URL
46
+ * @param ctx - Optional context object (only serializable parts will be sent)
47
+ * @returns Promise resolving to dispatch result with messageId and jobId
48
+ */
49
+ declare function dispatch<INPUT_SCHEMA extends ZodType<any>>(workerId: string, input: z.input<INPUT_SCHEMA>, inputSchema: INPUT_SCHEMA, options: DispatchOptions, ctx?: any): Promise<DispatchResult>;
50
+ /**
51
+ * Local development mode: runs the handler immediately in the same process.
52
+ * This bypasses SQS and Lambda for faster iteration during development.
53
+ *
54
+ * @param handler - The worker handler function
55
+ * @param input - The input data
56
+ * @param ctx - The context object
57
+ * @returns The handler result
58
+ */
59
+ declare function dispatchLocal<INPUT, OUTPUT>(handler: (params: {
60
+ input: INPUT;
61
+ ctx: any;
62
+ }) => Promise<OUTPUT>, input: INPUT, ctx?: any): Promise<OUTPUT>;
63
+
64
+ export { type DispatchOptions, type DispatchResult, type SerializedContext, dispatch, dispatchLocal };
package/dist/client.js ADDED
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/client.ts
21
+ var client_exports = {};
22
+ __export(client_exports, {
23
+ dispatch: () => dispatch,
24
+ dispatchLocal: () => dispatchLocal
25
+ });
26
+ module.exports = __toCommonJS(client_exports);
27
+ function getWorkersTriggerUrl() {
28
+ const raw = process.env.WORKER_BASE_URL || process.env.NEXT_PUBLIC_WORKER_BASE_URL || process.env.WORKERS_TRIGGER_API_URL || process.env.NEXT_PUBLIC_WORKERS_TRIGGER_API_URL || process.env.WORKERS_CONFIG_API_URL || process.env.NEXT_PUBLIC_WORKERS_CONFIG_API_URL;
29
+ if (!raw) {
30
+ throw new Error(
31
+ "WORKER_BASE_URL (preferred) or NEXT_PUBLIC_WORKER_BASE_URL is required for background workers"
32
+ );
33
+ }
34
+ const url = new URL(raw);
35
+ url.search = "";
36
+ url.hash = "";
37
+ const path = url.pathname || "";
38
+ url.pathname = path.replace(/\/?workers\/(trigger|config)\/?$/, "");
39
+ const basePath = url.pathname.replace(/\/+$/, "");
40
+ url.pathname = `${basePath}/workers/trigger`.replace(/\/+$/, "");
41
+ return url.toString();
42
+ }
43
+ function serializeContext(ctx) {
44
+ const serialized = {};
45
+ if (ctx.requestId) {
46
+ serialized.requestId = ctx.requestId;
47
+ }
48
+ if (ctx.metadata && typeof ctx.metadata === "object") {
49
+ Object.assign(serialized, ctx.metadata);
50
+ }
51
+ if (ctx._serializeContext && typeof ctx._serializeContext === "function") {
52
+ const custom = ctx._serializeContext();
53
+ Object.assign(serialized, custom);
54
+ }
55
+ return serialized;
56
+ }
57
+ async function dispatch(workerId, input, inputSchema, options, ctx) {
58
+ const validatedInput = inputSchema.parse(input);
59
+ const jobId = options.jobId || `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
60
+ const triggerUrl = getWorkersTriggerUrl();
61
+ const serializedContext = ctx ? serializeContext(ctx) : {};
62
+ const messageBody = {
63
+ workerId,
64
+ jobId,
65
+ input: validatedInput,
66
+ context: serializedContext,
67
+ webhookUrl: options.webhookUrl,
68
+ metadata: options.metadata || {},
69
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
70
+ };
71
+ const headers = {
72
+ "Content-Type": "application/json"
73
+ };
74
+ const triggerKey = process.env.WORKERS_TRIGGER_API_KEY;
75
+ if (triggerKey) {
76
+ headers["x-workers-trigger-key"] = triggerKey;
77
+ }
78
+ const response = await fetch(triggerUrl, {
79
+ method: "POST",
80
+ headers,
81
+ body: JSON.stringify({
82
+ workerId,
83
+ body: messageBody
84
+ })
85
+ });
86
+ if (!response.ok) {
87
+ const text = await response.text().catch(() => "");
88
+ throw new Error(
89
+ `Failed to trigger worker "${workerId}": ${response.status} ${response.statusText}${text ? ` - ${text}` : ""}`
90
+ );
91
+ }
92
+ const data = await response.json().catch(() => ({}));
93
+ const messageId = data?.messageId ? String(data.messageId) : `trigger-${jobId}`;
94
+ return {
95
+ messageId,
96
+ status: "queued",
97
+ jobId
98
+ };
99
+ }
100
+ async function dispatchLocal(handler, input, ctx) {
101
+ return handler({ input, ctx: ctx || {} });
102
+ }
103
+ // Annotate the CommonJS export names for ESM import in node:
104
+ 0 && (module.exports = {
105
+ dispatch,
106
+ dispatchLocal
107
+ });
108
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["/**\n * Client for dispatching background worker jobs.\n *\n * In production, dispatching happens via the workers HTTP API:\n * POST /workers/trigger -> enqueues message to SQS on the workers service side\n *\n * This avoids requiring AWS credentials in your Next.js app.\n */\n\nimport type { ZodType, z } from 'zod';\n\nexport interface DispatchOptions {\n /**\n * Optional webhook callback URL to notify when the job finishes.\n * Only called when provided. Default: no webhook (use job store / MongoDB only).\n */\n webhookUrl?: string;\n /**\n * Controls how dispatch executes.\n * - \"auto\" (default): local inline execution in development unless WORKERS_LOCAL_MODE=false.\n * - \"local\": force inline execution (no SQS).\n * - \"remote\": force SQS/Lambda dispatch even in development.\n */\n mode?: 'auto' | 'local' | 'remote';\n jobId?: string;\n metadata?: Record<string, any>;\n}\n\nexport interface DispatchResult {\n messageId: string;\n status: 'queued';\n jobId: string;\n}\n\nexport interface SerializedContext {\n requestId?: string;\n userId?: string;\n traceId?: string;\n [key: string]: any;\n}\n\n/**\n * Derives the full /workers/trigger URL from env.\n *\n * Preferred env vars:\n * - WORKER_BASE_URL: base URL of the workers service (e.g. https://.../prod)\n * - NEXT_PUBLIC_WORKER_BASE_URL: same, but exposed to the browser\n *\n * Legacy env vars (still supported for backwards compatibility):\n * - WORKERS_TRIGGER_API_URL / NEXT_PUBLIC_WORKERS_TRIGGER_API_URL\n * - WORKERS_CONFIG_API_URL / NEXT_PUBLIC_WORKERS_CONFIG_API_URL\n */\nfunction getWorkersTriggerUrl(): string {\n const raw =\n process.env.WORKER_BASE_URL ||\n process.env.NEXT_PUBLIC_WORKER_BASE_URL ||\n process.env.WORKERS_TRIGGER_API_URL ||\n process.env.NEXT_PUBLIC_WORKERS_TRIGGER_API_URL ||\n process.env.WORKERS_CONFIG_API_URL ||\n process.env.NEXT_PUBLIC_WORKERS_CONFIG_API_URL;\n\n if (!raw) {\n throw new Error(\n 'WORKER_BASE_URL (preferred) or NEXT_PUBLIC_WORKER_BASE_URL is required for background workers'\n );\n }\n\n const url = new URL(raw);\n url.search = '';\n url.hash = '';\n\n const path = url.pathname || '';\n\n // If the user pointed at a specific endpoint, normalize back to the service root.\n url.pathname = path.replace(/\\/?workers\\/(trigger|config)\\/?$/, '');\n\n const basePath = url.pathname.replace(/\\/+$/, '');\n url.pathname = `${basePath}/workers/trigger`.replace(/\\/+$/, '');\n\n return url.toString();\n}\n\n/**\n * Serializes context data for transmission to Lambda.\n * Only serializes safe, JSON-compatible properties.\n */\nfunction serializeContext(ctx: any): SerializedContext {\n const serialized: SerializedContext = {};\n\n if (ctx.requestId) {\n serialized.requestId = ctx.requestId;\n }\n\n // Extract any additional serializable metadata\n if (ctx.metadata && typeof ctx.metadata === 'object') {\n Object.assign(serialized, ctx.metadata);\n }\n\n // Allow custom context serialization via a helper property\n if (ctx._serializeContext && typeof ctx._serializeContext === 'function') {\n const custom = ctx._serializeContext();\n Object.assign(serialized, custom);\n }\n\n return serialized;\n}\n\n/**\n * Dispatches a background worker job to SQS.\n *\n * @param workerId - The ID of the worker to dispatch\n * @param input - The input data for the worker (will be validated against inputSchema)\n * @param inputSchema - Zod schema for input validation\n * @param options - Dispatch options including webhook URL\n * @param ctx - Optional context object (only serializable parts will be sent)\n * @returns Promise resolving to dispatch result with messageId and jobId\n */\nexport async function dispatch<INPUT_SCHEMA extends ZodType<any>>(\n workerId: string,\n input: z.input<INPUT_SCHEMA>,\n inputSchema: INPUT_SCHEMA,\n options: DispatchOptions,\n ctx?: any\n): Promise<DispatchResult> {\n // Validate input against schema\n const validatedInput = inputSchema.parse(input);\n\n // Generate job ID if not provided\n const jobId =\n options.jobId || `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n\n // Resolve /workers/trigger endpoint URL\n const triggerUrl = getWorkersTriggerUrl();\n\n // Serialize context (only safe, JSON-compatible parts)\n const serializedContext = ctx ? serializeContext(ctx) : {};\n\n // Job updates use MongoDB only; never pass jobStoreUrl/origin URL.\n const messageBody = {\n workerId,\n jobId,\n input: validatedInput,\n context: serializedContext,\n webhookUrl: options.webhookUrl,\n metadata: options.metadata || {},\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const triggerKey = process.env.WORKERS_TRIGGER_API_KEY;\n if (triggerKey) {\n headers['x-workers-trigger-key'] = triggerKey;\n }\n\n const response = await fetch(triggerUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n workerId,\n body: messageBody,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Failed to trigger worker \"${workerId}\": ${response.status} ${response.statusText}${text ? ` - ${text}` : ''}`\n );\n }\n\n const data = (await response.json().catch(() => ({}))) as any;\n const messageId = data?.messageId ? String(data.messageId) : `trigger-${jobId}`;\n\n return {\n messageId,\n status: 'queued',\n jobId,\n };\n}\n\n/**\n * Local development mode: runs the handler immediately in the same process.\n * This bypasses SQS and Lambda for faster iteration during development.\n *\n * @param handler - The worker handler function\n * @param input - The input data\n * @param ctx - The context object\n * @returns The handler result\n */\nexport async function dispatchLocal<INPUT, OUTPUT>(\n handler: (params: { input: INPUT; ctx: any }) => Promise<OUTPUT>,\n input: INPUT,\n ctx?: any\n): Promise<OUTPUT> {\n return handler({ input, ctx: ctx || {} });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoDA,SAAS,uBAA+B;AACtC,QAAM,MACJ,QAAQ,IAAI,mBACZ,QAAQ,IAAI,+BACZ,QAAQ,IAAI,2BACZ,QAAQ,IAAI,uCACZ,QAAQ,IAAI,0BACZ,QAAQ,IAAI;AAEd,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,IAAI,IAAI,GAAG;AACvB,MAAI,SAAS;AACb,MAAI,OAAO;AAEX,QAAM,OAAO,IAAI,YAAY;AAG7B,MAAI,WAAW,KAAK,QAAQ,oCAAoC,EAAE;AAElE,QAAM,WAAW,IAAI,SAAS,QAAQ,QAAQ,EAAE;AAChD,MAAI,WAAW,GAAG,QAAQ,mBAAmB,QAAQ,QAAQ,EAAE;AAE/D,SAAO,IAAI,SAAS;AACtB;AAMA,SAAS,iBAAiB,KAA6B;AACrD,QAAM,aAAgC,CAAC;AAEvC,MAAI,IAAI,WAAW;AACjB,eAAW,YAAY,IAAI;AAAA,EAC7B;AAGA,MAAI,IAAI,YAAY,OAAO,IAAI,aAAa,UAAU;AACpD,WAAO,OAAO,YAAY,IAAI,QAAQ;AAAA,EACxC;AAGA,MAAI,IAAI,qBAAqB,OAAO,IAAI,sBAAsB,YAAY;AACxE,UAAM,SAAS,IAAI,kBAAkB;AACrC,WAAO,OAAO,YAAY,MAAM;AAAA,EAClC;AAEA,SAAO;AACT;AAYA,eAAsB,SACpB,UACA,OACA,aACA,SACA,KACyB;AAEzB,QAAM,iBAAiB,YAAY,MAAM,KAAK;AAG9C,QAAM,QACJ,QAAQ,SAAS,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAG/E,QAAM,aAAa,qBAAqB;AAGxC,QAAM,oBAAoB,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAGzD,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA,IACT,YAAY,QAAQ;AAAA,IACpB,UAAU,QAAQ,YAAY,CAAC;AAAA,IAC/B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AAEA,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,EAClB;AACA,QAAM,aAAa,QAAQ,IAAI;AAC/B,MAAI,YAAY;AACd,YAAQ,uBAAuB,IAAI;AAAA,EACrC;AAEA,QAAM,WAAW,MAAM,MAAM,YAAY;AAAA,IACvC,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAAA,EACH,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,UAAM,IAAI;AAAA,MACR,6BAA6B,QAAQ,MAAM,SAAS,MAAM,IAAI,SAAS,UAAU,GAAG,OAAO,MAAM,IAAI,KAAK,EAAE;AAAA,IAC9G;AAAA,EACF;AAEA,QAAM,OAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,QAAM,YAAY,MAAM,YAAY,OAAO,KAAK,SAAS,IAAI,WAAW,KAAK;AAE7E,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AAWA,eAAsB,cACpB,SACA,OACA,KACiB;AACjB,SAAO,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,EAAE,CAAC;AAC1C;","names":[]}
@@ -0,0 +1,10 @@
1
+ import {
2
+ dispatch,
3
+ dispatchLocal
4
+ } from "./chunk-FQCZSXDI.mjs";
5
+ import "./chunk-BJTO5JO5.mjs";
6
+ export {
7
+ dispatch,
8
+ dispatchLocal
9
+ };
10
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Workers-config client for resolving queue URLs from the workers-config API Lambda.
3
+ */
4
+ interface WorkersConfig {
5
+ version: string;
6
+ stage: string;
7
+ region: string;
8
+ workers: Record<string, {
9
+ queueUrl: string;
10
+ region: string;
11
+ }>;
12
+ }
13
+ /**
14
+ * Fetches the workers configuration from the workers-config API.
15
+ * Results are cached for 5 minutes to reduce API calls.
16
+ *
17
+ * @param apiUrl - The URL of the workers-config API endpoint
18
+ * @param apiKey - Optional API key for authentication (sent as x-workers-config-key header)
19
+ * @returns The workers configuration mapping worker IDs to queue URLs
20
+ */
21
+ declare function getWorkersConfig(apiUrl: string, apiKey?: string): Promise<WorkersConfig>;
22
+ /**
23
+ * Resolves the queue URL for a specific worker ID.
24
+ * Throws an error if the worker ID is not found in the configuration.
25
+ *
26
+ * @param workerId - The ID of the worker
27
+ * @param apiUrl - The URL of the workers-config API endpoint
28
+ * @param apiKey - Optional API key for authentication
29
+ * @returns The queue URL for the worker
30
+ */
31
+ declare function resolveQueueUrl(workerId: string, apiUrl: string, apiKey?: string): Promise<string>;
32
+ /**
33
+ * Clears the cached workers configuration.
34
+ * Useful for testing or when you need to force a refresh.
35
+ */
36
+ declare function clearWorkersConfigCache(): void;
37
+
38
+ export { type WorkersConfig, clearWorkersConfigCache, getWorkersConfig, resolveQueueUrl };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Workers-config client for resolving queue URLs from the workers-config API Lambda.
3
+ */
4
+ interface WorkersConfig {
5
+ version: string;
6
+ stage: string;
7
+ region: string;
8
+ workers: Record<string, {
9
+ queueUrl: string;
10
+ region: string;
11
+ }>;
12
+ }
13
+ /**
14
+ * Fetches the workers configuration from the workers-config API.
15
+ * Results are cached for 5 minutes to reduce API calls.
16
+ *
17
+ * @param apiUrl - The URL of the workers-config API endpoint
18
+ * @param apiKey - Optional API key for authentication (sent as x-workers-config-key header)
19
+ * @returns The workers configuration mapping worker IDs to queue URLs
20
+ */
21
+ declare function getWorkersConfig(apiUrl: string, apiKey?: string): Promise<WorkersConfig>;
22
+ /**
23
+ * Resolves the queue URL for a specific worker ID.
24
+ * Throws an error if the worker ID is not found in the configuration.
25
+ *
26
+ * @param workerId - The ID of the worker
27
+ * @param apiUrl - The URL of the workers-config API endpoint
28
+ * @param apiKey - Optional API key for authentication
29
+ * @returns The queue URL for the worker
30
+ */
31
+ declare function resolveQueueUrl(workerId: string, apiUrl: string, apiKey?: string): Promise<string>;
32
+ /**
33
+ * Clears the cached workers configuration.
34
+ * Useful for testing or when you need to force a refresh.
35
+ */
36
+ declare function clearWorkersConfigCache(): void;
37
+
38
+ export { type WorkersConfig, clearWorkersConfigCache, getWorkersConfig, resolveQueueUrl };
package/dist/config.js ADDED
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/config.ts
21
+ var config_exports = {};
22
+ __export(config_exports, {
23
+ clearWorkersConfigCache: () => clearWorkersConfigCache,
24
+ getWorkersConfig: () => getWorkersConfig,
25
+ resolveQueueUrl: () => resolveQueueUrl
26
+ });
27
+ module.exports = __toCommonJS(config_exports);
28
+ var cachedConfig = null;
29
+ var cacheExpiry = 0;
30
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
31
+ async function getWorkersConfig(apiUrl, apiKey) {
32
+ const now = Date.now();
33
+ if (cachedConfig && now < cacheExpiry) {
34
+ return cachedConfig;
35
+ }
36
+ const headers = {
37
+ "Content-Type": "application/json"
38
+ };
39
+ if (apiKey) {
40
+ headers["x-workers-config-key"] = apiKey;
41
+ }
42
+ const response = await fetch(apiUrl, {
43
+ method: "GET",
44
+ headers
45
+ });
46
+ if (!response.ok) {
47
+ throw new Error(
48
+ `Failed to fetch workers config: ${response.status} ${response.statusText}`
49
+ );
50
+ }
51
+ const config = await response.json();
52
+ cachedConfig = config;
53
+ cacheExpiry = now + CACHE_TTL_MS;
54
+ return config;
55
+ }
56
+ async function resolveQueueUrl(workerId, apiUrl, apiKey) {
57
+ const config = await getWorkersConfig(apiUrl, apiKey);
58
+ const worker = config.workers[workerId];
59
+ if (!worker) {
60
+ throw new Error(
61
+ `Worker "${workerId}" not found in workers config. Available workers: ${Object.keys(config.workers).join(", ")}`
62
+ );
63
+ }
64
+ return worker.queueUrl;
65
+ }
66
+ function clearWorkersConfigCache() {
67
+ cachedConfig = null;
68
+ cacheExpiry = 0;
69
+ }
70
+ // Annotate the CommonJS export names for ESM import in node:
71
+ 0 && (module.exports = {
72
+ clearWorkersConfigCache,
73
+ getWorkersConfig,
74
+ resolveQueueUrl
75
+ });
76
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts"],"sourcesContent":["/**\n * Workers-config client for resolving queue URLs from the workers-config API Lambda.\n */\n\nexport interface WorkersConfig {\n version: string;\n stage: string;\n region: string;\n workers: Record<\n string,\n {\n queueUrl: string;\n region: string;\n }\n >;\n}\n\nlet cachedConfig: WorkersConfig | null = null;\nlet cacheExpiry: number = 0;\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Fetches the workers configuration from the workers-config API.\n * Results are cached for 5 minutes to reduce API calls.\n *\n * @param apiUrl - The URL of the workers-config API endpoint\n * @param apiKey - Optional API key for authentication (sent as x-workers-config-key header)\n * @returns The workers configuration mapping worker IDs to queue URLs\n */\nexport async function getWorkersConfig(\n apiUrl: string,\n apiKey?: string\n): Promise<WorkersConfig> {\n const now = Date.now();\n\n // Return cached config if still valid\n if (cachedConfig && now < cacheExpiry) {\n return cachedConfig;\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['x-workers-config-key'] = apiKey;\n }\n\n const response = await fetch(apiUrl, {\n method: 'GET',\n headers,\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch workers config: ${response.status} ${response.statusText}`\n );\n }\n\n const config = (await response.json()) as WorkersConfig;\n cachedConfig = config;\n cacheExpiry = now + CACHE_TTL_MS;\n\n return config;\n}\n\n/**\n * Resolves the queue URL for a specific worker ID.\n * Throws an error if the worker ID is not found in the configuration.\n *\n * @param workerId - The ID of the worker\n * @param apiUrl - The URL of the workers-config API endpoint\n * @param apiKey - Optional API key for authentication\n * @returns The queue URL for the worker\n */\nexport async function resolveQueueUrl(\n workerId: string,\n apiUrl: string,\n apiKey?: string\n): Promise<string> {\n const config = await getWorkersConfig(apiUrl, apiKey);\n const worker = config.workers[workerId];\n\n if (!worker) {\n throw new Error(\n `Worker \"${workerId}\" not found in workers config. Available workers: ${Object.keys(config.workers).join(', ')}`\n );\n }\n\n return worker.queueUrl;\n}\n\n/**\n * Clears the cached workers configuration.\n * Useful for testing or when you need to force a refresh.\n */\nexport function clearWorkersConfigCache(): void {\n cachedConfig = null;\n cacheExpiry = 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,IAAI,eAAqC;AACzC,IAAI,cAAsB;AAC1B,IAAM,eAAe,IAAI,KAAK;AAU9B,eAAsB,iBACpB,QACA,QACwB;AACxB,QAAM,MAAM,KAAK,IAAI;AAGrB,MAAI,gBAAgB,MAAM,aAAa;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,EAClB;AAEA,MAAI,QAAQ;AACV,YAAQ,sBAAsB,IAAI;AAAA,EACpC;AAEA,QAAM,WAAW,MAAM,MAAM,QAAQ;AAAA,IACnC,QAAQ;AAAA,IACR;AAAA,EACF,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,mCAAmC,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,IAC3E;AAAA,EACF;AAEA,QAAM,SAAU,MAAM,SAAS,KAAK;AACpC,iBAAe;AACf,gBAAc,MAAM;AAEpB,SAAO;AACT;AAWA,eAAsB,gBACpB,UACA,QACA,QACiB;AACjB,QAAM,SAAS,MAAM,iBAAiB,QAAQ,MAAM;AACpD,QAAM,SAAS,OAAO,QAAQ,QAAQ;AAEtC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR,WAAW,QAAQ,qDAAqD,OAAO,KAAK,OAAO,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IAChH;AAAA,EACF;AAEA,SAAO,OAAO;AAChB;AAMO,SAAS,0BAAgC;AAC9C,iBAAe;AACf,gBAAc;AAChB;","names":[]}
@@ -0,0 +1,12 @@
1
+ import {
2
+ clearWorkersConfigCache,
3
+ getWorkersConfig,
4
+ resolveQueueUrl
5
+ } from "./chunk-ZYYWZ3PR.mjs";
6
+ import "./chunk-BJTO5JO5.mjs";
7
+ export {
8
+ clearWorkersConfigCache,
9
+ getWorkersConfig,
10
+ resolveQueueUrl
11
+ };
12
+ //# sourceMappingURL=config.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,96 @@
1
+ import { SQSEvent, Context } from 'aws-lambda';
2
+ import { ZodType } from 'zod';
3
+
4
+ /**
5
+ * Generic Lambda handler wrapper for worker agents.
6
+ * Handles SQS events, executes user handlers, and sends webhook callbacks.
7
+ * Job store: MongoDB only. Never uses HTTP/origin URL for job updates.
8
+ */
9
+
10
+ interface JobStoreUpdate {
11
+ status?: 'queued' | 'running' | 'completed' | 'failed';
12
+ metadata?: Record<string, any>;
13
+ progress?: number;
14
+ progressMessage?: string;
15
+ output?: any;
16
+ error?: {
17
+ message: string;
18
+ stack?: string;
19
+ name?: string;
20
+ };
21
+ }
22
+ interface JobStore {
23
+ /**
24
+ * Update job in job store.
25
+ * @param update - Update object with status, metadata, progress, output, or error
26
+ */
27
+ update(update: JobStoreUpdate): Promise<void>;
28
+ /**
29
+ * Get current job record from job store.
30
+ * @returns Job record or null if not found
31
+ */
32
+ get(): Promise<{
33
+ jobId: string;
34
+ workerId: string;
35
+ status: 'queued' | 'running' | 'completed' | 'failed';
36
+ input: any;
37
+ output?: any;
38
+ error?: {
39
+ message: string;
40
+ stack?: string;
41
+ };
42
+ metadata?: Record<string, any>;
43
+ createdAt: string;
44
+ updatedAt: string;
45
+ completedAt?: string;
46
+ } | null>;
47
+ }
48
+ interface WorkerHandlerParams<INPUT, OUTPUT> {
49
+ input: INPUT;
50
+ ctx: {
51
+ jobId: string;
52
+ workerId: string;
53
+ requestId?: string;
54
+ /**
55
+ * Job store interface for updating and retrieving job state.
56
+ * Uses MongoDB directly when configured; never HTTP/origin URL.
57
+ */
58
+ jobStore?: JobStore;
59
+ [key: string]: any;
60
+ };
61
+ }
62
+ type WorkerHandler<INPUT, OUTPUT> = (params: WorkerHandlerParams<INPUT, OUTPUT>) => Promise<OUTPUT>;
63
+ interface SQSMessageBody {
64
+ workerId: string;
65
+ jobId: string;
66
+ input: any;
67
+ context: Record<string, any>;
68
+ webhookUrl?: string;
69
+ /** @deprecated Never use. Job updates use MongoDB only. */
70
+ jobStoreUrl?: string;
71
+ metadata?: Record<string, any>;
72
+ timestamp: string;
73
+ }
74
+ interface WebhookPayload {
75
+ jobId: string;
76
+ workerId: string;
77
+ status: 'success' | 'error';
78
+ output?: any;
79
+ error?: {
80
+ message: string;
81
+ stack?: string;
82
+ name?: string;
83
+ };
84
+ metadata?: Record<string, any>;
85
+ }
86
+ /**
87
+ * Creates a Lambda handler function that processes SQS events for workers.
88
+ * Job store: MongoDB only. Never uses HTTP/origin URL for job updates.
89
+ *
90
+ * @param handler - The user's worker handler function
91
+ * @param outputSchema - Optional Zod schema for output validation
92
+ * @returns A Lambda handler function
93
+ */
94
+ declare function createLambdaHandler<INPUT, OUTPUT>(handler: WorkerHandler<INPUT, OUTPUT>, outputSchema?: ZodType<OUTPUT>): (event: SQSEvent, context: Context) => Promise<void>;
95
+
96
+ export { type JobStore, type JobStoreUpdate, type SQSMessageBody, type WebhookPayload, type WorkerHandler, type WorkerHandlerParams, createLambdaHandler };