ocuclaw 1.2.4 → 1.3.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.
Files changed (60) hide show
  1. package/README.md +21 -6
  2. package/dist/config/runtime-config.js +84 -3
  3. package/dist/domain/activity-status-adapter.js +138 -605
  4. package/dist/domain/activity-status-arbiter.js +109 -0
  5. package/dist/domain/activity-status-labels.js +906 -0
  6. package/dist/domain/code-span-regions.js +103 -0
  7. package/dist/domain/conversation-state.js +14 -1
  8. package/dist/domain/debug-store.js +56 -182
  9. package/dist/domain/glasses-ui-content-summary.js +62 -0
  10. package/dist/domain/glasses-ui-system-prompt.js +28 -0
  11. package/dist/domain/message-emoji-allowlist.js +16 -0
  12. package/dist/domain/message-emoji-filter.js +33 -55
  13. package/dist/domain/neural-emoji-reactor-system-prompt.js +43 -0
  14. package/dist/domain/neural-emoji-reactor-tag-config.js +56 -0
  15. package/dist/domain/neural-pace-modulator-system-prompt.js +32 -0
  16. package/dist/domain/neural-pace-modulator-tag-config.js +51 -0
  17. package/dist/domain/tagged-span-parser.js +121 -0
  18. package/dist/domain/tagged-span-strip.js +38 -0
  19. package/dist/even-ai/even-ai-endpoint.js +91 -0
  20. package/dist/even-ai/even-ai-run-waiter.js +14 -0
  21. package/dist/even-ai/even-ai-settings-store.js +14 -0
  22. package/dist/gateway/gateway-bridge.js +14 -2
  23. package/dist/gateway/gateway-timing-ledger.js +457 -0
  24. package/dist/gateway/openclaw-client.js +462 -38
  25. package/dist/index.js +28 -1
  26. package/dist/runtime/downstream-handler.js +754 -83
  27. package/dist/runtime/ocuclaw-settings-store.js +74 -31
  28. package/dist/runtime/plugin-version-service.js +23 -0
  29. package/dist/runtime/protocol-adapter.js +9 -0
  30. package/dist/runtime/provider-usage-select.js +168 -0
  31. package/dist/runtime/relay-client-nudge-controller.js +553 -0
  32. package/dist/runtime/relay-core.js +1293 -225
  33. package/dist/runtime/relay-health-monitor.js +172 -0
  34. package/dist/runtime/relay-operation-registry.js +263 -0
  35. package/dist/runtime/relay-service.js +201 -1
  36. package/dist/runtime/relay-worker-approval-replay-cache.js +68 -0
  37. package/dist/runtime/relay-worker-entry.js +32 -0
  38. package/dist/runtime/relay-worker-health.js +272 -0
  39. package/dist/runtime/relay-worker-protocol.js +281 -0
  40. package/dist/runtime/relay-worker-queue.js +202 -0
  41. package/dist/runtime/relay-worker-supervisor.js +1004 -0
  42. package/dist/runtime/relay-worker-transport.js +1051 -0
  43. package/dist/runtime/session-context-service.js +189 -0
  44. package/dist/runtime/session-service.js +638 -27
  45. package/dist/runtime/upstream-runtime.js +1167 -60
  46. package/dist/tools/device-info-tool.js +242 -0
  47. package/dist/tools/glasses-ui-cron.js +427 -0
  48. package/dist/tools/glasses-ui-descriptors.js +261 -0
  49. package/dist/tools/glasses-ui-limits.js +21 -0
  50. package/dist/tools/glasses-ui-paint-floor.js +99 -0
  51. package/dist/tools/glasses-ui-recipes.js +581 -0
  52. package/dist/tools/glasses-ui-surfaces.js +278 -0
  53. package/dist/tools/glasses-ui-template.js +182 -0
  54. package/dist/tools/glasses-ui-tool.js +1111 -0
  55. package/dist/tools/session-title-tool.js +209 -0
  56. package/dist/version.js +2 -0
  57. package/openclaw.plugin.json +163 -15
  58. package/package.json +14 -5
  59. package/skills/glasses-ui/SKILL.md +156 -0
  60. package/dist/runtime/downstream-server.js +0 -1891
