@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/oc-session.js
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
// Sync check: when bumping devDependencies.openclaw, diff upstream
|
|
6
6
|
// pi-coding-agent/dist/core/session-manager.js for new migration steps
|
|
7
7
|
// or structural changes to createBranchedSession / _buildIndex.
|
|
8
|
-
import { randomUUID } from
|
|
9
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync
|
|
10
|
-
import { join, resolve } from
|
|
8
|
+
import { randomUUID } from 'node:crypto';
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { join, resolve } from 'node:path';
|
|
11
11
|
export const CURRENT_SESSION_VERSION = 3;
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
13
|
// Helpers
|
|
@@ -23,7 +23,7 @@ function generateId(existing) {
|
|
|
23
23
|
function loadEntries(filePath) {
|
|
24
24
|
if (!existsSync(filePath))
|
|
25
25
|
return [];
|
|
26
|
-
const lines = readFileSync(filePath,
|
|
26
|
+
const lines = readFileSync(filePath, 'utf-8').trim().split('\n');
|
|
27
27
|
const entries = [];
|
|
28
28
|
for (const line of lines) {
|
|
29
29
|
if (!line.trim())
|
|
@@ -38,7 +38,7 @@ function loadEntries(filePath) {
|
|
|
38
38
|
if (entries.length === 0)
|
|
39
39
|
return entries;
|
|
40
40
|
const h = entries[0];
|
|
41
|
-
if (h.type !==
|
|
41
|
+
if (h.type !== 'session' || typeof h.id !== 'string')
|
|
42
42
|
return [];
|
|
43
43
|
return entries;
|
|
44
44
|
}
|
|
@@ -47,7 +47,7 @@ function migrateV1ToV2(entries) {
|
|
|
47
47
|
const ids = new Set();
|
|
48
48
|
let prevId = null;
|
|
49
49
|
for (const entry of entries) {
|
|
50
|
-
if (entry.type ===
|
|
50
|
+
if (entry.type === 'session') {
|
|
51
51
|
entry.version = 2;
|
|
52
52
|
continue;
|
|
53
53
|
}
|
|
@@ -56,11 +56,11 @@ function migrateV1ToV2(entries) {
|
|
|
56
56
|
ids.add(e.id);
|
|
57
57
|
e.parentId = prevId;
|
|
58
58
|
prevId = e.id;
|
|
59
|
-
if (e.type ===
|
|
59
|
+
if (e.type === 'compaction') {
|
|
60
60
|
const comp = e;
|
|
61
|
-
if (typeof comp.firstKeptEntryIndex ===
|
|
61
|
+
if (typeof comp.firstKeptEntryIndex === 'number') {
|
|
62
62
|
const target = entries[comp.firstKeptEntryIndex];
|
|
63
|
-
if (target && target.type !==
|
|
63
|
+
if (target && target.type !== 'session') {
|
|
64
64
|
comp.firstKeptEntryId = target.id;
|
|
65
65
|
}
|
|
66
66
|
delete comp.firstKeptEntryIndex;
|
|
@@ -70,18 +70,20 @@ function migrateV1ToV2(entries) {
|
|
|
70
70
|
}
|
|
71
71
|
function migrateV2ToV3(entries) {
|
|
72
72
|
for (const entry of entries) {
|
|
73
|
-
if (entry.type ===
|
|
73
|
+
if (entry.type === 'session') {
|
|
74
74
|
entry.version = 3;
|
|
75
75
|
continue;
|
|
76
76
|
}
|
|
77
77
|
const e = entry;
|
|
78
|
-
if (e.type ===
|
|
79
|
-
e.message
|
|
78
|
+
if (e.type === 'message' &&
|
|
79
|
+
e.message &&
|
|
80
|
+
e.message.role === 'hookMessage') {
|
|
81
|
+
e.message.role = 'custom';
|
|
80
82
|
}
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
function migrate(entries) {
|
|
84
|
-
const header = entries.find((e) => e.type ===
|
|
86
|
+
const header = entries.find((e) => e.type === 'session');
|
|
85
87
|
const version = header?.version ?? 1;
|
|
86
88
|
if (version >= CURRENT_SESSION_VERSION)
|
|
87
89
|
return false;
|
|
@@ -95,7 +97,7 @@ function migrate(entries) {
|
|
|
95
97
|
// SessionManager (read-only subset + createBranchedSession)
|
|
96
98
|
// ---------------------------------------------------------------------------
|
|
97
99
|
export class SessionManager {
|
|
98
|
-
sessionId =
|
|
100
|
+
sessionId = '';
|
|
99
101
|
sessionFile;
|
|
100
102
|
sessionDir;
|
|
101
103
|
cwd;
|
|
@@ -136,7 +138,7 @@ export class SessionManager {
|
|
|
136
138
|
this.flushed = true;
|
|
137
139
|
return;
|
|
138
140
|
}
|
|
139
|
-
const header = this.fileEntries.find((e) => e.type ===
|
|
141
|
+
const header = this.fileEntries.find((e) => e.type === 'session');
|
|
140
142
|
if (header && header.version > CURRENT_SESSION_VERSION) {
|
|
141
143
|
throw new Error(`Session file ${this.sessionFile} uses version ${header.version}, ` +
|
|
142
144
|
`but oc-session.ts only supports up to ${CURRENT_SESSION_VERSION}. ` +
|
|
@@ -152,13 +154,19 @@ export class SessionManager {
|
|
|
152
154
|
this.sessionId = randomUUID();
|
|
153
155
|
const timestamp = new Date().toISOString();
|
|
154
156
|
this.fileEntries = [
|
|
155
|
-
{
|
|
157
|
+
{
|
|
158
|
+
type: 'session',
|
|
159
|
+
version: CURRENT_SESSION_VERSION,
|
|
160
|
+
id: this.sessionId,
|
|
161
|
+
timestamp,
|
|
162
|
+
cwd: this.cwd,
|
|
163
|
+
},
|
|
156
164
|
];
|
|
157
165
|
this.byId.clear();
|
|
158
166
|
this.labelsById.clear();
|
|
159
167
|
this.leafId = null;
|
|
160
168
|
this.flushed = false;
|
|
161
|
-
const ts = timestamp.replace(/[:.]/g,
|
|
169
|
+
const ts = timestamp.replace(/[:.]/g, '-');
|
|
162
170
|
this.sessionFile = join(this.sessionDir, `${ts}_${this.sessionId}.jsonl`);
|
|
163
171
|
}
|
|
164
172
|
buildIndex() {
|
|
@@ -167,12 +175,12 @@ export class SessionManager {
|
|
|
167
175
|
this.labelTimestampsById.clear();
|
|
168
176
|
this.leafId = null;
|
|
169
177
|
for (const entry of this.fileEntries) {
|
|
170
|
-
if (entry.type ===
|
|
178
|
+
if (entry.type === 'session')
|
|
171
179
|
continue;
|
|
172
180
|
const e = entry;
|
|
173
181
|
this.byId.set(e.id, e);
|
|
174
182
|
this.leafId = e.id;
|
|
175
|
-
if (e.type ===
|
|
183
|
+
if (e.type === 'label') {
|
|
176
184
|
if (e.label) {
|
|
177
185
|
this.labelsById.set(e.targetId, e.label);
|
|
178
186
|
this.labelTimestampsById.set(e.targetId, e.timestamp);
|
|
@@ -187,7 +195,7 @@ export class SessionManager {
|
|
|
187
195
|
rewrite() {
|
|
188
196
|
if (!this.sessionFile)
|
|
189
197
|
return;
|
|
190
|
-
writeFileSync(this.sessionFile, this.fileEntries.map((e) => JSON.stringify(e)).join(
|
|
198
|
+
writeFileSync(this.sessionFile, this.fileEntries.map((e) => JSON.stringify(e)).join('\n') + '\n');
|
|
191
199
|
}
|
|
192
200
|
// -- Public accessors ------------------------------------------------------
|
|
193
201
|
getLeafId() {
|
|
@@ -220,13 +228,13 @@ export class SessionManager {
|
|
|
220
228
|
const branch = this.getBranch(leafId);
|
|
221
229
|
if (branch.length === 0)
|
|
222
230
|
throw new Error(`Entry ${leafId} not found`);
|
|
223
|
-
const pathWithoutLabels = branch.filter((e) => e.type !==
|
|
231
|
+
const pathWithoutLabels = branch.filter((e) => e.type !== 'label');
|
|
224
232
|
const newId = randomUUID();
|
|
225
233
|
const timestamp = new Date().toISOString();
|
|
226
|
-
const ts = timestamp.replace(/[:.]/g,
|
|
234
|
+
const ts = timestamp.replace(/[:.]/g, '-');
|
|
227
235
|
const newFile = join(this.sessionDir, `${ts}_${newId}.jsonl`);
|
|
228
236
|
const header = {
|
|
229
|
-
type:
|
|
237
|
+
type: 'session',
|
|
230
238
|
version: CURRENT_SESSION_VERSION,
|
|
231
239
|
id: newId,
|
|
232
240
|
timestamp,
|
|
@@ -245,7 +253,7 @@ export class SessionManager {
|
|
|
245
253
|
const labelEntries = [];
|
|
246
254
|
for (const { targetId, label, timestamp: labelTs } of labelsToWrite) {
|
|
247
255
|
const le = {
|
|
248
|
-
type:
|
|
256
|
+
type: 'label',
|
|
249
257
|
id: generateId(pathEntryIds),
|
|
250
258
|
parentId,
|
|
251
259
|
timestamp: labelTs ?? timestamp,
|
|
@@ -260,7 +268,7 @@ export class SessionManager {
|
|
|
260
268
|
this.sessionId = newId;
|
|
261
269
|
this.sessionFile = newFile;
|
|
262
270
|
this.buildIndex();
|
|
263
|
-
const hasAssistant = this.fileEntries.some((e) => e.type ===
|
|
271
|
+
const hasAssistant = this.fileEntries.some((e) => e.type === 'message' && e.message?.role === 'assistant');
|
|
264
272
|
if (hasAssistant) {
|
|
265
273
|
this.rewrite();
|
|
266
274
|
this.flushed = true;
|
|
@@ -273,9 +281,9 @@ export class SessionManager {
|
|
|
273
281
|
// -- Factory ---------------------------------------------------------------
|
|
274
282
|
static open(path) {
|
|
275
283
|
const entries = loadEntries(path);
|
|
276
|
-
const header = entries.find((e) => e.type ===
|
|
284
|
+
const header = entries.find((e) => e.type === 'session');
|
|
277
285
|
const cwd = header?.cwd ?? process.cwd();
|
|
278
|
-
const dir = resolve(path,
|
|
286
|
+
const dir = resolve(path, '..');
|
|
279
287
|
return new SessionManager(cwd, dir, path);
|
|
280
288
|
}
|
|
281
289
|
}
|
package/dist/outbound.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ChannelPlugin } from
|
|
1
|
+
import type { ChannelPlugin } from 'openclaw/plugin-sdk/core';
|
|
2
2
|
/** Extract ChannelOutboundAdapter from ChannelPlugin (removed from public SDK exports in 2026.3.24). */
|
|
3
|
-
type ChannelOutboundAdapter = NonNullable<ChannelPlugin[
|
|
3
|
+
type ChannelOutboundAdapter = NonNullable<ChannelPlugin['outbound']>;
|
|
4
4
|
export declare const parallOutbound: ChannelOutboundAdapter;
|
|
5
5
|
export {};
|
|
6
6
|
//# sourceMappingURL=outbound.d.ts.map
|
package/dist/outbound.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbound.d.ts","sourceRoot":"","sources":["../src/outbound.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,wGAAwG;AACxG,KAAK,sBAAsB,GAAG,WAAW,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;AAMrE,eAAO,MAAM,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"outbound.d.ts","sourceRoot":"","sources":["../src/outbound.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,wGAAwG;AACxG,KAAK,sBAAsB,GAAG,WAAW,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;AAMrE,eAAO,MAAM,cAAc,EAAE,sBA4B5B,CAAC"}
|
package/dist/outbound.js
CHANGED
|
@@ -1,30 +1,29 @@
|
|
|
1
|
-
import { resolveParallAccount } from
|
|
2
|
-
import { getParallAccountState } from
|
|
3
|
-
import { ParallClient } from
|
|
1
|
+
import { resolveParallAccount } from './accounts.js';
|
|
2
|
+
import { getParallAccountState } from './runtime.js';
|
|
3
|
+
import { ParallClient } from '@parall/sdk';
|
|
4
4
|
export const parallOutbound = {
|
|
5
|
-
deliveryMode:
|
|
5
|
+
deliveryMode: 'direct',
|
|
6
6
|
textChunkLimit: 10000,
|
|
7
7
|
chunker: null,
|
|
8
8
|
sendText: async ({ cfg, to, text, accountId }) => {
|
|
9
9
|
const account = resolveParallAccount({ cfg, accountId: accountId ?? undefined });
|
|
10
10
|
if (!account.enabled)
|
|
11
|
-
throw new Error(
|
|
11
|
+
throw new Error('Parall account is disabled');
|
|
12
12
|
if (!account.configured)
|
|
13
|
-
throw new Error(
|
|
13
|
+
throw new Error('Parall account is not configured: parall_url/api_key/org_id required');
|
|
14
14
|
const state = getParallAccountState(account.accountId);
|
|
15
|
-
const client = state?.client ??
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const client = state?.client ??
|
|
16
|
+
new ParallClient({
|
|
17
|
+
baseUrl: account.config.parall_url,
|
|
18
|
+
token: account.config.api_key,
|
|
19
|
+
});
|
|
19
20
|
const orgId = state?.orgId ?? account.config.org_id;
|
|
20
21
|
const chatId = to;
|
|
21
|
-
// Outbound path has no step context — send without agent_step_id.
|
|
22
|
-
// Step linkage happens via the CLI's ENV-injected PRLL_STEP_ID in the normal dispatch path.
|
|
23
22
|
const req = {
|
|
24
|
-
message_type:
|
|
23
|
+
message_type: 'text',
|
|
25
24
|
content: { text },
|
|
26
25
|
};
|
|
27
26
|
const msg = await client.sendMessage(orgId, chatId, req);
|
|
28
|
-
return { channel:
|
|
27
|
+
return { channel: 'parall', messageId: msg.id, channelId: chatId };
|
|
29
28
|
},
|
|
30
29
|
};
|
package/dist/routing.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { defaultRoutingStrategy, routeTrigger, } from
|
|
2
|
-
export type { RoutingStrategy, TriggerDisposition, } from
|
|
1
|
+
export { defaultRoutingStrategy, routeTrigger, } from '@parall/agent-core';
|
|
2
|
+
export type { RoutingStrategy, TriggerDisposition, } from '@parall/agent-core';
|
|
3
3
|
//# sourceMappingURL=routing.d.ts.map
|
package/dist/routing.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { defaultRoutingStrategy, routeTrigger, } from
|
|
1
|
+
export { defaultRoutingStrategy, routeTrigger, } from '@parall/agent-core';
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { PluginRuntime } from
|
|
2
|
-
import type { ParallClient, ParallWs } from
|
|
3
|
-
import type { AgentIdentity } from
|
|
4
|
-
export type { ForkResult, DispatchState, ParallEvent } from
|
|
5
|
-
export { setSessionChatId, getSessionChatId, setSessionMessageId, getSessionMessageId, clearSessionMessageId, setDispatchMessageId, getDispatchMessageId, clearDispatchMessageId, setDispatchGroupKey, getDispatchGroupKey, clearDispatchGroupKey, setDispatchNoReply, getDispatchNoReply, clearDispatchNoReply, } from
|
|
1
|
+
import type { PluginRuntime } from 'openclaw/plugin-sdk';
|
|
2
|
+
import type { ParallClient, ParallWs } from '@parall/sdk';
|
|
3
|
+
import type { AgentIdentity } from '@parall/agent-core';
|
|
4
|
+
export type { ForkResult, DispatchState, ParallEvent } from '@parall/agent-core';
|
|
5
|
+
export { setSessionChatId, getSessionChatId, setSessionMessageId, getSessionMessageId, clearSessionMessageId, setDispatchMessageId, getDispatchMessageId, clearDispatchMessageId, setDispatchGroupKey, getDispatchGroupKey, clearDispatchGroupKey, setDispatchNoReply, getDispatchNoReply, clearDispatchNoReply, } from '@parall/agent-core';
|
|
6
6
|
export type ParallAccountState = {
|
|
7
7
|
client: ParallClient;
|
|
8
8
|
apiUrl: string;
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAIF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,QAEnD;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAKD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,QAEjF;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,QAEzD;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEvF;AAED,wBAAgB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAIF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,QAEnD;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAKD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,QAEjF;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,QAEzD;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEvF;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,QAOvB;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEhG;AAED,wBAAgB,yBAAyB,IAAI,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAEnF;AAID,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,QAEvD;AAED,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,SAAS,CAE5D"}
|
package/dist/runtime.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { setSessionChatId, getSessionChatId, setSessionMessageId, getSessionMessageId, clearSessionMessageId, setDispatchMessageId, getDispatchMessageId, clearDispatchMessageId, setDispatchGroupKey, getDispatchGroupKey, clearDispatchGroupKey, setDispatchNoReply, getDispatchNoReply, clearDispatchNoReply, } from
|
|
1
|
+
export { setSessionChatId, getSessionChatId, setSessionMessageId, getSessionMessageId, clearSessionMessageId, setDispatchMessageId, getDispatchMessageId, clearDispatchMessageId, setDispatchGroupKey, getDispatchGroupKey, clearDispatchGroupKey, setDispatchNoReply, getDispatchNoReply, clearDispatchNoReply, } from '@parall/agent-core';
|
|
2
2
|
let runtime = null;
|
|
3
3
|
export function setParallRuntime(next) {
|
|
4
4
|
runtime = next;
|
|
5
5
|
}
|
|
6
6
|
export function getParallRuntime() {
|
|
7
7
|
if (!runtime) {
|
|
8
|
-
throw new Error(
|
|
8
|
+
throw new Error('Parall runtime not initialized');
|
|
9
9
|
}
|
|
10
10
|
return runtime;
|
|
11
11
|
}
|
package/dist/session.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const PRLL_SESSION_PREFIX =
|
|
1
|
+
const PRLL_SESSION_PREFIX = 'agent:main:parall:';
|
|
2
2
|
/** Build OpenClaw session key from Parall account, chat type, and chat ID. */
|
|
3
3
|
export function buildSessionKey(accountId, chatType, chatId) {
|
|
4
4
|
return `${PRLL_SESSION_PREFIX}${accountId}:${chatType}:${chatId}`;
|
|
@@ -11,7 +11,7 @@ export function extractAccountIdFromSessionKey(sessionKey) {
|
|
|
11
11
|
if (!sessionKey?.startsWith(PRLL_SESSION_PREFIX))
|
|
12
12
|
return undefined;
|
|
13
13
|
const rest = sessionKey.slice(PRLL_SESSION_PREFIX.length);
|
|
14
|
-
const firstColon = rest.indexOf(
|
|
14
|
+
const firstColon = rest.indexOf(':');
|
|
15
15
|
if (firstColon < 0)
|
|
16
16
|
return undefined;
|
|
17
17
|
return rest.slice(0, firstColon) || undefined;
|
|
@@ -25,10 +25,10 @@ export function extractChatIdFromSessionKey(sessionKey) {
|
|
|
25
25
|
return undefined;
|
|
26
26
|
const rest = sessionKey.slice(PRLL_SESSION_PREFIX.length);
|
|
27
27
|
// Skip accountId and chatType segments
|
|
28
|
-
const parts = rest.split(
|
|
28
|
+
const parts = rest.split(':');
|
|
29
29
|
if (parts.length < 3)
|
|
30
30
|
return undefined;
|
|
31
|
-
return parts.slice(2).join(
|
|
31
|
+
return parts.slice(2).join(':') || undefined;
|
|
32
32
|
}
|
|
33
33
|
/** Build the single orchestrator session key for all Parall events. */
|
|
34
34
|
export function buildOrchestratorSessionKey(accountId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wiki-helper.d.ts","sourceRoot":"","sources":["../src/wiki-helper.ts"],"names":[],"mappings":"AAGA,KAAK,MAAM,GAAG;IACZ,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;
|
|
1
|
+
{"version":3,"file":"wiki-helper.d.ts","sourceRoot":"","sources":["../src/wiki-helper.ts"],"names":[],"mappings":"AAGA,KAAK,MAAM,GAAG;IACZ,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AA8GF,wBAAsB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAoD/F"}
|
package/dist/wiki-helper.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { spawn, spawnSync } from
|
|
2
|
-
import path from
|
|
1
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
const DEFAULT_SYNC_TIMEOUT_MS = 90_000; // includes npx cold-start download time
|
|
4
4
|
const DEFAULT_WATCH_INTERVAL_SEC = 30;
|
|
5
5
|
function isCommandMissing(error) {
|
|
6
|
-
return typeof error ===
|
|
6
|
+
return typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT';
|
|
7
7
|
}
|
|
8
8
|
// Prefer bare `parall` (globally installed in hosted images). Fall back to
|
|
9
9
|
// npx for self-hosted environments that haven't installed @parall/cli yet.
|
|
10
10
|
let _cli;
|
|
11
11
|
function resolveParallCli() {
|
|
12
12
|
if (!_cli) {
|
|
13
|
-
const r = spawnSync(
|
|
13
|
+
const r = spawnSync('parall', ['--version'], { stdio: 'ignore', timeout: 5_000 });
|
|
14
14
|
_cli = r.error
|
|
15
|
-
? { cmd:
|
|
16
|
-
: { cmd:
|
|
15
|
+
? { cmd: 'npx', prefix: ['--yes', '@parall/cli@latest'] }
|
|
16
|
+
: { cmd: 'parall', prefix: [] };
|
|
17
17
|
}
|
|
18
18
|
return _cli;
|
|
19
19
|
}
|
|
20
20
|
function resolveMountRoot(stateDir) {
|
|
21
|
-
return process.env.PRLL_WIKI_MOUNT_ROOT?.trim() || path.join(stateDir,
|
|
21
|
+
return process.env.PRLL_WIKI_MOUNT_ROOT?.trim() || path.join(stateDir, 'workspace');
|
|
22
22
|
}
|
|
23
23
|
function resolveWatchIntervalSec() {
|
|
24
24
|
const raw = process.env.PRLL_WIKI_REFRESH_INTERVAL_SEC?.trim();
|
|
@@ -43,9 +43,9 @@ async function runWikiSync(params, env) {
|
|
|
43
43
|
let timedOut = false;
|
|
44
44
|
let settled = false;
|
|
45
45
|
const { cmd, prefix } = resolveParallCli();
|
|
46
|
-
const child = spawn(cmd, [...prefix,
|
|
46
|
+
const child = spawn(cmd, [...prefix, 'wiki', 'sync'], {
|
|
47
47
|
env,
|
|
48
|
-
stdio:
|
|
48
|
+
stdio: 'ignore',
|
|
49
49
|
});
|
|
50
50
|
const settle = (value) => {
|
|
51
51
|
if (settled)
|
|
@@ -56,33 +56,33 @@ async function runWikiSync(params, env) {
|
|
|
56
56
|
const timer = setTimeout(() => {
|
|
57
57
|
timedOut = true;
|
|
58
58
|
params.log?.warn?.(`parall[${params.accountId}]: parall sync timed out after ${DEFAULT_SYNC_TIMEOUT_MS}ms`);
|
|
59
|
-
child.kill(
|
|
60
|
-
setTimeout(() => child.kill(
|
|
59
|
+
child.kill('SIGTERM');
|
|
60
|
+
setTimeout(() => child.kill('SIGKILL'), 5_000).unref();
|
|
61
61
|
}, DEFAULT_SYNC_TIMEOUT_MS);
|
|
62
62
|
timer.unref();
|
|
63
|
-
child.on(
|
|
63
|
+
child.on('error', (error) => {
|
|
64
64
|
clearTimeout(timer);
|
|
65
65
|
if (isCommandMissing(error)) {
|
|
66
66
|
params.log?.warn?.(`parall[${params.accountId}]: parall not installed, skipping wiki auto-sync/watch`);
|
|
67
|
-
settle(
|
|
67
|
+
settle('missing');
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
70
|
params.log?.warn?.(`parall[${params.accountId}]: parall sync failed to start: ${String(error)}`);
|
|
71
|
-
settle(
|
|
71
|
+
settle('failed');
|
|
72
72
|
});
|
|
73
|
-
child.on(
|
|
73
|
+
child.on('exit', (code, signal) => {
|
|
74
74
|
clearTimeout(timer);
|
|
75
75
|
if (timedOut) {
|
|
76
|
-
settle(
|
|
76
|
+
settle('failed');
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
79
|
if (code === 0) {
|
|
80
80
|
params.log?.info?.(`parall[${params.accountId}]: parall sync completed`);
|
|
81
|
-
settle(
|
|
81
|
+
settle('ok');
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
|
-
params.log?.warn?.(`parall[${params.accountId}]: parall sync exited with code=${code ??
|
|
85
|
-
settle(
|
|
84
|
+
params.log?.warn?.(`parall[${params.accountId}]: parall sync exited with code=${code ?? 'null'} signal=${signal ?? 'null'}`);
|
|
85
|
+
settle('failed');
|
|
86
86
|
});
|
|
87
87
|
});
|
|
88
88
|
}
|
|
@@ -90,7 +90,7 @@ export async function startWikiHelper(params) {
|
|
|
90
90
|
const mountRoot = resolveMountRoot(params.stateDir);
|
|
91
91
|
const env = buildWikiHelperEnv(params, mountRoot);
|
|
92
92
|
const syncResult = await runWikiSync(params, env);
|
|
93
|
-
if (syncResult ===
|
|
93
|
+
if (syncResult === 'missing') {
|
|
94
94
|
return {
|
|
95
95
|
mountRoot,
|
|
96
96
|
stop() { },
|
|
@@ -99,11 +99,11 @@ export async function startWikiHelper(params) {
|
|
|
99
99
|
const intervalSec = resolveWatchIntervalSec();
|
|
100
100
|
let stopped = false;
|
|
101
101
|
const { cmd, prefix } = resolveParallCli();
|
|
102
|
-
const watch = spawn(cmd, [...prefix,
|
|
102
|
+
const watch = spawn(cmd, [...prefix, 'wiki', 'watch', '--interval-sec', String(intervalSec)], {
|
|
103
103
|
env,
|
|
104
|
-
stdio:
|
|
104
|
+
stdio: 'ignore',
|
|
105
105
|
});
|
|
106
|
-
watch.on(
|
|
106
|
+
watch.on('error', (error) => {
|
|
107
107
|
if (stopped)
|
|
108
108
|
return;
|
|
109
109
|
if (isCommandMissing(error)) {
|
|
@@ -112,10 +112,10 @@ export async function startWikiHelper(params) {
|
|
|
112
112
|
}
|
|
113
113
|
params.log?.warn?.(`parall[${params.accountId}]: parall watch failed: ${String(error)}`);
|
|
114
114
|
});
|
|
115
|
-
watch.on(
|
|
115
|
+
watch.on('exit', (code, signal) => {
|
|
116
116
|
if (stopped)
|
|
117
117
|
return;
|
|
118
|
-
params.log?.warn?.(`parall[${params.accountId}]: parall watch exited with code=${code ??
|
|
118
|
+
params.log?.warn?.(`parall[${params.accountId}]: parall watch exited with code=${code ?? 'null'} signal=${signal ?? 'null'}`);
|
|
119
119
|
});
|
|
120
120
|
params.log?.info?.(`parall[${params.accountId}]: parall watch started (interval=${intervalSec}s)`);
|
|
121
121
|
return {
|
|
@@ -123,8 +123,8 @@ export async function startWikiHelper(params) {
|
|
|
123
123
|
stop() {
|
|
124
124
|
stopped = true;
|
|
125
125
|
if (watch.exitCode === null && watch.signalCode === null) {
|
|
126
|
-
watch.kill(
|
|
127
|
-
setTimeout(() => watch.kill(
|
|
126
|
+
watch.kill('SIGTERM');
|
|
127
|
+
setTimeout(() => watch.kill('SIGKILL'), 5_000).unref();
|
|
128
128
|
}
|
|
129
129
|
},
|
|
130
130
|
};
|
package/openclaw.plugin.json
CHANGED
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
"parall_url": { "type": "string", "description": "Parall API base URL" },
|
|
13
13
|
"api_key": { "type": "string", "description": "Agent API key (agk_xxx)" },
|
|
14
14
|
"org_id": { "type": "string", "description": "Organisation ID" },
|
|
15
|
-
"ws_url": {
|
|
15
|
+
"ws_url": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "WebSocket URL (optional, derived from parall_url)"
|
|
18
|
+
}
|
|
16
19
|
},
|
|
17
20
|
"required": ["parall_url", "api_key", "org_id"]
|
|
18
21
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/parall",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.32.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/sdk": "1.
|
|
20
|
-
"@parall/agent-core": "1.
|
|
19
|
+
"@parall/sdk": "1.32.0",
|
|
20
|
+
"@parall/agent-core": "1.32.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/node": "^22.0.0",
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: parall-clips
|
|
3
|
+
description: "Parall clip operations: list installed clips, invoke clip commands, inspect clip details. Use when: the task requires external capabilities (GitHub, web search, etc.), user asks about available tools/clips, or you need to call a clip command."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Parall Clips
|
|
7
|
+
|
|
8
|
+
Clips are capability extensions — packaged toolkits that give you extra commands (e.g. GitHub operations, web search, code analysis). Clips installed in the org are available for any agent to invoke via the CLI.
|
|
9
|
+
|
|
10
|
+
## Discovering available clips
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# List all clips installed in the org
|
|
14
|
+
parall clip list
|
|
15
|
+
|
|
16
|
+
# Show detailed info about a clip (manifest, commands, version)
|
|
17
|
+
parall clip info <alias>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Invoking a clip command
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Invoke a command on a clip by alias
|
|
24
|
+
parall clip invoke <alias> <command> [input]
|
|
25
|
+
|
|
26
|
+
# input is optional — when provided, it can be a JSON string or plain text
|
|
27
|
+
parall clip invoke github-tools list-repos '{"org": "acme"}'
|
|
28
|
+
parall clip invoke web-search search "latest Node.js LTS version"
|
|
29
|
+
|
|
30
|
+
# Custom timeout (default 30s)
|
|
31
|
+
parall clip invoke github-tools create-issue '{"title": "Bug report"}' --timeout 60000
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## How clips work
|
|
35
|
+
|
|
36
|
+
1. An org admin installs a clip from the Pinix registry or creates a custom one
|
|
37
|
+
2. `parall clip list` shows every clip installed in the org
|
|
38
|
+
3. You can only **invoke** clips that an admin has **bound to you** — invoking an unbound clip returns a "not bound" error. Ask an admin to bind the clip if you need it.
|
|
39
|
+
4. Each clip exposes one or more named commands with typed input/output
|
|
40
|
+
|
|
41
|
+
## When to use clips
|
|
42
|
+
|
|
43
|
+
- Check `parall clip list` when a task requires capabilities beyond your built-in tools (e.g. GitHub API, external services, specialized analysis)
|
|
44
|
+
- Use `parall clip info <alias>` to discover available commands and their expected input format
|
|
45
|
+
- If `parall clip invoke` reports the clip isn't bound to you, that clip exists in the org but hasn't been granted to you — ask an admin to bind it
|
|
46
|
+
- Clip invocations return JSON output on success or an error message on failure
|
|
47
|
+
|
|
48
|
+
CLI command results are JSON on stdout.
|
package/src/accounts.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ResolvedParallAccount, ParallChannelConfig } from
|
|
1
|
+
import type { ResolvedParallAccount, ParallChannelConfig } from './types.js';
|
|
2
2
|
|
|
3
|
-
const DEFAULT_ACCOUNT_ID =
|
|
3
|
+
const DEFAULT_ACCOUNT_ID = 'default';
|
|
4
4
|
|
|
5
5
|
type OpenClawConfig = Record<string, unknown>;
|
|
6
6
|
|
|
@@ -22,9 +22,9 @@ export function resolveParallAccount(params: {
|
|
|
22
22
|
const { cfg, accountId = DEFAULT_ACCOUNT_ID } = params;
|
|
23
23
|
const parallCfg = readParallConfig(cfg);
|
|
24
24
|
const config: ParallChannelConfig = {
|
|
25
|
-
parall_url: parallCfg?.parall_url ??
|
|
26
|
-
api_key: parallCfg?.api_key ??
|
|
27
|
-
org_id: parallCfg?.org_id ??
|
|
25
|
+
parall_url: parallCfg?.parall_url ?? '',
|
|
26
|
+
api_key: parallCfg?.api_key ?? '',
|
|
27
|
+
org_id: parallCfg?.org_id ?? '',
|
|
28
28
|
ws_url: parallCfg?.ws_url,
|
|
29
29
|
enabled: parallCfg?.enabled,
|
|
30
30
|
};
|
package/src/channel.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import type { ChannelPlugin } from
|
|
2
|
-
import { listParallAccountIds, resolveParallAccount } from
|
|
3
|
-
import { parallGateway } from
|
|
4
|
-
import { parallOutbound } from
|
|
5
|
-
import type { ResolvedParallAccount } from
|
|
1
|
+
import type { ChannelPlugin } from 'openclaw/plugin-sdk/core';
|
|
2
|
+
import { listParallAccountIds, resolveParallAccount } from './accounts.js';
|
|
3
|
+
import { parallGateway } from './gateway.js';
|
|
4
|
+
import { parallOutbound } from './outbound.js';
|
|
5
|
+
import type { ResolvedParallAccount } from './types.js';
|
|
6
6
|
|
|
7
|
-
const meta: ChannelPlugin[
|
|
8
|
-
id:
|
|
9
|
-
label:
|
|
10
|
-
selectionLabel:
|
|
11
|
-
docsPath:
|
|
12
|
-
blurb:
|
|
7
|
+
const meta: ChannelPlugin['meta'] = {
|
|
8
|
+
id: 'parall',
|
|
9
|
+
label: 'Parall',
|
|
10
|
+
selectionLabel: 'Parall IM',
|
|
11
|
+
docsPath: '/channels/parall',
|
|
12
|
+
blurb: 'Agent-Native IM platform.',
|
|
13
13
|
order: 80,
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export const parallPlugin: ChannelPlugin<ResolvedParallAccount> = {
|
|
17
|
-
id:
|
|
17
|
+
id: 'parall',
|
|
18
18
|
meta,
|
|
19
19
|
capabilities: {
|
|
20
|
-
chatTypes: [
|
|
20
|
+
chatTypes: ['direct', 'group'],
|
|
21
21
|
polls: false,
|
|
22
22
|
threads: false,
|
|
23
23
|
media: true,
|
|
@@ -27,7 +27,8 @@ export const parallPlugin: ChannelPlugin<ResolvedParallAccount> = {
|
|
|
27
27
|
},
|
|
28
28
|
config: {
|
|
29
29
|
listAccountIds: (cfg) => listParallAccountIds(cfg),
|
|
30
|
-
resolveAccount: (cfg, accountId) =>
|
|
30
|
+
resolveAccount: (cfg, accountId) =>
|
|
31
|
+
resolveParallAccount({ cfg, accountId: accountId ?? undefined }),
|
|
31
32
|
isConfigured: (account) => account.configured,
|
|
32
33
|
describeAccount: (account) => ({
|
|
33
34
|
accountId: account.accountId,
|