@lobu/worker 2.8.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 (117) hide show
  1. package/dist/core/error-handler.d.ts +7 -0
  2. package/dist/core/error-handler.d.ts.map +1 -0
  3. package/dist/core/error-handler.js +58 -0
  4. package/dist/core/error-handler.js.map +1 -0
  5. package/dist/core/project-scanner.d.ts +9 -0
  6. package/dist/core/project-scanner.d.ts.map +1 -0
  7. package/dist/core/project-scanner.js +64 -0
  8. package/dist/core/project-scanner.js.map +1 -0
  9. package/dist/core/types.d.ts +102 -0
  10. package/dist/core/types.d.ts.map +1 -0
  11. package/dist/core/types.js +8 -0
  12. package/dist/core/types.js.map +1 -0
  13. package/dist/core/url-utils.d.ts +5 -0
  14. package/dist/core/url-utils.d.ts.map +1 -0
  15. package/dist/core/url-utils.js +13 -0
  16. package/dist/core/url-utils.js.map +1 -0
  17. package/dist/core/workspace.d.ts +29 -0
  18. package/dist/core/workspace.d.ts.map +1 -0
  19. package/dist/core/workspace.js +104 -0
  20. package/dist/core/workspace.js.map +1 -0
  21. package/dist/embedded/just-bash-bootstrap.d.ts +21 -0
  22. package/dist/embedded/just-bash-bootstrap.d.ts.map +1 -0
  23. package/dist/embedded/just-bash-bootstrap.js +215 -0
  24. package/dist/embedded/just-bash-bootstrap.js.map +1 -0
  25. package/dist/gateway/gateway-integration.d.ts +57 -0
  26. package/dist/gateway/gateway-integration.d.ts.map +1 -0
  27. package/dist/gateway/gateway-integration.js +209 -0
  28. package/dist/gateway/gateway-integration.js.map +1 -0
  29. package/dist/gateway/message-batcher.d.ts +27 -0
  30. package/dist/gateway/message-batcher.d.ts.map +1 -0
  31. package/dist/gateway/message-batcher.js +102 -0
  32. package/dist/gateway/message-batcher.js.map +1 -0
  33. package/dist/gateway/sse-client.d.ts +74 -0
  34. package/dist/gateway/sse-client.d.ts.map +1 -0
  35. package/dist/gateway/sse-client.js +748 -0
  36. package/dist/gateway/sse-client.js.map +1 -0
  37. package/dist/gateway/types.d.ts +60 -0
  38. package/dist/gateway/types.d.ts.map +1 -0
  39. package/dist/gateway/types.js +6 -0
  40. package/dist/gateway/types.js.map +1 -0
  41. package/dist/index.d.ts +3 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +112 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/instructions/builder.d.ts +8 -0
  46. package/dist/instructions/builder.d.ts.map +1 -0
  47. package/dist/instructions/builder.js +53 -0
  48. package/dist/instructions/builder.js.map +1 -0
  49. package/dist/instructions/providers.d.ts +13 -0
  50. package/dist/instructions/providers.d.ts.map +1 -0
  51. package/dist/instructions/providers.js +26 -0
  52. package/dist/instructions/providers.js.map +1 -0
  53. package/dist/modules/lifecycle.d.ts +18 -0
  54. package/dist/modules/lifecycle.d.ts.map +1 -0
  55. package/dist/modules/lifecycle.js +56 -0
  56. package/dist/modules/lifecycle.js.map +1 -0
  57. package/dist/openclaw/custom-tools.d.ts +17 -0
  58. package/dist/openclaw/custom-tools.d.ts.map +1 -0
  59. package/dist/openclaw/custom-tools.js +195 -0
  60. package/dist/openclaw/custom-tools.js.map +1 -0
  61. package/dist/openclaw/instructions.d.ts +15 -0
  62. package/dist/openclaw/instructions.d.ts.map +1 -0
  63. package/dist/openclaw/instructions.js +32 -0
  64. package/dist/openclaw/instructions.js.map +1 -0
  65. package/dist/openclaw/model-resolver.d.ts +30 -0
  66. package/dist/openclaw/model-resolver.d.ts.map +1 -0
  67. package/dist/openclaw/model-resolver.js +147 -0
  68. package/dist/openclaw/model-resolver.js.map +1 -0
  69. package/dist/openclaw/plugin-loader.d.ts +39 -0
  70. package/dist/openclaw/plugin-loader.d.ts.map +1 -0
  71. package/dist/openclaw/plugin-loader.js +347 -0
  72. package/dist/openclaw/plugin-loader.js.map +1 -0
  73. package/dist/openclaw/processor.d.ts +38 -0
  74. package/dist/openclaw/processor.d.ts.map +1 -0
  75. package/dist/openclaw/processor.js +182 -0
  76. package/dist/openclaw/processor.js.map +1 -0
  77. package/dist/openclaw/session-context.d.ts +44 -0
  78. package/dist/openclaw/session-context.d.ts.map +1 -0
  79. package/dist/openclaw/session-context.js +151 -0
  80. package/dist/openclaw/session-context.js.map +1 -0
  81. package/dist/openclaw/tool-policy.d.ts +23 -0
  82. package/dist/openclaw/tool-policy.d.ts.map +1 -0
  83. package/dist/openclaw/tool-policy.js +151 -0
  84. package/dist/openclaw/tool-policy.js.map +1 -0
  85. package/dist/openclaw/tools.d.ts +6 -0
  86. package/dist/openclaw/tools.d.ts.map +1 -0
  87. package/dist/openclaw/tools.js +158 -0
  88. package/dist/openclaw/tools.js.map +1 -0
  89. package/dist/openclaw/worker.d.ts +39 -0
  90. package/dist/openclaw/worker.d.ts.map +1 -0
  91. package/dist/openclaw/worker.js +1340 -0
  92. package/dist/openclaw/worker.js.map +1 -0
  93. package/dist/server.d.ts +7 -0
  94. package/dist/server.d.ts.map +1 -0
  95. package/dist/server.js +304 -0
  96. package/dist/server.js.map +1 -0
  97. package/dist/shared/audio-provider-suggestions.d.ts +13 -0
  98. package/dist/shared/audio-provider-suggestions.d.ts.map +1 -0
  99. package/dist/shared/audio-provider-suggestions.js +105 -0
  100. package/dist/shared/audio-provider-suggestions.js.map +1 -0
  101. package/dist/shared/processor-utils.d.ts +6 -0
  102. package/dist/shared/processor-utils.d.ts.map +1 -0
  103. package/dist/shared/processor-utils.js +30 -0
  104. package/dist/shared/processor-utils.js.map +1 -0
  105. package/dist/shared/provider-auth-hints.d.ts +6 -0
  106. package/dist/shared/provider-auth-hints.d.ts.map +1 -0
  107. package/dist/shared/provider-auth-hints.js +51 -0
  108. package/dist/shared/provider-auth-hints.js.map +1 -0
  109. package/dist/shared/tool-display-config.d.ts +16 -0
  110. package/dist/shared/tool-display-config.d.ts.map +1 -0
  111. package/dist/shared/tool-display-config.js +67 -0
  112. package/dist/shared/tool-display-config.js.map +1 -0
  113. package/dist/shared/tool-implementations.d.ts +55 -0
  114. package/dist/shared/tool-implementations.d.ts.map +1 -0
  115. package/dist/shared/tool-implementations.js +519 -0
  116. package/dist/shared/tool-implementations.js.map +1 -0
  117. package/package.json +55 -0
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ /**
3
+ * Worker-side just-bash bootstrap for embedded deployment mode.
4
+ *
5
+ * Creates a just-bash Bash instance from environment variables and wraps it
6
+ * as a BashOperations interface for pi-coding-agent's bash tool.
7
+ *
8
+ * When nix binaries are detected on PATH (via nix-shell wrapper from gateway)
9
+ * or known CLI tools (e.g. owletto) are found, they are registered as
10
+ * just-bash customCommands that delegate to real exec.
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ var __importDefault = (this && this.__importDefault) || function (mod) {
46
+ return (mod && mod.__esModule) ? mod : { "default": mod };
47
+ };
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.buildBinaryInvocation = buildBinaryInvocation;
50
+ exports.createEmbeddedBashOps = createEmbeddedBashOps;
51
+ const node_child_process_1 = require("node:child_process");
52
+ const node_fs_1 = __importDefault(require("node:fs"));
53
+ const node_path_1 = __importDefault(require("node:path"));
54
+ const EMBEDDED_BASH_LIMITS = {
55
+ maxCommandCount: 50_000,
56
+ maxLoopIterations: 50_000,
57
+ maxCallDepth: 50,
58
+ };
59
+ function buildBinaryInvocation(binaryPath, args) {
60
+ try {
61
+ const firstLine = node_fs_1.default.readFileSync(binaryPath, "utf8").split("\n", 1)[0] || "";
62
+ if (firstLine === "#!/usr/bin/env node" || firstLine.endsWith("/node")) {
63
+ return { command: "node", args: [binaryPath, ...args] };
64
+ }
65
+ }
66
+ catch {
67
+ // Fall back to executing the binary directly.
68
+ }
69
+ return { command: binaryPath, args };
70
+ }
71
+ /**
72
+ * Discover binaries to register as custom commands:
73
+ * 1. All executables from /nix/store/ PATH directories
74
+ * 2. Known CLI tools (owletto) from anywhere on PATH
75
+ */
76
+ function discoverBinaries() {
77
+ const binaries = new Map();
78
+ const pathDirs = (process.env.PATH || "").split(":");
79
+ for (const dir of pathDirs) {
80
+ if (!dir.includes("/nix/store/"))
81
+ continue;
82
+ try {
83
+ for (const entry of node_fs_1.default.readdirSync(dir)) {
84
+ const fullPath = node_path_1.default.join(dir, entry);
85
+ try {
86
+ node_fs_1.default.accessSync(fullPath, node_fs_1.default.constants.X_OK);
87
+ if (!binaries.has(entry))
88
+ binaries.set(entry, fullPath);
89
+ }
90
+ catch {
91
+ // not executable
92
+ }
93
+ }
94
+ }
95
+ catch {
96
+ // directory not readable
97
+ }
98
+ }
99
+ // Discover known CLI tools from full PATH
100
+ for (const name of ["owletto"]) {
101
+ if (binaries.has(name))
102
+ continue;
103
+ for (const dir of pathDirs) {
104
+ const fullPath = node_path_1.default.join(dir, name);
105
+ try {
106
+ node_fs_1.default.accessSync(fullPath, node_fs_1.default.constants.X_OK);
107
+ binaries.set(name, fullPath);
108
+ break;
109
+ }
110
+ catch {
111
+ // not found
112
+ }
113
+ }
114
+ }
115
+ return binaries;
116
+ }
117
+ /**
118
+ * Create just-bash customCommands from a map of binary name → full path.
119
+ * Each custom command delegates to the real binary via child_process.execFile.
120
+ */
121
+ async function buildCustomCommands(binaries) {
122
+ const { defineCommand } = await Promise.resolve().then(() => __importStar(require("just-bash")));
123
+ const commands = [];
124
+ for (const [name, binaryPath] of binaries) {
125
+ commands.push(defineCommand(name, async (args, ctx) => {
126
+ const invocation = buildBinaryInvocation(binaryPath, args);
127
+ // Convert ctx.env (Map-like) to a plain Record for child_process
128
+ const envRecord = { ...process.env };
129
+ if (ctx.env && typeof ctx.env.forEach === "function") {
130
+ ctx.env.forEach((v, k) => {
131
+ envRecord[k] = v;
132
+ });
133
+ }
134
+ else if (ctx.env && typeof ctx.env === "object") {
135
+ Object.assign(envRecord, ctx.env);
136
+ }
137
+ return new Promise((resolve) => {
138
+ (0, node_child_process_1.execFile)(invocation.command, invocation.args, {
139
+ cwd: ctx.cwd,
140
+ env: envRecord,
141
+ maxBuffer: 10 * 1024 * 1024,
142
+ }, (error, stdout, stderr) => {
143
+ resolve({
144
+ stdout: stdout || "",
145
+ stderr: stderr || (error?.message ?? ""),
146
+ exitCode: error?.code ? Number(error.code) || 1 : 0,
147
+ });
148
+ });
149
+ });
150
+ }));
151
+ }
152
+ return commands;
153
+ }
154
+ /**
155
+ * Create a BashOperations adapter backed by a just-bash Bash instance.
156
+ * Reads configuration from environment variables.
157
+ */
158
+ async function createEmbeddedBashOps() {
159
+ const { Bash, ReadWriteFs } = await Promise.resolve().then(() => __importStar(require("just-bash")));
160
+ const workspaceDir = process.env.WORKSPACE_DIR || "/workspace";
161
+ const bashFs = new ReadWriteFs({ root: workspaceDir });
162
+ // Parse allowed domains from env var (set by gateway)
163
+ let allowedDomains = [];
164
+ if (process.env.JUST_BASH_ALLOWED_DOMAINS) {
165
+ try {
166
+ allowedDomains = JSON.parse(process.env.JUST_BASH_ALLOWED_DOMAINS);
167
+ }
168
+ catch {
169
+ console.error(`[embedded] Failed to parse JUST_BASH_ALLOWED_DOMAINS: ${process.env.JUST_BASH_ALLOWED_DOMAINS}`);
170
+ }
171
+ }
172
+ const network = allowedDomains.length > 0
173
+ ? {
174
+ allowedUrlPrefixes: allowedDomains.flatMap((domain) => [
175
+ `https://${domain}/`,
176
+ `http://${domain}/`,
177
+ ]),
178
+ allowedMethods: ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"],
179
+ }
180
+ : undefined;
181
+ // Discover nix binaries and known CLI tools, register as custom commands
182
+ const binaries = discoverBinaries();
183
+ const customCommands = binaries.size > 0 ? await buildCustomCommands(binaries) : [];
184
+ if (binaries.size > 0) {
185
+ const names = [...binaries.keys()].slice(0, 20).join(", ");
186
+ const suffix = binaries.size > 20 ? `, ... (${binaries.size} total)` : "";
187
+ console.log(`[embedded] Registered ${binaries.size} custom commands: ${names}${suffix}`);
188
+ }
189
+ const bashInstance = new Bash({
190
+ fs: bashFs,
191
+ cwd: "/",
192
+ env: Object.fromEntries(Object.entries(process.env).filter((entry) => entry[1] !== undefined)),
193
+ executionLimits: EMBEDDED_BASH_LIMITS,
194
+ ...(network && { network }),
195
+ ...(customCommands.length > 0 && { customCommands }),
196
+ });
197
+ return {
198
+ async exec(command, cwd, { onData, signal, timeout }) {
199
+ const timeoutMs = timeout !== undefined && timeout > 0 ? timeout * 1000 : undefined;
200
+ const result = await bashInstance.exec(command, {
201
+ cwd,
202
+ signal,
203
+ env: { TIMEOUT_MS: timeoutMs ? String(timeoutMs) : "" },
204
+ });
205
+ if (result.stdout) {
206
+ onData(Buffer.from(result.stdout));
207
+ }
208
+ if (result.stderr) {
209
+ onData(Buffer.from(result.stderr));
210
+ }
211
+ return { exitCode: result.exitCode };
212
+ },
213
+ };
214
+ }
215
+ //# sourceMappingURL=just-bash-bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"just-bash-bootstrap.js","sourceRoot":"","sources":["../../src/embedded/just-bash-bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * HTTP implementation of WorkerTransport
3
+ * Sends worker responses to gateway via HTTP POST requests
4
+ */
5
+ import { type WorkerTransport, type WorkerTransportConfig } from "@lobu/core";
6
+ /**
7
+ * HTTP transport for worker-to-gateway communication
8
+ * Implements retry logic and deduplication for streaming responses
9
+ */
10
+ export declare class HttpWorkerTransport implements WorkerTransport {
11
+ private gatewayUrl;
12
+ private workerToken;
13
+ private userId;
14
+ private channelId;
15
+ private conversationId;
16
+ private originalMessageTs;
17
+ private botResponseTs?;
18
+ processedMessageIds: string[];
19
+ private jobId?;
20
+ private moduleData?;
21
+ private teamId;
22
+ private platform?;
23
+ private platformMetadata?;
24
+ private accumulatedStreamContent;
25
+ private lastStreamDelta;
26
+ constructor(config: WorkerTransportConfig);
27
+ setJobId(jobId: string): void;
28
+ setModuleData(moduleData: Record<string, unknown>): void;
29
+ signalDone(finalDelta?: string): Promise<void>;
30
+ sendStreamDelta(delta: string, isFullReplacement?: boolean, isFinal?: boolean): Promise<void>;
31
+ signalCompletion(): Promise<void>;
32
+ signalError(error: Error, errorCode?: string): Promise<void>;
33
+ sendStatusUpdate(elapsedSeconds: number, state: string): Promise<void>;
34
+ /**
35
+ * Build base response payload with common fields shared across all response types
36
+ */
37
+ private buildBaseResponse;
38
+ /**
39
+ * Build exec response payload with exec-specific fields
40
+ */
41
+ private buildExecResponse;
42
+ /**
43
+ * Send exec output (stdout/stderr) to gateway
44
+ */
45
+ sendExecOutput(execId: string, stream: "stdout" | "stderr", content: string): Promise<void>;
46
+ /**
47
+ * Send exec completion to gateway
48
+ */
49
+ sendExecComplete(execId: string, exitCode: number): Promise<void>;
50
+ /**
51
+ * Send exec error to gateway
52
+ */
53
+ sendExecError(execId: string, errorMessage: string): Promise<void>;
54
+ private sendResponse;
55
+ private normalizeForComparison;
56
+ }
57
+ //# sourceMappingURL=gateway-integration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-integration.d.ts","sourceRoot":"","sources":["../../src/gateway/gateway-integration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC3B,MAAM,YAAY,CAAC;AAKpB;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IACzD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,aAAa,CAAC,CAAS;IACxB,mBAAmB,EAAE,MAAM,EAAE,CAAM;IAC1C,OAAO,CAAC,KAAK,CAAC,CAAS;IACvB,OAAO,CAAC,UAAU,CAAC,CAA0B;IAC7C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAC,CAA0B;IACnD,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,eAAe,CAAc;gBAEzB,MAAM,EAAE,qBAAqB;IAczC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIlD,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C,eAAe,CACnB,KAAK,EAAE,MAAM,EACb,iBAAiB,GAAE,OAAe,EAClC,OAAO,GAAE,OAAe,GACvB,OAAO,CAAC,IAAI,CAAC;IA2EV,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IASjC,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5D,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ5E;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;OAEG;IACG,cAAc,CAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAC3B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC;IAMhB;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvE;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAM1D,YAAY;IAoD1B,OAAO,CAAC,sBAAsB;CAG/B"}
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ /**
3
+ * HTTP implementation of WorkerTransport
4
+ * Sends worker responses to gateway via HTTP POST requests
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.HttpWorkerTransport = void 0;
8
+ const core_1 = require("@lobu/core");
9
+ const logger = (0, core_1.createLogger)("http-worker-transport");
10
+ /**
11
+ * HTTP transport for worker-to-gateway communication
12
+ * Implements retry logic and deduplication for streaming responses
13
+ */
14
+ class HttpWorkerTransport {
15
+ gatewayUrl;
16
+ workerToken;
17
+ userId;
18
+ channelId;
19
+ conversationId;
20
+ originalMessageTs;
21
+ botResponseTs;
22
+ processedMessageIds = [];
23
+ jobId;
24
+ moduleData;
25
+ teamId;
26
+ platform;
27
+ platformMetadata;
28
+ accumulatedStreamContent = [];
29
+ lastStreamDelta = "";
30
+ constructor(config) {
31
+ this.gatewayUrl = config.gatewayUrl;
32
+ this.workerToken = config.workerToken;
33
+ this.userId = config.userId;
34
+ this.channelId = config.channelId;
35
+ this.conversationId = config.conversationId;
36
+ this.originalMessageTs = config.originalMessageTs;
37
+ this.botResponseTs = config.botResponseTs;
38
+ this.teamId = config.teamId;
39
+ this.platform = config.platform;
40
+ this.platformMetadata = config.platformMetadata;
41
+ this.processedMessageIds = config.processedMessageIds || [];
42
+ }
43
+ setJobId(jobId) {
44
+ this.jobId = jobId;
45
+ }
46
+ setModuleData(moduleData) {
47
+ this.moduleData = moduleData;
48
+ }
49
+ async signalDone(finalDelta) {
50
+ // Send final delta if there is one
51
+ if (finalDelta) {
52
+ await this.sendStreamDelta(finalDelta, false, true);
53
+ }
54
+ await this.signalCompletion();
55
+ }
56
+ async sendStreamDelta(delta, isFullReplacement = false, isFinal = false) {
57
+ let actualDelta = delta;
58
+ // Handle final result with deduplication
59
+ if (isFinal) {
60
+ logger.info(`🔍 Processing final result with deduplication`);
61
+ logger.info(`Final text length: ${delta.length} chars`);
62
+ const accumulatedStr = this.accumulatedStreamContent.join("");
63
+ const accumulatedLength = accumulatedStr.length;
64
+ logger.info(`Accumulated length: ${accumulatedLength} chars`);
65
+ // Check if final result is identical to what we've already sent
66
+ if (delta === accumulatedStr) {
67
+ logger.info(`✅ Final result is identical to accumulated content - skipping duplicate`);
68
+ return;
69
+ }
70
+ // Check if accumulated content is a prefix of final result
71
+ if (delta.startsWith(accumulatedStr)) {
72
+ // Only send the missing part
73
+ actualDelta = delta.slice(accumulatedLength);
74
+ if (actualDelta.length === 0) {
75
+ logger.info(`✅ Final result fully contained in accumulated content - skipping`);
76
+ return;
77
+ }
78
+ logger.info(`📝 Final result has ${actualDelta.length} new chars - sending delta only`);
79
+ }
80
+ else if (accumulatedLength > 0) {
81
+ const normalizedFinal = this.normalizeForComparison(delta);
82
+ const normalizedLastDelta = this.normalizeForComparison(this.lastStreamDelta);
83
+ if (normalizedFinal.length > 0 &&
84
+ normalizedFinal === normalizedLastDelta) {
85
+ logger.info(`✅ Final result matches last streamed delta (normalized) - skipping duplicate`);
86
+ return;
87
+ }
88
+ // Content differs - log warning and send full final result
89
+ logger.warn(`⚠️ Final result differs from accumulated content!`);
90
+ logger.warn(`First 100 chars of accumulated: ${accumulatedStr.substring(0, 100)}`);
91
+ logger.warn(`First 100 chars of final: ${delta.substring(0, 100)}`);
92
+ logger.info(`📤 Sending full final result (${delta.length} chars)`);
93
+ }
94
+ }
95
+ // Track accumulated content for deduplication using array buffer (O(1) append)
96
+ if (!isFullReplacement) {
97
+ this.accumulatedStreamContent.push(actualDelta);
98
+ }
99
+ else {
100
+ this.accumulatedStreamContent = [actualDelta];
101
+ }
102
+ this.lastStreamDelta = actualDelta;
103
+ await this.sendResponse(this.buildBaseResponse({
104
+ delta: actualDelta,
105
+ moduleData: this.moduleData,
106
+ isFullReplacement,
107
+ }));
108
+ }
109
+ async signalCompletion() {
110
+ await this.sendResponse(this.buildBaseResponse({
111
+ processedMessageIds: this.processedMessageIds,
112
+ moduleData: this.moduleData,
113
+ }));
114
+ }
115
+ async signalError(error, errorCode) {
116
+ await this.sendResponse(this.buildBaseResponse({
117
+ error: error.message,
118
+ ...(errorCode && { errorCode }),
119
+ }));
120
+ }
121
+ async sendStatusUpdate(elapsedSeconds, state) {
122
+ await this.sendResponse(this.buildBaseResponse({
123
+ statusUpdate: { elapsedSeconds, state },
124
+ }));
125
+ }
126
+ /**
127
+ * Build base response payload with common fields shared across all response types
128
+ */
129
+ buildBaseResponse(additionalFields) {
130
+ return {
131
+ messageId: this.originalMessageTs,
132
+ channelId: this.channelId,
133
+ conversationId: this.conversationId,
134
+ userId: this.userId,
135
+ teamId: this.teamId,
136
+ timestamp: Date.now(),
137
+ originalMessageId: this.originalMessageTs,
138
+ botResponseId: this.botResponseTs,
139
+ ...additionalFields,
140
+ };
141
+ }
142
+ /**
143
+ * Build exec response payload with exec-specific fields
144
+ */
145
+ buildExecResponse(execId, additionalFields) {
146
+ return this.buildBaseResponse({ execId, ...additionalFields });
147
+ }
148
+ /**
149
+ * Send exec output (stdout/stderr) to gateway
150
+ */
151
+ async sendExecOutput(execId, stream, content) {
152
+ await this.sendResponse(this.buildExecResponse(execId, { delta: content, execStream: stream }));
153
+ }
154
+ /**
155
+ * Send exec completion to gateway
156
+ */
157
+ async sendExecComplete(execId, exitCode) {
158
+ await this.sendResponse(this.buildExecResponse(execId, { execExitCode: exitCode }));
159
+ }
160
+ /**
161
+ * Send exec error to gateway
162
+ */
163
+ async sendExecError(execId, errorMessage) {
164
+ await this.sendResponse(this.buildExecResponse(execId, { error: errorMessage }));
165
+ }
166
+ async sendResponse(data) {
167
+ const responseUrl = `${this.gatewayUrl}/worker/response`;
168
+ const basePayload = {
169
+ ...data,
170
+ ...(this.platform && !data.platform ? { platform: this.platform } : {}),
171
+ ...(!data.platformMetadata && this.platformMetadata
172
+ ? { platformMetadata: this.platformMetadata }
173
+ : {}),
174
+ };
175
+ const payload = this.jobId
176
+ ? { jobId: this.jobId, ...basePayload }
177
+ : basePayload;
178
+ await (0, core_1.retryWithBackoff)(async () => {
179
+ logger.info(`[WORKER-HTTP] Sending to ${responseUrl}: ${JSON.stringify(payload).substring(0, 500)}`);
180
+ if (payload.delta) {
181
+ logger.info(`[WORKER-HTTP] Stream delta payload: deltaLength=${payload.delta?.length}`);
182
+ }
183
+ const response = await fetch(responseUrl, {
184
+ method: "POST",
185
+ headers: {
186
+ Authorization: `Bearer ${this.workerToken}`,
187
+ "Content-Type": "application/json",
188
+ },
189
+ body: JSON.stringify(payload),
190
+ signal: AbortSignal.timeout(30_000),
191
+ });
192
+ if (!response.ok) {
193
+ throw new Error(`Failed to send response to dispatcher: ${response.status} ${response.statusText}`);
194
+ }
195
+ logger.debug("Response sent to dispatcher successfully");
196
+ }, {
197
+ maxRetries: 2,
198
+ baseDelay: 1000,
199
+ onRetry: (attempt, error) => {
200
+ logger.warn(`Failed to send response (attempt ${attempt}/2):`, error);
201
+ },
202
+ });
203
+ }
204
+ normalizeForComparison(text) {
205
+ return text.replace(/\r\n/g, "\n").trim();
206
+ }
207
+ }
208
+ exports.HttpWorkerTransport = HttpWorkerTransport;
209
+ //# sourceMappingURL=gateway-integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-integration.js","sourceRoot":"","sources":["../../src/gateway/gateway-integration.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,qCAKoB;AAGpB,MAAM,MAAM,GAAG,IAAA,mBAAY,EAAC,uBAAuB,CAAC,CAAC;AAErD;;;GAGG;AACH,MAAa,mBAAmB;IACtB,UAAU,CAAS;IACnB,WAAW,CAAS;IACpB,MAAM,CAAS;IACf,SAAS,CAAS;IAClB,cAAc,CAAS;IACvB,iBAAiB,CAAS;IAC1B,aAAa,CAAU;IACxB,mBAAmB,GAAa,EAAE,CAAC;IAClC,KAAK,CAAU;IACf,UAAU,CAA2B;IACrC,MAAM,CAAS;IACf,QAAQ,CAAU;IAClB,gBAAgB,CAA2B;IAC3C,wBAAwB,GAAa,EAAE,CAAC;IACxC,eAAe,GAAW,EAAE,CAAC;IAErC,YAAY,MAA6B;QACvC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC5C,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;QAClD,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;QAChD,IAAI,CAAC,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC;IAC9D,CAAC;IAED,QAAQ,CAAC,KAAa;QACpB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,aAAa,CAAC,UAAmC;QAC/C,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAmB;QAClC,mCAAmC;QACnC,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAa,EACb,oBAA6B,KAAK,EAClC,UAAmB,KAAK;QAExB,IAAI,WAAW,GAAG,KAAK,CAAC;QAExB,yCAAyC;QACzC,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;YAC7D,MAAM,CAAC,IAAI,CAAC,sBAAsB,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;YACxD,MAAM,cAAc,GAAG,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9D,MAAM,iBAAiB,GAAG,cAAc,CAAC,MAAM,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,uBAAuB,iBAAiB,QAAQ,CAAC,CAAC;YAE9D,gEAAgE;YAChE,IAAI,KAAK,KAAK,cAAc,EAAE,CAAC;gBAC7B,MAAM,CAAC,IAAI,CACT,yEAAyE,CAC1E,CAAC;gBACF,OAAO;YACT,CAAC;YAED,2DAA2D;YAC3D,IAAI,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBACrC,6BAA6B;gBAC7B,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;gBAC7C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC7B,MAAM,CAAC,IAAI,CACT,kEAAkE,CACnE,CAAC;oBACF,OAAO;gBACT,CAAC;gBACD,MAAM,CAAC,IAAI,CACT,uBAAuB,WAAW,CAAC,MAAM,iCAAiC,CAC3E,CAAC;YACJ,CAAC;iBAAM,IAAI,iBAAiB,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,eAAe,GAAG,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;gBAC3D,MAAM,mBAAmB,GAAG,IAAI,CAAC,sBAAsB,CACrD,IAAI,CAAC,eAAe,CACrB,CAAC;gBAEF,IACE,eAAe,CAAC,MAAM,GAAG,CAAC;oBAC1B,eAAe,KAAK,mBAAmB,EACvC,CAAC;oBACD,MAAM,CAAC,IAAI,CACT,8EAA8E,CAC/E,CAAC;oBACF,OAAO;gBACT,CAAC;gBAED,2DAA2D;gBAC3D,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;gBAClE,MAAM,CAAC,IAAI,CACT,mCAAmC,cAAc,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CACtE,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,6BAA6B,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBACpE,MAAM,CAAC,IAAI,CAAC,iCAAiC,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QAED,+EAA+E;QAC/E,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,wBAAwB,GAAG,CAAC,WAAW,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC;QAEnC,MAAM,IAAI,CAAC,YAAY,CACrB,IAAI,CAAC,iBAAiB,CAAC;YACrB,KAAK,EAAE,WAAW;YAClB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,iBAAiB;SAClB,CAAC,CACH,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,IAAI,CAAC,YAAY,CACrB,IAAI,CAAC,iBAAiB,CAAC;YACrB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;YAC7C,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CACH,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAY,EAAE,SAAkB;QAChD,MAAM,IAAI,CAAC,YAAY,CACrB,IAAI,CAAC,iBAAiB,CAAC;YACrB,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,GAAG,CAAC,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;SAChC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,cAAsB,EAAE,KAAa;QAC1D,MAAM,IAAI,CAAC,YAAY,CACrB,IAAI,CAAC,iBAAiB,CAAC;YACrB,YAAY,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE;SACxC,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,iBAAiB,CACvB,gBAAwC;QAExC,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,iBAAiB;YACjC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,GAAG,gBAAgB;SACpB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,iBAAiB,CACvB,MAAc,EACd,gBAAuC;QAEvC,OAAO,IAAI,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC,CAAC;IACjE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAClB,MAAc,EACd,MAA2B,EAC3B,OAAe;QAEf,MAAM,IAAI,CAAC,YAAY,CACrB,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CACvE,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,MAAc,EAAE,QAAgB;QACrD,MAAM,IAAI,CAAC,YAAY,CACrB,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAC3D,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,MAAc,EAAE,YAAoB;QACtD,MAAM,IAAI,CAAC,YAAY,CACrB,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CACxD,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,IAAkB;QAC3C,MAAM,WAAW,GAAG,GAAG,IAAI,CAAC,UAAU,kBAAkB,CAAC;QACzD,MAAM,WAAW,GAAG;YAClB,GAAG,IAAI;YACP,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,gBAAgB;gBACjD,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE;gBAC7C,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK;YACxB,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,WAAW,EAAE;YACvC,CAAC,CAAC,WAAW,CAAC;QAEhB,MAAM,IAAA,uBAAgB,EACpB,KAAK,IAAI,EAAE;YACT,MAAM,CAAC,IAAI,CACT,4BAA4B,WAAW,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CACxF,CAAC;YACF,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM,CAAC,IAAI,CACT,mDAAmD,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,CAC3E,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,EAAE;gBACxC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,WAAW,EAAE;oBAC3C,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC7B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;aACpC,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CACb,0CAA0C,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACnF,CAAC;YACJ,CAAC;YAED,MAAM,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC3D,CAAC,EACD;YACE,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;gBAC1B,MAAM,CAAC,IAAI,CAAC,oCAAoC,OAAO,MAAM,EAAE,KAAK,CAAC,CAAC;YACxE,CAAC;SACF,CACF,CAAC;IACJ,CAAC;IAEO,sBAAsB,CAAC,IAAY;QACzC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,CAAC;CACF;AA3QD,kDA2QC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Message batching for grouping rapid messages
3
+ */
4
+ import type { QueuedMessage } from "./types";
5
+ interface BatcherConfig {
6
+ onBatchReady?: (messages: QueuedMessage[]) => Promise<void>;
7
+ batchWindowMs?: number;
8
+ }
9
+ /**
10
+ * Simple message batcher - collects messages for a short window, then processes
11
+ */
12
+ export declare class MessageBatcher {
13
+ private messageQueue;
14
+ private isProcessing;
15
+ private batchTimer;
16
+ private readonly batchWindowMs;
17
+ private readonly onBatchReady?;
18
+ private hasProcessedInitialBatch;
19
+ constructor(config?: BatcherConfig);
20
+ addMessage(message: QueuedMessage): Promise<void>;
21
+ private processBatch;
22
+ stop(): void;
23
+ isCurrentlyProcessing(): boolean;
24
+ getPendingCount(): number;
25
+ }
26
+ export {};
27
+ //# sourceMappingURL=message-batcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-batcher.d.ts","sourceRoot":"","sources":["../../src/gateway/message-batcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAI7C,UAAU,aAAa;IACrB,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAA+C;IAC7E,OAAO,CAAC,wBAAwB,CAAS;gBAE7B,MAAM,GAAE,aAAkB;IAKhC,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;YAqCzC,YAAY;IA8C1B,IAAI,IAAI,IAAI;IAOZ,qBAAqB,IAAI,OAAO;IAIhC,eAAe,IAAI,MAAM;CAG1B"}
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ /**
3
+ * Message batching for grouping rapid messages
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MessageBatcher = void 0;
7
+ const core_1 = require("@lobu/core");
8
+ const logger = (0, core_1.createLogger)("message-batcher");
9
+ /**
10
+ * Simple message batcher - collects messages for a short window, then processes
11
+ */
12
+ class MessageBatcher {
13
+ messageQueue = [];
14
+ isProcessing = false;
15
+ batchTimer = null;
16
+ batchWindowMs;
17
+ onBatchReady;
18
+ hasProcessedInitialBatch = false;
19
+ constructor(config = {}) {
20
+ this.batchWindowMs = config.batchWindowMs ?? 2000; // 2 second window by default
21
+ this.onBatchReady = config.onBatchReady;
22
+ }
23
+ async addMessage(message) {
24
+ this.messageQueue.push(message);
25
+ // If already processing, message will be picked up in next batch
26
+ if (this.isProcessing) {
27
+ logger.info(`Message queued (${this.messageQueue.length} pending, processing in progress)`);
28
+ return;
29
+ }
30
+ // If no batch timer running, start one
31
+ if (!this.batchTimer) {
32
+ if (!this.hasProcessedInitialBatch) {
33
+ this.hasProcessedInitialBatch = true;
34
+ logger.info(`Processing first message immediately (skipping ${this.batchWindowMs}ms batch window)`);
35
+ await this.processBatch();
36
+ return;
37
+ }
38
+ logger.info(`Starting ${this.batchWindowMs}ms batch window (${this.messageQueue.length} message(s))`);
39
+ this.batchTimer = setTimeout(() => {
40
+ void this.processBatch().catch(() => {
41
+ // Error already logged in processBatch
42
+ });
43
+ }, this.batchWindowMs);
44
+ }
45
+ else {
46
+ logger.info(`Message added to batch window (${this.messageQueue.length} pending)`);
47
+ }
48
+ }
49
+ async processBatch() {
50
+ if (this.batchTimer) {
51
+ clearTimeout(this.batchTimer);
52
+ this.batchTimer = null;
53
+ }
54
+ if (this.messageQueue.length === 0) {
55
+ return;
56
+ }
57
+ this.isProcessing = true;
58
+ try {
59
+ const messagesToProcess = [...this.messageQueue];
60
+ this.messageQueue = [];
61
+ logger.info(`Processing batch of ${messagesToProcess.length} messages`);
62
+ messagesToProcess.sort((a, b) => a.timestamp - b.timestamp);
63
+ if (this.onBatchReady) {
64
+ await this.onBatchReady(messagesToProcess);
65
+ }
66
+ // If more messages arrived during processing, start new batch
67
+ if (this.messageQueue.length > 0) {
68
+ if (this.batchTimer) {
69
+ clearTimeout(this.batchTimer);
70
+ this.batchTimer = null;
71
+ }
72
+ logger.info(`Starting new batch window for ${this.messageQueue.length} queued messages`);
73
+ this.batchTimer = setTimeout(() => {
74
+ void this.processBatch().catch(() => {
75
+ // Error already logged in processBatch
76
+ });
77
+ }, this.batchWindowMs);
78
+ }
79
+ }
80
+ catch (error) {
81
+ logger.error("Error during batch processing:", error);
82
+ throw error;
83
+ }
84
+ finally {
85
+ this.isProcessing = false;
86
+ }
87
+ }
88
+ stop() {
89
+ if (this.batchTimer) {
90
+ clearTimeout(this.batchTimer);
91
+ this.batchTimer = null;
92
+ }
93
+ }
94
+ isCurrentlyProcessing() {
95
+ return this.isProcessing;
96
+ }
97
+ getPendingCount() {
98
+ return this.messageQueue.length;
99
+ }
100
+ }
101
+ exports.MessageBatcher = MessageBatcher;
102
+ //# sourceMappingURL=message-batcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-batcher.js","sourceRoot":"","sources":["../../src/gateway/message-batcher.ts"],"names":[],"mappings":"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"}