@parall/parall 1.30.0 → 1.31.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/gateway.d.ts.map +1 -1
- package/dist/gateway.js +80 -57
- package/package.json +3 -3
- package/src/gateway.ts +82 -55
package/dist/gateway.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,uGAAuG;AACvG,KAAK,qBAAqB,CAAC,CAAC,GAAG,OAAO,IAAI,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,uGAAuG;AACvG,KAAK,qBAAqB,CAAC,CAAC,GAAG,OAAO,IAAI,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AA4BnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAoRxD,eAAO,MAAM,aAAa,EAAE,qBAAqB,CAAC,qBAAqB,CAsItE,CAAC"}
|
package/dist/gateway.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ParallAgentGateway, parseShutdownDeadlineMs, } from "@parall/agent-core";
|
|
2
|
+
import { appendPreparedLocalAttachmentRefs, ensureLocalAttachmentGitExclude, pinLocalAttachmentPaths, } from "@parall/agent-core/internal/attachment-input";
|
|
2
3
|
import { ApiError, ParallClient, ParallWs } from "@parall/sdk";
|
|
3
4
|
import * as crypto from "node:crypto";
|
|
4
5
|
import * as os from "node:os";
|
|
@@ -146,68 +147,86 @@ async function waitForOpenClawSessionId(sessionsDir, sessionKey, timeoutMs = 10_
|
|
|
146
147
|
}
|
|
147
148
|
function createOpenClawDispatchAdapter(opts) {
|
|
148
149
|
return {
|
|
149
|
-
async *dispatch({ event, earlierEvents = [], bodyForAgent, sessionKey }) {
|
|
150
|
-
|
|
151
|
-
let
|
|
152
|
-
let turnGroupKey = "";
|
|
153
|
-
const run = opts.core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
154
|
-
ctx: buildInboundCtx(opts.core, opts.accountId, event, sessionKey, bodyForAgent, earlierEvents),
|
|
155
|
-
cfg: opts.cfg,
|
|
156
|
-
dispatcherOptions: {
|
|
157
|
-
deliver: async (payload) => {
|
|
158
|
-
const replyText = payload.text?.trim();
|
|
159
|
-
if (!replyText)
|
|
160
|
-
return;
|
|
161
|
-
stream.push({
|
|
162
|
-
type: "text",
|
|
163
|
-
text: replyText,
|
|
164
|
-
project: false,
|
|
165
|
-
groupKey: turnGroupKey || undefined,
|
|
166
|
-
});
|
|
167
|
-
},
|
|
168
|
-
onReplyStart: () => {
|
|
169
|
-
turnGroupKey = crypto.randomUUID();
|
|
170
|
-
setDispatchGroupKey(sessionKey, turnGroupKey);
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
replyOptions: {
|
|
174
|
-
onReasoningStream: (payload) => {
|
|
175
|
-
reasoningBuffer += payload.text ?? "";
|
|
176
|
-
},
|
|
177
|
-
onReasoningEnd: async () => {
|
|
178
|
-
if (!reasoningBuffer)
|
|
179
|
-
return;
|
|
180
|
-
stream.push({
|
|
181
|
-
type: "thinking",
|
|
182
|
-
text: reasoningBuffer,
|
|
183
|
-
groupKey: turnGroupKey || undefined,
|
|
184
|
-
});
|
|
185
|
-
reasoningBuffer = "";
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
});
|
|
189
|
-
run.then(() => stream.end()).catch((err) => stream.fail(err));
|
|
190
|
-
let sessionId;
|
|
150
|
+
async *dispatch({ event, earlierEvents = [], bodyForAgent, sessionKey, context }) {
|
|
151
|
+
let promptBody = bodyForAgent;
|
|
152
|
+
let releasePreparedAttachments = () => { };
|
|
191
153
|
try {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
154
|
+
const prepared = await appendPreparedLocalAttachmentRefs(bodyForAgent, event, context, {
|
|
155
|
+
workspaceDir: opts.workspaceDir,
|
|
156
|
+
log: context.log,
|
|
157
|
+
});
|
|
158
|
+
promptBody = prepared.body;
|
|
159
|
+
releasePreparedAttachments = pinLocalAttachmentPaths(prepared.attachments.images);
|
|
196
160
|
}
|
|
197
|
-
catch {
|
|
198
|
-
|
|
161
|
+
catch (err) {
|
|
162
|
+
context.log?.warn?.(`failed to prepare local attachments: ${String(err)}`);
|
|
199
163
|
}
|
|
200
|
-
|
|
201
|
-
stream
|
|
164
|
+
try {
|
|
165
|
+
const stream = createRuntimeEventStream();
|
|
166
|
+
let reasoningBuffer = "";
|
|
167
|
+
let turnGroupKey = "";
|
|
168
|
+
const run = opts.core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
169
|
+
ctx: buildInboundCtx(opts.core, opts.accountId, event, sessionKey, promptBody, earlierEvents),
|
|
170
|
+
cfg: opts.cfg,
|
|
171
|
+
dispatcherOptions: {
|
|
172
|
+
deliver: async (payload) => {
|
|
173
|
+
const replyText = payload.text?.trim();
|
|
174
|
+
if (!replyText)
|
|
175
|
+
return;
|
|
176
|
+
stream.push({
|
|
177
|
+
type: "text",
|
|
178
|
+
text: replyText,
|
|
179
|
+
project: false,
|
|
180
|
+
groupKey: turnGroupKey || undefined,
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
onReplyStart: () => {
|
|
184
|
+
turnGroupKey = crypto.randomUUID();
|
|
185
|
+
setDispatchGroupKey(sessionKey, turnGroupKey);
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
replyOptions: {
|
|
189
|
+
onReasoningStream: (payload) => {
|
|
190
|
+
reasoningBuffer += payload.text ?? "";
|
|
191
|
+
},
|
|
192
|
+
onReasoningEnd: async () => {
|
|
193
|
+
if (!reasoningBuffer)
|
|
194
|
+
return;
|
|
195
|
+
stream.push({
|
|
196
|
+
type: "thinking",
|
|
197
|
+
text: reasoningBuffer,
|
|
198
|
+
groupKey: turnGroupKey || undefined,
|
|
199
|
+
});
|
|
200
|
+
reasoningBuffer = "";
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
run.then(() => stream.end()).catch((err) => stream.fail(err));
|
|
205
|
+
let sessionId;
|
|
206
|
+
try {
|
|
207
|
+
sessionId = await Promise.race([
|
|
208
|
+
waitForOpenClawSessionId(opts.sessionsDir, sessionKey),
|
|
209
|
+
run.then(() => null, (err) => { throw err; }),
|
|
210
|
+
]);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
sessionId = null;
|
|
214
|
+
}
|
|
215
|
+
if (!sessionId) {
|
|
216
|
+
stream.fail(new Error(`OpenClaw did not expose a sessionId for ${sessionKey}`));
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
yield {
|
|
220
|
+
type: "runtime_session",
|
|
221
|
+
runtimeSessionId: sessionId,
|
|
222
|
+
runtimeLaneKey: sessionKey,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
yield* stream.stream();
|
|
202
226
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
type: "runtime_session",
|
|
206
|
-
runtimeSessionId: sessionId,
|
|
207
|
-
runtimeLaneKey: sessionKey,
|
|
208
|
-
};
|
|
227
|
+
finally {
|
|
228
|
+
releasePreparedAttachments();
|
|
209
229
|
}
|
|
210
|
-
yield* stream.stream();
|
|
211
230
|
},
|
|
212
231
|
getBranchPoint(sessionKey) {
|
|
213
232
|
const transcriptFile = resolveTranscriptFile(opts.sessionsDir, sessionKey);
|
|
@@ -308,11 +327,14 @@ export const parallGateway = {
|
|
|
308
327
|
});
|
|
309
328
|
const orchestratorKey = buildOrchestratorSessionKey(ctx.accountId);
|
|
310
329
|
const sessionsDir = path.join(stateDir, "agents", "main", "sessions");
|
|
330
|
+
const workspaceDir = process.cwd();
|
|
331
|
+
ensureLocalAttachmentGitExclude(workspaceDir);
|
|
311
332
|
const dispatchAdapter = createOpenClawDispatchAdapter({
|
|
312
333
|
core,
|
|
313
334
|
cfg: ctx.cfg,
|
|
314
335
|
accountId: ctx.accountId,
|
|
315
336
|
sessionsDir,
|
|
337
|
+
workspaceDir,
|
|
316
338
|
});
|
|
317
339
|
const gateway = new ParallAgentGateway({
|
|
318
340
|
accountId: ctx.accountId,
|
|
@@ -358,6 +380,7 @@ export const parallGateway = {
|
|
|
358
380
|
removeParallAccountState(ctx.accountId);
|
|
359
381
|
},
|
|
360
382
|
onNewSession: () => { clearSessionState(sessionsDir, orchestratorKey); },
|
|
383
|
+
onSessionStale: () => { clearSessionState(sessionsDir, orchestratorKey); },
|
|
361
384
|
});
|
|
362
385
|
try {
|
|
363
386
|
await gateway.run(ctx.abortSignal);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/parall",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.31.0",
|
|
4
4
|
"description": "OpenClaw channel plugin for Parall IM",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"openclaw.plugin.json"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@parall/
|
|
20
|
-
"@parall/
|
|
19
|
+
"@parall/sdk": "1.31.0",
|
|
20
|
+
"@parall/agent-core": "1.31.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/node": "^22.0.0",
|
package/src/gateway.ts
CHANGED
|
@@ -10,6 +10,11 @@ import {
|
|
|
10
10
|
type ParallEvent,
|
|
11
11
|
type RuntimeEvent,
|
|
12
12
|
} from "@parall/agent-core";
|
|
13
|
+
import {
|
|
14
|
+
appendPreparedLocalAttachmentRefs,
|
|
15
|
+
ensureLocalAttachmentGitExclude,
|
|
16
|
+
pinLocalAttachmentPaths,
|
|
17
|
+
} from "@parall/agent-core/internal/attachment-input";
|
|
13
18
|
import { ApiError, ParallClient, ParallWs } from "@parall/sdk";
|
|
14
19
|
import type { ParallChannelConfig } from "./types.js";
|
|
15
20
|
import * as crypto from "node:crypto";
|
|
@@ -185,68 +190,86 @@ function createOpenClawDispatchAdapter(opts: {
|
|
|
185
190
|
cfg: Record<string, unknown>;
|
|
186
191
|
accountId: string;
|
|
187
192
|
sessionsDir: string;
|
|
193
|
+
workspaceDir: string;
|
|
188
194
|
}): DispatchAdapter {
|
|
189
195
|
return {
|
|
190
|
-
async *dispatch({ event, earlierEvents = [], bodyForAgent, sessionKey }) {
|
|
191
|
-
|
|
192
|
-
let
|
|
193
|
-
|
|
196
|
+
async *dispatch({ event, earlierEvents = [], bodyForAgent, sessionKey, context }) {
|
|
197
|
+
let promptBody = bodyForAgent;
|
|
198
|
+
let releasePreparedAttachments = () => {};
|
|
199
|
+
try {
|
|
200
|
+
const prepared = await appendPreparedLocalAttachmentRefs(bodyForAgent, event, context, {
|
|
201
|
+
workspaceDir: opts.workspaceDir,
|
|
202
|
+
log: context.log,
|
|
203
|
+
});
|
|
204
|
+
promptBody = prepared.body;
|
|
205
|
+
releasePreparedAttachments = pinLocalAttachmentPaths(prepared.attachments.images);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
context.log?.warn?.(`failed to prepare local attachments: ${String(err)}`);
|
|
208
|
+
}
|
|
194
209
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
210
|
+
try {
|
|
211
|
+
const stream = createRuntimeEventStream();
|
|
212
|
+
let reasoningBuffer = "";
|
|
213
|
+
let turnGroupKey = "";
|
|
214
|
+
|
|
215
|
+
const run = opts.core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
216
|
+
ctx: buildInboundCtx(opts.core, opts.accountId, event, sessionKey, promptBody, earlierEvents),
|
|
217
|
+
cfg: opts.cfg,
|
|
218
|
+
dispatcherOptions: {
|
|
219
|
+
deliver: async (payload: { text?: string }) => {
|
|
220
|
+
const replyText = payload.text?.trim();
|
|
221
|
+
if (!replyText) return;
|
|
222
|
+
stream.push({
|
|
223
|
+
type: "text",
|
|
224
|
+
text: replyText,
|
|
225
|
+
project: false,
|
|
226
|
+
groupKey: turnGroupKey || undefined,
|
|
227
|
+
});
|
|
228
|
+
},
|
|
229
|
+
onReplyStart: () => {
|
|
230
|
+
turnGroupKey = crypto.randomUUID();
|
|
231
|
+
setDispatchGroupKey(sessionKey, turnGroupKey);
|
|
232
|
+
},
|
|
217
233
|
},
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
234
|
+
replyOptions: {
|
|
235
|
+
onReasoningStream: (payload: { text?: string }) => {
|
|
236
|
+
reasoningBuffer += payload.text ?? "";
|
|
237
|
+
},
|
|
238
|
+
onReasoningEnd: async () => {
|
|
239
|
+
if (!reasoningBuffer) return;
|
|
240
|
+
stream.push({
|
|
241
|
+
type: "thinking",
|
|
242
|
+
text: reasoningBuffer,
|
|
243
|
+
groupKey: turnGroupKey || undefined,
|
|
244
|
+
});
|
|
245
|
+
reasoningBuffer = "";
|
|
246
|
+
},
|
|
226
247
|
},
|
|
227
|
-
}
|
|
228
|
-
});
|
|
248
|
+
});
|
|
229
249
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
250
|
+
run.then(() => stream.end()).catch((err) => stream.fail(err));
|
|
251
|
+
let sessionId: string | null;
|
|
252
|
+
try {
|
|
253
|
+
sessionId = await Promise.race([
|
|
254
|
+
waitForOpenClawSessionId(opts.sessionsDir, sessionKey),
|
|
255
|
+
run.then(() => null as string | null, (err) => { throw err; }),
|
|
256
|
+
]);
|
|
257
|
+
} catch {
|
|
258
|
+
sessionId = null;
|
|
259
|
+
}
|
|
260
|
+
if (!sessionId) {
|
|
261
|
+
stream.fail(new Error(`OpenClaw did not expose a sessionId for ${sessionKey}`));
|
|
262
|
+
} else {
|
|
263
|
+
yield {
|
|
264
|
+
type: "runtime_session",
|
|
265
|
+
runtimeSessionId: sessionId,
|
|
266
|
+
runtimeLaneKey: sessionKey,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
yield* stream.stream();
|
|
270
|
+
} finally {
|
|
271
|
+
releasePreparedAttachments();
|
|
248
272
|
}
|
|
249
|
-
yield* stream.stream();
|
|
250
273
|
},
|
|
251
274
|
|
|
252
275
|
getBranchPoint(sessionKey: string): string | undefined {
|
|
@@ -351,11 +374,14 @@ export const parallGateway: ChannelGatewayAdapter<ResolvedParallAccount> = {
|
|
|
351
374
|
});
|
|
352
375
|
const orchestratorKey = buildOrchestratorSessionKey(ctx.accountId);
|
|
353
376
|
const sessionsDir = path.join(stateDir, "agents", "main", "sessions");
|
|
377
|
+
const workspaceDir = process.cwd();
|
|
378
|
+
ensureLocalAttachmentGitExclude(workspaceDir);
|
|
354
379
|
const dispatchAdapter = createOpenClawDispatchAdapter({
|
|
355
380
|
core,
|
|
356
381
|
cfg: ctx.cfg,
|
|
357
382
|
accountId: ctx.accountId,
|
|
358
383
|
sessionsDir,
|
|
384
|
+
workspaceDir,
|
|
359
385
|
});
|
|
360
386
|
|
|
361
387
|
const gateway = new ParallAgentGateway({
|
|
@@ -402,6 +428,7 @@ export const parallGateway: ChannelGatewayAdapter<ResolvedParallAccount> = {
|
|
|
402
428
|
removeParallAccountState(ctx.accountId);
|
|
403
429
|
},
|
|
404
430
|
onNewSession: () => { clearSessionState(sessionsDir, orchestratorKey); },
|
|
431
|
+
onSessionStale: () => { clearSessionState(sessionsDir, orchestratorKey); },
|
|
405
432
|
});
|
|
406
433
|
|
|
407
434
|
try {
|