@@ -0,0 +1,202 @@
1
+ import {
2
+ formatSendAck,
3
+ formatWorkerOperationReceived,
4
+ formatWorkerQueueTimeoutAck,
5
+ formatWorkerRestartUncertainAck,
6
+ normalizeRequestId,
7
+ } from "./relay-worker-protocol.js";
8
+
9
+ const DEFAULT_MAX_ENTRIES = 32;
10
+ const DEFAULT_TTL_MS = 30_000;
11
+ const DEFAULT_RETAINED_FINAL_TTL_MS = 30_000;
12
+
13
+ function normalizeNonNegativeInteger(value, fallback) {
14
+ if (!Number.isFinite(Number(value))) return fallback;
15
+ return Math.max(0, Math.floor(Number(value)));
16
+ }
17
+
18
+ function makeFinalResult(entry, finalFrame, reason) {
19
+ return {
20
+ clientId: entry.clientId,
21
+ requestId: entry.requestId,
22
+ finalFrame,
23
+ reason,
24
+ };
25
+ }
26
+
27
+ export function createWorkerMessageSendQueue(options = {}) {
28
+ const now = typeof options.now === "function" ? options.now : () => Date.now();
29
+ const workerEpoch = normalizeNonNegativeInteger(options.workerEpoch, 0);
30
+ const maxEntries = normalizeNonNegativeInteger(options.maxEntries, DEFAULT_MAX_ENTRIES);
31
+ const ttlMs = normalizeNonNegativeInteger(options.ttlMs, DEFAULT_TTL_MS);
32
+ const retainedFinalTtlMs = normalizeNonNegativeInteger(
33
+ options.retainedFinalTtlMs,
34
+ DEFAULT_RETAINED_FINAL_TTL_MS,
35
+ );
36
+ const entries = new Map();
37
+ const retainedFinals = new Map();
38
+
39
+ function nowMs() {
40
+ return normalizeNonNegativeInteger(now(), Date.now());
41
+ }
42
+
43
+ function pruneRetainedFinals(atMs = nowMs()) {
44
+ for (const [requestId, retained] of retainedFinals.entries()) {
45
+ if (retained.expiresAtMs <= atMs) {
46
+ retainedFinals.delete(requestId);
47
+ }
48
+ }
49
+ }
50
+
51
+ function retainFinal(requestId, finalFrame, atMs = nowMs()) {
52
+ if (!requestId || retainedFinalTtlMs <= 0) return;
53
+ retainedFinals.set(requestId, {
54
+ finalFrame,
55
+ expiresAtMs: atMs + retainedFinalTtlMs,
56
+ });
57
+ }
58
+
59
+ function enqueue(raw = {}) {
60
+ const atMs = nowMs();
61
+ pruneRetainedFinals(atMs);
62
+
63
+ const requestId = normalizeRequestId(raw.requestId);
64
+ if (!requestId) {
65
+ return {
66
+ status: "rejected",
67
+ finalFrame: formatSendAck(null, "rejected", "Missing or invalid requestId.", "invalid_request"),
68
+ };
69
+ }
70
+
71
+ const retainedFinal = retainedFinals.get(requestId);
72
+ if (retainedFinal) {
73
+ return {
74
+ status: "duplicate_final",
75
+ finalFrame: retainedFinal.finalFrame,
76
+ };
77
+ }
78
+
79
+ const existing = entries.get(requestId);
80
+ if (existing) {
81
+ return {
82
+ status: "duplicate_queued",
83
+ receipt: existing.receipt,
84
+ };
85
+ }
86
+
87
+ if (entries.size >= maxEntries) {
88
+ const finalFrame = formatSendAck(
89
+ requestId,
90
+ "rejected",
91
+ "Relay worker message queue is full.",
92
+ "worker_queue_full",
93
+ );
94
+ retainFinal(requestId, finalFrame, atMs);
95
+ return {
96
+ status: "rejected",
97
+ finalFrame,
98
+ };
99
+ }
100
+
101
+ const receipt = formatWorkerOperationReceived({
102
+ requestId,
103
+ operation: "message.send",
104
+ workerEpoch,
105
+ receivedAtMs: atMs,
106
+ });
107
+ entries.set(requestId, {
108
+ clientId: raw.clientId,
109
+ requestId,
110
+ text: raw.text,
111
+ sessionKey: raw.sessionKey,
112
+ attachment: raw.attachment,
113
+ receipt,
114
+ workerEpoch,
115
+ queuedAtMs: atMs,
116
+ expiresAtMs: atMs + ttlMs,
117
+ });
118
+ return {
119
+ status: "queued",
120
+ receipt,
121
+ };
122
+ }
123
+
124
+ function drainReady(limit = entries.size) {
125
+ const max = normalizeNonNegativeInteger(limit, entries.size);
126
+ const drained = [];
127
+ for (const [requestId, entry] of entries.entries()) {
128
+ if (drained.length >= max) break;
129
+ entries.delete(requestId);
130
+ drained.push({ ...entry });
131
+ }
132
+ return drained;
133
+ }
134
+
135
+ function expire() {
136
+ const atMs = nowMs();
137
+ pruneRetainedFinals(atMs);
138
+ const expired = [];
139
+ for (const [requestId, entry] of entries.entries()) {
140
+ if (entry.expiresAtMs > atMs) continue;
141
+ entries.delete(requestId);
142
+ const finalFrame = formatWorkerQueueTimeoutAck(requestId);
143
+ retainFinal(requestId, finalFrame, atMs);
144
+ expired.push(makeFinalResult(entry, finalFrame, "worker_queue_timeout"));
145
+ }
146
+ return expired;
147
+ }
148
+
149
+ function settle(requestId) {
150
+ const id = normalizeRequestId(requestId);
151
+ if (!id) return false;
152
+ return entries.delete(id);
153
+ }
154
+
155
+ function depthSnapshot() {
156
+ return { "message.send": entries.size };
157
+ }
158
+
159
+ function reconcileOldEpochPending(params = {}) {
160
+ const atMs = nowMs();
161
+ pruneRetainedFinals(atMs);
162
+ const mainResults = new Map();
163
+ for (const result of Array.isArray(params.mainResults) ? params.mainResults : []) {
164
+ const requestId = normalizeRequestId(result && result.requestId);
165
+ if (requestId) {
166
+ mainResults.set(requestId, result);
167
+ }
168
+ }
169
+
170
+ const results = [];
171
+ for (const rawRequestId of Array.isArray(params.requestIds) ? params.requestIds : []) {
172
+ const requestId = normalizeRequestId(rawRequestId);
173
+ if (!requestId) continue;
174
+ const mainResult = mainResults.get(requestId);
175
+ if (mainResult && mainResult.known) {
176
+ const forwarded = { requestId };
177
+ if (mainResult.receiptFrame) forwarded.receiptFrame = mainResult.receiptFrame;
178
+ if (mainResult.finalFrame) forwarded.finalFrame = mainResult.finalFrame;
179
+ results.push(forwarded);
180
+ continue;
181
+ }
182
+
183
+ const finalFrame = formatWorkerRestartUncertainAck(requestId);
184
+ retainFinal(requestId, finalFrame, atMs);
185
+ results.push({
186
+ requestId,
187
+ finalFrame,
188
+ reason: "worker_restarted_before_main_accept",
189
+ });
190
+ }
191
+ return results;
192
+ }
193
+
194
+ return {
195
+ enqueue,
196
+ drainReady,
197
+ expire,
198
+ settle,
199
+ depthSnapshot,
200
+ reconcileOldEpochPending,
201
+ };
202
+ }