@lobu/worker 3.0.5 → 3.0.7

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 (46) hide show
  1. package/USAGE.md +120 -0
  2. package/docs/custom-base-image.md +88 -0
  3. package/package.json +2 -2
  4. package/scripts/worker-entrypoint.sh +184 -0
  5. package/src/__tests__/audio-provider-suggestions.test.ts +198 -0
  6. package/src/__tests__/embedded-just-bash-bootstrap.test.ts +39 -0
  7. package/src/__tests__/embedded-tools.test.ts +558 -0
  8. package/src/__tests__/instructions.test.ts +59 -0
  9. package/src/__tests__/memory-flush-runtime.test.ts +138 -0
  10. package/src/__tests__/memory-flush.test.ts +64 -0
  11. package/src/__tests__/model-resolver.test.ts +156 -0
  12. package/src/__tests__/processor.test.ts +225 -0
  13. package/src/__tests__/setup.ts +109 -0
  14. package/src/__tests__/sse-client.test.ts +48 -0
  15. package/src/__tests__/tool-policy.test.ts +269 -0
  16. package/src/__tests__/worker.test.ts +89 -0
  17. package/src/core/error-handler.ts +70 -0
  18. package/src/core/project-scanner.ts +65 -0
  19. package/src/core/types.ts +125 -0
  20. package/src/core/url-utils.ts +9 -0
  21. package/src/core/workspace.ts +138 -0
  22. package/src/embedded/just-bash-bootstrap.ts +228 -0
  23. package/src/gateway/gateway-integration.ts +287 -0
  24. package/src/gateway/message-batcher.ts +128 -0
  25. package/src/gateway/sse-client.ts +955 -0
  26. package/src/gateway/types.ts +68 -0
  27. package/src/index.ts +146 -0
  28. package/src/instructions/builder.ts +80 -0
  29. package/src/instructions/providers.ts +27 -0
  30. package/src/modules/lifecycle.ts +92 -0
  31. package/src/openclaw/custom-tools.ts +290 -0
  32. package/src/openclaw/instructions.ts +38 -0
  33. package/src/openclaw/model-resolver.ts +150 -0
  34. package/src/openclaw/plugin-loader.ts +427 -0
  35. package/src/openclaw/processor.ts +216 -0
  36. package/src/openclaw/session-context.ts +277 -0
  37. package/src/openclaw/tool-policy.ts +212 -0
  38. package/src/openclaw/tools.ts +208 -0
  39. package/src/openclaw/worker.ts +1792 -0
  40. package/src/server.ts +329 -0
  41. package/src/shared/audio-provider-suggestions.ts +132 -0
  42. package/src/shared/processor-utils.ts +33 -0
  43. package/src/shared/provider-auth-hints.ts +64 -0
  44. package/src/shared/tool-display-config.ts +75 -0
  45. package/src/shared/tool-implementations.ts +768 -0
  46. package/tsconfig.json +21 -0
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Message batching for grouping rapid messages
3
+ */
4
+
5
+ import { createLogger } from "@lobu/core";
6
+ import type { QueuedMessage } from "./types";
7
+
8
+ const logger = createLogger("message-batcher");
9
+
10
+ interface BatcherConfig {
11
+ onBatchReady?: (messages: QueuedMessage[]) => Promise<void>;
12
+ batchWindowMs?: number;
13
+ }
14
+
15
+ /**
16
+ * Simple message batcher - collects messages for a short window, then processes
17
+ */
18
+ export class MessageBatcher {
19
+ private messageQueue: QueuedMessage[] = [];
20
+ private isProcessing = false;
21
+ private batchTimer: NodeJS.Timeout | null = null;
22
+ private readonly batchWindowMs: number;
23
+ private readonly onBatchReady?: (messages: QueuedMessage[]) => Promise<void>;
24
+ private hasProcessedInitialBatch = false;
25
+
26
+ constructor(config: BatcherConfig = {}) {
27
+ this.batchWindowMs = config.batchWindowMs ?? 2000; // 2 second window by default
28
+ this.onBatchReady = config.onBatchReady;
29
+ }
30
+
31
+ async addMessage(message: QueuedMessage): Promise<void> {
32
+ this.messageQueue.push(message);
33
+
34
+ // If already processing, message will be picked up in next batch
35
+ if (this.isProcessing) {
36
+ logger.info(
37
+ `Message queued (${this.messageQueue.length} pending, processing in progress)`
38
+ );
39
+ return;
40
+ }
41
+
42
+ // If no batch timer running, start one
43
+ if (!this.batchTimer) {
44
+ if (!this.hasProcessedInitialBatch) {
45
+ this.hasProcessedInitialBatch = true;
46
+ logger.info(
47
+ `Processing first message immediately (skipping ${this.batchWindowMs}ms batch window)`
48
+ );
49
+ await this.processBatch();
50
+ return;
51
+ }
52
+
53
+ logger.info(
54
+ `Starting ${this.batchWindowMs}ms batch window (${this.messageQueue.length} message(s))`
55
+ );
56
+ this.batchTimer = setTimeout(() => {
57
+ void this.processBatch().catch(() => {
58
+ // Error already logged in processBatch
59
+ });
60
+ }, this.batchWindowMs);
61
+ } else {
62
+ logger.info(
63
+ `Message added to batch window (${this.messageQueue.length} pending)`
64
+ );
65
+ }
66
+ }
67
+
68
+ private async processBatch(): Promise<void> {
69
+ if (this.batchTimer) {
70
+ clearTimeout(this.batchTimer);
71
+ this.batchTimer = null;
72
+ }
73
+
74
+ if (this.messageQueue.length === 0) {
75
+ return;
76
+ }
77
+
78
+ this.isProcessing = true;
79
+
80
+ try {
81
+ const messagesToProcess = [...this.messageQueue];
82
+ this.messageQueue = [];
83
+
84
+ logger.info(`Processing batch of ${messagesToProcess.length} messages`);
85
+ messagesToProcess.sort((a, b) => a.timestamp - b.timestamp);
86
+
87
+ if (this.onBatchReady) {
88
+ await this.onBatchReady(messagesToProcess);
89
+ }
90
+
91
+ // If more messages arrived during processing, start new batch
92
+ if (this.messageQueue.length > 0) {
93
+ if (this.batchTimer) {
94
+ clearTimeout(this.batchTimer);
95
+ this.batchTimer = null;
96
+ }
97
+ logger.info(
98
+ `Starting new batch window for ${this.messageQueue.length} queued messages`
99
+ );
100
+ this.batchTimer = setTimeout(() => {
101
+ void this.processBatch().catch(() => {
102
+ // Error already logged in processBatch
103
+ });
104
+ }, this.batchWindowMs);
105
+ }
106
+ } catch (error) {
107
+ logger.error("Error during batch processing:", error);
108
+ throw error;
109
+ } finally {
110
+ this.isProcessing = false;
111
+ }
112
+ }
113
+
114
+ stop(): void {
115
+ if (this.batchTimer) {
116
+ clearTimeout(this.batchTimer);
117
+ this.batchTimer = null;
118
+ }
119
+ }
120
+
121
+ isCurrentlyProcessing(): boolean {
122
+ return this.isProcessing;
123
+ }
124
+
125
+ getPendingCount(): number {
126
+ return this.messageQueue.length;
127
+ }
128
+ }