@parall/parall 1.26.0 → 1.26.2
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 +9 -0
- package/dist/accounts.d.ts.map +1 -0
- package/dist/accounts.js +29 -0
- package/dist/channel.d.ts +4 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +36 -0
- package/dist/config-manager.d.ts +22 -0
- package/dist/config-manager.d.ts.map +1 -0
- package/dist/config-manager.js +154 -0
- package/dist/fork.d.ts +30 -0
- package/dist/fork.d.ts.map +1 -0
- package/dist/fork.js +162 -0
- package/dist/gateway.d.ts +7 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +330 -0
- package/dist/hooks.d.ts +3 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +194 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/outbound.d.ts +6 -0
- package/dist/outbound.d.ts.map +1 -0
- package/dist/outbound.js +30 -0
- package/dist/routing.d.ts +3 -0
- package/dist/routing.d.ts.map +1 -0
- package/dist/routing.js +1 -0
- package/dist/runtime.d.ts +26 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +32 -0
- package/dist/session.d.ts +15 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +36 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/wiki-helper.d.ts +21 -0
- package/dist/wiki-helper.d.ts.map +1 -0
- package/dist/wiki-helper.js +131 -0
- package/openclaw.plugin.json +17 -0
- package/package.json +7 -6
- package/src/config-manager.ts +16 -1
- package/src/fork.ts +6 -4
- package/src/gateway.ts +14 -1
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export { setSessionChatId, getSessionChatId, setSessionMessageId, getSessionMessageId, clearSessionMessageId, setDispatchMessageId, getDispatchMessageId, clearDispatchMessageId, setDispatchGroupKey, getDispatchGroupKey, clearDispatchGroupKey, setDispatchNoReply, getDispatchNoReply, clearDispatchNoReply, } from "@parall/agent-core";
|
|
2
|
+
let runtime = null;
|
|
3
|
+
export function setParallRuntime(next) {
|
|
4
|
+
runtime = next;
|
|
5
|
+
}
|
|
6
|
+
export function getParallRuntime() {
|
|
7
|
+
if (!runtime) {
|
|
8
|
+
throw new Error("Parall runtime not initialized");
|
|
9
|
+
}
|
|
10
|
+
return runtime;
|
|
11
|
+
}
|
|
12
|
+
// Cached client state per account, populated by gateway.ts startAccount
|
|
13
|
+
const accountStates = new Map();
|
|
14
|
+
export function setParallAccountState(accountId, state) {
|
|
15
|
+
accountStates.set(accountId, state);
|
|
16
|
+
}
|
|
17
|
+
export function removeParallAccountState(accountId) {
|
|
18
|
+
accountStates.delete(accountId);
|
|
19
|
+
}
|
|
20
|
+
export function getParallAccountState(accountId) {
|
|
21
|
+
return accountStates.get(accountId);
|
|
22
|
+
}
|
|
23
|
+
export function getAllParallAccountStates() {
|
|
24
|
+
return new Map(accountStates);
|
|
25
|
+
}
|
|
26
|
+
let agentIdentity;
|
|
27
|
+
export function setAgentIdentity(identity) {
|
|
28
|
+
agentIdentity = identity;
|
|
29
|
+
}
|
|
30
|
+
export function getAgentIdentity() {
|
|
31
|
+
return agentIdentity;
|
|
32
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Build OpenClaw session key from Parall account, chat type, and chat ID. */
|
|
2
|
+
export declare function buildSessionKey(accountId: string, chatType: string, chatId: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Extract account ID from an OpenClaw session key.
|
|
5
|
+
* Format: "agent:main:parall:{accountId}:{type}:{chatId}"
|
|
6
|
+
*/
|
|
7
|
+
export declare function extractAccountIdFromSessionKey(sessionKey: string | undefined): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Extract chat ID from an OpenClaw session key.
|
|
10
|
+
* Format: "agent:main:parall:{accountId}:{type}:{chatId}"
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractChatIdFromSessionKey(sessionKey: string | undefined): string | undefined;
|
|
13
|
+
/** Build the single orchestrator session key for all Parall events. */
|
|
14
|
+
export declare function buildOrchestratorSessionKey(accountId: string): string;
|
|
15
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAMjG;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAO9F;AAED,uEAAuE;AACvE,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const PRLL_SESSION_PREFIX = "agent:main:parall:";
|
|
2
|
+
/** Build OpenClaw session key from Parall account, chat type, and chat ID. */
|
|
3
|
+
export function buildSessionKey(accountId, chatType, chatId) {
|
|
4
|
+
return `${PRLL_SESSION_PREFIX}${accountId}:${chatType}:${chatId}`;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Extract account ID from an OpenClaw session key.
|
|
8
|
+
* Format: "agent:main:parall:{accountId}:{type}:{chatId}"
|
|
9
|
+
*/
|
|
10
|
+
export function extractAccountIdFromSessionKey(sessionKey) {
|
|
11
|
+
if (!sessionKey?.startsWith(PRLL_SESSION_PREFIX))
|
|
12
|
+
return undefined;
|
|
13
|
+
const rest = sessionKey.slice(PRLL_SESSION_PREFIX.length);
|
|
14
|
+
const firstColon = rest.indexOf(":");
|
|
15
|
+
if (firstColon < 0)
|
|
16
|
+
return undefined;
|
|
17
|
+
return rest.slice(0, firstColon) || undefined;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Extract chat ID from an OpenClaw session key.
|
|
21
|
+
* Format: "agent:main:parall:{accountId}:{type}:{chatId}"
|
|
22
|
+
*/
|
|
23
|
+
export function extractChatIdFromSessionKey(sessionKey) {
|
|
24
|
+
if (!sessionKey?.startsWith(PRLL_SESSION_PREFIX))
|
|
25
|
+
return undefined;
|
|
26
|
+
const rest = sessionKey.slice(PRLL_SESSION_PREFIX.length);
|
|
27
|
+
// Skip accountId and chatType segments
|
|
28
|
+
const parts = rest.split(":");
|
|
29
|
+
if (parts.length < 3)
|
|
30
|
+
return undefined;
|
|
31
|
+
return parts.slice(2).join(":") || undefined;
|
|
32
|
+
}
|
|
33
|
+
/** Build the single orchestrator session key for all Parall events. */
|
|
34
|
+
export function buildOrchestratorSessionKey(accountId) {
|
|
35
|
+
return `${PRLL_SESSION_PREFIX}${accountId}:orchestrator`;
|
|
36
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type ParallChannelConfig = {
|
|
2
|
+
enabled?: boolean;
|
|
3
|
+
/** Parall server URL, e.g. "https://parall.example.com" */
|
|
4
|
+
parall_url: string;
|
|
5
|
+
/** Agent API key (agk_xxx) */
|
|
6
|
+
api_key: string;
|
|
7
|
+
/** Organization ID */
|
|
8
|
+
org_id: string;
|
|
9
|
+
/** WS Gateway URL (defaults to parall_url with ws:// scheme + /ws path) */
|
|
10
|
+
ws_url?: string;
|
|
11
|
+
};
|
|
12
|
+
export type ResolvedParallAccount = {
|
|
13
|
+
accountId: string;
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
configured: boolean;
|
|
16
|
+
config: ParallChannelConfig;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,mBAAmB,CAAC;CAC7B,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type Logger = {
|
|
2
|
+
info?: (message: string) => void;
|
|
3
|
+
warn?: (message: string) => void;
|
|
4
|
+
error?: (message: string) => void;
|
|
5
|
+
};
|
|
6
|
+
type StartWikiHelperParams = {
|
|
7
|
+
accountId: string;
|
|
8
|
+
parallUrl: string;
|
|
9
|
+
apiKey: string;
|
|
10
|
+
orgId: string;
|
|
11
|
+
agentId: string;
|
|
12
|
+
stateDir: string;
|
|
13
|
+
log?: Logger;
|
|
14
|
+
};
|
|
15
|
+
type WikiHelperRuntime = {
|
|
16
|
+
mountRoot: string;
|
|
17
|
+
stop: () => void;
|
|
18
|
+
};
|
|
19
|
+
export declare function startWikiHelper(params: StartWikiHelperParams): Promise<WikiHelperRuntime>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=wiki-helper.d.ts.map
|
|
@@ -0,0 +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;AAqGF,wBAAsB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgD/F"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const DEFAULT_SYNC_TIMEOUT_MS = 90_000; // includes npx cold-start download time
|
|
4
|
+
const DEFAULT_WATCH_INTERVAL_SEC = 30;
|
|
5
|
+
function isCommandMissing(error) {
|
|
6
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
7
|
+
}
|
|
8
|
+
// Prefer bare `parall` (globally installed in hosted images). Fall back to
|
|
9
|
+
// npx for self-hosted environments that haven't installed @parall/cli yet.
|
|
10
|
+
let _cli;
|
|
11
|
+
function resolveParallCli() {
|
|
12
|
+
if (!_cli) {
|
|
13
|
+
const r = spawnSync("parall", ["--version"], { stdio: "ignore", timeout: 5_000 });
|
|
14
|
+
_cli = r.error
|
|
15
|
+
? { cmd: "npx", prefix: ["--yes", "@parall/cli@latest"] }
|
|
16
|
+
: { cmd: "parall", prefix: [] };
|
|
17
|
+
}
|
|
18
|
+
return _cli;
|
|
19
|
+
}
|
|
20
|
+
function resolveMountRoot(stateDir) {
|
|
21
|
+
return process.env.PRLL_WIKI_MOUNT_ROOT?.trim() || path.join(stateDir, "workspace");
|
|
22
|
+
}
|
|
23
|
+
function resolveWatchIntervalSec() {
|
|
24
|
+
const raw = process.env.PRLL_WIKI_REFRESH_INTERVAL_SEC?.trim();
|
|
25
|
+
if (!raw) {
|
|
26
|
+
return DEFAULT_WATCH_INTERVAL_SEC;
|
|
27
|
+
}
|
|
28
|
+
const parsed = Number.parseInt(raw, 10);
|
|
29
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_WATCH_INTERVAL_SEC;
|
|
30
|
+
}
|
|
31
|
+
function buildWikiHelperEnv(params, mountRoot) {
|
|
32
|
+
return {
|
|
33
|
+
...process.env,
|
|
34
|
+
PRLL_API_URL: params.parallUrl,
|
|
35
|
+
PRLL_API_KEY: params.apiKey,
|
|
36
|
+
PRLL_ORG_ID: params.orgId,
|
|
37
|
+
PRLL_AGENT_ID: params.agentId,
|
|
38
|
+
PRLL_WIKI_MOUNT_ROOT: mountRoot,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function runWikiSync(params, env) {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
let timedOut = false;
|
|
44
|
+
let settled = false;
|
|
45
|
+
const { cmd, prefix } = resolveParallCli();
|
|
46
|
+
const child = spawn(cmd, [...prefix, "wiki", "sync"], {
|
|
47
|
+
env,
|
|
48
|
+
stdio: "ignore",
|
|
49
|
+
});
|
|
50
|
+
const settle = (value) => {
|
|
51
|
+
if (settled)
|
|
52
|
+
return;
|
|
53
|
+
settled = true;
|
|
54
|
+
resolve(value);
|
|
55
|
+
};
|
|
56
|
+
const timer = setTimeout(() => {
|
|
57
|
+
timedOut = true;
|
|
58
|
+
params.log?.warn?.(`parall[${params.accountId}]: parall sync timed out after ${DEFAULT_SYNC_TIMEOUT_MS}ms`);
|
|
59
|
+
child.kill("SIGTERM");
|
|
60
|
+
setTimeout(() => child.kill("SIGKILL"), 5_000).unref();
|
|
61
|
+
}, DEFAULT_SYNC_TIMEOUT_MS);
|
|
62
|
+
timer.unref();
|
|
63
|
+
child.on("error", (error) => {
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
if (isCommandMissing(error)) {
|
|
66
|
+
params.log?.warn?.(`parall[${params.accountId}]: parall not installed, skipping wiki auto-sync/watch`);
|
|
67
|
+
settle("missing");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
params.log?.warn?.(`parall[${params.accountId}]: parall sync failed to start: ${String(error)}`);
|
|
71
|
+
settle("failed");
|
|
72
|
+
});
|
|
73
|
+
child.on("exit", (code, signal) => {
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
if (timedOut) {
|
|
76
|
+
settle("failed");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (code === 0) {
|
|
80
|
+
params.log?.info?.(`parall[${params.accountId}]: parall sync completed`);
|
|
81
|
+
settle("ok");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
params.log?.warn?.(`parall[${params.accountId}]: parall sync exited with code=${code ?? "null"} signal=${signal ?? "null"}`);
|
|
85
|
+
settle("failed");
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
export async function startWikiHelper(params) {
|
|
90
|
+
const mountRoot = resolveMountRoot(params.stateDir);
|
|
91
|
+
const env = buildWikiHelperEnv(params, mountRoot);
|
|
92
|
+
const syncResult = await runWikiSync(params, env);
|
|
93
|
+
if (syncResult === "missing") {
|
|
94
|
+
return {
|
|
95
|
+
mountRoot,
|
|
96
|
+
stop() { },
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const intervalSec = resolveWatchIntervalSec();
|
|
100
|
+
let stopped = false;
|
|
101
|
+
const { cmd, prefix } = resolveParallCli();
|
|
102
|
+
const watch = spawn(cmd, [...prefix, "wiki", "watch", "--interval-sec", String(intervalSec)], {
|
|
103
|
+
env,
|
|
104
|
+
stdio: "ignore",
|
|
105
|
+
});
|
|
106
|
+
watch.on("error", (error) => {
|
|
107
|
+
if (stopped)
|
|
108
|
+
return;
|
|
109
|
+
if (isCommandMissing(error)) {
|
|
110
|
+
params.log?.warn?.(`parall[${params.accountId}]: parall disappeared before watch could start`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
params.log?.warn?.(`parall[${params.accountId}]: parall watch failed: ${String(error)}`);
|
|
114
|
+
});
|
|
115
|
+
watch.on("exit", (code, signal) => {
|
|
116
|
+
if (stopped)
|
|
117
|
+
return;
|
|
118
|
+
params.log?.warn?.(`parall[${params.accountId}]: parall watch exited with code=${code ?? "null"} signal=${signal ?? "null"}`);
|
|
119
|
+
});
|
|
120
|
+
params.log?.info?.(`parall[${params.accountId}]: parall watch started (interval=${intervalSec}s)`);
|
|
121
|
+
return {
|
|
122
|
+
mountRoot,
|
|
123
|
+
stop() {
|
|
124
|
+
stopped = true;
|
|
125
|
+
if (watch.exitCode === null && watch.signalCode === null) {
|
|
126
|
+
watch.kill("SIGTERM");
|
|
127
|
+
setTimeout(() => watch.kill("SIGKILL"), 5_000).unref();
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "parall",
|
|
3
3
|
"channels": ["parall"],
|
|
4
|
+
"channelConfigs": {
|
|
5
|
+
"parall": {
|
|
6
|
+
"label": "Parall",
|
|
7
|
+
"description": "Agent-Native IM platform.",
|
|
8
|
+
"schema": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"additionalProperties": true,
|
|
11
|
+
"properties": {
|
|
12
|
+
"parall_url": { "type": "string", "description": "Parall API base URL" },
|
|
13
|
+
"api_key": { "type": "string", "description": "Agent API key (agk_xxx)" },
|
|
14
|
+
"org_id": { "type": "string", "description": "Organisation ID" },
|
|
15
|
+
"ws_url": { "type": "string", "description": "WebSocket URL (optional, derived from parall_url)" }
|
|
16
|
+
},
|
|
17
|
+
"required": ["parall_url", "api_key", "org_id"]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
4
21
|
"skills": [
|
|
5
22
|
"./skills/parall-wiki",
|
|
6
23
|
"./skills/parall-tasks",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/parall",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.2",
|
|
4
4
|
"description": "OpenClaw channel plugin for Parall IM",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -11,28 +11,29 @@
|
|
|
11
11
|
"type": "module",
|
|
12
12
|
"files": [
|
|
13
13
|
"src",
|
|
14
|
+
"dist",
|
|
14
15
|
"skills",
|
|
15
16
|
"openclaw.plugin.json"
|
|
16
17
|
],
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"@parall/
|
|
19
|
-
"@parall/
|
|
19
|
+
"@parall/sdk": "1.26.2",
|
|
20
|
+
"@parall/agent-core": "1.26.2"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@types/node": "^22.0.0",
|
|
23
|
-
"openclaw": "2026.
|
|
24
|
+
"openclaw": "2026.5.7",
|
|
24
25
|
"typescript": "^5.7.0"
|
|
25
26
|
},
|
|
26
27
|
"peerDependencies": {
|
|
27
28
|
"@mariozechner/pi-coding-agent": "*",
|
|
28
|
-
"openclaw": ">=2026.
|
|
29
|
+
"openclaw": ">=2026.5.7"
|
|
29
30
|
},
|
|
30
31
|
"openclaw": {
|
|
31
32
|
"extensions": [
|
|
32
33
|
"./src/index.ts"
|
|
33
34
|
],
|
|
34
35
|
"install": {
|
|
35
|
-
"minHostVersion": ">=2026.
|
|
36
|
+
"minHostVersion": ">=2026.5.7"
|
|
36
37
|
}
|
|
37
38
|
},
|
|
38
39
|
"scripts": {
|
package/src/config-manager.ts
CHANGED
|
@@ -73,6 +73,21 @@ function applyToOpenClawConfig(
|
|
|
73
73
|
const platformProviders = (platformModels.providers ?? {}) as Record<string, unknown>;
|
|
74
74
|
const platformParall = (platformProviders.parall ?? {}) as Record<string, unknown>;
|
|
75
75
|
|
|
76
|
+
// Only forward keys OpenClaw's model schema recognizes — its strict Zod
|
|
77
|
+
// validation rejects unrecognized keys and skips the entire config reload.
|
|
78
|
+
const OPENCLAW_MODEL_KEYS = new Set(["id", "name", "contextWindow", "maxTokens"]);
|
|
79
|
+
if (Array.isArray(platformParall.models)) {
|
|
80
|
+
platformParall.models = (platformParall.models as Record<string, unknown>[]).map((m) => {
|
|
81
|
+
const cleaned: Record<string, unknown> = {};
|
|
82
|
+
for (const [k, v] of Object.entries(m)) {
|
|
83
|
+
if (OPENCLAW_MODEL_KEYS.has(k)) {
|
|
84
|
+
cleaned[k] = v;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return cleaned;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
76
91
|
providers.parall = {
|
|
77
92
|
...existingParall,
|
|
78
93
|
...platformParall,
|
|
@@ -84,7 +99,7 @@ function applyToOpenClawConfig(
|
|
|
84
99
|
// Strip keys OpenClaw doesn't recognize from agents.defaults — platform-only
|
|
85
100
|
// keys like thinking_effort are consumed by agent-core's PlatformConfigManager.
|
|
86
101
|
// See: OpenClaw agents.defaults config schema.
|
|
87
|
-
const OPENCLAW_AGENTS_DEFAULTS_KEYS = new Set(["model", "
|
|
102
|
+
const OPENCLAW_AGENTS_DEFAULTS_KEYS = new Set(["model", "compaction"]);
|
|
88
103
|
|
|
89
104
|
// Unconditionally sanitize existing defaults to self-heal already-poisoned
|
|
90
105
|
// openclaw.json files (e.g. mode=self agents that were poisoned while in
|
package/src/fork.ts
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
//
|
|
3
3
|
// When the orchestrator's main session is busy, new events are handled by
|
|
4
4
|
// forking the main session's transcript and dispatching to the fork in parallel.
|
|
5
|
-
// The
|
|
6
|
-
//
|
|
7
|
-
//
|
|
5
|
+
// The caller provides a pre-dispatch branch point so the fork inherits
|
|
6
|
+
// history up to (but not including) the in-flight dispatch. Without a
|
|
7
|
+
// branch point, the fork falls back to the current on-disk leaf — which
|
|
8
|
+
// may include partial in-flight state.
|
|
8
9
|
|
|
9
10
|
import * as fs from "node:fs";
|
|
10
11
|
import * as path from "node:path";
|
|
@@ -102,6 +103,7 @@ export function forkOrchestratorSession(opts: {
|
|
|
102
103
|
accountId: string;
|
|
103
104
|
transcriptFile: string;
|
|
104
105
|
sessionsDir: string;
|
|
106
|
+
branchPointId?: string;
|
|
105
107
|
}): ForkSessionResult | null {
|
|
106
108
|
const { orchestratorSessionKey, accountId, transcriptFile, sessionsDir } = opts;
|
|
107
109
|
|
|
@@ -109,7 +111,7 @@ export function forkOrchestratorSession(opts: {
|
|
|
109
111
|
|
|
110
112
|
try {
|
|
111
113
|
const manager = SessionManager.open(transcriptFile);
|
|
112
|
-
const leafId = manager.getLeafId();
|
|
114
|
+
const leafId = opts.branchPointId ?? manager.getLeafId();
|
|
113
115
|
|
|
114
116
|
let sessionId: string;
|
|
115
117
|
let sessionFile: string;
|
package/src/gateway.ts
CHANGED
|
@@ -27,6 +27,7 @@ import { buildOrchestratorSessionKey } from "./session.js";
|
|
|
27
27
|
import type { ResolvedParallAccount } from "./types.js";
|
|
28
28
|
import { fetchAndApplyPlatformConfig } from "./config-manager.js";
|
|
29
29
|
import { startWikiHelper } from "./wiki-helper.js";
|
|
30
|
+
import { SessionManager } from "@mariozechner/pi-coding-agent";
|
|
30
31
|
import { cleanupForkSession, forkOrchestratorSession, resolveTranscriptFile } from "./fork.js";
|
|
31
32
|
|
|
32
33
|
function resolveWsUrl(account: ResolvedParallAccount): string {
|
|
@@ -210,7 +211,18 @@ function createOpenClawDispatchAdapter(opts: {
|
|
|
210
211
|
yield* stream.stream();
|
|
211
212
|
},
|
|
212
213
|
|
|
213
|
-
|
|
214
|
+
getBranchPoint(sessionKey: string): string | undefined {
|
|
215
|
+
const transcriptFile = resolveTranscriptFile(opts.sessionsDir, sessionKey);
|
|
216
|
+
if (!transcriptFile) return undefined;
|
|
217
|
+
try {
|
|
218
|
+
const manager = SessionManager.open(transcriptFile);
|
|
219
|
+
return manager.getLeafId() ?? undefined;
|
|
220
|
+
} catch {
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
forkSession({ sessionKey, preDispatchBranchPoint }) {
|
|
214
226
|
const transcriptFile = resolveTranscriptFile(opts.sessionsDir, sessionKey);
|
|
215
227
|
if (!transcriptFile) return null;
|
|
216
228
|
return forkOrchestratorSession({
|
|
@@ -218,6 +230,7 @@ function createOpenClawDispatchAdapter(opts: {
|
|
|
218
230
|
accountId: opts.accountId,
|
|
219
231
|
transcriptFile,
|
|
220
232
|
sessionsDir: opts.sessionsDir,
|
|
233
|
+
branchPointId: preDispatchBranchPoint,
|
|
221
234
|
});
|
|
222
235
|
},
|
|
223
236
|
|