@parall/parall 1.30.0 → 1.32.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/dist/accounts.d.ts +1 -1
- package/dist/accounts.js +4 -4
- package/dist/channel.d.ts +2 -2
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +10 -10
- package/dist/config-manager.d.ts +1 -1
- package/dist/config-manager.d.ts.map +1 -1
- package/dist/config-manager.js +70 -30
- package/dist/fork.d.ts.map +1 -1
- package/dist/fork.js +17 -17
- package/dist/gateway.d.ts +3 -3
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +214 -171
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +52 -26
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -7
- package/dist/oc-session.d.ts.map +1 -1
- package/dist/oc-session.js +35 -27
- package/dist/outbound.d.ts +2 -2
- package/dist/outbound.d.ts.map +1 -1
- package/dist/outbound.js +13 -14
- package/dist/routing.d.ts +2 -2
- package/dist/routing.js +1 -1
- package/dist/runtime.d.ts +5 -5
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +2 -2
- package/dist/session.js +4 -4
- package/dist/wiki-helper.d.ts.map +1 -1
- package/dist/wiki-helper.js +27 -27
- package/openclaw.plugin.json +4 -1
- package/package.json +3 -3
- package/skills/parall-clips/SKILL.md +48 -0
- package/src/accounts.ts +5 -5
- package/src/channel.ts +15 -14
- package/src/config-manager.ts +79 -34
- package/src/fork.ts +26 -22
- package/src/gateway.ts +245 -175
- package/src/hooks.ts +109 -50
- package/src/index.ts +8 -8
- package/src/oc-session.ts +43 -35
- package/src/outbound.ts +18 -17
- package/src/routing.ts +2 -2
- package/src/runtime.ts +11 -7
- package/src/session.ts +4 -4
- package/src/wiki-helper.ts +47 -34
package/src/gateway.ts
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
|
-
import type { PluginRuntime } from
|
|
2
|
-
import type { ChannelPlugin } from
|
|
1
|
+
import type { PluginRuntime } from 'openclaw/plugin-sdk';
|
|
2
|
+
import type { ChannelPlugin } from 'openclaw/plugin-sdk/core';
|
|
3
3
|
|
|
4
4
|
/** Extract ChannelGatewayAdapter from ChannelPlugin (removed from public SDK exports in 2026.3.24). */
|
|
5
|
-
type ChannelGatewayAdapter<T = unknown> = NonNullable<ChannelPlugin<T>[
|
|
5
|
+
type ChannelGatewayAdapter<T = unknown> = NonNullable<ChannelPlugin<T>['gateway']>;
|
|
6
6
|
import {
|
|
7
7
|
ParallAgentGateway,
|
|
8
8
|
parseShutdownDeadlineMs,
|
|
9
|
+
parseForkDeadlineMs,
|
|
10
|
+
parseDispatchDeadlineMs,
|
|
11
|
+
initAgentTelemetry,
|
|
12
|
+
createOtelLogger,
|
|
9
13
|
type DispatchAdapter,
|
|
10
14
|
type ParallEvent,
|
|
11
15
|
type RuntimeEvent,
|
|
12
|
-
} from
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
import {
|
|
16
|
+
} from '@parall/agent-core';
|
|
17
|
+
import {
|
|
18
|
+
appendPreparedLocalAttachmentRefs,
|
|
19
|
+
ensureLocalAttachmentGitExclude,
|
|
20
|
+
pinLocalAttachmentPaths,
|
|
21
|
+
} from '@parall/agent-core/internal/attachment-input';
|
|
22
|
+
import { ApiError, ParallClient, ParallWs } from '@parall/sdk';
|
|
23
|
+
import type { ParallChannelConfig } from './types.js';
|
|
24
|
+
import * as crypto from 'node:crypto';
|
|
25
|
+
import * as os from 'node:os';
|
|
26
|
+
import * as path from 'node:path';
|
|
27
|
+
import { resolveParallAccount } from './accounts.js';
|
|
19
28
|
import {
|
|
20
29
|
getParallRuntime,
|
|
21
30
|
removeParallAccountState,
|
|
@@ -23,18 +32,24 @@ import {
|
|
|
23
32
|
setAgentSessionBinding,
|
|
24
33
|
setDispatchGroupKey,
|
|
25
34
|
setParallAccountState,
|
|
26
|
-
} from
|
|
27
|
-
import { buildOrchestratorSessionKey } from
|
|
28
|
-
import type { ResolvedParallAccount } from
|
|
29
|
-
import { fetchAndApplyPlatformConfig } from
|
|
30
|
-
import { startWikiHelper } from
|
|
31
|
-
import { SessionManager } from
|
|
32
|
-
import {
|
|
35
|
+
} from './runtime.js';
|
|
36
|
+
import { buildOrchestratorSessionKey } from './session.js';
|
|
37
|
+
import type { ResolvedParallAccount } from './types.js';
|
|
38
|
+
import { fetchAndApplyPlatformConfig } from './config-manager.js';
|
|
39
|
+
import { startWikiHelper } from './wiki-helper.js';
|
|
40
|
+
import { SessionManager } from './oc-session.js';
|
|
41
|
+
import {
|
|
42
|
+
cleanupForkSession,
|
|
43
|
+
clearSessionState,
|
|
44
|
+
forkOrchestratorSession,
|
|
45
|
+
resolveSessionId,
|
|
46
|
+
resolveTranscriptFile,
|
|
47
|
+
} from './fork.js';
|
|
33
48
|
|
|
34
49
|
function resolveWsUrl(account: ResolvedParallAccount): string {
|
|
35
50
|
if (account.config.ws_url) return account.config.ws_url;
|
|
36
|
-
const base = account.config.parall_url.replace(/\/$/,
|
|
37
|
-
const wsBase = base.replace(/^http/,
|
|
51
|
+
const base = account.config.parall_url.replace(/\/$/, '');
|
|
52
|
+
const wsBase = base.replace(/^http/, 'ws');
|
|
38
53
|
return `${wsBase}/ws`;
|
|
39
54
|
}
|
|
40
55
|
|
|
@@ -70,15 +85,15 @@ function buildInboundCtx(
|
|
|
70
85
|
To: `parall:orchestrator`,
|
|
71
86
|
SessionKey: sessionKey,
|
|
72
87
|
AccountId: accountId,
|
|
73
|
-
ChatType: event.targetType ??
|
|
88
|
+
ChatType: event.targetType ?? 'unknown',
|
|
74
89
|
SenderName: event.senderName,
|
|
75
90
|
SenderId: event.senderId,
|
|
76
|
-
Provider:
|
|
77
|
-
Surface:
|
|
91
|
+
Provider: 'parall' as const,
|
|
92
|
+
Surface: 'parall' as const,
|
|
78
93
|
MessageSid: event.messageId,
|
|
79
94
|
Timestamp: Date.now(),
|
|
80
95
|
CommandAuthorized: true,
|
|
81
|
-
OriginatingChannel:
|
|
96
|
+
OriginatingChannel: 'parall' as const,
|
|
82
97
|
OriginatingTo: `parall:orchestrator`,
|
|
83
98
|
});
|
|
84
99
|
}
|
|
@@ -91,13 +106,13 @@ function buildInboundHistory(events: ParallEvent[]): Array<{ sender: string; bod
|
|
|
91
106
|
if (event.threadRootId) meta.push(`[Thread: ${event.threadRootId}]`);
|
|
92
107
|
if (event.attachments?.length) {
|
|
93
108
|
for (const att of event.attachments) {
|
|
94
|
-
const safeMime = att.mimeType.replace(/[\r\n[\]|]/g,
|
|
109
|
+
const safeMime = att.mimeType.replace(/[\r\n[\]|]/g, ' ').trim();
|
|
95
110
|
meta.push(`[Attachment: prll://${att.id} | ${safeMime}]`);
|
|
96
111
|
}
|
|
97
112
|
}
|
|
98
113
|
return {
|
|
99
114
|
sender: event.senderName,
|
|
100
|
-
body: meta.length > 0 ? `${meta.join(
|
|
115
|
+
body: meta.length > 0 ? `${meta.join(' ')}\n${event.body}` : event.body,
|
|
101
116
|
};
|
|
102
117
|
});
|
|
103
118
|
}
|
|
@@ -185,68 +200,106 @@ function createOpenClawDispatchAdapter(opts: {
|
|
|
185
200
|
cfg: Record<string, unknown>;
|
|
186
201
|
accountId: string;
|
|
187
202
|
sessionsDir: string;
|
|
203
|
+
workspaceDir: string;
|
|
188
204
|
}): DispatchAdapter {
|
|
205
|
+
const activeStreams = new Map<string, ReturnType<typeof createRuntimeEventStream>>();
|
|
206
|
+
|
|
189
207
|
return {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
let turnGroupKey = "";
|
|
208
|
+
abortDispatch(sessionKey: string): void {
|
|
209
|
+
activeStreams.get(sessionKey)?.fail(new Error('dispatch deadline exceeded'));
|
|
210
|
+
},
|
|
194
211
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
212
|
+
async *dispatch({ event, earlierEvents = [], bodyForAgent, sessionKey, context }) {
|
|
213
|
+
let promptBody = bodyForAgent;
|
|
214
|
+
let releasePreparedAttachments = () => {};
|
|
215
|
+
try {
|
|
216
|
+
const prepared = await appendPreparedLocalAttachmentRefs(bodyForAgent, event, context, {
|
|
217
|
+
workspaceDir: opts.workspaceDir,
|
|
218
|
+
log: context.log,
|
|
219
|
+
});
|
|
220
|
+
promptBody = prepared.body;
|
|
221
|
+
releasePreparedAttachments = pinLocalAttachmentPaths(prepared.attachments.images);
|
|
222
|
+
} catch (err) {
|
|
223
|
+
context.log?.warn?.(`failed to prepare local attachments: ${String(err)}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
const stream = createRuntimeEventStream();
|
|
228
|
+
activeStreams.set(sessionKey, stream);
|
|
229
|
+
let reasoningBuffer = '';
|
|
230
|
+
let turnGroupKey = '';
|
|
231
|
+
|
|
232
|
+
const run = opts.core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
233
|
+
ctx: buildInboundCtx(
|
|
234
|
+
opts.core,
|
|
235
|
+
opts.accountId,
|
|
236
|
+
event,
|
|
237
|
+
sessionKey,
|
|
238
|
+
promptBody,
|
|
239
|
+
earlierEvents,
|
|
240
|
+
),
|
|
241
|
+
cfg: opts.cfg,
|
|
242
|
+
dispatcherOptions: {
|
|
243
|
+
deliver: async (payload: { text?: string }) => {
|
|
244
|
+
const replyText = payload.text?.trim();
|
|
245
|
+
if (!replyText) return;
|
|
246
|
+
stream.push({
|
|
247
|
+
type: 'text',
|
|
248
|
+
text: replyText,
|
|
249
|
+
project: false,
|
|
250
|
+
groupKey: turnGroupKey || undefined,
|
|
251
|
+
});
|
|
252
|
+
},
|
|
253
|
+
onReplyStart: () => {
|
|
254
|
+
turnGroupKey = crypto.randomUUID();
|
|
255
|
+
setDispatchGroupKey(sessionKey, turnGroupKey);
|
|
256
|
+
},
|
|
217
257
|
},
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
258
|
+
replyOptions: {
|
|
259
|
+
onReasoningStream: (payload: { text?: string }) => {
|
|
260
|
+
reasoningBuffer += payload.text ?? '';
|
|
261
|
+
},
|
|
262
|
+
onReasoningEnd: async () => {
|
|
263
|
+
if (!reasoningBuffer) return;
|
|
264
|
+
stream.push({
|
|
265
|
+
type: 'thinking',
|
|
266
|
+
text: reasoningBuffer,
|
|
267
|
+
groupKey: turnGroupKey || undefined,
|
|
268
|
+
});
|
|
269
|
+
reasoningBuffer = '';
|
|
270
|
+
},
|
|
226
271
|
},
|
|
227
|
-
}
|
|
228
|
-
});
|
|
272
|
+
});
|
|
229
273
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
274
|
+
run.then(() => stream.end()).catch((err) => stream.fail(err));
|
|
275
|
+
let sessionId: string | null;
|
|
276
|
+
try {
|
|
277
|
+
sessionId = await Promise.race([
|
|
278
|
+
waitForOpenClawSessionId(opts.sessionsDir, sessionKey),
|
|
279
|
+
run.then(
|
|
280
|
+
() => null as string | null,
|
|
281
|
+
(err) => {
|
|
282
|
+
throw err;
|
|
283
|
+
},
|
|
284
|
+
),
|
|
285
|
+
]);
|
|
286
|
+
} catch {
|
|
287
|
+
sessionId = null;
|
|
288
|
+
}
|
|
289
|
+
if (!sessionId) {
|
|
290
|
+
stream.fail(new Error(`OpenClaw did not expose a sessionId for ${sessionKey}`));
|
|
291
|
+
} else {
|
|
292
|
+
yield {
|
|
293
|
+
type: 'runtime_session',
|
|
294
|
+
runtimeSessionId: sessionId,
|
|
295
|
+
runtimeLaneKey: sessionKey,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
yield* stream.stream();
|
|
299
|
+
} finally {
|
|
300
|
+
activeStreams.delete(sessionKey);
|
|
301
|
+
releasePreparedAttachments();
|
|
248
302
|
}
|
|
249
|
-
yield* stream.stream();
|
|
250
303
|
},
|
|
251
304
|
|
|
252
305
|
getBranchPoint(sessionKey: string): string | undefined {
|
|
@@ -273,7 +326,7 @@ function createOpenClawDispatchAdapter(opts: {
|
|
|
273
326
|
},
|
|
274
327
|
|
|
275
328
|
cleanupFork({ fork }) {
|
|
276
|
-
if (typeof fork.sessionFile !==
|
|
329
|
+
if (typeof fork.sessionFile !== 'string') return;
|
|
277
330
|
cleanupForkSession({
|
|
278
331
|
sessionFile: fork.sessionFile,
|
|
279
332
|
sessionKey: fork.sessionKey,
|
|
@@ -287,7 +340,8 @@ export const parallGateway: ChannelGatewayAdapter<ResolvedParallAccount> = {
|
|
|
287
340
|
startAccount: async (ctx) => {
|
|
288
341
|
const account = resolveParallAccount({ cfg: ctx.cfg, accountId: ctx.accountId });
|
|
289
342
|
if (!account.enabled) return;
|
|
290
|
-
if (!account.configured)
|
|
343
|
+
if (!account.configured)
|
|
344
|
+
throw new Error('Parall account is not configured: parall_url/api_key/org_id required');
|
|
291
345
|
|
|
292
346
|
const { config } = account;
|
|
293
347
|
const core = getParallRuntime();
|
|
@@ -308,109 +362,125 @@ export const parallGateway: ChannelGatewayAdapter<ResolvedParallAccount> = {
|
|
|
308
362
|
});
|
|
309
363
|
log?.info(`parall[${ctx.accountId}]: authenticated as ${me.display_name} (${agentUserId})`);
|
|
310
364
|
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
const openclawConfigPath = path.join(stateDir, "openclaw.json");
|
|
314
|
-
|
|
315
|
-
const configManagerOpts = {
|
|
316
|
-
client,
|
|
317
|
-
stateDir,
|
|
318
|
-
configPath: openclawConfigPath,
|
|
319
|
-
credentials: { api_key: config.api_key, parall_url: config.parall_url },
|
|
320
|
-
log,
|
|
321
|
-
};
|
|
322
|
-
|
|
365
|
+
const telemetry = await initAgentTelemetry('parall-openclaw-agent', 'openclaw');
|
|
366
|
+
const otelLog = createOtelLogger('agent', 'openclaw-agent');
|
|
323
367
|
try {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
368
|
+
const stateDir =
|
|
369
|
+
process.env.OPENCLAW_STATE_DIR || path.join(process.env.HOME || '/data', '.openclaw');
|
|
370
|
+
const openclawConfigPath = path.join(stateDir, 'openclaw.json');
|
|
328
371
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
try {
|
|
332
|
-
const wikiHelper = await startWikiHelper({
|
|
333
|
-
accountId: ctx.accountId,
|
|
334
|
-
parallUrl: config.parall_url,
|
|
335
|
-
apiKey: config.api_key,
|
|
336
|
-
orgId: config.org_id,
|
|
337
|
-
agentId: agentUserId,
|
|
372
|
+
const configManagerOpts = {
|
|
373
|
+
client,
|
|
338
374
|
stateDir,
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
} catch (err) {
|
|
344
|
-
log?.warn(`parall[${ctx.accountId}]: wiki helper startup failed: ${String(err)}`);
|
|
345
|
-
}
|
|
375
|
+
configPath: openclawConfigPath,
|
|
376
|
+
credentials: { api_key: config.api_key, parall_url: config.parall_url },
|
|
377
|
+
log: otelLog,
|
|
378
|
+
};
|
|
346
379
|
|
|
347
|
-
|
|
348
|
-
const ws = new ParallWs({
|
|
349
|
-
getTicket: () => client.getWsTicket(),
|
|
350
|
-
wsUrl,
|
|
351
|
-
});
|
|
352
|
-
const orchestratorKey = buildOrchestratorSessionKey(ctx.accountId);
|
|
353
|
-
const sessionsDir = path.join(stateDir, "agents", "main", "sessions");
|
|
354
|
-
const dispatchAdapter = createOpenClawDispatchAdapter({
|
|
355
|
-
core,
|
|
356
|
-
cfg: ctx.cfg,
|
|
357
|
-
accountId: ctx.accountId,
|
|
358
|
-
sessionsDir,
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
const gateway = new ParallAgentGateway({
|
|
362
|
-
accountId: ctx.accountId,
|
|
363
|
-
client,
|
|
364
|
-
ws,
|
|
365
|
-
connectionLabel: wsUrl,
|
|
366
|
-
config: {
|
|
367
|
-
parall_url: config.parall_url,
|
|
368
|
-
api_key: config.api_key,
|
|
369
|
-
org_id: config.org_id,
|
|
370
|
-
},
|
|
371
|
-
agentUserId,
|
|
372
|
-
runtimeType: "openclaw",
|
|
373
|
-
runtimeKey: orchestratorKey,
|
|
374
|
-
runtimeRef: { hostname: os.hostname(), pid: process.pid },
|
|
375
|
-
dispatchAdapter,
|
|
376
|
-
log,
|
|
377
|
-
shutdownDeadlineMs: parseShutdownDeadlineMs(process.env.PRLL_SHUTDOWN_DEADLINE_MS),
|
|
378
|
-
onConfigUpdate: async () => {
|
|
380
|
+
try {
|
|
379
381
|
await fetchAndApplyPlatformConfig(configManagerOpts);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
382
|
+
} catch (err) {
|
|
383
|
+
otelLog.warn(`parall[${ctx.accountId}]: platform config fetch failed: ${String(err)}`);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
let stopWikiHelper: (() => void) | null = null;
|
|
387
|
+
let wikiMountRoot: string | undefined;
|
|
388
|
+
try {
|
|
389
|
+
const wikiHelper = await startWikiHelper({
|
|
390
|
+
accountId: ctx.accountId,
|
|
391
|
+
parallUrl: config.parall_url,
|
|
385
392
|
apiKey: config.api_key,
|
|
386
393
|
orgId: config.org_id,
|
|
387
|
-
agentUserId,
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
sessionsDir,
|
|
391
|
-
runtimeRef: { hostname: os.hostname(), pid: process.pid },
|
|
392
|
-
wikiMountRoot,
|
|
393
|
-
ws,
|
|
394
|
-
orchestratorSessionKey: orchestratorKey,
|
|
394
|
+
agentId: agentUserId,
|
|
395
|
+
stateDir,
|
|
396
|
+
log: otelLog,
|
|
395
397
|
});
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
stopWikiHelper?.();
|
|
402
|
-
removeParallAccountState(ctx.accountId);
|
|
403
|
-
},
|
|
404
|
-
onNewSession: () => { clearSessionState(sessionsDir, orchestratorKey); },
|
|
405
|
-
});
|
|
398
|
+
wikiMountRoot = wikiHelper.mountRoot;
|
|
399
|
+
stopWikiHelper = wikiHelper.stop;
|
|
400
|
+
} catch (err) {
|
|
401
|
+
otelLog.warn(`parall[${ctx.accountId}]: wiki helper startup failed: ${String(err)}`);
|
|
402
|
+
}
|
|
406
403
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
404
|
+
const wsUrl = resolveWsUrl(account);
|
|
405
|
+
const ws = new ParallWs({
|
|
406
|
+
getTicket: () => client.getWsTicket(),
|
|
407
|
+
wsUrl,
|
|
408
|
+
});
|
|
409
|
+
const orchestratorKey = buildOrchestratorSessionKey(ctx.accountId);
|
|
410
|
+
const sessionsDir = path.join(stateDir, 'agents', 'main', 'sessions');
|
|
411
|
+
const workspaceDir = process.cwd();
|
|
412
|
+
ensureLocalAttachmentGitExclude(workspaceDir);
|
|
413
|
+
const dispatchAdapter = createOpenClawDispatchAdapter({
|
|
414
|
+
core,
|
|
415
|
+
cfg: ctx.cfg,
|
|
416
|
+
accountId: ctx.accountId,
|
|
417
|
+
sessionsDir,
|
|
418
|
+
workspaceDir,
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
const gateway = new ParallAgentGateway({
|
|
422
|
+
accountId: ctx.accountId,
|
|
423
|
+
client,
|
|
424
|
+
ws,
|
|
425
|
+
connectionLabel: wsUrl,
|
|
426
|
+
config: {
|
|
427
|
+
parall_url: config.parall_url,
|
|
428
|
+
api_key: config.api_key,
|
|
429
|
+
org_id: config.org_id,
|
|
430
|
+
},
|
|
431
|
+
agentUserId,
|
|
432
|
+
runtimeType: 'openclaw',
|
|
433
|
+
runtimeKey: orchestratorKey,
|
|
434
|
+
runtimeRef: { hostname: os.hostname(), pid: process.pid },
|
|
435
|
+
dispatchAdapter,
|
|
436
|
+
log: otelLog,
|
|
437
|
+
shutdownDeadlineMs: parseShutdownDeadlineMs(process.env.PRLL_SHUTDOWN_DEADLINE_MS),
|
|
438
|
+
forkDeadlineMs: parseForkDeadlineMs(process.env.PRLL_FORK_DEADLINE_MS),
|
|
439
|
+
dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
|
|
440
|
+
onConfigUpdate: async () => {
|
|
441
|
+
await fetchAndApplyPlatformConfig(configManagerOpts);
|
|
442
|
+
},
|
|
443
|
+
onSessionReady: async ({ activeSessionId }) => {
|
|
444
|
+
setParallAccountState(ctx.accountId, {
|
|
445
|
+
client,
|
|
446
|
+
apiUrl: config.parall_url,
|
|
447
|
+
apiKey: config.api_key,
|
|
448
|
+
orgId: config.org_id,
|
|
449
|
+
agentUserId,
|
|
450
|
+
activeSessionId,
|
|
451
|
+
sessionBindings: new Map<string, string>(),
|
|
452
|
+
sessionsDir,
|
|
453
|
+
runtimeRef: { hostname: os.hostname(), pid: process.pid },
|
|
454
|
+
wikiMountRoot,
|
|
455
|
+
ws,
|
|
456
|
+
orchestratorSessionKey: orchestratorKey,
|
|
457
|
+
});
|
|
458
|
+
},
|
|
459
|
+
onSessionBinding: async ({ sessionKey, agentSessionId }) => {
|
|
460
|
+
setAgentSessionBinding(ctx.accountId, sessionKey, agentSessionId);
|
|
461
|
+
},
|
|
462
|
+
onBeforeDisconnect: async () => {
|
|
463
|
+
stopWikiHelper?.();
|
|
464
|
+
removeParallAccountState(ctx.accountId);
|
|
465
|
+
},
|
|
466
|
+
onNewSession: () => {
|
|
467
|
+
clearSessionState(sessionsDir, orchestratorKey);
|
|
468
|
+
},
|
|
469
|
+
onSessionStale: () => {
|
|
470
|
+
clearSessionState(sessionsDir, orchestratorKey);
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
try {
|
|
475
|
+
await gateway.run(ctx.abortSignal);
|
|
476
|
+
} finally {
|
|
477
|
+
if (!ctx.abortSignal.aborted) {
|
|
478
|
+
stopWikiHelper?.();
|
|
479
|
+
removeParallAccountState(ctx.accountId);
|
|
480
|
+
}
|
|
413
481
|
}
|
|
482
|
+
} finally {
|
|
483
|
+
await telemetry.shutdown();
|
|
414
484
|
}
|
|
415
485
|
},
|
|
416
486
|
};
|