@parall/parall 1.31.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 +147 -127
- 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 +177 -134
- 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/dist/gateway.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { ParallAgentGateway, parseShutdownDeadlineMs, } from
|
|
2
|
-
import { appendPreparedLocalAttachmentRefs, ensureLocalAttachmentGitExclude, pinLocalAttachmentPaths, } from
|
|
3
|
-
import { ApiError, ParallClient, ParallWs } from
|
|
4
|
-
import * as crypto from
|
|
5
|
-
import * as os from
|
|
6
|
-
import * as path from
|
|
7
|
-
import { resolveParallAccount } from
|
|
8
|
-
import { getParallRuntime, removeParallAccountState, setAgentIdentity, setAgentSessionBinding, setDispatchGroupKey, setParallAccountState, } from
|
|
9
|
-
import { buildOrchestratorSessionKey } from
|
|
10
|
-
import { fetchAndApplyPlatformConfig } from
|
|
11
|
-
import { startWikiHelper } from
|
|
12
|
-
import { SessionManager } from
|
|
13
|
-
import { cleanupForkSession, clearSessionState, forkOrchestratorSession, resolveSessionId, resolveTranscriptFile } from
|
|
1
|
+
import { ParallAgentGateway, parseShutdownDeadlineMs, parseForkDeadlineMs, parseDispatchDeadlineMs, initAgentTelemetry, createOtelLogger, } from '@parall/agent-core';
|
|
2
|
+
import { appendPreparedLocalAttachmentRefs, ensureLocalAttachmentGitExclude, pinLocalAttachmentPaths, } from '@parall/agent-core/internal/attachment-input';
|
|
3
|
+
import { ApiError, ParallClient, ParallWs } from '@parall/sdk';
|
|
4
|
+
import * as crypto from 'node:crypto';
|
|
5
|
+
import * as os from 'node:os';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import { resolveParallAccount } from './accounts.js';
|
|
8
|
+
import { getParallRuntime, removeParallAccountState, setAgentIdentity, setAgentSessionBinding, setDispatchGroupKey, setParallAccountState, } from './runtime.js';
|
|
9
|
+
import { buildOrchestratorSessionKey } from './session.js';
|
|
10
|
+
import { fetchAndApplyPlatformConfig } from './config-manager.js';
|
|
11
|
+
import { startWikiHelper } from './wiki-helper.js';
|
|
12
|
+
import { SessionManager } from './oc-session.js';
|
|
13
|
+
import { cleanupForkSession, clearSessionState, forkOrchestratorSession, resolveSessionId, resolveTranscriptFile, } from './fork.js';
|
|
14
14
|
function resolveWsUrl(account) {
|
|
15
15
|
if (account.config.ws_url)
|
|
16
16
|
return account.config.ws_url;
|
|
17
|
-
const base = account.config.parall_url.replace(/\/$/,
|
|
18
|
-
const wsBase = base.replace(/^http/,
|
|
17
|
+
const base = account.config.parall_url.replace(/\/$/, '');
|
|
18
|
+
const wsBase = base.replace(/^http/, 'ws');
|
|
19
19
|
return `${wsBase}/ws`;
|
|
20
20
|
}
|
|
21
21
|
async function getAgentMeWithLegacyFallback(client, orgId) {
|
|
@@ -43,15 +43,15 @@ function buildInboundCtx(core, accountId, event, sessionKey, bodyForAgent, earli
|
|
|
43
43
|
To: `parall:orchestrator`,
|
|
44
44
|
SessionKey: sessionKey,
|
|
45
45
|
AccountId: accountId,
|
|
46
|
-
ChatType: event.targetType ??
|
|
46
|
+
ChatType: event.targetType ?? 'unknown',
|
|
47
47
|
SenderName: event.senderName,
|
|
48
48
|
SenderId: event.senderId,
|
|
49
|
-
Provider:
|
|
50
|
-
Surface:
|
|
49
|
+
Provider: 'parall',
|
|
50
|
+
Surface: 'parall',
|
|
51
51
|
MessageSid: event.messageId,
|
|
52
52
|
Timestamp: Date.now(),
|
|
53
53
|
CommandAuthorized: true,
|
|
54
|
-
OriginatingChannel:
|
|
54
|
+
OriginatingChannel: 'parall',
|
|
55
55
|
OriginatingTo: `parall:orchestrator`,
|
|
56
56
|
});
|
|
57
57
|
}
|
|
@@ -65,13 +65,13 @@ function buildInboundHistory(events) {
|
|
|
65
65
|
meta.push(`[Thread: ${event.threadRootId}]`);
|
|
66
66
|
if (event.attachments?.length) {
|
|
67
67
|
for (const att of event.attachments) {
|
|
68
|
-
const safeMime = att.mimeType.replace(/[\r\n[\]|]/g,
|
|
68
|
+
const safeMime = att.mimeType.replace(/[\r\n[\]|]/g, ' ').trim();
|
|
69
69
|
meta.push(`[Attachment: prll://${att.id} | ${safeMime}]`);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
return {
|
|
73
73
|
sender: event.senderName,
|
|
74
|
-
body: meta.length > 0 ? `${meta.join(
|
|
74
|
+
body: meta.length > 0 ? `${meta.join(' ')}\n${event.body}` : event.body,
|
|
75
75
|
};
|
|
76
76
|
});
|
|
77
77
|
}
|
|
@@ -146,7 +146,11 @@ async function waitForOpenClawSessionId(sessionsDir, sessionKey, timeoutMs = 10_
|
|
|
146
146
|
return null;
|
|
147
147
|
}
|
|
148
148
|
function createOpenClawDispatchAdapter(opts) {
|
|
149
|
+
const activeStreams = new Map();
|
|
149
150
|
return {
|
|
151
|
+
abortDispatch(sessionKey) {
|
|
152
|
+
activeStreams.get(sessionKey)?.fail(new Error('dispatch deadline exceeded'));
|
|
153
|
+
},
|
|
150
154
|
async *dispatch({ event, earlierEvents = [], bodyForAgent, sessionKey, context }) {
|
|
151
155
|
let promptBody = bodyForAgent;
|
|
152
156
|
let releasePreparedAttachments = () => { };
|
|
@@ -163,8 +167,9 @@ function createOpenClawDispatchAdapter(opts) {
|
|
|
163
167
|
}
|
|
164
168
|
try {
|
|
165
169
|
const stream = createRuntimeEventStream();
|
|
166
|
-
|
|
167
|
-
let
|
|
170
|
+
activeStreams.set(sessionKey, stream);
|
|
171
|
+
let reasoningBuffer = '';
|
|
172
|
+
let turnGroupKey = '';
|
|
168
173
|
const run = opts.core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
169
174
|
ctx: buildInboundCtx(opts.core, opts.accountId, event, sessionKey, promptBody, earlierEvents),
|
|
170
175
|
cfg: opts.cfg,
|
|
@@ -174,7 +179,7 @@ function createOpenClawDispatchAdapter(opts) {
|
|
|
174
179
|
if (!replyText)
|
|
175
180
|
return;
|
|
176
181
|
stream.push({
|
|
177
|
-
type:
|
|
182
|
+
type: 'text',
|
|
178
183
|
text: replyText,
|
|
179
184
|
project: false,
|
|
180
185
|
groupKey: turnGroupKey || undefined,
|
|
@@ -187,17 +192,17 @@ function createOpenClawDispatchAdapter(opts) {
|
|
|
187
192
|
},
|
|
188
193
|
replyOptions: {
|
|
189
194
|
onReasoningStream: (payload) => {
|
|
190
|
-
reasoningBuffer += payload.text ??
|
|
195
|
+
reasoningBuffer += payload.text ?? '';
|
|
191
196
|
},
|
|
192
197
|
onReasoningEnd: async () => {
|
|
193
198
|
if (!reasoningBuffer)
|
|
194
199
|
return;
|
|
195
200
|
stream.push({
|
|
196
|
-
type:
|
|
201
|
+
type: 'thinking',
|
|
197
202
|
text: reasoningBuffer,
|
|
198
203
|
groupKey: turnGroupKey || undefined,
|
|
199
204
|
});
|
|
200
|
-
reasoningBuffer =
|
|
205
|
+
reasoningBuffer = '';
|
|
201
206
|
},
|
|
202
207
|
},
|
|
203
208
|
});
|
|
@@ -206,7 +211,9 @@ function createOpenClawDispatchAdapter(opts) {
|
|
|
206
211
|
try {
|
|
207
212
|
sessionId = await Promise.race([
|
|
208
213
|
waitForOpenClawSessionId(opts.sessionsDir, sessionKey),
|
|
209
|
-
run.then(() => null, (err) => {
|
|
214
|
+
run.then(() => null, (err) => {
|
|
215
|
+
throw err;
|
|
216
|
+
}),
|
|
210
217
|
]);
|
|
211
218
|
}
|
|
212
219
|
catch {
|
|
@@ -217,7 +224,7 @@ function createOpenClawDispatchAdapter(opts) {
|
|
|
217
224
|
}
|
|
218
225
|
else {
|
|
219
226
|
yield {
|
|
220
|
-
type:
|
|
227
|
+
type: 'runtime_session',
|
|
221
228
|
runtimeSessionId: sessionId,
|
|
222
229
|
runtimeLaneKey: sessionKey,
|
|
223
230
|
};
|
|
@@ -225,6 +232,7 @@ function createOpenClawDispatchAdapter(opts) {
|
|
|
225
232
|
yield* stream.stream();
|
|
226
233
|
}
|
|
227
234
|
finally {
|
|
235
|
+
activeStreams.delete(sessionKey);
|
|
228
236
|
releasePreparedAttachments();
|
|
229
237
|
}
|
|
230
238
|
},
|
|
@@ -253,7 +261,7 @@ function createOpenClawDispatchAdapter(opts) {
|
|
|
253
261
|
});
|
|
254
262
|
},
|
|
255
263
|
cleanupFork({ fork }) {
|
|
256
|
-
if (typeof fork.sessionFile !==
|
|
264
|
+
if (typeof fork.sessionFile !== 'string')
|
|
257
265
|
return;
|
|
258
266
|
cleanupForkSession({
|
|
259
267
|
sessionFile: fork.sessionFile,
|
|
@@ -269,7 +277,7 @@ export const parallGateway = {
|
|
|
269
277
|
if (!account.enabled)
|
|
270
278
|
return;
|
|
271
279
|
if (!account.configured)
|
|
272
|
-
throw new Error(
|
|
280
|
+
throw new Error('Parall account is not configured: parall_url/api_key/org_id required');
|
|
273
281
|
const { config } = account;
|
|
274
282
|
const core = getParallRuntime();
|
|
275
283
|
const log = ctx.log;
|
|
@@ -286,110 +294,122 @@ export const parallGateway = {
|
|
|
286
294
|
description: me.agent_profile?.description ?? undefined,
|
|
287
295
|
});
|
|
288
296
|
log?.info(`parall[${ctx.accountId}]: authenticated as ${me.display_name} (${agentUserId})`);
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
const openclawConfigPath = path.join(stateDir, "openclaw.json");
|
|
292
|
-
const configManagerOpts = {
|
|
293
|
-
client,
|
|
294
|
-
stateDir,
|
|
295
|
-
configPath: openclawConfigPath,
|
|
296
|
-
credentials: { api_key: config.api_key, parall_url: config.parall_url },
|
|
297
|
-
log,
|
|
298
|
-
};
|
|
299
|
-
try {
|
|
300
|
-
await fetchAndApplyPlatformConfig(configManagerOpts);
|
|
301
|
-
}
|
|
302
|
-
catch (err) {
|
|
303
|
-
log?.warn(`parall[${ctx.accountId}]: platform config fetch failed: ${String(err)}`);
|
|
304
|
-
}
|
|
305
|
-
let stopWikiHelper = null;
|
|
306
|
-
let wikiMountRoot;
|
|
297
|
+
const telemetry = await initAgentTelemetry('parall-openclaw-agent', 'openclaw');
|
|
298
|
+
const otelLog = createOtelLogger('agent', 'openclaw-agent');
|
|
307
299
|
try {
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
orgId: config.org_id,
|
|
313
|
-
agentId: agentUserId,
|
|
300
|
+
const stateDir = process.env.OPENCLAW_STATE_DIR || path.join(process.env.HOME || '/data', '.openclaw');
|
|
301
|
+
const openclawConfigPath = path.join(stateDir, 'openclaw.json');
|
|
302
|
+
const configManagerOpts = {
|
|
303
|
+
client,
|
|
314
304
|
stateDir,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
catch (err) {
|
|
321
|
-
log?.warn(`parall[${ctx.accountId}]: wiki helper startup failed: ${String(err)}`);
|
|
322
|
-
}
|
|
323
|
-
const wsUrl = resolveWsUrl(account);
|
|
324
|
-
const ws = new ParallWs({
|
|
325
|
-
getTicket: () => client.getWsTicket(),
|
|
326
|
-
wsUrl,
|
|
327
|
-
});
|
|
328
|
-
const orchestratorKey = buildOrchestratorSessionKey(ctx.accountId);
|
|
329
|
-
const sessionsDir = path.join(stateDir, "agents", "main", "sessions");
|
|
330
|
-
const workspaceDir = process.cwd();
|
|
331
|
-
ensureLocalAttachmentGitExclude(workspaceDir);
|
|
332
|
-
const dispatchAdapter = createOpenClawDispatchAdapter({
|
|
333
|
-
core,
|
|
334
|
-
cfg: ctx.cfg,
|
|
335
|
-
accountId: ctx.accountId,
|
|
336
|
-
sessionsDir,
|
|
337
|
-
workspaceDir,
|
|
338
|
-
});
|
|
339
|
-
const gateway = new ParallAgentGateway({
|
|
340
|
-
accountId: ctx.accountId,
|
|
341
|
-
client,
|
|
342
|
-
ws,
|
|
343
|
-
connectionLabel: wsUrl,
|
|
344
|
-
config: {
|
|
345
|
-
parall_url: config.parall_url,
|
|
346
|
-
api_key: config.api_key,
|
|
347
|
-
org_id: config.org_id,
|
|
348
|
-
},
|
|
349
|
-
agentUserId,
|
|
350
|
-
runtimeType: "openclaw",
|
|
351
|
-
runtimeKey: orchestratorKey,
|
|
352
|
-
runtimeRef: { hostname: os.hostname(), pid: process.pid },
|
|
353
|
-
dispatchAdapter,
|
|
354
|
-
log,
|
|
355
|
-
shutdownDeadlineMs: parseShutdownDeadlineMs(process.env.PRLL_SHUTDOWN_DEADLINE_MS),
|
|
356
|
-
onConfigUpdate: async () => {
|
|
305
|
+
configPath: openclawConfigPath,
|
|
306
|
+
credentials: { api_key: config.api_key, parall_url: config.parall_url },
|
|
307
|
+
log: otelLog,
|
|
308
|
+
};
|
|
309
|
+
try {
|
|
357
310
|
await fetchAndApplyPlatformConfig(configManagerOpts);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
otelLog.warn(`parall[${ctx.accountId}]: platform config fetch failed: ${String(err)}`);
|
|
314
|
+
}
|
|
315
|
+
let stopWikiHelper = null;
|
|
316
|
+
let wikiMountRoot;
|
|
317
|
+
try {
|
|
318
|
+
const wikiHelper = await startWikiHelper({
|
|
319
|
+
accountId: ctx.accountId,
|
|
320
|
+
parallUrl: config.parall_url,
|
|
363
321
|
apiKey: config.api_key,
|
|
364
322
|
orgId: config.org_id,
|
|
365
|
-
agentUserId,
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
sessionsDir,
|
|
369
|
-
runtimeRef: { hostname: os.hostname(), pid: process.pid },
|
|
370
|
-
wikiMountRoot,
|
|
371
|
-
ws,
|
|
372
|
-
orchestratorSessionKey: orchestratorKey,
|
|
323
|
+
agentId: agentUserId,
|
|
324
|
+
stateDir,
|
|
325
|
+
log: otelLog,
|
|
373
326
|
});
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
327
|
+
wikiMountRoot = wikiHelper.mountRoot;
|
|
328
|
+
stopWikiHelper = wikiHelper.stop;
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
otelLog.warn(`parall[${ctx.accountId}]: wiki helper startup failed: ${String(err)}`);
|
|
332
|
+
}
|
|
333
|
+
const wsUrl = resolveWsUrl(account);
|
|
334
|
+
const ws = new ParallWs({
|
|
335
|
+
getTicket: () => client.getWsTicket(),
|
|
336
|
+
wsUrl,
|
|
337
|
+
});
|
|
338
|
+
const orchestratorKey = buildOrchestratorSessionKey(ctx.accountId);
|
|
339
|
+
const sessionsDir = path.join(stateDir, 'agents', 'main', 'sessions');
|
|
340
|
+
const workspaceDir = process.cwd();
|
|
341
|
+
ensureLocalAttachmentGitExclude(workspaceDir);
|
|
342
|
+
const dispatchAdapter = createOpenClawDispatchAdapter({
|
|
343
|
+
core,
|
|
344
|
+
cfg: ctx.cfg,
|
|
345
|
+
accountId: ctx.accountId,
|
|
346
|
+
sessionsDir,
|
|
347
|
+
workspaceDir,
|
|
348
|
+
});
|
|
349
|
+
const gateway = new ParallAgentGateway({
|
|
350
|
+
accountId: ctx.accountId,
|
|
351
|
+
client,
|
|
352
|
+
ws,
|
|
353
|
+
connectionLabel: wsUrl,
|
|
354
|
+
config: {
|
|
355
|
+
parall_url: config.parall_url,
|
|
356
|
+
api_key: config.api_key,
|
|
357
|
+
org_id: config.org_id,
|
|
358
|
+
},
|
|
359
|
+
agentUserId,
|
|
360
|
+
runtimeType: 'openclaw',
|
|
361
|
+
runtimeKey: orchestratorKey,
|
|
362
|
+
runtimeRef: { hostname: os.hostname(), pid: process.pid },
|
|
363
|
+
dispatchAdapter,
|
|
364
|
+
log: otelLog,
|
|
365
|
+
shutdownDeadlineMs: parseShutdownDeadlineMs(process.env.PRLL_SHUTDOWN_DEADLINE_MS),
|
|
366
|
+
forkDeadlineMs: parseForkDeadlineMs(process.env.PRLL_FORK_DEADLINE_MS),
|
|
367
|
+
dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
|
|
368
|
+
onConfigUpdate: async () => {
|
|
369
|
+
await fetchAndApplyPlatformConfig(configManagerOpts);
|
|
370
|
+
},
|
|
371
|
+
onSessionReady: async ({ activeSessionId }) => {
|
|
372
|
+
setParallAccountState(ctx.accountId, {
|
|
373
|
+
client,
|
|
374
|
+
apiUrl: config.parall_url,
|
|
375
|
+
apiKey: config.api_key,
|
|
376
|
+
orgId: config.org_id,
|
|
377
|
+
agentUserId,
|
|
378
|
+
activeSessionId,
|
|
379
|
+
sessionBindings: new Map(),
|
|
380
|
+
sessionsDir,
|
|
381
|
+
runtimeRef: { hostname: os.hostname(), pid: process.pid },
|
|
382
|
+
wikiMountRoot,
|
|
383
|
+
ws,
|
|
384
|
+
orchestratorSessionKey: orchestratorKey,
|
|
385
|
+
});
|
|
386
|
+
},
|
|
387
|
+
onSessionBinding: async ({ sessionKey, agentSessionId }) => {
|
|
388
|
+
setAgentSessionBinding(ctx.accountId, sessionKey, agentSessionId);
|
|
389
|
+
},
|
|
390
|
+
onBeforeDisconnect: async () => {
|
|
391
|
+
stopWikiHelper?.();
|
|
392
|
+
removeParallAccountState(ctx.accountId);
|
|
393
|
+
},
|
|
394
|
+
onNewSession: () => {
|
|
395
|
+
clearSessionState(sessionsDir, orchestratorKey);
|
|
396
|
+
},
|
|
397
|
+
onSessionStale: () => {
|
|
398
|
+
clearSessionState(sessionsDir, orchestratorKey);
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
try {
|
|
402
|
+
await gateway.run(ctx.abortSignal);
|
|
403
|
+
}
|
|
404
|
+
finally {
|
|
405
|
+
if (!ctx.abortSignal.aborted) {
|
|
406
|
+
stopWikiHelper?.();
|
|
407
|
+
removeParallAccountState(ctx.accountId);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
387
410
|
}
|
|
388
411
|
finally {
|
|
389
|
-
|
|
390
|
-
stopWikiHelper?.();
|
|
391
|
-
removeParallAccountState(ctx.accountId);
|
|
392
|
-
}
|
|
412
|
+
await telemetry.shutdown();
|
|
393
413
|
}
|
|
394
414
|
},
|
|
395
415
|
};
|
package/dist/hooks.d.ts
CHANGED
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AA+G7D,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,iBAAiB,QA6KzD"}
|
package/dist/hooks.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { PRLL_BEHAVIOR, PRLL_REFERENCE_GUIDE, buildIdentity } from
|
|
2
|
-
import { extractAccountIdFromSessionKey } from
|
|
3
|
-
import { clearDispatchGroupKey, getAgentIdentity, getAgentSessionBinding, getDispatchGroupKey, getDispatchMessageId, getParallAccountState, getSessionChatId, setAgentSessionBinding } from
|
|
4
|
-
import { resolveSessionId } from
|
|
1
|
+
import { PRLL_BEHAVIOR, PRLL_REFERENCE_GUIDE, buildIdentity, isParallSendCommand, isParallNoReplyCommand, recordToolCall, recordMessageSend, recordNoReply, } from '@parall/agent-core';
|
|
2
|
+
import { extractAccountIdFromSessionKey } from './session.js';
|
|
3
|
+
import { clearDispatchGroupKey, getAgentIdentity, getAgentSessionBinding, getDispatchGroupKey, getDispatchMessageId, getParallAccountState, getSessionChatId, setAgentSessionBinding, } from './runtime.js';
|
|
4
|
+
import { resolveSessionId } from './fork.js';
|
|
5
5
|
/**
|
|
6
6
|
* Map the session's stored target ID (whatever the current dispatch routed
|
|
7
7
|
* to — chat, task, or schedule) to the `target_type` field on agent_step.
|
|
8
8
|
* Keeps tool_call / tool_result attribution correct across event types.
|
|
9
9
|
*/
|
|
10
10
|
function stepTargetType(targetId) {
|
|
11
|
-
if (targetId.startsWith(
|
|
12
|
-
return
|
|
13
|
-
if (targetId.startsWith(
|
|
14
|
-
return
|
|
15
|
-
if (targetId.startsWith(
|
|
16
|
-
return
|
|
17
|
-
return
|
|
11
|
+
if (targetId.startsWith('cht_'))
|
|
12
|
+
return 'chat';
|
|
13
|
+
if (targetId.startsWith('tsk_'))
|
|
14
|
+
return 'task';
|
|
15
|
+
if (targetId.startsWith('sch_'))
|
|
16
|
+
return 'schedule';
|
|
17
|
+
return '';
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Resolve the ParallClient + orgId + sessionId for a hook context.
|
|
@@ -46,7 +46,7 @@ async function resolveClientForHook(sessionKey) {
|
|
|
46
46
|
: undefined;
|
|
47
47
|
try {
|
|
48
48
|
const session = await state.client.createAgentSession(state.orgId, state.agentUserId, {
|
|
49
|
-
runtime_type:
|
|
49
|
+
runtime_type: 'openclaw',
|
|
50
50
|
runtime_key: sessionKey,
|
|
51
51
|
runtime_lane_key: sessionKey,
|
|
52
52
|
runtime_session_id: runtimeSessionId,
|
|
@@ -100,14 +100,34 @@ export function registerParallHooks(api) {
|
|
|
100
100
|
// registration time, only after the gateway authenticates via getMe().
|
|
101
101
|
// Uses process-global identity because hosted agents run one-agent-per-pod;
|
|
102
102
|
// before_prompt_build doesn't receive session context anyway.
|
|
103
|
-
api.on(
|
|
103
|
+
api.on('before_prompt_build', () => {
|
|
104
104
|
return {
|
|
105
|
-
appendSystemContext: [
|
|
105
|
+
appendSystemContext: [
|
|
106
|
+
buildIdentity(getAgentIdentity()),
|
|
107
|
+
PRLL_CHANNEL_CONTEXT,
|
|
108
|
+
PRLL_BEHAVIOR,
|
|
109
|
+
PRLL_REFERENCE_GUIDE,
|
|
110
|
+
].join('\n\n'),
|
|
106
111
|
};
|
|
107
112
|
});
|
|
108
|
-
|
|
109
|
-
|
|
113
|
+
const pendingSendCalls = new Map();
|
|
114
|
+
// before_tool_call -> (1) update dispatch metrics, (2) await step creation, (3) ENV injection
|
|
115
|
+
// OpenClaw tool calls bypass the RuntimeEvent stream (they go through hooks, not the
|
|
116
|
+
// gateway-base for-await loop), so dispatch metrics must be updated here as well.
|
|
117
|
+
api.on('before_tool_call', async (event, ctx) => {
|
|
110
118
|
const sessionKey = ctx.sessionKey;
|
|
119
|
+
if (sessionKey) {
|
|
120
|
+
recordToolCall(sessionKey);
|
|
121
|
+
if (event.toolName === 'exec' && event.toolCallId) {
|
|
122
|
+
const command = event.params?.command;
|
|
123
|
+
if (isParallSendCommand(command)) {
|
|
124
|
+
pendingSendCalls.set(event.toolCallId, true);
|
|
125
|
+
}
|
|
126
|
+
else if (isParallNoReplyCommand(command)) {
|
|
127
|
+
recordNoReply(sessionKey);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
111
131
|
// (1) Create tool_call step and await to get step ID
|
|
112
132
|
let stepId;
|
|
113
133
|
const resolved = await resolveClientForHook(sessionKey);
|
|
@@ -115,14 +135,14 @@ export function registerParallHooks(api) {
|
|
|
115
135
|
const groupKey = sessionKey ? getDispatchGroupKey(sessionKey) : undefined;
|
|
116
136
|
try {
|
|
117
137
|
const step = await resolved.client.createAgentStep(resolved.orgId, resolved.agentUserId, resolved.sessionId, {
|
|
118
|
-
step_type:
|
|
138
|
+
step_type: 'tool_call',
|
|
119
139
|
target_type: stepTargetType(resolved.chatId),
|
|
120
140
|
target_id: resolved.chatId || undefined,
|
|
121
141
|
content: {
|
|
122
142
|
call_id: event.toolCallId,
|
|
123
143
|
tool_name: event.toolName,
|
|
124
144
|
tool_input: event.params ?? {},
|
|
125
|
-
status:
|
|
145
|
+
status: 'running',
|
|
126
146
|
started_at: new Date().toISOString(),
|
|
127
147
|
},
|
|
128
148
|
group_key: groupKey,
|
|
@@ -135,7 +155,7 @@ export function registerParallHooks(api) {
|
|
|
135
155
|
}
|
|
136
156
|
}
|
|
137
157
|
// (2) ENV injection — only for the exec (Bash) tool
|
|
138
|
-
if (event.toolName !==
|
|
158
|
+
if (event.toolName !== 'exec')
|
|
139
159
|
return;
|
|
140
160
|
if (!sessionKey)
|
|
141
161
|
return;
|
|
@@ -162,7 +182,7 @@ export function registerParallHooks(api) {
|
|
|
162
182
|
if (stepId)
|
|
163
183
|
injectedEnv.PRLL_STEP_ID = stepId;
|
|
164
184
|
if (chatId) {
|
|
165
|
-
if (chatId.startsWith(
|
|
185
|
+
if (chatId.startsWith('sch_')) {
|
|
166
186
|
// Schedule-triggered dispatch: expose PRLL_SCHEDULE_ID so the agent
|
|
167
187
|
// can resolve the schedule; deliberately do NOT set PRLL_CHAT_ID,
|
|
168
188
|
// because schedule events have no chat to reply into, and leaving
|
|
@@ -194,21 +214,27 @@ export function registerParallHooks(api) {
|
|
|
194
214
|
},
|
|
195
215
|
};
|
|
196
216
|
});
|
|
197
|
-
// after_tool_call -> send tool_result step to AgentSession
|
|
198
|
-
api.on(
|
|
217
|
+
// after_tool_call -> track CLI outcomes + send tool_result step to AgentSession
|
|
218
|
+
api.on('after_tool_call', async (event, ctx) => {
|
|
219
|
+
if (ctx.sessionKey && event.toolCallId && pendingSendCalls.delete(event.toolCallId)) {
|
|
220
|
+
recordMessageSend(ctx.sessionKey, !event.error);
|
|
221
|
+
}
|
|
199
222
|
const resolved = await resolveClientForHook(ctx.sessionKey);
|
|
200
223
|
if (!resolved?.sessionId || !event.toolCallId)
|
|
201
224
|
return;
|
|
202
225
|
try {
|
|
203
226
|
await resolved.client.createAgentStep(resolved.orgId, resolved.agentUserId, resolved.sessionId, {
|
|
204
|
-
step_type:
|
|
227
|
+
step_type: 'tool_result',
|
|
205
228
|
target_type: stepTargetType(resolved.chatId),
|
|
206
229
|
target_id: resolved.chatId || undefined,
|
|
207
230
|
content: {
|
|
208
231
|
call_id: event.toolCallId,
|
|
209
232
|
tool_name: event.toolName,
|
|
210
|
-
status: event.error ?
|
|
211
|
-
output: event.error ??
|
|
233
|
+
status: event.error ? 'error' : 'success',
|
|
234
|
+
output: event.error ??
|
|
235
|
+
(typeof event.result === 'string'
|
|
236
|
+
? event.result
|
|
237
|
+
: JSON.stringify(event.result ?? '')),
|
|
212
238
|
duration_ms: event.durationMs ?? 0,
|
|
213
239
|
collapsible: true,
|
|
214
240
|
},
|
|
@@ -221,7 +247,7 @@ export function registerParallHooks(api) {
|
|
|
221
247
|
// agent_end -> end of a dispatch cycle, NOT end of session.
|
|
222
248
|
// Session lives across dispatches — don't update session status here.
|
|
223
249
|
// Dispatch-specific IDs are cleaned up in the generic gateway; hooks only own the group key.
|
|
224
|
-
api.on(
|
|
250
|
+
api.on('agent_end', async (event, ctx) => {
|
|
225
251
|
if (ctx.sessionKey) {
|
|
226
252
|
clearDispatchGroupKey(ctx.sessionKey);
|
|
227
253
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { emptyPluginConfigSchema } from
|
|
2
|
-
import { parallPlugin } from
|
|
3
|
-
import { setParallRuntime } from
|
|
4
|
-
import { registerParallHooks } from
|
|
1
|
+
import { emptyPluginConfigSchema } from 'openclaw/plugin-sdk/core';
|
|
2
|
+
import { parallPlugin } from './channel.js';
|
|
3
|
+
import { setParallRuntime } from './runtime.js';
|
|
4
|
+
import { registerParallHooks } from './hooks.js';
|
|
5
5
|
const plugin = {
|
|
6
|
-
id:
|
|
7
|
-
name:
|
|
8
|
-
description:
|
|
6
|
+
id: 'parall',
|
|
7
|
+
name: 'Parall',
|
|
8
|
+
description: 'Parall IM channel plugin — Agent-Native messaging with tool call visualization.',
|
|
9
9
|
configSchema: emptyPluginConfigSchema(),
|
|
10
10
|
register(api) {
|
|
11
11
|
setParallRuntime(api.runtime);
|
package/dist/oc-session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oc-session.d.ts","sourceRoot":"","sources":["../src/oc-session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"oc-session.d.ts","sourceRoot":"","sources":["../src/oc-session.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAsHzC,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,mBAAmB,CAA6B;IACxD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO;IAeP,OAAO,CAAC,IAAI;IA+BZ,OAAO,CAAC,SAAS;IAoBjB,OAAO,CAAC,UAAU;IAsBlB,OAAO,CAAC,OAAO;IAUf,SAAS,IAAI,MAAM,GAAG,IAAI;IAI1B,MAAM,IAAI,MAAM;IAIhB,aAAa,IAAI,MAAM;IAIvB,YAAY,IAAI,MAAM;IAItB,cAAc,IAAI,MAAM,GAAG,SAAS;IAMpC,OAAO,CAAC,SAAS;IAWjB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IA+DzD,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;CAO1C"}
|