ocuclaw 1.2.4 → 1.3.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.
- package/README.md +18 -5
- package/dist/config/runtime-config.js +81 -3
- package/dist/domain/activity-status-adapter.js +138 -605
- package/dist/domain/activity-status-arbiter.js +109 -0
- package/dist/domain/activity-status-labels.js +906 -0
- package/dist/domain/code-span-regions.js +103 -0
- package/dist/domain/conversation-state.js +14 -1
- package/dist/domain/debug-store.js +38 -182
- package/dist/domain/glasses-ui-content-summary.js +62 -0
- package/dist/domain/glasses-ui-system-prompt.js +28 -0
- package/dist/domain/message-emoji-allowlist.js +16 -0
- package/dist/domain/message-emoji-filter.js +33 -55
- package/dist/domain/neural-emoji-reactor-system-prompt.js +43 -0
- package/dist/domain/neural-emoji-reactor-tag-config.js +56 -0
- package/dist/domain/neural-pace-modulator-system-prompt.js +32 -0
- package/dist/domain/neural-pace-modulator-tag-config.js +51 -0
- package/dist/domain/tagged-span-parser.js +121 -0
- package/dist/domain/tagged-span-strip.js +38 -0
- package/dist/even-ai/even-ai-endpoint.js +91 -0
- package/dist/even-ai/even-ai-run-waiter.js +14 -0
- package/dist/even-ai/even-ai-settings-store.js +14 -0
- package/dist/gateway/gateway-bridge.js +14 -2
- package/dist/gateway/gateway-timing-ledger.js +457 -0
- package/dist/gateway/openclaw-client.js +462 -38
- package/dist/index.js +28 -1
- package/dist/runtime/downstream-handler.js +754 -83
- package/dist/runtime/downstream-server.js +700 -534
- package/dist/runtime/ocuclaw-settings-store.js +74 -31
- package/dist/runtime/plugin-update-service.js +216 -0
- package/dist/runtime/protocol-adapter.js +9 -0
- package/dist/runtime/provider-usage-select.js +168 -0
- package/dist/runtime/relay-client-nudge-controller.js +553 -0
- package/dist/runtime/relay-core.js +1209 -204
- package/dist/runtime/relay-health-monitor.js +172 -0
- package/dist/runtime/relay-operation-registry.js +263 -0
- package/dist/runtime/relay-service.js +201 -1
- package/dist/runtime/relay-worker-approval-replay-cache.js +68 -0
- package/dist/runtime/relay-worker-entry.js +32 -0
- package/dist/runtime/relay-worker-health.js +272 -0
- package/dist/runtime/relay-worker-protocol.js +285 -0
- package/dist/runtime/relay-worker-queue.js +202 -0
- package/dist/runtime/relay-worker-supervisor.js +1081 -0
- package/dist/runtime/relay-worker-transport.js +1051 -0
- package/dist/runtime/session-context-service.js +189 -0
- package/dist/runtime/session-service.js +615 -24
- package/dist/runtime/upstream-runtime.js +1167 -60
- package/dist/tools/device-info-tool.js +242 -0
- package/dist/tools/glasses-ui-cron.js +427 -0
- package/dist/tools/glasses-ui-descriptors.js +261 -0
- package/dist/tools/glasses-ui-limits.js +21 -0
- package/dist/tools/glasses-ui-paint-floor.js +99 -0
- package/dist/tools/glasses-ui-recipes.js +746 -0
- package/dist/tools/glasses-ui-surfaces.js +278 -0
- package/dist/tools/glasses-ui-template.js +182 -0
- package/dist/tools/glasses-ui-tool.js +1147 -0
- package/dist/tools/session-title-tool.js +209 -0
- package/dist/version.js +2 -0
- package/openclaw.plugin.json +163 -15
- package/package.json +12 -4
|
@@ -133,6 +133,14 @@ function createPluginRpcGatewayBridge(opts) {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
function sendMessage(text, sessionKey, attachment, requestOptions) {
|
|
136
|
+
const requestOpts = { expectFinal: false };
|
|
137
|
+
if (
|
|
138
|
+
requestOptions &&
|
|
139
|
+
typeof requestOptions.diagnostic === "object" &&
|
|
140
|
+
requestOptions.diagnostic !== null
|
|
141
|
+
) {
|
|
142
|
+
requestOpts.diagnostic = requestOptions.diagnostic;
|
|
143
|
+
}
|
|
136
144
|
return request(
|
|
137
145
|
"agent",
|
|
138
146
|
buildAgentRequestParams(
|
|
@@ -142,12 +150,16 @@ function createPluginRpcGatewayBridge(opts) {
|
|
|
142
150
|
idempotencyKeyFactory,
|
|
143
151
|
requestOptions,
|
|
144
152
|
),
|
|
145
|
-
|
|
153
|
+
requestOpts,
|
|
146
154
|
);
|
|
147
155
|
}
|
|
148
156
|
|
|
149
157
|
function resolveApproval(id, decision) {
|
|
150
|
-
|
|
158
|
+
const method =
|
|
159
|
+
typeof id === "string" && id.startsWith("plugin:")
|
|
160
|
+
? "plugin.approval.resolve"
|
|
161
|
+
: "exec.approval.resolve";
|
|
162
|
+
return request(method, { id, decision });
|
|
151
163
|
}
|
|
152
164
|
|
|
153
165
|
function off(eventName, listener) {
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
export const AGENT_ACK_SLOW_MS = 1000;
|
|
2
|
+
export const AGENT_LIFECYCLE_WAIT_SLOW_MS = 1500;
|
|
3
|
+
export const GATEWAY_REQUEST_SLOW_MS = 1500;
|
|
4
|
+
export const ACCEPTED_RUN_TTL_MS = 120000;
|
|
5
|
+
|
|
6
|
+
const CATEGORY_RELAY_PROTOCOL = "relay.protocol";
|
|
7
|
+
const CATEGORY_OPENCLAW_RUN = "openclaw.run";
|
|
8
|
+
|
|
9
|
+
function isObject(value) {
|
|
10
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function pickId(value) {
|
|
14
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
15
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function pickBoolean(value) {
|
|
20
|
+
return value === true ? true : value === false ? false : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function pickNonNegativeNumber(value) {
|
|
24
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
25
|
+
return Math.floor(value);
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function textCharsFromParams(params) {
|
|
31
|
+
if (!isObject(params)) return null;
|
|
32
|
+
if (typeof params.message === "string") return params.message.length;
|
|
33
|
+
if (typeof params.text === "string") return params.text.length;
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function attachmentBytesFromAttachment(attachment) {
|
|
38
|
+
if (!isObject(attachment)) return 0;
|
|
39
|
+
const explicit =
|
|
40
|
+
pickNonNegativeNumber(attachment.bytes) ??
|
|
41
|
+
pickNonNegativeNumber(attachment.byteLength) ??
|
|
42
|
+
pickNonNegativeNumber(attachment.size);
|
|
43
|
+
if (explicit != null) return explicit;
|
|
44
|
+
if (typeof attachment.content === "string") return attachment.content.length;
|
|
45
|
+
if (typeof attachment.base64Data === "string") return attachment.base64Data.length;
|
|
46
|
+
if (typeof attachment.data === "string") return attachment.data.length;
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function attachmentSummaryFromParams(params) {
|
|
51
|
+
if (!isObject(params)) {
|
|
52
|
+
return { hasAttachment: false, attachmentBytes: 0 };
|
|
53
|
+
}
|
|
54
|
+
const attachments = Array.isArray(params.attachments) ? params.attachments : [];
|
|
55
|
+
let attachmentBytes = 0;
|
|
56
|
+
for (const attachment of attachments) {
|
|
57
|
+
attachmentBytes += attachmentBytesFromAttachment(attachment);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
hasAttachment: attachments.length > 0,
|
|
61
|
+
attachmentBytes,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function sanitizeDiagnostic(args) {
|
|
66
|
+
const diagnostic = isObject(args.diagnostic) ? args.diagnostic : {};
|
|
67
|
+
const params = isObject(args.params) ? args.params : {};
|
|
68
|
+
const attachmentSummary = attachmentSummaryFromParams(params);
|
|
69
|
+
const textChars =
|
|
70
|
+
pickNonNegativeNumber(diagnostic.textChars) ?? textCharsFromParams(params) ?? 0;
|
|
71
|
+
const attachmentBytes =
|
|
72
|
+
pickNonNegativeNumber(diagnostic.attachmentBytes) ??
|
|
73
|
+
attachmentSummary.attachmentBytes;
|
|
74
|
+
const hasAttachment =
|
|
75
|
+
pickBoolean(diagnostic.hasAttachment) ?? attachmentSummary.hasAttachment;
|
|
76
|
+
return {
|
|
77
|
+
messageId: pickId(diagnostic.messageId ?? args.messageId),
|
|
78
|
+
source: pickId(diagnostic.source ?? args.source),
|
|
79
|
+
textChars,
|
|
80
|
+
hasAttachment,
|
|
81
|
+
attachmentBytes,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function responseStatus(args) {
|
|
86
|
+
return pickId(args.status ?? (isObject(args.response) ? args.response.status : null));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function responseRunId(args) {
|
|
90
|
+
return pickId(args.runId ?? (isObject(args.response) ? args.response.runId : null));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function responseErrorCode(args) {
|
|
94
|
+
if (args.errorCode != null) return pickId(args.errorCode);
|
|
95
|
+
if (isObject(args.error) && args.error.code != null) return pickId(args.error.code);
|
|
96
|
+
if (isObject(args.response) && args.response.errorCode != null) {
|
|
97
|
+
return pickId(args.response.errorCode);
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function gatewayEventText(args) {
|
|
103
|
+
if (typeof args.text === "string") return args.text;
|
|
104
|
+
if (isObject(args.data) && typeof args.data.text === "string") {
|
|
105
|
+
return args.data.text;
|
|
106
|
+
}
|
|
107
|
+
if (isObject(args.payload) && typeof args.payload.text === "string") {
|
|
108
|
+
return args.payload.text;
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function isAgentGatewayEvent(args) {
|
|
114
|
+
const kind = pickId(args.kind ?? args.type ?? args.eventType);
|
|
115
|
+
if (kind === "agent") return true;
|
|
116
|
+
if (kind != null && kind !== "agent") return false;
|
|
117
|
+
return pickId(args.runId) != null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function safeLoggerWarn(logger, message) {
|
|
121
|
+
if (!logger) return;
|
|
122
|
+
if (typeof logger.warn === "function") {
|
|
123
|
+
logger.warn(message);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (typeof logger === "function") {
|
|
127
|
+
logger(message);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function createGatewayTimingLedger(opts = {}) {
|
|
132
|
+
const getNow = typeof opts.now === "function" ? opts.now : () => Date.now();
|
|
133
|
+
const emitTiming =
|
|
134
|
+
typeof opts.emitTiming === "function" ? opts.emitTiming : () => {};
|
|
135
|
+
const setTimer =
|
|
136
|
+
typeof opts.setTimer === "function" ? opts.setTimer : setTimeout;
|
|
137
|
+
const clearTimer =
|
|
138
|
+
typeof opts.clearTimer === "function" ? opts.clearTimer : clearTimeout;
|
|
139
|
+
let logger = opts.logger || null;
|
|
140
|
+
const requests = new Map();
|
|
141
|
+
const acceptedRuns = new Map();
|
|
142
|
+
|
|
143
|
+
function nowMs() {
|
|
144
|
+
const value = Number(getNow());
|
|
145
|
+
return Number.isFinite(value) ? Math.floor(value) : Date.now();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function emit(category, event, severity, context, data) {
|
|
149
|
+
emitTiming({
|
|
150
|
+
category,
|
|
151
|
+
event,
|
|
152
|
+
severity,
|
|
153
|
+
context: context || {},
|
|
154
|
+
data: data || {},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function clearTimerRef(ref) {
|
|
159
|
+
if (ref == null) return;
|
|
160
|
+
clearTimer(ref);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function requestContext(request) {
|
|
164
|
+
return {
|
|
165
|
+
requestId: request.requestId,
|
|
166
|
+
method: request.method,
|
|
167
|
+
messageId: request.messageId,
|
|
168
|
+
sessionKey: request.sessionKey,
|
|
169
|
+
source: request.source,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function runContext(run) {
|
|
174
|
+
return {
|
|
175
|
+
runId: run.runId,
|
|
176
|
+
requestId: run.requestId,
|
|
177
|
+
messageId: run.messageId,
|
|
178
|
+
sessionKey: run.sessionKey,
|
|
179
|
+
source: run.source,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function scheduleRequestSlowTimer(request) {
|
|
184
|
+
const thresholdMs =
|
|
185
|
+
request.method === "agent" ? AGENT_ACK_SLOW_MS : GATEWAY_REQUEST_SLOW_MS;
|
|
186
|
+
request.slowTimer = setTimer(() => {
|
|
187
|
+
if (request.slowEmitted) return;
|
|
188
|
+
request.slowEmitted = true;
|
|
189
|
+
const elapsedMs = Math.max(0, nowMs() - request.sentAtMs);
|
|
190
|
+
const data = {
|
|
191
|
+
requestId: request.requestId,
|
|
192
|
+
method: request.method,
|
|
193
|
+
elapsedMs,
|
|
194
|
+
thresholdMs,
|
|
195
|
+
pendingRequests: requests.size,
|
|
196
|
+
expectFinal: request.expectFinal,
|
|
197
|
+
sessionKey: request.sessionKey,
|
|
198
|
+
messageId: request.messageId,
|
|
199
|
+
source: request.source,
|
|
200
|
+
};
|
|
201
|
+
emit(
|
|
202
|
+
CATEGORY_RELAY_PROTOCOL,
|
|
203
|
+
"gateway_request_slow",
|
|
204
|
+
"warn",
|
|
205
|
+
requestContext(request),
|
|
206
|
+
data,
|
|
207
|
+
);
|
|
208
|
+
safeLoggerWarn(
|
|
209
|
+
logger,
|
|
210
|
+
`[openclaw-timing] slow request method=${request.method} requestId=${request.requestId} elapsedMs=${elapsedMs} pendingRequests=${requests.size}`,
|
|
211
|
+
);
|
|
212
|
+
}, thresholdMs);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function scheduleAcceptedRunTimers(run) {
|
|
216
|
+
run.lifecycleWaitTimer = setTimer(() => {
|
|
217
|
+
if (run.lifecycleSlowEmitted || run.lifecycleStartedAtMs != null) return;
|
|
218
|
+
run.lifecycleSlowEmitted = true;
|
|
219
|
+
const ackToLifecycleMs = Math.max(0, nowMs() - run.acceptedAtMs);
|
|
220
|
+
emit(
|
|
221
|
+
CATEGORY_OPENCLAW_RUN,
|
|
222
|
+
"agent_lifecycle_wait_slow",
|
|
223
|
+
"warn",
|
|
224
|
+
runContext(run),
|
|
225
|
+
{
|
|
226
|
+
runId: run.runId,
|
|
227
|
+
requestId: run.requestId,
|
|
228
|
+
messageId: run.messageId,
|
|
229
|
+
sessionKey: run.sessionKey,
|
|
230
|
+
source: run.source,
|
|
231
|
+
ackToLifecycleMs,
|
|
232
|
+
thresholdMs: AGENT_LIFECYCLE_WAIT_SLOW_MS,
|
|
233
|
+
pendingRequests: requests.size,
|
|
234
|
+
},
|
|
235
|
+
);
|
|
236
|
+
safeLoggerWarn(
|
|
237
|
+
logger,
|
|
238
|
+
`[openclaw-timing] slow accepted-run runId=${run.runId} messageId=${run.messageId || "none"} ackToLifecycleMs=${ackToLifecycleMs} pendingRequests=${requests.size}`,
|
|
239
|
+
);
|
|
240
|
+
}, AGENT_LIFECYCLE_WAIT_SLOW_MS);
|
|
241
|
+
run.ttlTimer = setTimer(() => {
|
|
242
|
+
const current = acceptedRuns.get(run.runId);
|
|
243
|
+
if (current !== run) return;
|
|
244
|
+
clearTimerRef(run.lifecycleWaitTimer);
|
|
245
|
+
acceptedRuns.delete(run.runId);
|
|
246
|
+
}, ACCEPTED_RUN_TTL_MS);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function removeRun(runId) {
|
|
250
|
+
const key = pickId(runId);
|
|
251
|
+
if (!key) return;
|
|
252
|
+
const run = acceptedRuns.get(key);
|
|
253
|
+
if (!run) return;
|
|
254
|
+
clearTimerRef(run.lifecycleWaitTimer);
|
|
255
|
+
clearTimerRef(run.ttlTimer);
|
|
256
|
+
acceptedRuns.delete(key);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return {
|
|
260
|
+
clear(reason) {
|
|
261
|
+
for (const request of requests.values()) {
|
|
262
|
+
clearTimerRef(request.slowTimer);
|
|
263
|
+
}
|
|
264
|
+
for (const run of acceptedRuns.values()) {
|
|
265
|
+
clearTimerRef(run.lifecycleWaitTimer);
|
|
266
|
+
clearTimerRef(run.ttlTimer);
|
|
267
|
+
}
|
|
268
|
+
requests.clear();
|
|
269
|
+
acceptedRuns.clear();
|
|
270
|
+
void reason;
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
pendingRequestCount() {
|
|
274
|
+
return requests.size;
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
recordGatewayEventReceived(args = {}) {
|
|
278
|
+
if (!isAgentGatewayEvent(args)) return;
|
|
279
|
+
const receivedAtMs = nowMs();
|
|
280
|
+
const runId = pickId(args.runId);
|
|
281
|
+
const run = runId ? acceptedRuns.get(runId) : null;
|
|
282
|
+
const stream = pickId(args.stream ?? args.channel);
|
|
283
|
+
const phase = pickId(args.phase ?? args.state);
|
|
284
|
+
const text = gatewayEventText(args);
|
|
285
|
+
const isLifecycleStart = stream === "lifecycle" && phase === "start";
|
|
286
|
+
|
|
287
|
+
if (run && isLifecycleStart) {
|
|
288
|
+
clearTimerRef(run.lifecycleWaitTimer);
|
|
289
|
+
run.lifecycleWaitTimer = null;
|
|
290
|
+
run.lifecycleStartedAtMs = receivedAtMs;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const sinceRunStartMs =
|
|
294
|
+
run && run.lifecycleStartedAtMs != null
|
|
295
|
+
? Math.max(0, receivedAtMs - run.lifecycleStartedAtMs)
|
|
296
|
+
: null;
|
|
297
|
+
const data = {
|
|
298
|
+
eventKind: "agent",
|
|
299
|
+
runId,
|
|
300
|
+
requestId: run ? run.requestId : null,
|
|
301
|
+
messageId: run ? run.messageId : null,
|
|
302
|
+
sessionKey: run ? run.sessionKey : null,
|
|
303
|
+
source: run ? run.source : null,
|
|
304
|
+
stream,
|
|
305
|
+
phase,
|
|
306
|
+
sinceAcceptedMs: run ? Math.max(0, receivedAtMs - run.acceptedAtMs) : null,
|
|
307
|
+
sinceRunStartMs,
|
|
308
|
+
rawAssistantChars:
|
|
309
|
+
stream === "assistant" && text != null ? text.length : null,
|
|
310
|
+
pendingRequests: requests.size,
|
|
311
|
+
};
|
|
312
|
+
emit(
|
|
313
|
+
CATEGORY_OPENCLAW_RUN,
|
|
314
|
+
"gateway_event_received",
|
|
315
|
+
"debug",
|
|
316
|
+
{
|
|
317
|
+
sessionKey: data.sessionKey,
|
|
318
|
+
runId,
|
|
319
|
+
requestId: data.requestId,
|
|
320
|
+
messageId: data.messageId,
|
|
321
|
+
stream,
|
|
322
|
+
phase,
|
|
323
|
+
},
|
|
324
|
+
data,
|
|
325
|
+
);
|
|
326
|
+
},
|
|
327
|
+
|
|
328
|
+
recordRequestSent(args = {}) {
|
|
329
|
+
const requestId = pickId(args.requestId ?? args.id);
|
|
330
|
+
if (!requestId) return;
|
|
331
|
+
const sentAtMs = nowMs();
|
|
332
|
+
const diagnostic = sanitizeDiagnostic(args);
|
|
333
|
+
const request = {
|
|
334
|
+
requestId,
|
|
335
|
+
method: pickId(args.method) || "unknown",
|
|
336
|
+
expectFinal: args.expectFinal === true,
|
|
337
|
+
sessionKey: pickId(
|
|
338
|
+
args.sessionKey ?? (isObject(args.params) ? args.params.sessionKey : null),
|
|
339
|
+
),
|
|
340
|
+
messageId: diagnostic.messageId,
|
|
341
|
+
source: diagnostic.source,
|
|
342
|
+
textChars: diagnostic.textChars,
|
|
343
|
+
hasAttachment: diagnostic.hasAttachment,
|
|
344
|
+
attachmentBytes: diagnostic.attachmentBytes,
|
|
345
|
+
sentAtMs,
|
|
346
|
+
slowTimer: null,
|
|
347
|
+
slowEmitted: false,
|
|
348
|
+
};
|
|
349
|
+
const existing = requests.get(requestId);
|
|
350
|
+
if (existing) {
|
|
351
|
+
clearTimerRef(existing.slowTimer);
|
|
352
|
+
}
|
|
353
|
+
requests.set(requestId, request);
|
|
354
|
+
scheduleRequestSlowTimer(request);
|
|
355
|
+
emit(
|
|
356
|
+
CATEGORY_RELAY_PROTOCOL,
|
|
357
|
+
"gateway_request_sent",
|
|
358
|
+
"info",
|
|
359
|
+
requestContext(request),
|
|
360
|
+
{
|
|
361
|
+
requestId,
|
|
362
|
+
method: request.method,
|
|
363
|
+
expectFinal: request.expectFinal,
|
|
364
|
+
sessionKey: request.sessionKey,
|
|
365
|
+
messageId: request.messageId,
|
|
366
|
+
source: request.source,
|
|
367
|
+
textChars: request.textChars,
|
|
368
|
+
hasAttachment: request.hasAttachment,
|
|
369
|
+
attachmentBytes: request.attachmentBytes,
|
|
370
|
+
pendingRequests: requests.size,
|
|
371
|
+
},
|
|
372
|
+
);
|
|
373
|
+
},
|
|
374
|
+
|
|
375
|
+
recordResponseReceived(args = {}) {
|
|
376
|
+
const requestId = pickId(args.requestId ?? args.id);
|
|
377
|
+
const request = requestId ? requests.get(requestId) : null;
|
|
378
|
+
const receivedAtMs = nowMs();
|
|
379
|
+
const method = request ? request.method : pickId(args.method) || "unknown";
|
|
380
|
+
const status = responseStatus(args);
|
|
381
|
+
const runId = responseRunId(args);
|
|
382
|
+
const ok = args.ok === true;
|
|
383
|
+
const errorCode = responseErrorCode(args);
|
|
384
|
+
if (request && status === "accepted") {
|
|
385
|
+
clearTimerRef(request.slowTimer);
|
|
386
|
+
request.slowTimer = null;
|
|
387
|
+
}
|
|
388
|
+
const elapsedMs = request ? Math.max(0, receivedAtMs - request.sentAtMs) : null;
|
|
389
|
+
const data = {
|
|
390
|
+
requestId,
|
|
391
|
+
method,
|
|
392
|
+
ok,
|
|
393
|
+
status,
|
|
394
|
+
elapsedMs,
|
|
395
|
+
runId,
|
|
396
|
+
errorCode,
|
|
397
|
+
messageId: request ? request.messageId : null,
|
|
398
|
+
sessionKey: request ? request.sessionKey : null,
|
|
399
|
+
source: request ? request.source : null,
|
|
400
|
+
pendingRequests: requests.size,
|
|
401
|
+
};
|
|
402
|
+
emit(
|
|
403
|
+
CATEGORY_RELAY_PROTOCOL,
|
|
404
|
+
"gateway_response_received",
|
|
405
|
+
ok ? "info" : "warn",
|
|
406
|
+
request ? requestContext(request) : { requestId, method },
|
|
407
|
+
data,
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
if (ok && method === "agent" && status === "accepted" && runId) {
|
|
411
|
+
const run = {
|
|
412
|
+
runId,
|
|
413
|
+
requestId,
|
|
414
|
+
messageId: request ? request.messageId : null,
|
|
415
|
+
sessionKey: request ? request.sessionKey : null,
|
|
416
|
+
source: request ? request.source : null,
|
|
417
|
+
acceptedAtMs: receivedAtMs,
|
|
418
|
+
lifecycleStartedAtMs: null,
|
|
419
|
+
lifecycleWaitTimer: null,
|
|
420
|
+
lifecycleSlowEmitted: false,
|
|
421
|
+
ttlTimer: null,
|
|
422
|
+
};
|
|
423
|
+
removeRun(runId);
|
|
424
|
+
acceptedRuns.set(runId, run);
|
|
425
|
+
scheduleAcceptedRunTimers(run);
|
|
426
|
+
emit(
|
|
427
|
+
CATEGORY_OPENCLAW_RUN,
|
|
428
|
+
"agent_request_accepted",
|
|
429
|
+
"info",
|
|
430
|
+
runContext(run),
|
|
431
|
+
{
|
|
432
|
+
runId,
|
|
433
|
+
requestId,
|
|
434
|
+
messageId: run.messageId,
|
|
435
|
+
sessionKey: run.sessionKey,
|
|
436
|
+
source: run.source,
|
|
437
|
+
ackElapsedMs: elapsedMs,
|
|
438
|
+
pendingRequests: requests.size,
|
|
439
|
+
},
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (request && args.keepPending !== true) {
|
|
444
|
+
clearTimerRef(request.slowTimer);
|
|
445
|
+
requests.delete(requestId);
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
|
|
449
|
+
recordRunTerminal(args = {}) {
|
|
450
|
+
removeRun(args.runId ?? args.id);
|
|
451
|
+
},
|
|
452
|
+
|
|
453
|
+
setLogger(nextLogger) {
|
|
454
|
+
logger = nextLogger || null;
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
}
|