@zeulewan/glueclaw-provider 1.3.0 → 1.5.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/README.md +13 -1
- package/index.ts +23 -2
- package/install.sh +13 -66
- package/package.json +1 -1
- package/src/stream.ts +115 -13
package/README.md
CHANGED
|
@@ -50,11 +50,23 @@ The only way this breaks is if Anthropic changes how `--system-prompt` or `--out
|
|
|
50
50
|
|
|
51
51
|
Switch in TUI: `/model glueclaw/glueclaw-opus`
|
|
52
52
|
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
| Env var | Default | Description |
|
|
56
|
+
| ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
57
|
+
| `GLUECLAW_REQUEST_TIMEOUT_MS` | `120000` | Maximum time (in milliseconds) to wait for the Claude CLI subprocess to complete a single request before it is terminated. Increase if long-running tool calls or extensive reasoning trip the default 120s limit. Invalid or non-positive values fall back to the default. |
|
|
58
|
+
|
|
59
|
+
Example (10 minute timeout):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
export GLUECLAW_REQUEST_TIMEOUT_MS=600000
|
|
63
|
+
```
|
|
64
|
+
|
|
53
65
|
## Notes
|
|
54
66
|
|
|
55
67
|
- Tested with Telegram and OpenClaw TUI
|
|
56
68
|
- Switching between GlueClaw and other backends (e.g. Codex) works seamlessly via `/model`
|
|
57
|
-
- The installer
|
|
69
|
+
- The installer does not patch OpenClaw's dist. GlueClaw starts the MCP loopback in-process when available.
|
|
58
70
|
|
|
59
71
|
## Disclaimer
|
|
60
72
|
|
package/index.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
1
2
|
import {
|
|
2
3
|
definePluginEntry,
|
|
3
4
|
type OpenClawPluginApi,
|
|
4
5
|
} from "openclaw/plugin-sdk/plugin-entry";
|
|
5
6
|
import { createClaudeCliStreamFn } from "./src/stream.js";
|
|
6
7
|
import { MODEL_CATALOG } from "./src/catalog.js";
|
|
8
|
+
import { resolveSessionKey } from "./src/session-key.js";
|
|
7
9
|
|
|
8
10
|
const PROVIDER_ID = "glueclaw";
|
|
9
11
|
const PROVIDER_LABEL = "GlueClaw";
|
|
@@ -18,6 +20,17 @@ const MODEL_MAP: Readonly<Record<string, string>> = {
|
|
|
18
20
|
"glueclaw-haiku": "claude-haiku-4-5",
|
|
19
21
|
};
|
|
20
22
|
|
|
23
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 120_000;
|
|
24
|
+
|
|
25
|
+
function resolveRequestTimeoutMs(): number {
|
|
26
|
+
const raw = process.env.GLUECLAW_REQUEST_TIMEOUT_MS;
|
|
27
|
+
if (raw === undefined || raw === "") return DEFAULT_REQUEST_TIMEOUT_MS;
|
|
28
|
+
const parsed = Number(raw);
|
|
29
|
+
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
30
|
+
return DEFAULT_REQUEST_TIMEOUT_MS;
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
33
|
+
|
|
21
34
|
export default definePluginEntry({
|
|
22
35
|
register(api: OpenClawPluginApi): void {
|
|
23
36
|
const authProfile = () =>
|
|
@@ -69,11 +82,19 @@ export default definePluginEntry({
|
|
|
69
82
|
},
|
|
70
83
|
}),
|
|
71
84
|
},
|
|
72
|
-
createStreamFn: (ctx: {
|
|
85
|
+
createStreamFn: (ctx: {
|
|
86
|
+
modelId: string;
|
|
87
|
+
agentDir?: string;
|
|
88
|
+
sessionId?: string;
|
|
89
|
+
sessionKey?: string;
|
|
90
|
+
}) => {
|
|
73
91
|
const realModel = MODEL_MAP[ctx.modelId] ?? ctx.modelId;
|
|
92
|
+
const agentId = ctx.agentDir ? basename(ctx.agentDir) : undefined;
|
|
74
93
|
return createClaudeCliStreamFn({
|
|
75
|
-
sessionKey: ctx
|
|
94
|
+
sessionKey: resolveSessionKey(ctx),
|
|
95
|
+
agentId,
|
|
76
96
|
modelOverride: realModel,
|
|
97
|
+
requestTimeoutMs: resolveRequestTimeoutMs(),
|
|
77
98
|
});
|
|
78
99
|
},
|
|
79
100
|
resolveSyntheticAuth: () => ({
|
package/install.sh
CHANGED
|
@@ -29,14 +29,6 @@ oc_config() {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
sedi() {
|
|
33
|
-
if [[ "$(uname)" == "Darwin" ]]; then
|
|
34
|
-
sed -i '' "$@"
|
|
35
|
-
else
|
|
36
|
-
sed -i "$@"
|
|
37
|
-
fi
|
|
38
|
-
}
|
|
39
|
-
|
|
40
32
|
require_cmd() {
|
|
41
33
|
command -v "$1" >/dev/null 2>&1 || die "$1 not found. $2"
|
|
42
34
|
}
|
|
@@ -121,14 +113,6 @@ else
|
|
|
121
113
|
fi
|
|
122
114
|
echo ""
|
|
123
115
|
|
|
124
|
-
# Find OpenClaw dist
|
|
125
|
-
OPENCLAW_BIN="$(command -v openclaw)"
|
|
126
|
-
OPENCLAW_ROOT="$(dirname "$OPENCLAW_BIN")/../lib/node_modules/openclaw"
|
|
127
|
-
# Suppress not-found: fallback path may not exist
|
|
128
|
-
[ ! -d "$OPENCLAW_ROOT/dist" ] && OPENCLAW_ROOT="$(npm root -g 2>/dev/null)/openclaw"
|
|
129
|
-
[ ! -d "$OPENCLAW_ROOT/dist" ] && die "Cannot find OpenClaw dist"
|
|
130
|
-
OPENCLAW_DIST="$OPENCLAW_ROOT/dist"
|
|
131
|
-
|
|
132
116
|
# Detect shell config
|
|
133
117
|
if [ -f "${HOME}/.zshrc" ]; then
|
|
134
118
|
SHELL_RC="${HOME}/.zshrc"
|
|
@@ -142,17 +126,7 @@ fi
|
|
|
142
126
|
|
|
143
127
|
GW_PID=""
|
|
144
128
|
GW_LOG=""
|
|
145
|
-
BACKUP_FILE=""
|
|
146
129
|
cleanup() {
|
|
147
|
-
# Restore MCP patch backup if script failed mid-patch
|
|
148
|
-
if [ -n "$BACKUP_FILE" ] && [ -f "$BACKUP_FILE" ]; then
|
|
149
|
-
if [ -w "$(dirname "$BACKUP_FILE")" ]; then
|
|
150
|
-
mv "$BACKUP_FILE" "${BACKUP_FILE%.glueclaw-bak}" 2>/dev/null || true
|
|
151
|
-
else
|
|
152
|
-
sudo mv "$BACKUP_FILE" "${BACKUP_FILE%.glueclaw-bak}" 2>/dev/null || true
|
|
153
|
-
fi
|
|
154
|
-
echo " Restored backup: $(basename "$BACKUP_FILE")" >&2
|
|
155
|
-
fi
|
|
156
130
|
if [ -n "$GW_PID" ] && kill -0 "$GW_PID" 2>/dev/null; then
|
|
157
131
|
kill "$GW_PID" 2>/dev/null || true
|
|
158
132
|
fi
|
|
@@ -162,19 +136,19 @@ trap cleanup INT TERM
|
|
|
162
136
|
|
|
163
137
|
# --- 1. Dependencies ---
|
|
164
138
|
|
|
165
|
-
echo "[1/
|
|
139
|
+
echo "[1/6] Installing dependencies..."
|
|
166
140
|
cd "$PLUGIN_DIR"
|
|
167
141
|
npm install --silent || die "npm install failed"
|
|
168
142
|
|
|
169
143
|
# --- 2. Environment ---
|
|
170
144
|
|
|
171
|
-
echo "[2/
|
|
145
|
+
echo "[2/6] Setting up environment..."
|
|
172
146
|
ensure_line "$SHELL_RC" "GLUECLAW_KEY" "export GLUECLAW_KEY=local"
|
|
173
147
|
export GLUECLAW_KEY=local
|
|
174
148
|
|
|
175
149
|
# --- 3. Plugin registration ---
|
|
176
150
|
|
|
177
|
-
echo "[3/
|
|
151
|
+
echo "[3/6] Registering plugin..."
|
|
178
152
|
# GlueClaw is on OpenClaw's official safe plugin list. Try standard install first,
|
|
179
153
|
# fall back to --dangerously-force-unsafe-install for older OpenClaw versions,
|
|
180
154
|
# then manual config as last resort.
|
|
@@ -188,7 +162,7 @@ fi
|
|
|
188
162
|
|
|
189
163
|
# --- 4. Model config ---
|
|
190
164
|
|
|
191
|
-
echo "[4/
|
|
165
|
+
echo "[4/6] Configuring models..."
|
|
192
166
|
# These two are fatal — without them, nothing works
|
|
193
167
|
oc_config models.providers.glueclaw \
|
|
194
168
|
'{"baseUrl":"local://glueclaw","models":[{"id":"glueclaw-opus","name":"GlueClaw Opus","contextWindow":1000000},{"id":"glueclaw-sonnet","name":"GlueClaw Sonnet","contextWindow":1000000},{"id":"glueclaw-haiku","name":"GlueClaw Haiku","contextWindow":200000}]}' \
|
|
@@ -211,47 +185,20 @@ oc_config gateway.tools.allow \
|
|
|
211
185
|
|
|
212
186
|
# --- 5. Auth profile ---
|
|
213
187
|
|
|
214
|
-
echo "[5/
|
|
188
|
+
echo "[5/6] Setting up auth..."
|
|
215
189
|
AGENT_DIR="${HOME}/.openclaw/agents/main/agent"
|
|
216
190
|
mkdir -p "$AGENT_DIR" || die "Cannot create $AGENT_DIR"
|
|
217
191
|
AUTH_FILE="$AGENT_DIR/auth-profiles.json"
|
|
218
192
|
write_auth_profile "$AUTH_FILE"
|
|
219
193
|
|
|
220
|
-
# --- 6.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
# Use sudo for file operations if dist directory is not writable (global npm install)
|
|
227
|
-
ELEVATE=""
|
|
228
|
-
if [ ! -w "$OPENCLAW_DIST" ]; then
|
|
229
|
-
echo " OpenClaw dist is root-owned, using sudo for patch..."
|
|
230
|
-
ELEVATE="sudo"
|
|
231
|
-
fi
|
|
232
|
-
|
|
233
|
-
if ! grep -q "__GLUECLAW_MCP" "$SERVER_FILE"; then
|
|
234
|
-
$ELEVATE cp "$SERVER_FILE" "${SERVER_FILE}.glueclaw-bak" || die "Cannot backup $SERVER_FILE"
|
|
235
|
-
BACKUP_FILE="${SERVER_FILE}.glueclaw-bak"
|
|
236
|
-
# shellcheck disable=SC2016
|
|
237
|
-
if [ -n "$ELEVATE" ]; then
|
|
238
|
-
$ELEVATE sed -i 's/logDebug(`mcp loopback listening/process.env.__GLUECLAW_MCP_PORT = String(address.port); process.env.__GLUECLAW_MCP_TOKEN = token; logDebug(`mcp loopback listening/' "$SERVER_FILE" ||
|
|
239
|
-
die "Failed to patch $SERVER_FILE"
|
|
240
|
-
else
|
|
241
|
-
sedi 's/logDebug(`mcp loopback listening/process.env.__GLUECLAW_MCP_PORT = String(address.port); process.env.__GLUECLAW_MCP_TOKEN = token; logDebug(`mcp loopback listening/' "$SERVER_FILE" ||
|
|
242
|
-
die "Failed to patch $SERVER_FILE"
|
|
243
|
-
fi
|
|
244
|
-
# Validate the patch actually applied
|
|
245
|
-
grep -q "__GLUECLAW_MCP_PORT" "$SERVER_FILE" || die "MCP patch did not apply — sed replacement failed"
|
|
246
|
-
BACKUP_FILE="" # Patch succeeded, don't restore on cleanup
|
|
247
|
-
echo " Patched $(basename "$SERVER_FILE")"
|
|
248
|
-
else
|
|
249
|
-
echo " Already patched"
|
|
250
|
-
fi
|
|
251
|
-
|
|
252
|
-
# --- 7. Restart gateway ---
|
|
194
|
+
# --- 6. Restart gateway ---
|
|
195
|
+
# Note: GlueClaw bootstraps OpenClaw's MCP loopback in-process from
|
|
196
|
+
# src/stream.ts (see docs/RFC-001-sessions-send-native.md). No dist patching
|
|
197
|
+
# is needed — GlueClaw shares OpenClaw's module cache as an in-process
|
|
198
|
+
# provider, so calling ensureMcpLoopbackServer() and getActiveMcpLoopbackRuntime()
|
|
199
|
+
# directly is sufficient.
|
|
253
200
|
|
|
254
|
-
echo "[
|
|
201
|
+
echo "[6/6] Starting gateway..."
|
|
255
202
|
# Stop any existing gateway first
|
|
256
203
|
pkill -f "openclaw.*gateway" 2>/dev/null || true
|
|
257
204
|
openclaw gateway stop 2>/dev/null || true
|
|
@@ -312,4 +259,4 @@ echo " Default: glueclaw/glueclaw-sonnet"
|
|
|
312
259
|
echo ""
|
|
313
260
|
echo " Run: openclaw tui"
|
|
314
261
|
echo ""
|
|
315
|
-
echo " Re-run after OpenClaw updates to
|
|
262
|
+
echo " Re-run after OpenClaw updates to refresh plugin registration."
|
package/package.json
CHANGED
package/src/stream.ts
CHANGED
|
@@ -7,12 +7,14 @@ import {
|
|
|
7
7
|
rmSync,
|
|
8
8
|
renameSync,
|
|
9
9
|
} from "node:fs";
|
|
10
|
-
import { join } from "node:path";
|
|
10
|
+
import { basename, delimiter, dirname, join, normalize } from "node:path";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
import { randomBytes } from "node:crypto";
|
|
13
|
+
import { pathToFileURL } from "node:url";
|
|
13
14
|
import { createAssistantMessageEventStream } from "@mariozechner/pi-ai";
|
|
14
15
|
import type { StreamFn } from "@mariozechner/pi-agent-core";
|
|
15
16
|
import type { AssistantMessage, Usage, TextContent } from "@mariozechner/pi-ai";
|
|
17
|
+
import { deriveTurnSessionKey } from "./session-key.js";
|
|
16
18
|
|
|
17
19
|
const PROCESS_TIMEOUT_MS = 5000;
|
|
18
20
|
const REQUEST_TIMEOUT_MS = 120_000;
|
|
@@ -91,12 +93,99 @@ export function buildMsg(
|
|
|
91
93
|
};
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
interface McpLoopbackRuntime {
|
|
97
|
+
port: number;
|
|
98
|
+
ownerToken: string;
|
|
99
|
+
nonOwnerToken?: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let _mcpLoopback: { port: number; token: string } | undefined;
|
|
103
|
+
let _mcpBootstrapAttempted = false;
|
|
104
|
+
|
|
105
|
+
function getEnvMcpLoopback(): { port: number; token: string } | undefined {
|
|
106
|
+
const portRaw = process.env.__GLUECLAW_MCP_PORT;
|
|
98
107
|
const token = process.env.__GLUECLAW_MCP_TOKEN;
|
|
99
|
-
if (
|
|
108
|
+
if (!portRaw || !token) return undefined;
|
|
109
|
+
|
|
110
|
+
const port = Number.parseInt(portRaw, 10);
|
|
111
|
+
if (!Number.isFinite(port) || port <= 0) return undefined;
|
|
112
|
+
return { port, token };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function openClawDistFromNodePath(nodePath: string): string | undefined {
|
|
116
|
+
const normalized = normalize(nodePath);
|
|
117
|
+
if (!normalized.includes("openclaw")) return undefined;
|
|
118
|
+
if (basename(normalized) !== "node_modules") return undefined;
|
|
119
|
+
return join(dirname(normalized), "dist");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function resetMcpLoopbackForTests(): void {
|
|
123
|
+
_mcpLoopback = undefined;
|
|
124
|
+
_mcpBootstrapAttempted = false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Bootstrap OpenClaw's MCP loopback server in-process and return the
|
|
128
|
+
* port + owner token. GlueClaw runs inside the gateway process, so we
|
|
129
|
+
* share OpenClaw's module cache: importing the same `mcp-http-*.js`
|
|
130
|
+
* the gateway loaded gives us the singleton, and a no-op when another
|
|
131
|
+
* caller already started it.
|
|
132
|
+
*
|
|
133
|
+
* Returns undefined if the OpenClaw dist cannot be located or its API
|
|
134
|
+
* has changed — in that case the claude subprocess simply runs without
|
|
135
|
+
* session tools, matching pre-RFC-001 behavior. */
|
|
136
|
+
export async function getMcpLoopback(): Promise<
|
|
137
|
+
{ port: number; token: string } | undefined
|
|
138
|
+
> {
|
|
139
|
+
const envLoopback = getEnvMcpLoopback();
|
|
140
|
+
if (envLoopback) return envLoopback;
|
|
141
|
+
|
|
142
|
+
if (_mcpLoopback) return _mcpLoopback;
|
|
143
|
+
if (_mcpBootstrapAttempted) return undefined;
|
|
144
|
+
_mcpBootstrapAttempted = true;
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
const { readdir } = await import("node:fs/promises");
|
|
148
|
+
const nodePaths = (process.env.NODE_PATH ?? "").split(delimiter);
|
|
149
|
+
const distDirs = nodePaths
|
|
150
|
+
.map(openClawDistFromNodePath)
|
|
151
|
+
.filter((p): p is string => Boolean(p));
|
|
152
|
+
|
|
153
|
+
for (const distDir of distDirs) {
|
|
154
|
+
try {
|
|
155
|
+
const files = await readdir(distDir);
|
|
156
|
+
const mcpFile = files.find(
|
|
157
|
+
(f) => f.startsWith("mcp-http-") && f.endsWith(".js"),
|
|
158
|
+
);
|
|
159
|
+
if (!mcpFile) continue;
|
|
160
|
+
const mod = (await import(
|
|
161
|
+
pathToFileURL(join(distDir, mcpFile)).href
|
|
162
|
+
)) as Record<string, unknown>;
|
|
163
|
+
// Minified aliases: n=ensureMcpLoopbackServer, i=getActiveMcpLoopbackRuntime
|
|
164
|
+
const ensureFn = (mod["n"] ?? mod["ensureMcpLoopbackServer"]) as
|
|
165
|
+
| (() => Promise<unknown>)
|
|
166
|
+
| undefined;
|
|
167
|
+
const getRuntime = (mod["i"] ?? mod["getActiveMcpLoopbackRuntime"]) as
|
|
168
|
+
| (() => McpLoopbackRuntime | undefined)
|
|
169
|
+
| undefined;
|
|
170
|
+
if (
|
|
171
|
+
typeof ensureFn !== "function" ||
|
|
172
|
+
typeof getRuntime !== "function"
|
|
173
|
+
) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
await ensureFn();
|
|
177
|
+
const runtime = getRuntime();
|
|
178
|
+
if (runtime?.port && runtime.ownerToken) {
|
|
179
|
+
_mcpLoopback = { port: runtime.port, token: runtime.ownerToken };
|
|
180
|
+
return _mcpLoopback;
|
|
181
|
+
}
|
|
182
|
+
} catch {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} catch {
|
|
187
|
+
// Non-fatal: session tools simply won't be available
|
|
188
|
+
}
|
|
100
189
|
return undefined;
|
|
101
190
|
}
|
|
102
191
|
|
|
@@ -170,6 +259,7 @@ function evictSessions(): void {
|
|
|
170
259
|
export function createClaudeCliStreamFn(opts: {
|
|
171
260
|
claudeBin?: string;
|
|
172
261
|
sessionKey?: string;
|
|
262
|
+
agentId?: string;
|
|
173
263
|
modelOverride?: string;
|
|
174
264
|
requestTimeoutMs?: number;
|
|
175
265
|
}): StreamFn {
|
|
@@ -183,6 +273,15 @@ export function createClaudeCliStreamFn(opts: {
|
|
|
183
273
|
let mcpCleanup: (() => void) | undefined;
|
|
184
274
|
let stderrBuf = "";
|
|
185
275
|
try {
|
|
276
|
+
const turnSessionKey = deriveTurnSessionKey({
|
|
277
|
+
agentId: opts.agentId,
|
|
278
|
+
systemPrompt: context.systemPrompt,
|
|
279
|
+
messages: context.messages as
|
|
280
|
+
| Array<{ role: string; content: unknown }>
|
|
281
|
+
| undefined,
|
|
282
|
+
});
|
|
283
|
+
const effectiveSessionKey =
|
|
284
|
+
turnSessionKey ?? opts.sessionKey ?? "default";
|
|
186
285
|
// Scrub Anthropic detection triggers (see docs/detection-patterns.md)
|
|
187
286
|
const cleanPrompt = scrubPrompt(context.systemPrompt ?? "");
|
|
188
287
|
const resolvedModel = opts.modelOverride ?? model.id;
|
|
@@ -194,14 +293,17 @@ export function createClaudeCliStreamFn(opts: {
|
|
|
194
293
|
"--verbose",
|
|
195
294
|
"--include-partial-messages",
|
|
196
295
|
];
|
|
197
|
-
// Resume session for multi-turn conversation memory
|
|
198
|
-
|
|
296
|
+
// Resume session for multi-turn conversation memory.
|
|
297
|
+
// Always re-inject the system prompt — on resumptions the CLI would
|
|
298
|
+
// otherwise stick to whatever identity was used on the first turn,
|
|
299
|
+
// leaving no way for callers to reinforce or correct an agent's
|
|
300
|
+
// identity across turns.
|
|
301
|
+
const sessionKey = `glueclaw:${effectiveSessionKey}`;
|
|
199
302
|
const existingSessionId = sessionMap.get(sessionKey);
|
|
200
303
|
if (existingSessionId) {
|
|
201
304
|
args.push("--resume", existingSessionId);
|
|
202
|
-
} else {
|
|
203
|
-
if (cleanPrompt) args.push("--system-prompt", cleanPrompt);
|
|
204
305
|
}
|
|
306
|
+
if (cleanPrompt) args.push("--system-prompt", cleanPrompt);
|
|
205
307
|
if (resolvedModel) args.push("--model", resolvedModel);
|
|
206
308
|
|
|
207
309
|
// Debug: log args for resume troubleshooting
|
|
@@ -226,14 +328,14 @@ export function createClaudeCliStreamFn(opts: {
|
|
|
226
328
|
delete env.ANTHROPIC_API_KEY_OLD;
|
|
227
329
|
|
|
228
330
|
// Wire up MCP bridge for OpenClaw gateway tools
|
|
229
|
-
const loopback = getMcpLoopback();
|
|
331
|
+
const loopback = await getMcpLoopback();
|
|
230
332
|
if (loopback) {
|
|
231
333
|
const mcp = writeMcpConfig(loopback.port);
|
|
232
334
|
mcpCleanup = mcp.cleanup;
|
|
233
335
|
args.push("--strict-mcp-config", "--mcp-config", mcp.path);
|
|
234
336
|
env.OPENCLAW_MCP_TOKEN = loopback.token;
|
|
235
|
-
env.OPENCLAW_MCP_SESSION_KEY =
|
|
236
|
-
env.OPENCLAW_MCP_AGENT_ID = "main";
|
|
337
|
+
env.OPENCLAW_MCP_SESSION_KEY = effectiveSessionKey;
|
|
338
|
+
env.OPENCLAW_MCP_AGENT_ID = opts.agentId ?? "main";
|
|
237
339
|
env.OPENCLAW_MCP_ACCOUNT_ID = "";
|
|
238
340
|
env.OPENCLAW_MCP_MESSAGE_CHANNEL = "";
|
|
239
341
|
}
|