pubblue 0.6.9 → 0.7.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/{chunk-JSX5KHV3.js → chunk-5LI2HLKX.js} +552 -72
- package/dist/index.js +70 -49
- package/dist/live-daemon-entry.js +181 -217
- package/dist/sdk-IV5ZYS3G.js +12299 -0
- package/package.json +4 -1
|
@@ -33,6 +33,59 @@ function toCliFailure(error) {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
// ../shared/protocol-runtime-core.ts
|
|
37
|
+
function readRecord(input) {
|
|
38
|
+
return input && typeof input === "object" && !Array.isArray(input) ? input : null;
|
|
39
|
+
}
|
|
40
|
+
function readString(input) {
|
|
41
|
+
return typeof input === "string" ? input : void 0;
|
|
42
|
+
}
|
|
43
|
+
function readNonEmptyString(input) {
|
|
44
|
+
return typeof input === "string" && input.trim().length > 0 ? input : void 0;
|
|
45
|
+
}
|
|
46
|
+
function readFiniteNumber(input) {
|
|
47
|
+
return typeof input === "number" && Number.isFinite(input) ? input : void 0;
|
|
48
|
+
}
|
|
49
|
+
function readBoolean(input) {
|
|
50
|
+
return typeof input === "boolean" ? input : void 0;
|
|
51
|
+
}
|
|
52
|
+
function readStringArray(input) {
|
|
53
|
+
if (!Array.isArray(input)) return void 0;
|
|
54
|
+
const values = input.filter((entry) => typeof entry === "string");
|
|
55
|
+
return values.length === input.length ? values : void 0;
|
|
56
|
+
}
|
|
57
|
+
function readStringRecord(input) {
|
|
58
|
+
const record = readRecord(input);
|
|
59
|
+
if (!record) return void 0;
|
|
60
|
+
const entries = Object.entries(record);
|
|
61
|
+
const values = entries.filter((entry) => typeof entry[1] === "string");
|
|
62
|
+
if (values.length !== entries.length) return void 0;
|
|
63
|
+
return Object.fromEntries(values);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ../shared/live-api-core.ts
|
|
67
|
+
function parseLiveInfo(input) {
|
|
68
|
+
if (input === null || input === void 0) return null;
|
|
69
|
+
const record = readRecord(input);
|
|
70
|
+
if (!record) return null;
|
|
71
|
+
const slug = readNonEmptyString(record.slug);
|
|
72
|
+
const browserCandidates = readStringArray(record.browserCandidates);
|
|
73
|
+
const agentCandidates = readStringArray(record.agentCandidates);
|
|
74
|
+
const createdAt = readFiniteNumber(record.createdAt);
|
|
75
|
+
if (!slug || !browserCandidates || !agentCandidates || createdAt === void 0) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
slug,
|
|
80
|
+
status: readString(record.status),
|
|
81
|
+
browserOffer: readString(record.browserOffer),
|
|
82
|
+
agentAnswer: readString(record.agentAnswer),
|
|
83
|
+
browserCandidates,
|
|
84
|
+
agentCandidates,
|
|
85
|
+
createdAt
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
36
89
|
// src/lib/api.ts
|
|
37
90
|
var PubApiError = class extends Error {
|
|
38
91
|
constructor(message, status, retryAfterSeconds) {
|
|
@@ -56,8 +109,8 @@ var PubApiClient = class {
|
|
|
56
109
|
getApiKey() {
|
|
57
110
|
return this.apiKey;
|
|
58
111
|
}
|
|
59
|
-
async request(
|
|
60
|
-
const url = new URL(
|
|
112
|
+
async request(path5, options = {}) {
|
|
113
|
+
const url = new URL(path5, this.baseUrl);
|
|
61
114
|
const res = await fetch(url, {
|
|
62
115
|
...options,
|
|
63
116
|
headers: {
|
|
@@ -163,15 +216,19 @@ var PubApiClient = class {
|
|
|
163
216
|
});
|
|
164
217
|
}
|
|
165
218
|
// -- Agent live management ------------------------------------------------
|
|
166
|
-
async
|
|
219
|
+
async getLive(daemonSessionId) {
|
|
167
220
|
const params = new URLSearchParams();
|
|
168
221
|
if (daemonSessionId) {
|
|
169
222
|
params.set("daemonSessionId", daemonSessionId);
|
|
170
223
|
}
|
|
171
224
|
const query = params.toString();
|
|
172
|
-
const
|
|
173
|
-
const data = await this.request(
|
|
174
|
-
|
|
225
|
+
const path5 = query ? `/api/v1/agent/live?${query}` : "/api/v1/agent/live";
|
|
226
|
+
const data = await this.request(path5);
|
|
227
|
+
const live = parseLiveInfo(data.live);
|
|
228
|
+
if (data.live !== null && data.live !== void 0 && live === null) {
|
|
229
|
+
throw new PubApiError("Invalid live snapshot response from server.", 502);
|
|
230
|
+
}
|
|
231
|
+
return live;
|
|
175
232
|
}
|
|
176
233
|
async signalAnswer(opts) {
|
|
177
234
|
await this.request("/api/v1/agent/live/signal", {
|
|
@@ -185,8 +242,8 @@ var PubApiClient = class {
|
|
|
185
242
|
params.set("daemonSessionId", daemonSessionId);
|
|
186
243
|
}
|
|
187
244
|
const query = params.toString();
|
|
188
|
-
const
|
|
189
|
-
await this.request(
|
|
245
|
+
const path5 = query ? `/api/v1/agent/live?${query}` : "/api/v1/agent/live";
|
|
246
|
+
await this.request(path5, { method: "DELETE" });
|
|
190
247
|
}
|
|
191
248
|
// -- Telegram bot token ---------------------------------------------------
|
|
192
249
|
async uploadBotToken(opts) {
|
|
@@ -198,20 +255,21 @@ var PubApiClient = class {
|
|
|
198
255
|
async deleteBotToken() {
|
|
199
256
|
await this.request("/api/v1/agent/telegram-bot", { method: "DELETE" });
|
|
200
257
|
}
|
|
201
|
-
// -- Per-slug live info ---------------------------------------------------
|
|
202
|
-
async getLive(slug) {
|
|
203
|
-
const data = await this.request(
|
|
204
|
-
`/api/v1/pubs/${encodeURIComponent(slug)}/live`
|
|
205
|
-
);
|
|
206
|
-
return data.live;
|
|
207
|
-
}
|
|
208
258
|
};
|
|
209
259
|
|
|
210
260
|
// ../shared/bridge-protocol-core.ts
|
|
261
|
+
var BRIDGE_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
262
|
+
"text",
|
|
263
|
+
"html",
|
|
264
|
+
"binary",
|
|
265
|
+
"stream-start",
|
|
266
|
+
"stream-data",
|
|
267
|
+
"stream-end",
|
|
268
|
+
"event"
|
|
269
|
+
]);
|
|
211
270
|
var CONTROL_CHANNEL = "_control";
|
|
212
271
|
var CHANNELS = {
|
|
213
272
|
CHAT: "chat",
|
|
214
|
-
CANVAS: "canvas",
|
|
215
273
|
RENDER_ERROR: "render-error",
|
|
216
274
|
AUDIO: "audio",
|
|
217
275
|
MEDIA: "media",
|
|
@@ -228,13 +286,51 @@ function generateMessageId() {
|
|
|
228
286
|
function encodeMessage(msg) {
|
|
229
287
|
return JSON.stringify(msg);
|
|
230
288
|
}
|
|
289
|
+
function parseBridgeMessageMeta(input) {
|
|
290
|
+
if (input === void 0) return void 0;
|
|
291
|
+
const record = readRecord(input);
|
|
292
|
+
if (!record) return null;
|
|
293
|
+
const meta = { ...record };
|
|
294
|
+
const knownStringKeys = ["mime", "filename", "title"];
|
|
295
|
+
for (const key of knownStringKeys) {
|
|
296
|
+
if (record[key] === void 0) continue;
|
|
297
|
+
const value = readString(record[key]);
|
|
298
|
+
if (value === void 0) return null;
|
|
299
|
+
meta[key] = value;
|
|
300
|
+
}
|
|
301
|
+
const knownNumberKeys = ["sampleRate", "width", "height", "size"];
|
|
302
|
+
for (const key of knownNumberKeys) {
|
|
303
|
+
if (record[key] === void 0) continue;
|
|
304
|
+
const value = readFiniteNumber(record[key]);
|
|
305
|
+
if (value === void 0) return null;
|
|
306
|
+
meta[key] = value;
|
|
307
|
+
}
|
|
308
|
+
return meta;
|
|
309
|
+
}
|
|
310
|
+
function parseBridgeMessage(input) {
|
|
311
|
+
const record = readRecord(input);
|
|
312
|
+
if (!record) return null;
|
|
313
|
+
const id = readNonEmptyString(record.id);
|
|
314
|
+
const type = readString(record.type);
|
|
315
|
+
if (!id || !type || !BRIDGE_MESSAGE_TYPES.has(type)) {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
const data = record.data === void 0 ? void 0 : readString(record.data);
|
|
319
|
+
if (record.data !== void 0 && data === void 0) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
const meta = parseBridgeMessageMeta(record.meta);
|
|
323
|
+
if (meta === null) return null;
|
|
324
|
+
return {
|
|
325
|
+
id,
|
|
326
|
+
type,
|
|
327
|
+
data,
|
|
328
|
+
meta
|
|
329
|
+
};
|
|
330
|
+
}
|
|
231
331
|
function decodeMessage(raw) {
|
|
232
332
|
try {
|
|
233
|
-
|
|
234
|
-
if (parsed && typeof parsed.id === "string" && typeof parsed.type === "string") {
|
|
235
|
-
return parsed;
|
|
236
|
-
}
|
|
237
|
-
return null;
|
|
333
|
+
return parseBridgeMessage(JSON.parse(raw));
|
|
238
334
|
} catch (_error) {
|
|
239
335
|
return null;
|
|
240
336
|
}
|
|
@@ -327,7 +423,6 @@ function buildSessionBriefing(slug, ctx, instructions) {
|
|
|
327
423
|
"## Pub Context"
|
|
328
424
|
];
|
|
329
425
|
if (ctx.title) lines.push(`- Title: ${ctx.title}`);
|
|
330
|
-
if (ctx.contentType) lines.push(`- Content type: ${ctx.contentType}`);
|
|
331
426
|
if (ctx.isPublic !== void 0)
|
|
332
427
|
lines.push(`- Visibility: ${ctx.isPublic ? "public" : "private"}`);
|
|
333
428
|
if (ctx.canvasContentFilePath) {
|
|
@@ -809,25 +904,269 @@ async function createClaudeCodeBridgeRunner(config, abortSignal) {
|
|
|
809
904
|
};
|
|
810
905
|
}
|
|
811
906
|
|
|
907
|
+
// src/lib/live-bridge-claude-sdk.ts
|
|
908
|
+
import * as fs2 from "fs";
|
|
909
|
+
import * as os2 from "os";
|
|
910
|
+
import * as path2 from "path";
|
|
911
|
+
async function tryImportSdk() {
|
|
912
|
+
try {
|
|
913
|
+
return await import("./sdk-IV5ZYS3G.js");
|
|
914
|
+
} catch {
|
|
915
|
+
return null;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
function isClaudeSdkAvailableInEnv(env) {
|
|
919
|
+
return isClaudeCodeAvailableInEnv(env);
|
|
920
|
+
}
|
|
921
|
+
async function isClaudeSdkImportable() {
|
|
922
|
+
return await tryImportSdk() !== null;
|
|
923
|
+
}
|
|
924
|
+
function buildSdkSessionOptions(env = process.env) {
|
|
925
|
+
const model = env.CLAUDE_CODE_MODEL?.trim() || "claude-sonnet-4-6";
|
|
926
|
+
const claudePath = resolveClaudeCodePath(env);
|
|
927
|
+
const allowedToolsRaw = env.CLAUDE_CODE_ALLOWED_TOOLS?.trim();
|
|
928
|
+
const allowedTools = allowedToolsRaw ? allowedToolsRaw.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
|
|
929
|
+
const sdkEnv = { ...env };
|
|
930
|
+
delete sdkEnv.CLAUDECODE;
|
|
931
|
+
return { model, claudePath, allowedTools, sdkEnv };
|
|
932
|
+
}
|
|
933
|
+
function buildAppendSystemPrompt(bridgeSystemPrompt, env = process.env) {
|
|
934
|
+
const userSystemPrompt = env.CLAUDE_CODE_APPEND_SYSTEM_PROMPT?.trim();
|
|
935
|
+
const effective = [bridgeSystemPrompt, userSystemPrompt].filter(Boolean).join("\n\n");
|
|
936
|
+
return effective.length > 0 ? effective : void 0;
|
|
937
|
+
}
|
|
938
|
+
async function runClaudeSdkBridgeStartupProbe(env = process.env) {
|
|
939
|
+
const { model, claudePath, allowedTools } = buildSdkSessionOptions(env);
|
|
940
|
+
const cwd = env.CLAUDE_CODE_CWD?.trim() || env.PUBBLUE_PROJECT_ROOT || void 0;
|
|
941
|
+
const sdk = await tryImportSdk();
|
|
942
|
+
if (!sdk) {
|
|
943
|
+
throw new Error(
|
|
944
|
+
"Claude Agent SDK (@anthropic-ai/claude-agent-sdk) is not importable. Install it and retry."
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
await runAgentWritePongProbe({
|
|
948
|
+
label: "Claude SDK",
|
|
949
|
+
baseEnv: env,
|
|
950
|
+
execute: async (probeEnv) => {
|
|
951
|
+
const probeEnvClean = { ...probeEnv };
|
|
952
|
+
delete probeEnvClean.CLAUDECODE;
|
|
953
|
+
const socketPath = probeEnv.PUBBLUE_AGENT_SOCKET ?? "";
|
|
954
|
+
const logPath = path2.join(os2.tmpdir(), "pubblue-sdk-probe.log");
|
|
955
|
+
const appendLog = (line) => {
|
|
956
|
+
try {
|
|
957
|
+
fs2.appendFileSync(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
958
|
+
`);
|
|
959
|
+
} catch (error) {
|
|
960
|
+
if (process.env.PUBBLUE_DEBUG === "1") {
|
|
961
|
+
console.warn(`Warning: failed to append SDK probe log: ${errorMessage(error)}`);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
};
|
|
965
|
+
appendLog(`probe start socket=${socketPath}`);
|
|
966
|
+
const prompt = [
|
|
967
|
+
"This is a startup connectivity probe.",
|
|
968
|
+
"Run this exact shell command now:",
|
|
969
|
+
`PUBBLUE_AGENT_SOCKET=${socketPath} pubblue write "pong"`,
|
|
970
|
+
"Do not explain. Just execute it."
|
|
971
|
+
].join("\n");
|
|
972
|
+
const q = sdk.query({
|
|
973
|
+
prompt,
|
|
974
|
+
options: {
|
|
975
|
+
model,
|
|
976
|
+
pathToClaudeCodeExecutable: claudePath,
|
|
977
|
+
env: probeEnvClean,
|
|
978
|
+
allowedTools,
|
|
979
|
+
cwd: os2.tmpdir(),
|
|
980
|
+
maxTurns: 2,
|
|
981
|
+
persistSession: false,
|
|
982
|
+
canUseTool: async (toolName, input) => {
|
|
983
|
+
appendLog(`canUseTool: tool=${toolName}`);
|
|
984
|
+
return { behavior: "allow", updatedInput: input };
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
});
|
|
988
|
+
for await (const msg of q) {
|
|
989
|
+
appendLog(`msg: type=${msg.type} ${JSON.stringify(msg).slice(0, 300)}`);
|
|
990
|
+
}
|
|
991
|
+
appendLog("probe stream completed");
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
return { claudePath, cwd };
|
|
995
|
+
}
|
|
996
|
+
var MAX_SESSION_RECREATIONS = 2;
|
|
997
|
+
async function createClaudeSdkBridgeRunner(config, abortSignal) {
|
|
998
|
+
const { slug, sendMessage, debugLog, sessionBriefing } = config;
|
|
999
|
+
const env = process.env;
|
|
1000
|
+
const sdk = await tryImportSdk();
|
|
1001
|
+
if (!sdk) {
|
|
1002
|
+
throw new Error("Claude Agent SDK is not importable.");
|
|
1003
|
+
}
|
|
1004
|
+
const loadedSdk = sdk;
|
|
1005
|
+
const { model, claudePath, allowedTools, sdkEnv } = buildSdkSessionOptions(env);
|
|
1006
|
+
const appendSystemPrompt = buildAppendSystemPrompt(config.instructions.systemPrompt, env);
|
|
1007
|
+
let sessionId;
|
|
1008
|
+
let forwardedMessageCount = 0;
|
|
1009
|
+
let lastError;
|
|
1010
|
+
let stopped = abortSignal?.aborted ?? false;
|
|
1011
|
+
let sessionRecreations = 0;
|
|
1012
|
+
let activeSession = null;
|
|
1013
|
+
if (abortSignal) {
|
|
1014
|
+
abortSignal.addEventListener(
|
|
1015
|
+
"abort",
|
|
1016
|
+
() => {
|
|
1017
|
+
stopped = true;
|
|
1018
|
+
activeSession?.close();
|
|
1019
|
+
},
|
|
1020
|
+
{ once: true }
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
const canvasReminderEvery = resolveCanvasReminderEvery();
|
|
1024
|
+
function createSession() {
|
|
1025
|
+
const session2 = loadedSdk.unstable_v2_createSession({
|
|
1026
|
+
model,
|
|
1027
|
+
pathToClaudeCodeExecutable: claudePath,
|
|
1028
|
+
env: {
|
|
1029
|
+
...sdkEnv,
|
|
1030
|
+
...appendSystemPrompt ? { CLAUDE_CODE_APPEND_SYSTEM_PROMPT: appendSystemPrompt } : {}
|
|
1031
|
+
},
|
|
1032
|
+
allowedTools,
|
|
1033
|
+
canUseTool: async (_tool, input) => ({ behavior: "allow", updatedInput: input })
|
|
1034
|
+
});
|
|
1035
|
+
activeSession = session2;
|
|
1036
|
+
return session2;
|
|
1037
|
+
}
|
|
1038
|
+
async function consumeStream(session2) {
|
|
1039
|
+
for await (const msg of session2.stream()) {
|
|
1040
|
+
if (stopped) break;
|
|
1041
|
+
if (msg.type === "assistant") {
|
|
1042
|
+
debugLog("sdk assistant message received");
|
|
1043
|
+
} else if (msg.type === "result") {
|
|
1044
|
+
if ("session_id" in msg && typeof msg.session_id === "string") {
|
|
1045
|
+
sessionId = msg.session_id;
|
|
1046
|
+
debugLog(`captured session_id: ${sessionId}`);
|
|
1047
|
+
}
|
|
1048
|
+
if (msg.subtype !== "success") {
|
|
1049
|
+
throw new Error(`Claude SDK result error: ${msg.subtype}`);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
async function sendAndStream(session2, prompt) {
|
|
1055
|
+
await session2.send(prompt);
|
|
1056
|
+
await consumeStream(session2);
|
|
1057
|
+
}
|
|
1058
|
+
async function deliverWithRecovery(prompt) {
|
|
1059
|
+
if (stopped) return;
|
|
1060
|
+
try {
|
|
1061
|
+
if (!activeSession) throw new Error("session not initialized");
|
|
1062
|
+
await sendAndStream(activeSession, prompt);
|
|
1063
|
+
} catch (error) {
|
|
1064
|
+
const msg = errorMessage(error);
|
|
1065
|
+
debugLog(`session error: ${msg}`, error);
|
|
1066
|
+
if (stopped || sessionRecreations >= MAX_SESSION_RECREATIONS) {
|
|
1067
|
+
throw error;
|
|
1068
|
+
}
|
|
1069
|
+
debugLog(`recreating session (attempt ${sessionRecreations + 1}/${MAX_SESSION_RECREATIONS})`);
|
|
1070
|
+
sessionRecreations += 1;
|
|
1071
|
+
try {
|
|
1072
|
+
activeSession?.close();
|
|
1073
|
+
} catch (error2) {
|
|
1074
|
+
debugLog(`failed to close previous SDK session: ${errorMessage(error2)}`, error2);
|
|
1075
|
+
}
|
|
1076
|
+
const newSession = createSession();
|
|
1077
|
+
await sendAndStream(newSession, sessionBriefing);
|
|
1078
|
+
debugLog("session briefing re-delivered after recovery");
|
|
1079
|
+
await sendAndStream(newSession, prompt);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
const session = createSession();
|
|
1083
|
+
await sendAndStream(session, sessionBriefing);
|
|
1084
|
+
debugLog("session briefing delivered via SDK");
|
|
1085
|
+
const queue = createBridgeEntryQueue({
|
|
1086
|
+
onEntry: async (entry) => {
|
|
1087
|
+
const includeCanvasReminder = shouldIncludeCanvasPolicyReminder(
|
|
1088
|
+
forwardedMessageCount + 1,
|
|
1089
|
+
canvasReminderEvery
|
|
1090
|
+
);
|
|
1091
|
+
const chat = readTextChatMessage(entry);
|
|
1092
|
+
if (chat) {
|
|
1093
|
+
const prompt = buildInboundPrompt(slug, chat, includeCanvasReminder, config.instructions);
|
|
1094
|
+
await deliverWithRecovery(prompt);
|
|
1095
|
+
forwardedMessageCount += 1;
|
|
1096
|
+
config.onDeliveryUpdate?.({
|
|
1097
|
+
channel: entry.channel,
|
|
1098
|
+
messageId: entry.msg.id,
|
|
1099
|
+
stage: "confirmed"
|
|
1100
|
+
});
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
const renderError = readRenderErrorMessage(entry);
|
|
1104
|
+
if (renderError) {
|
|
1105
|
+
const prompt = buildRenderErrorPrompt(slug, renderError, config.instructions);
|
|
1106
|
+
await deliverWithRecovery(prompt);
|
|
1107
|
+
forwardedMessageCount += 1;
|
|
1108
|
+
config.onDeliveryUpdate?.({
|
|
1109
|
+
channel: entry.channel,
|
|
1110
|
+
messageId: entry.msg.id,
|
|
1111
|
+
stage: "confirmed"
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
1114
|
+
},
|
|
1115
|
+
onError: (error, entry) => {
|
|
1116
|
+
const message = errorMessage(error);
|
|
1117
|
+
lastError = message;
|
|
1118
|
+
debugLog(`bridge entry processing failed: ${message}`, error);
|
|
1119
|
+
config.onDeliveryUpdate?.({
|
|
1120
|
+
channel: entry.channel,
|
|
1121
|
+
messageId: entry.msg.id,
|
|
1122
|
+
stage: "failed",
|
|
1123
|
+
error: message
|
|
1124
|
+
});
|
|
1125
|
+
void sendMessage(CHANNELS.CHAT, {
|
|
1126
|
+
id: generateMessageId(),
|
|
1127
|
+
type: "text",
|
|
1128
|
+
data: `Bridge error: ${message}`
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
return {
|
|
1133
|
+
enqueue: (entries) => queue.enqueue(entries),
|
|
1134
|
+
async stop() {
|
|
1135
|
+
if (stopped) return;
|
|
1136
|
+
stopped = true;
|
|
1137
|
+
await queue.stop();
|
|
1138
|
+
activeSession?.close();
|
|
1139
|
+
},
|
|
1140
|
+
status() {
|
|
1141
|
+
return {
|
|
1142
|
+
running: !stopped,
|
|
1143
|
+
sessionId,
|
|
1144
|
+
lastError,
|
|
1145
|
+
forwardedMessages: forwardedMessageCount
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
|
|
812
1151
|
// src/lib/live-bridge-openclaw.ts
|
|
813
1152
|
import { execFile } from "child_process";
|
|
814
1153
|
import { existsSync as existsSync5 } from "fs";
|
|
815
|
-
import { join as
|
|
1154
|
+
import { join as join6 } from "path";
|
|
816
1155
|
import { promisify } from "util";
|
|
817
1156
|
|
|
818
1157
|
// src/lib/live-bridge-openclaw-attachments.ts
|
|
819
1158
|
import { createHash } from "crypto";
|
|
820
1159
|
import { mkdirSync, renameSync, unlinkSync as unlinkSync2, writeFileSync } from "fs";
|
|
821
|
-
import { basename, extname, join as
|
|
1160
|
+
import { basename, extname, join as join5 } from "path";
|
|
822
1161
|
|
|
823
1162
|
// src/lib/live-bridge-openclaw-session.ts
|
|
824
1163
|
import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
|
|
825
|
-
import { join as
|
|
1164
|
+
import { join as join4 } from "path";
|
|
826
1165
|
|
|
827
1166
|
// src/lib/openclaw-paths.ts
|
|
828
1167
|
import { existsSync as existsSync3, readFileSync } from "fs";
|
|
829
1168
|
import { homedir } from "os";
|
|
830
|
-
import { dirname, isAbsolute, join as
|
|
1169
|
+
import { dirname, isAbsolute, join as join3, resolve } from "path";
|
|
831
1170
|
function trimToUndefined(value) {
|
|
832
1171
|
const trimmed = value?.trim();
|
|
833
1172
|
return trimmed ? trimmed : void 0;
|
|
@@ -846,7 +1185,7 @@ function resolveBaseHome(env) {
|
|
|
846
1185
|
function expandHomePrefix(input, home) {
|
|
847
1186
|
if (input === "~") return home;
|
|
848
1187
|
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
849
|
-
return
|
|
1188
|
+
return join3(home, input.slice(2));
|
|
850
1189
|
}
|
|
851
1190
|
return input;
|
|
852
1191
|
}
|
|
@@ -864,12 +1203,12 @@ function resolveOpenClawHome(env = process.env) {
|
|
|
864
1203
|
function resolveOpenClawStateDir(env = process.env) {
|
|
865
1204
|
const configured = trimToUndefined(env.OPENCLAW_STATE_DIR);
|
|
866
1205
|
if (configured) return resolvePathFromInput(configured, env);
|
|
867
|
-
return
|
|
1206
|
+
return join3(resolveOpenClawHome(env), ".openclaw");
|
|
868
1207
|
}
|
|
869
1208
|
function resolveOpenClawConfigPath(env = process.env) {
|
|
870
1209
|
const configured = trimToUndefined(env.OPENCLAW_CONFIG_PATH);
|
|
871
1210
|
if (configured) return resolvePathFromInput(configured, env);
|
|
872
|
-
return
|
|
1211
|
+
return join3(resolveOpenClawStateDir(env), "openclaw.json");
|
|
873
1212
|
}
|
|
874
1213
|
function readWorkspaceFromOpenClawConfig(configPath) {
|
|
875
1214
|
if (!existsSync3(configPath)) return null;
|
|
@@ -899,13 +1238,13 @@ function resolveOpenClawWorkspaceDir(env = process.env) {
|
|
|
899
1238
|
const configPath = resolveOpenClawConfigPath(env);
|
|
900
1239
|
const fromConfig = readWorkspaceFromOpenClawConfig(configPath);
|
|
901
1240
|
if (fromConfig) return resolveWorkspacePath(fromConfig, configPath, env);
|
|
902
|
-
return
|
|
1241
|
+
return join3(resolveOpenClawStateDir(env), "workspace");
|
|
903
1242
|
}
|
|
904
1243
|
|
|
905
1244
|
// src/lib/live-bridge-openclaw-session.ts
|
|
906
1245
|
var OPENCLAW_MAIN_SESSION_KEY = "agent:main:main";
|
|
907
1246
|
function resolveOpenClawSessionsPath(env = process.env) {
|
|
908
|
-
return
|
|
1247
|
+
return join4(resolveOpenClawStateDir(env), "agents", "main", "sessions", "sessions.json");
|
|
909
1248
|
}
|
|
910
1249
|
function buildThreadCandidateKeys(threadId) {
|
|
911
1250
|
const trimmed = threadId?.trim();
|
|
@@ -981,7 +1320,7 @@ var DEFAULT_ATTACHMENT_MAX_BYTES = 5 * 1024 * 1024;
|
|
|
981
1320
|
function resolveAttachmentRootDir() {
|
|
982
1321
|
const configured = process.env.OPENCLAW_ATTACHMENT_DIR?.trim();
|
|
983
1322
|
if (configured) return configured;
|
|
984
|
-
return
|
|
1323
|
+
return join5(resolveOpenClawStateDir(), "pubblue-inbox");
|
|
985
1324
|
}
|
|
986
1325
|
function resolveAttachmentMaxBytes() {
|
|
987
1326
|
const raw = Number.parseInt(process.env.OPENCLAW_ATTACHMENT_MAX_BYTES ?? "", 10);
|
|
@@ -1022,12 +1361,12 @@ function resolveAttachmentFilename(params) {
|
|
|
1022
1361
|
}
|
|
1023
1362
|
function ensureDirectoryWritable(dirPath) {
|
|
1024
1363
|
mkdirSync(dirPath, { recursive: true });
|
|
1025
|
-
const probe =
|
|
1364
|
+
const probe = join5(dirPath, `.bridge-writecheck-${process.pid}-${Date.now()}`);
|
|
1026
1365
|
writeFileSync(probe, "ok\n", { mode: 384 });
|
|
1027
1366
|
unlinkSync2(probe);
|
|
1028
1367
|
}
|
|
1029
1368
|
function stageAttachment(params) {
|
|
1030
|
-
const slugDir =
|
|
1369
|
+
const slugDir = join5(params.attachmentRoot, sanitizeFilename(params.slug));
|
|
1031
1370
|
ensureDirectoryWritable(slugDir);
|
|
1032
1371
|
const mime = (params.mime || "application/octet-stream").trim();
|
|
1033
1372
|
const resolvedName = resolveAttachmentFilename({
|
|
@@ -1037,7 +1376,7 @@ function stageAttachment(params) {
|
|
|
1037
1376
|
mime
|
|
1038
1377
|
});
|
|
1039
1378
|
const collisionSafeName = `${Date.now()}-${sanitizeFilename(params.messageId)}-${resolvedName}`;
|
|
1040
|
-
const targetPath =
|
|
1379
|
+
const targetPath = join5(slugDir, collisionSafeName);
|
|
1041
1380
|
const tempPath = `${targetPath}.tmp-${process.pid}`;
|
|
1042
1381
|
writeFileSync(tempPath, params.bytes, { mode: 384 });
|
|
1043
1382
|
renameSync(tempPath, targetPath);
|
|
@@ -1219,9 +1558,9 @@ function getOpenClawDiscoveryPaths(env = process.env) {
|
|
|
1219
1558
|
return [
|
|
1220
1559
|
.../* @__PURE__ */ new Set([
|
|
1221
1560
|
"/app/dist/index.js",
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1561
|
+
join6(home, "openclaw", "dist", "index.js"),
|
|
1562
|
+
join6(stateDir, "openclaw"),
|
|
1563
|
+
join6(home, ".openclaw", "openclaw"),
|
|
1225
1564
|
"/usr/local/bin/openclaw",
|
|
1226
1565
|
"/opt/homebrew/bin/openclaw"
|
|
1227
1566
|
])
|
|
@@ -1258,7 +1597,7 @@ function resolveOpenClawPath(env = process.env) {
|
|
|
1258
1597
|
"OpenClaw executable was not found.",
|
|
1259
1598
|
"Configure it with: pubblue configure --set openclaw.path=/absolute/path/to/openclaw",
|
|
1260
1599
|
"Or set OPENCLAW_PATH in environment.",
|
|
1261
|
-
|
|
1600
|
+
`Checked: ${discoveryPaths.join(", ")}`
|
|
1262
1601
|
].join(" ")
|
|
1263
1602
|
);
|
|
1264
1603
|
}
|
|
@@ -1486,35 +1825,35 @@ async function createOpenClawBridgeRunner(config) {
|
|
|
1486
1825
|
}
|
|
1487
1826
|
|
|
1488
1827
|
// src/lib/live-runtime/daemon-files.ts
|
|
1489
|
-
import * as
|
|
1490
|
-
import * as
|
|
1828
|
+
import * as fs4 from "fs";
|
|
1829
|
+
import * as path4 from "path";
|
|
1491
1830
|
|
|
1492
1831
|
// src/lib/config.ts
|
|
1493
|
-
import * as
|
|
1494
|
-
import * as
|
|
1832
|
+
import * as fs3 from "fs";
|
|
1833
|
+
import * as path3 from "path";
|
|
1495
1834
|
var DEFAULT_BASE_URL = "https://silent-guanaco-514.convex.site";
|
|
1496
1835
|
function getConfigDir(homeDir) {
|
|
1497
1836
|
const explicit = process.env.PUBBLUE_CONFIG_DIR?.trim();
|
|
1498
1837
|
if (explicit) return explicit;
|
|
1499
1838
|
if (homeDir) {
|
|
1500
|
-
return
|
|
1839
|
+
return path3.join(path3.resolve(homeDir), ".openclaw", "pubblue");
|
|
1501
1840
|
}
|
|
1502
|
-
return
|
|
1841
|
+
return path3.join(resolveOpenClawStateDir(), "pubblue");
|
|
1503
1842
|
}
|
|
1504
1843
|
function getConfigPath(homeDir) {
|
|
1505
1844
|
const dir = getConfigDir(homeDir);
|
|
1506
|
-
|
|
1507
|
-
return
|
|
1845
|
+
fs3.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
1846
|
+
return path3.join(dir, "config.json");
|
|
1508
1847
|
}
|
|
1509
1848
|
function readConfig(homeDir) {
|
|
1510
1849
|
const configPath = getConfigPath(homeDir);
|
|
1511
|
-
if (!
|
|
1512
|
-
const raw =
|
|
1850
|
+
if (!fs3.existsSync(configPath)) return null;
|
|
1851
|
+
const raw = fs3.readFileSync(configPath, "utf-8");
|
|
1513
1852
|
return JSON.parse(raw);
|
|
1514
1853
|
}
|
|
1515
1854
|
function saveConfig(config, homeDir) {
|
|
1516
1855
|
const configPath = getConfigPath(homeDir);
|
|
1517
|
-
|
|
1856
|
+
fs3.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
1518
1857
|
`, {
|
|
1519
1858
|
mode: 384
|
|
1520
1859
|
});
|
|
@@ -1546,39 +1885,32 @@ function getTelegramMiniAppUrl(slug) {
|
|
|
1546
1885
|
|
|
1547
1886
|
// src/lib/live-runtime/daemon-files.ts
|
|
1548
1887
|
function liveInfoDir() {
|
|
1549
|
-
const dir =
|
|
1550
|
-
|
|
1888
|
+
const dir = path4.join(getConfigDir(), "lives");
|
|
1889
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
1551
1890
|
return dir;
|
|
1552
1891
|
}
|
|
1553
1892
|
function liveInfoPath(slug) {
|
|
1554
|
-
return
|
|
1893
|
+
return path4.join(liveInfoDir(), `${slug}.json`);
|
|
1555
1894
|
}
|
|
1556
1895
|
function liveLogPath(slug) {
|
|
1557
|
-
return
|
|
1896
|
+
return path4.join(liveInfoDir(), `${slug}.log`);
|
|
1558
1897
|
}
|
|
1559
1898
|
function sanitizeSlugForFilename(slug) {
|
|
1560
1899
|
const sanitized = slug.trim().replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
1561
1900
|
return sanitized.length > 0 ? sanitized : "live";
|
|
1562
1901
|
}
|
|
1563
|
-
function
|
|
1564
|
-
if (contentType === "html") return "html";
|
|
1565
|
-
if (contentType === "markdown") return "md";
|
|
1566
|
-
if (contentType === "text") return "txt";
|
|
1567
|
-
return "txt";
|
|
1568
|
-
}
|
|
1569
|
-
function liveSessionContentPath(slug, contentType, rootDir) {
|
|
1902
|
+
function liveSessionContentPath(slug, rootDir) {
|
|
1570
1903
|
const safeSlug = sanitizeSlugForFilename(slug);
|
|
1571
|
-
|
|
1572
|
-
return path3.join(rootDir ?? liveInfoDir(), `${safeSlug}.session-content.${ext}`);
|
|
1904
|
+
return path4.join(rootDir ?? liveInfoDir(), `${safeSlug}.session-content.html`);
|
|
1573
1905
|
}
|
|
1574
1906
|
function writeLiveSessionContentFile(params) {
|
|
1575
|
-
const filePath = liveSessionContentPath(params.slug, params.
|
|
1576
|
-
|
|
1577
|
-
|
|
1907
|
+
const filePath = liveSessionContentPath(params.slug, params.rootDir);
|
|
1908
|
+
fs4.mkdirSync(path4.dirname(filePath), { recursive: true });
|
|
1909
|
+
fs4.writeFileSync(filePath, params.content, "utf-8");
|
|
1578
1910
|
return filePath;
|
|
1579
1911
|
}
|
|
1580
1912
|
function latestCliVersionPath() {
|
|
1581
|
-
return
|
|
1913
|
+
return path4.join(liveInfoDir(), "cli-version.txt");
|
|
1582
1914
|
}
|
|
1583
1915
|
function isMissingPathError(error) {
|
|
1584
1916
|
if (typeof error !== "object" || error === null || !("code" in error)) return false;
|
|
@@ -1588,7 +1920,7 @@ function isMissingPathError(error) {
|
|
|
1588
1920
|
function readLatestCliVersion(versionPath) {
|
|
1589
1921
|
const resolved = versionPath || latestCliVersionPath();
|
|
1590
1922
|
try {
|
|
1591
|
-
const value =
|
|
1923
|
+
const value = fs4.readFileSync(resolved, "utf-8").trim();
|
|
1592
1924
|
return value.length === 0 ? null : value;
|
|
1593
1925
|
} catch (error) {
|
|
1594
1926
|
if (isMissingPathError(error)) return null;
|
|
@@ -1599,13 +1931,13 @@ function writeLatestCliVersion(version, versionPath) {
|
|
|
1599
1931
|
const trimmed = version.trim();
|
|
1600
1932
|
if (trimmed.length === 0) return;
|
|
1601
1933
|
const resolved = versionPath || latestCliVersionPath();
|
|
1602
|
-
const dir =
|
|
1603
|
-
|
|
1604
|
-
|
|
1934
|
+
const dir = path4.dirname(resolved);
|
|
1935
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
1936
|
+
fs4.writeFileSync(resolved, trimmed, "utf-8");
|
|
1605
1937
|
}
|
|
1606
1938
|
function readLogTail(logPath, maxChars = 4e3) {
|
|
1607
1939
|
try {
|
|
1608
|
-
const content =
|
|
1940
|
+
const content = fs4.readFileSync(logPath, "utf-8");
|
|
1609
1941
|
if (content.length <= maxChars) return content;
|
|
1610
1942
|
return content.slice(-maxChars);
|
|
1611
1943
|
} catch (error) {
|
|
@@ -1614,10 +1946,152 @@ function readLogTail(logPath, maxChars = 4e3) {
|
|
|
1614
1946
|
}
|
|
1615
1947
|
}
|
|
1616
1948
|
|
|
1949
|
+
// src/lib/live-ipc-protocol.ts
|
|
1950
|
+
function parseBufferedBridgeMessage(input) {
|
|
1951
|
+
const record = readRecord(input);
|
|
1952
|
+
if (!record) return null;
|
|
1953
|
+
const channel = readString(record.channel);
|
|
1954
|
+
const msg = parseBridgeMessage(record.msg);
|
|
1955
|
+
if (!channel || !msg) return null;
|
|
1956
|
+
return {
|
|
1957
|
+
channel,
|
|
1958
|
+
msg,
|
|
1959
|
+
timestamp: readFiniteNumber(record.timestamp)
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1962
|
+
function parseBridgeStatus(input) {
|
|
1963
|
+
if (input === null) return null;
|
|
1964
|
+
const record = readRecord(input);
|
|
1965
|
+
if (!record) return null;
|
|
1966
|
+
const running = readBoolean(record.running);
|
|
1967
|
+
const forwardedMessages = readFiniteNumber(record.forwardedMessages);
|
|
1968
|
+
if (running === void 0 || forwardedMessages === void 0) return null;
|
|
1969
|
+
const sessionSourceRaw = record.sessionSource === void 0 ? void 0 : readString(record.sessionSource);
|
|
1970
|
+
const sessionSource = sessionSourceRaw === void 0 || sessionSourceRaw === "env" || sessionSourceRaw === "thread-canonical" || sessionSourceRaw === "thread-legacy" || sessionSourceRaw === "main-fallback" ? sessionSourceRaw : null;
|
|
1971
|
+
if (sessionSource === null) return null;
|
|
1972
|
+
return {
|
|
1973
|
+
running,
|
|
1974
|
+
sessionId: readString(record.sessionId),
|
|
1975
|
+
sessionKey: readString(record.sessionKey),
|
|
1976
|
+
sessionSource,
|
|
1977
|
+
lastError: readString(record.lastError),
|
|
1978
|
+
forwardedMessages
|
|
1979
|
+
};
|
|
1980
|
+
}
|
|
1981
|
+
function parseIpcRequest(input) {
|
|
1982
|
+
const record = readRecord(input);
|
|
1983
|
+
if (!record) return null;
|
|
1984
|
+
const method = readString(record.method);
|
|
1985
|
+
const params = readRecord(record.params);
|
|
1986
|
+
if (!method || !params) return null;
|
|
1987
|
+
if (method === "write") {
|
|
1988
|
+
const msg = parseBridgeMessage(params.msg);
|
|
1989
|
+
if (!msg) return null;
|
|
1990
|
+
const channel = params.channel === void 0 ? void 0 : readString(params.channel);
|
|
1991
|
+
const binaryBase64 = params.binaryBase64 === void 0 ? void 0 : readString(params.binaryBase64);
|
|
1992
|
+
if (params.channel !== void 0 && channel === void 0) return null;
|
|
1993
|
+
if (params.binaryBase64 !== void 0 && binaryBase64 === void 0) return null;
|
|
1994
|
+
return {
|
|
1995
|
+
method,
|
|
1996
|
+
params: {
|
|
1997
|
+
channel,
|
|
1998
|
+
msg,
|
|
1999
|
+
binaryBase64
|
|
2000
|
+
}
|
|
2001
|
+
};
|
|
2002
|
+
}
|
|
2003
|
+
if (method === "read") {
|
|
2004
|
+
const channel = params.channel === void 0 ? void 0 : readString(params.channel);
|
|
2005
|
+
if (params.channel !== void 0 && channel === void 0) return null;
|
|
2006
|
+
return { method, params: { channel } };
|
|
2007
|
+
}
|
|
2008
|
+
if (method === "channels" || method === "status" || method === "active-slug" || method === "close") {
|
|
2009
|
+
return { method, params: {} };
|
|
2010
|
+
}
|
|
2011
|
+
return null;
|
|
2012
|
+
}
|
|
2013
|
+
function parseIpcResponse(method, input) {
|
|
2014
|
+
const record = readRecord(input);
|
|
2015
|
+
if (!record) return null;
|
|
2016
|
+
const ok = readBoolean(record.ok);
|
|
2017
|
+
if (ok === void 0) return null;
|
|
2018
|
+
const error = record.error === void 0 ? void 0 : readString(record.error);
|
|
2019
|
+
if (record.error !== void 0 && error === void 0) return null;
|
|
2020
|
+
if (!ok) return { ok, error };
|
|
2021
|
+
if (method === "write") {
|
|
2022
|
+
const delivered = record.delivered === void 0 ? void 0 : readBoolean(record.delivered);
|
|
2023
|
+
if (record.delivered !== void 0 && delivered === void 0) return null;
|
|
2024
|
+
return { ok, delivered, error };
|
|
2025
|
+
}
|
|
2026
|
+
if (method === "read") {
|
|
2027
|
+
if (record.messages === void 0) return { ok, error };
|
|
2028
|
+
if (!Array.isArray(record.messages)) return null;
|
|
2029
|
+
const messages = record.messages.map((entry) => parseBufferedBridgeMessage(entry)).filter((entry) => entry !== null);
|
|
2030
|
+
if (messages.length !== record.messages.length) return null;
|
|
2031
|
+
return { ok, messages, error };
|
|
2032
|
+
}
|
|
2033
|
+
if (method === "channels") {
|
|
2034
|
+
if (record.channels === void 0) return { ok, error };
|
|
2035
|
+
if (!Array.isArray(record.channels)) return null;
|
|
2036
|
+
const channels = record.channels.map((entry) => {
|
|
2037
|
+
const channelRecord = readRecord(entry);
|
|
2038
|
+
if (!channelRecord) return null;
|
|
2039
|
+
const name = readString(channelRecord.name);
|
|
2040
|
+
const direction = readString(channelRecord.direction);
|
|
2041
|
+
if (!name || !direction) return null;
|
|
2042
|
+
return { name, direction };
|
|
2043
|
+
}).filter((entry) => entry !== null);
|
|
2044
|
+
if (channels.length !== record.channels.length) return null;
|
|
2045
|
+
return { ok, channels, error };
|
|
2046
|
+
}
|
|
2047
|
+
if (method === "status") {
|
|
2048
|
+
const connected = readBoolean(record.connected);
|
|
2049
|
+
const signalingConnected = record.signalingConnected === null ? null : record.signalingConnected === void 0 ? void 0 : readBoolean(record.signalingConnected);
|
|
2050
|
+
const activeSlug = record.activeSlug === null ? null : record.activeSlug === void 0 ? void 0 : readString(record.activeSlug);
|
|
2051
|
+
const uptime = readFiniteNumber(record.uptime);
|
|
2052
|
+
const bufferedMessages = readFiniteNumber(record.bufferedMessages);
|
|
2053
|
+
const lastError = record.lastError === null ? null : record.lastError === void 0 ? void 0 : readString(record.lastError);
|
|
2054
|
+
const bridgeMode = record.bridgeMode === null ? null : record.bridgeMode === void 0 ? void 0 : readString(record.bridgeMode);
|
|
2055
|
+
if (connected === void 0 || signalingConnected === void 0 || activeSlug === void 0 || uptime === void 0 || !Array.isArray(record.channels) || bufferedMessages === void 0 || lastError === void 0 || bridgeMode === void 0) {
|
|
2056
|
+
return null;
|
|
2057
|
+
}
|
|
2058
|
+
const channels = record.channels.filter((entry) => typeof entry === "string");
|
|
2059
|
+
if (channels.length !== record.channels.length) return null;
|
|
2060
|
+
const bridge = record.bridge === void 0 ? null : parseBridgeStatus(record.bridge);
|
|
2061
|
+
if (record.bridge !== void 0 && bridge === null && record.bridge !== null) return null;
|
|
2062
|
+
return {
|
|
2063
|
+
ok,
|
|
2064
|
+
connected,
|
|
2065
|
+
signalingConnected,
|
|
2066
|
+
activeSlug,
|
|
2067
|
+
uptime,
|
|
2068
|
+
channels,
|
|
2069
|
+
bufferedMessages,
|
|
2070
|
+
lastError,
|
|
2071
|
+
bridgeMode,
|
|
2072
|
+
bridge,
|
|
2073
|
+
error
|
|
2074
|
+
};
|
|
2075
|
+
}
|
|
2076
|
+
if (method === "active-slug") {
|
|
2077
|
+
const slug = record.slug === null ? null : record.slug === void 0 ? void 0 : readString(record.slug);
|
|
2078
|
+
if (record.slug !== void 0 && slug === void 0) return null;
|
|
2079
|
+
return { ok, slug, error };
|
|
2080
|
+
}
|
|
2081
|
+
return { ok, error };
|
|
2082
|
+
}
|
|
2083
|
+
|
|
1617
2084
|
export {
|
|
1618
2085
|
failCli,
|
|
1619
2086
|
errorMessage,
|
|
1620
2087
|
toCliFailure,
|
|
2088
|
+
readRecord,
|
|
2089
|
+
readString,
|
|
2090
|
+
readNonEmptyString,
|
|
2091
|
+
readFiniteNumber,
|
|
2092
|
+
readStringArray,
|
|
2093
|
+
readStringRecord,
|
|
2094
|
+
parseLiveInfo,
|
|
1621
2095
|
PubApiError,
|
|
1622
2096
|
PubApiClient,
|
|
1623
2097
|
resolveOpenClawHome,
|
|
@@ -1638,12 +2112,18 @@ export {
|
|
|
1638
2112
|
makeDeliveryReceiptMessage,
|
|
1639
2113
|
parseAckMessage,
|
|
1640
2114
|
shouldAcknowledgeMessage,
|
|
2115
|
+
parseIpcRequest,
|
|
2116
|
+
parseIpcResponse,
|
|
1641
2117
|
buildSessionBriefing,
|
|
1642
2118
|
isClaudeCodeAvailableInEnv,
|
|
1643
2119
|
resolveClaudeCodePath,
|
|
1644
2120
|
buildClaudeArgs,
|
|
1645
2121
|
runClaudeCodeBridgeStartupProbe,
|
|
1646
2122
|
createClaudeCodeBridgeRunner,
|
|
2123
|
+
isClaudeSdkAvailableInEnv,
|
|
2124
|
+
isClaudeSdkImportable,
|
|
2125
|
+
runClaudeSdkBridgeStartupProbe,
|
|
2126
|
+
createClaudeSdkBridgeRunner,
|
|
1647
2127
|
isOpenClawAvailable,
|
|
1648
2128
|
resolveOpenClawRuntime,
|
|
1649
2129
|
runOpenClawBridgeStartupProbe,
|