pubblue 0.6.9 → 0.7.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/{chunk-JSX5KHV3.js → chunk-5ODXW2EM.js} +315 -47
- package/dist/index.js +50 -19
- package/dist/live-daemon-entry.js +81 -129
- package/dist/sdk-IV5ZYS3G.js +12299 -0
- package/package.json +4 -1
|
@@ -56,8 +56,8 @@ var PubApiClient = class {
|
|
|
56
56
|
getApiKey() {
|
|
57
57
|
return this.apiKey;
|
|
58
58
|
}
|
|
59
|
-
async request(
|
|
60
|
-
const url = new URL(
|
|
59
|
+
async request(path5, options = {}) {
|
|
60
|
+
const url = new URL(path5, this.baseUrl);
|
|
61
61
|
const res = await fetch(url, {
|
|
62
62
|
...options,
|
|
63
63
|
headers: {
|
|
@@ -169,8 +169,8 @@ var PubApiClient = class {
|
|
|
169
169
|
params.set("daemonSessionId", daemonSessionId);
|
|
170
170
|
}
|
|
171
171
|
const query = params.toString();
|
|
172
|
-
const
|
|
173
|
-
const data = await this.request(
|
|
172
|
+
const path5 = query ? `/api/v1/agent/live?${query}` : "/api/v1/agent/live";
|
|
173
|
+
const data = await this.request(path5);
|
|
174
174
|
return data.live;
|
|
175
175
|
}
|
|
176
176
|
async signalAnswer(opts) {
|
|
@@ -185,8 +185,8 @@ var PubApiClient = class {
|
|
|
185
185
|
params.set("daemonSessionId", daemonSessionId);
|
|
186
186
|
}
|
|
187
187
|
const query = params.toString();
|
|
188
|
-
const
|
|
189
|
-
await this.request(
|
|
188
|
+
const path5 = query ? `/api/v1/agent/live?${query}` : "/api/v1/agent/live";
|
|
189
|
+
await this.request(path5, { method: "DELETE" });
|
|
190
190
|
}
|
|
191
191
|
// -- Telegram bot token ---------------------------------------------------
|
|
192
192
|
async uploadBotToken(opts) {
|
|
@@ -809,25 +809,289 @@ async function createClaudeCodeBridgeRunner(config, abortSignal) {
|
|
|
809
809
|
};
|
|
810
810
|
}
|
|
811
811
|
|
|
812
|
+
// src/lib/live-bridge-claude-sdk.ts
|
|
813
|
+
import * as fs2 from "fs";
|
|
814
|
+
import * as os2 from "os";
|
|
815
|
+
import * as path2 from "path";
|
|
816
|
+
async function tryImportSdk() {
|
|
817
|
+
try {
|
|
818
|
+
return await import("./sdk-IV5ZYS3G.js");
|
|
819
|
+
} catch {
|
|
820
|
+
return null;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
function isClaudeSdkAvailableInEnv(env) {
|
|
824
|
+
return isClaudeCodeAvailableInEnv(env);
|
|
825
|
+
}
|
|
826
|
+
async function isClaudeSdkImportable() {
|
|
827
|
+
return await tryImportSdk() !== null;
|
|
828
|
+
}
|
|
829
|
+
function buildSdkSessionOptions(env = process.env) {
|
|
830
|
+
const model = env.CLAUDE_CODE_MODEL?.trim() || "claude-sonnet-4-6";
|
|
831
|
+
const claudePath = resolveClaudeCodePath(env);
|
|
832
|
+
const allowedToolsRaw = env.CLAUDE_CODE_ALLOWED_TOOLS?.trim();
|
|
833
|
+
const allowedTools = allowedToolsRaw ? allowedToolsRaw.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
|
|
834
|
+
const sdkEnv = { ...env };
|
|
835
|
+
delete sdkEnv.CLAUDECODE;
|
|
836
|
+
return { model, claudePath, allowedTools, sdkEnv };
|
|
837
|
+
}
|
|
838
|
+
function buildAppendSystemPrompt(bridgeSystemPrompt, env = process.env) {
|
|
839
|
+
const userSystemPrompt = env.CLAUDE_CODE_APPEND_SYSTEM_PROMPT?.trim();
|
|
840
|
+
const effective = [bridgeSystemPrompt, userSystemPrompt].filter(Boolean).join("\n\n");
|
|
841
|
+
return effective.length > 0 ? effective : void 0;
|
|
842
|
+
}
|
|
843
|
+
async function runClaudeSdkBridgeStartupProbe(env = process.env) {
|
|
844
|
+
const { model, claudePath, allowedTools } = buildSdkSessionOptions(env);
|
|
845
|
+
const cwd = env.CLAUDE_CODE_CWD?.trim() || env.PUBBLUE_PROJECT_ROOT || void 0;
|
|
846
|
+
const sdk = await tryImportSdk();
|
|
847
|
+
if (!sdk) {
|
|
848
|
+
throw new Error(
|
|
849
|
+
"Claude Agent SDK (@anthropic-ai/claude-agent-sdk) is not importable. Install it and retry."
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
await runAgentWritePongProbe({
|
|
853
|
+
label: "Claude SDK",
|
|
854
|
+
baseEnv: env,
|
|
855
|
+
execute: async (probeEnv) => {
|
|
856
|
+
const probeEnvClean = { ...probeEnv };
|
|
857
|
+
delete probeEnvClean.CLAUDECODE;
|
|
858
|
+
const socketPath = probeEnv.PUBBLUE_AGENT_SOCKET ?? "";
|
|
859
|
+
const logPath = path2.join(os2.tmpdir(), "pubblue-sdk-probe.log");
|
|
860
|
+
const appendLog = (line) => {
|
|
861
|
+
try {
|
|
862
|
+
fs2.appendFileSync(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
863
|
+
`);
|
|
864
|
+
} catch {
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
appendLog(`probe start socket=${socketPath}`);
|
|
868
|
+
const prompt = [
|
|
869
|
+
"This is a startup connectivity probe.",
|
|
870
|
+
"Run this exact shell command now:",
|
|
871
|
+
`PUBBLUE_AGENT_SOCKET=${socketPath} pubblue write "pong"`,
|
|
872
|
+
"Do not explain. Just execute it."
|
|
873
|
+
].join("\n");
|
|
874
|
+
const q = sdk.query({
|
|
875
|
+
prompt,
|
|
876
|
+
options: {
|
|
877
|
+
model,
|
|
878
|
+
pathToClaudeCodeExecutable: claudePath,
|
|
879
|
+
env: probeEnvClean,
|
|
880
|
+
allowedTools,
|
|
881
|
+
cwd: os2.tmpdir(),
|
|
882
|
+
maxTurns: 2,
|
|
883
|
+
persistSession: false,
|
|
884
|
+
canUseTool: async (toolName, input) => {
|
|
885
|
+
appendLog(`canUseTool: tool=${toolName}`);
|
|
886
|
+
return { behavior: "allow", updatedInput: input };
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
for await (const msg of q) {
|
|
891
|
+
appendLog(`msg: type=${msg.type} ${JSON.stringify(msg).slice(0, 300)}`);
|
|
892
|
+
}
|
|
893
|
+
appendLog("probe stream completed");
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
return { claudePath, cwd };
|
|
897
|
+
}
|
|
898
|
+
var MAX_SESSION_RECREATIONS = 2;
|
|
899
|
+
async function createClaudeSdkBridgeRunner(config, abortSignal) {
|
|
900
|
+
const { slug, sendMessage, debugLog, sessionBriefing } = config;
|
|
901
|
+
const env = process.env;
|
|
902
|
+
const sdk = await tryImportSdk();
|
|
903
|
+
if (!sdk) {
|
|
904
|
+
throw new Error("Claude Agent SDK is not importable.");
|
|
905
|
+
}
|
|
906
|
+
const { model, claudePath, allowedTools, sdkEnv } = buildSdkSessionOptions(env);
|
|
907
|
+
const appendSystemPrompt = buildAppendSystemPrompt(config.instructions.systemPrompt, env);
|
|
908
|
+
let sessionId;
|
|
909
|
+
let forwardedMessageCount = 0;
|
|
910
|
+
let lastError;
|
|
911
|
+
let stopped = abortSignal?.aborted ?? false;
|
|
912
|
+
let sessionRecreations = 0;
|
|
913
|
+
let activeSession = null;
|
|
914
|
+
if (abortSignal) {
|
|
915
|
+
abortSignal.addEventListener(
|
|
916
|
+
"abort",
|
|
917
|
+
() => {
|
|
918
|
+
stopped = true;
|
|
919
|
+
activeSession?.close();
|
|
920
|
+
},
|
|
921
|
+
{ once: true }
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
const canvasReminderEvery = resolveCanvasReminderEvery();
|
|
925
|
+
function createSession() {
|
|
926
|
+
const session2 = sdk.unstable_v2_createSession({
|
|
927
|
+
model,
|
|
928
|
+
pathToClaudeCodeExecutable: claudePath,
|
|
929
|
+
env: {
|
|
930
|
+
...sdkEnv,
|
|
931
|
+
...appendSystemPrompt ? { CLAUDE_CODE_APPEND_SYSTEM_PROMPT: appendSystemPrompt } : {}
|
|
932
|
+
},
|
|
933
|
+
allowedTools,
|
|
934
|
+
canUseTool: async (_tool, input) => ({ behavior: "allow", updatedInput: input })
|
|
935
|
+
});
|
|
936
|
+
activeSession = session2;
|
|
937
|
+
return session2;
|
|
938
|
+
}
|
|
939
|
+
async function consumeStream(session2) {
|
|
940
|
+
for await (const msg of session2.stream()) {
|
|
941
|
+
if (stopped) break;
|
|
942
|
+
if (msg.type === "assistant") {
|
|
943
|
+
debugLog(`sdk assistant message received`);
|
|
944
|
+
} else if (msg.type === "result") {
|
|
945
|
+
if ("session_id" in msg && typeof msg.session_id === "string") {
|
|
946
|
+
sessionId = msg.session_id;
|
|
947
|
+
debugLog(`captured session_id: ${sessionId}`);
|
|
948
|
+
}
|
|
949
|
+
if (msg.subtype !== "success") {
|
|
950
|
+
throw new Error(`Claude SDK result error: ${msg.subtype}`);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
async function sendAndStream(session2, prompt) {
|
|
956
|
+
await session2.send(prompt);
|
|
957
|
+
await consumeStream(session2);
|
|
958
|
+
}
|
|
959
|
+
async function deliverWithRecovery(prompt) {
|
|
960
|
+
if (stopped) return;
|
|
961
|
+
try {
|
|
962
|
+
if (!activeSession) throw new Error("session not initialized");
|
|
963
|
+
await sendAndStream(activeSession, prompt);
|
|
964
|
+
} catch (error) {
|
|
965
|
+
const msg = errorMessage(error);
|
|
966
|
+
debugLog(`session error: ${msg}`, error);
|
|
967
|
+
if (stopped || sessionRecreations >= MAX_SESSION_RECREATIONS) {
|
|
968
|
+
throw error;
|
|
969
|
+
}
|
|
970
|
+
debugLog(`recreating session (attempt ${sessionRecreations + 1}/${MAX_SESSION_RECREATIONS})`);
|
|
971
|
+
sessionRecreations += 1;
|
|
972
|
+
try {
|
|
973
|
+
activeSession?.close();
|
|
974
|
+
} catch {
|
|
975
|
+
}
|
|
976
|
+
const newSession = createSession();
|
|
977
|
+
await sendAndStream(newSession, sessionBriefing);
|
|
978
|
+
debugLog("session briefing re-delivered after recovery");
|
|
979
|
+
await sendAndStream(newSession, prompt);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
const session = createSession();
|
|
983
|
+
await sendAndStream(session, sessionBriefing);
|
|
984
|
+
debugLog("session briefing delivered via SDK");
|
|
985
|
+
const queue = createBridgeEntryQueue({
|
|
986
|
+
onEntry: async (entry) => {
|
|
987
|
+
const chat = readTextChatMessage(entry);
|
|
988
|
+
if (chat) {
|
|
989
|
+
const includeCanvasReminder = shouldIncludeCanvasPolicyReminder(
|
|
990
|
+
forwardedMessageCount + 1,
|
|
991
|
+
canvasReminderEvery
|
|
992
|
+
);
|
|
993
|
+
const prompt = buildInboundPrompt(slug, chat, includeCanvasReminder, config.instructions);
|
|
994
|
+
await deliverWithRecovery(prompt);
|
|
995
|
+
forwardedMessageCount += 1;
|
|
996
|
+
config.onDeliveryUpdate?.({
|
|
997
|
+
channel: entry.channel,
|
|
998
|
+
messageId: entry.msg.id,
|
|
999
|
+
stage: "confirmed"
|
|
1000
|
+
});
|
|
1001
|
+
return;
|
|
1002
|
+
}
|
|
1003
|
+
const renderError = readRenderErrorMessage(entry);
|
|
1004
|
+
if (renderError) {
|
|
1005
|
+
const prompt = buildRenderErrorPrompt(slug, renderError, config.instructions);
|
|
1006
|
+
await deliverWithRecovery(prompt);
|
|
1007
|
+
forwardedMessageCount += 1;
|
|
1008
|
+
config.onDeliveryUpdate?.({
|
|
1009
|
+
channel: entry.channel,
|
|
1010
|
+
messageId: entry.msg.id,
|
|
1011
|
+
stage: "confirmed"
|
|
1012
|
+
});
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
if (entry.msg.type === "binary" || entry.msg.type === "stream-start" || entry.msg.type === "stream-end") {
|
|
1016
|
+
const streamId = typeof entry.msg.meta?.streamId === "string" ? entry.msg.meta.streamId : void 0;
|
|
1017
|
+
if (entry.msg.type === "binary" && streamId) return;
|
|
1018
|
+
const deliveryMessageId = entry.msg.type === "stream-end" && streamId ? streamId : entry.msg.id;
|
|
1019
|
+
config.onDeliveryUpdate?.({
|
|
1020
|
+
channel: entry.channel,
|
|
1021
|
+
messageId: deliveryMessageId,
|
|
1022
|
+
stage: "failed",
|
|
1023
|
+
error: "Attachments are not supported in Claude SDK bridge mode."
|
|
1024
|
+
});
|
|
1025
|
+
if (entry.msg.type !== "stream-end") {
|
|
1026
|
+
void sendMessage(CHANNELS.CHAT, {
|
|
1027
|
+
id: generateMessageId(),
|
|
1028
|
+
type: "text",
|
|
1029
|
+
data: "Attachments are not supported in Claude SDK bridge mode."
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
},
|
|
1034
|
+
onError: (error, entry) => {
|
|
1035
|
+
const message = errorMessage(error);
|
|
1036
|
+
lastError = message;
|
|
1037
|
+
debugLog(`bridge entry processing failed: ${message}`, error);
|
|
1038
|
+
const deliveryMessageId = entry.msg.type === "stream-end" && typeof entry.msg.meta?.streamId === "string" ? entry.msg.meta.streamId : entry.msg.id;
|
|
1039
|
+
config.onDeliveryUpdate?.({
|
|
1040
|
+
channel: entry.channel,
|
|
1041
|
+
messageId: deliveryMessageId,
|
|
1042
|
+
stage: "failed",
|
|
1043
|
+
error: message
|
|
1044
|
+
});
|
|
1045
|
+
void sendMessage(CHANNELS.CHAT, {
|
|
1046
|
+
id: generateMessageId(),
|
|
1047
|
+
type: "text",
|
|
1048
|
+
data: `Bridge error: ${message}`
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
});
|
|
1052
|
+
debugLog(`claude-sdk bridge runner started (path=${claudePath})`);
|
|
1053
|
+
return {
|
|
1054
|
+
enqueue: (entries) => queue.enqueue(entries),
|
|
1055
|
+
async stop() {
|
|
1056
|
+
if (stopped) return;
|
|
1057
|
+
stopped = true;
|
|
1058
|
+
try {
|
|
1059
|
+
activeSession?.close();
|
|
1060
|
+
} catch {
|
|
1061
|
+
}
|
|
1062
|
+
activeSession = null;
|
|
1063
|
+
await queue.stop();
|
|
1064
|
+
},
|
|
1065
|
+
status() {
|
|
1066
|
+
return {
|
|
1067
|
+
running: !stopped,
|
|
1068
|
+
sessionId,
|
|
1069
|
+
lastError,
|
|
1070
|
+
forwardedMessages: forwardedMessageCount
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
|
|
812
1076
|
// src/lib/live-bridge-openclaw.ts
|
|
813
1077
|
import { execFile } from "child_process";
|
|
814
1078
|
import { existsSync as existsSync5 } from "fs";
|
|
815
|
-
import { join as
|
|
1079
|
+
import { join as join6 } from "path";
|
|
816
1080
|
import { promisify } from "util";
|
|
817
1081
|
|
|
818
1082
|
// src/lib/live-bridge-openclaw-attachments.ts
|
|
819
1083
|
import { createHash } from "crypto";
|
|
820
1084
|
import { mkdirSync, renameSync, unlinkSync as unlinkSync2, writeFileSync } from "fs";
|
|
821
|
-
import { basename, extname, join as
|
|
1085
|
+
import { basename, extname, join as join5 } from "path";
|
|
822
1086
|
|
|
823
1087
|
// src/lib/live-bridge-openclaw-session.ts
|
|
824
1088
|
import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
|
|
825
|
-
import { join as
|
|
1089
|
+
import { join as join4 } from "path";
|
|
826
1090
|
|
|
827
1091
|
// src/lib/openclaw-paths.ts
|
|
828
1092
|
import { existsSync as existsSync3, readFileSync } from "fs";
|
|
829
1093
|
import { homedir } from "os";
|
|
830
|
-
import { dirname, isAbsolute, join as
|
|
1094
|
+
import { dirname, isAbsolute, join as join3, resolve } from "path";
|
|
831
1095
|
function trimToUndefined(value) {
|
|
832
1096
|
const trimmed = value?.trim();
|
|
833
1097
|
return trimmed ? trimmed : void 0;
|
|
@@ -846,7 +1110,7 @@ function resolveBaseHome(env) {
|
|
|
846
1110
|
function expandHomePrefix(input, home) {
|
|
847
1111
|
if (input === "~") return home;
|
|
848
1112
|
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
849
|
-
return
|
|
1113
|
+
return join3(home, input.slice(2));
|
|
850
1114
|
}
|
|
851
1115
|
return input;
|
|
852
1116
|
}
|
|
@@ -864,12 +1128,12 @@ function resolveOpenClawHome(env = process.env) {
|
|
|
864
1128
|
function resolveOpenClawStateDir(env = process.env) {
|
|
865
1129
|
const configured = trimToUndefined(env.OPENCLAW_STATE_DIR);
|
|
866
1130
|
if (configured) return resolvePathFromInput(configured, env);
|
|
867
|
-
return
|
|
1131
|
+
return join3(resolveOpenClawHome(env), ".openclaw");
|
|
868
1132
|
}
|
|
869
1133
|
function resolveOpenClawConfigPath(env = process.env) {
|
|
870
1134
|
const configured = trimToUndefined(env.OPENCLAW_CONFIG_PATH);
|
|
871
1135
|
if (configured) return resolvePathFromInput(configured, env);
|
|
872
|
-
return
|
|
1136
|
+
return join3(resolveOpenClawStateDir(env), "openclaw.json");
|
|
873
1137
|
}
|
|
874
1138
|
function readWorkspaceFromOpenClawConfig(configPath) {
|
|
875
1139
|
if (!existsSync3(configPath)) return null;
|
|
@@ -899,13 +1163,13 @@ function resolveOpenClawWorkspaceDir(env = process.env) {
|
|
|
899
1163
|
const configPath = resolveOpenClawConfigPath(env);
|
|
900
1164
|
const fromConfig = readWorkspaceFromOpenClawConfig(configPath);
|
|
901
1165
|
if (fromConfig) return resolveWorkspacePath(fromConfig, configPath, env);
|
|
902
|
-
return
|
|
1166
|
+
return join3(resolveOpenClawStateDir(env), "workspace");
|
|
903
1167
|
}
|
|
904
1168
|
|
|
905
1169
|
// src/lib/live-bridge-openclaw-session.ts
|
|
906
1170
|
var OPENCLAW_MAIN_SESSION_KEY = "agent:main:main";
|
|
907
1171
|
function resolveOpenClawSessionsPath(env = process.env) {
|
|
908
|
-
return
|
|
1172
|
+
return join4(resolveOpenClawStateDir(env), "agents", "main", "sessions", "sessions.json");
|
|
909
1173
|
}
|
|
910
1174
|
function buildThreadCandidateKeys(threadId) {
|
|
911
1175
|
const trimmed = threadId?.trim();
|
|
@@ -981,7 +1245,7 @@ var DEFAULT_ATTACHMENT_MAX_BYTES = 5 * 1024 * 1024;
|
|
|
981
1245
|
function resolveAttachmentRootDir() {
|
|
982
1246
|
const configured = process.env.OPENCLAW_ATTACHMENT_DIR?.trim();
|
|
983
1247
|
if (configured) return configured;
|
|
984
|
-
return
|
|
1248
|
+
return join5(resolveOpenClawStateDir(), "pubblue-inbox");
|
|
985
1249
|
}
|
|
986
1250
|
function resolveAttachmentMaxBytes() {
|
|
987
1251
|
const raw = Number.parseInt(process.env.OPENCLAW_ATTACHMENT_MAX_BYTES ?? "", 10);
|
|
@@ -1022,12 +1286,12 @@ function resolveAttachmentFilename(params) {
|
|
|
1022
1286
|
}
|
|
1023
1287
|
function ensureDirectoryWritable(dirPath) {
|
|
1024
1288
|
mkdirSync(dirPath, { recursive: true });
|
|
1025
|
-
const probe =
|
|
1289
|
+
const probe = join5(dirPath, `.bridge-writecheck-${process.pid}-${Date.now()}`);
|
|
1026
1290
|
writeFileSync(probe, "ok\n", { mode: 384 });
|
|
1027
1291
|
unlinkSync2(probe);
|
|
1028
1292
|
}
|
|
1029
1293
|
function stageAttachment(params) {
|
|
1030
|
-
const slugDir =
|
|
1294
|
+
const slugDir = join5(params.attachmentRoot, sanitizeFilename(params.slug));
|
|
1031
1295
|
ensureDirectoryWritable(slugDir);
|
|
1032
1296
|
const mime = (params.mime || "application/octet-stream").trim();
|
|
1033
1297
|
const resolvedName = resolveAttachmentFilename({
|
|
@@ -1037,7 +1301,7 @@ function stageAttachment(params) {
|
|
|
1037
1301
|
mime
|
|
1038
1302
|
});
|
|
1039
1303
|
const collisionSafeName = `${Date.now()}-${sanitizeFilename(params.messageId)}-${resolvedName}`;
|
|
1040
|
-
const targetPath =
|
|
1304
|
+
const targetPath = join5(slugDir, collisionSafeName);
|
|
1041
1305
|
const tempPath = `${targetPath}.tmp-${process.pid}`;
|
|
1042
1306
|
writeFileSync(tempPath, params.bytes, { mode: 384 });
|
|
1043
1307
|
renameSync(tempPath, targetPath);
|
|
@@ -1219,9 +1483,9 @@ function getOpenClawDiscoveryPaths(env = process.env) {
|
|
|
1219
1483
|
return [
|
|
1220
1484
|
.../* @__PURE__ */ new Set([
|
|
1221
1485
|
"/app/dist/index.js",
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1486
|
+
join6(home, "openclaw", "dist", "index.js"),
|
|
1487
|
+
join6(stateDir, "openclaw"),
|
|
1488
|
+
join6(home, ".openclaw", "openclaw"),
|
|
1225
1489
|
"/usr/local/bin/openclaw",
|
|
1226
1490
|
"/opt/homebrew/bin/openclaw"
|
|
1227
1491
|
])
|
|
@@ -1258,7 +1522,7 @@ function resolveOpenClawPath(env = process.env) {
|
|
|
1258
1522
|
"OpenClaw executable was not found.",
|
|
1259
1523
|
"Configure it with: pubblue configure --set openclaw.path=/absolute/path/to/openclaw",
|
|
1260
1524
|
"Or set OPENCLAW_PATH in environment.",
|
|
1261
|
-
|
|
1525
|
+
`Checked: ${discoveryPaths.join(", ")}`
|
|
1262
1526
|
].join(" ")
|
|
1263
1527
|
);
|
|
1264
1528
|
}
|
|
@@ -1486,35 +1750,35 @@ async function createOpenClawBridgeRunner(config) {
|
|
|
1486
1750
|
}
|
|
1487
1751
|
|
|
1488
1752
|
// src/lib/live-runtime/daemon-files.ts
|
|
1489
|
-
import * as
|
|
1490
|
-
import * as
|
|
1753
|
+
import * as fs4 from "fs";
|
|
1754
|
+
import * as path4 from "path";
|
|
1491
1755
|
|
|
1492
1756
|
// src/lib/config.ts
|
|
1493
|
-
import * as
|
|
1494
|
-
import * as
|
|
1757
|
+
import * as fs3 from "fs";
|
|
1758
|
+
import * as path3 from "path";
|
|
1495
1759
|
var DEFAULT_BASE_URL = "https://silent-guanaco-514.convex.site";
|
|
1496
1760
|
function getConfigDir(homeDir) {
|
|
1497
1761
|
const explicit = process.env.PUBBLUE_CONFIG_DIR?.trim();
|
|
1498
1762
|
if (explicit) return explicit;
|
|
1499
1763
|
if (homeDir) {
|
|
1500
|
-
return
|
|
1764
|
+
return path3.join(path3.resolve(homeDir), ".openclaw", "pubblue");
|
|
1501
1765
|
}
|
|
1502
|
-
return
|
|
1766
|
+
return path3.join(resolveOpenClawStateDir(), "pubblue");
|
|
1503
1767
|
}
|
|
1504
1768
|
function getConfigPath(homeDir) {
|
|
1505
1769
|
const dir = getConfigDir(homeDir);
|
|
1506
|
-
|
|
1507
|
-
return
|
|
1770
|
+
fs3.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
1771
|
+
return path3.join(dir, "config.json");
|
|
1508
1772
|
}
|
|
1509
1773
|
function readConfig(homeDir) {
|
|
1510
1774
|
const configPath = getConfigPath(homeDir);
|
|
1511
|
-
if (!
|
|
1512
|
-
const raw =
|
|
1775
|
+
if (!fs3.existsSync(configPath)) return null;
|
|
1776
|
+
const raw = fs3.readFileSync(configPath, "utf-8");
|
|
1513
1777
|
return JSON.parse(raw);
|
|
1514
1778
|
}
|
|
1515
1779
|
function saveConfig(config, homeDir) {
|
|
1516
1780
|
const configPath = getConfigPath(homeDir);
|
|
1517
|
-
|
|
1781
|
+
fs3.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
1518
1782
|
`, {
|
|
1519
1783
|
mode: 384
|
|
1520
1784
|
});
|
|
@@ -1546,15 +1810,15 @@ function getTelegramMiniAppUrl(slug) {
|
|
|
1546
1810
|
|
|
1547
1811
|
// src/lib/live-runtime/daemon-files.ts
|
|
1548
1812
|
function liveInfoDir() {
|
|
1549
|
-
const dir =
|
|
1550
|
-
|
|
1813
|
+
const dir = path4.join(getConfigDir(), "lives");
|
|
1814
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
1551
1815
|
return dir;
|
|
1552
1816
|
}
|
|
1553
1817
|
function liveInfoPath(slug) {
|
|
1554
|
-
return
|
|
1818
|
+
return path4.join(liveInfoDir(), `${slug}.json`);
|
|
1555
1819
|
}
|
|
1556
1820
|
function liveLogPath(slug) {
|
|
1557
|
-
return
|
|
1821
|
+
return path4.join(liveInfoDir(), `${slug}.log`);
|
|
1558
1822
|
}
|
|
1559
1823
|
function sanitizeSlugForFilename(slug) {
|
|
1560
1824
|
const sanitized = slug.trim().replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
@@ -1569,16 +1833,16 @@ function resolveSessionContentExtension(contentType) {
|
|
|
1569
1833
|
function liveSessionContentPath(slug, contentType, rootDir) {
|
|
1570
1834
|
const safeSlug = sanitizeSlugForFilename(slug);
|
|
1571
1835
|
const ext = resolveSessionContentExtension(contentType);
|
|
1572
|
-
return
|
|
1836
|
+
return path4.join(rootDir ?? liveInfoDir(), `${safeSlug}.session-content.${ext}`);
|
|
1573
1837
|
}
|
|
1574
1838
|
function writeLiveSessionContentFile(params) {
|
|
1575
1839
|
const filePath = liveSessionContentPath(params.slug, params.contentType, params.rootDir);
|
|
1576
|
-
|
|
1577
|
-
|
|
1840
|
+
fs4.mkdirSync(path4.dirname(filePath), { recursive: true });
|
|
1841
|
+
fs4.writeFileSync(filePath, params.content, "utf-8");
|
|
1578
1842
|
return filePath;
|
|
1579
1843
|
}
|
|
1580
1844
|
function latestCliVersionPath() {
|
|
1581
|
-
return
|
|
1845
|
+
return path4.join(liveInfoDir(), "cli-version.txt");
|
|
1582
1846
|
}
|
|
1583
1847
|
function isMissingPathError(error) {
|
|
1584
1848
|
if (typeof error !== "object" || error === null || !("code" in error)) return false;
|
|
@@ -1588,7 +1852,7 @@ function isMissingPathError(error) {
|
|
|
1588
1852
|
function readLatestCliVersion(versionPath) {
|
|
1589
1853
|
const resolved = versionPath || latestCliVersionPath();
|
|
1590
1854
|
try {
|
|
1591
|
-
const value =
|
|
1855
|
+
const value = fs4.readFileSync(resolved, "utf-8").trim();
|
|
1592
1856
|
return value.length === 0 ? null : value;
|
|
1593
1857
|
} catch (error) {
|
|
1594
1858
|
if (isMissingPathError(error)) return null;
|
|
@@ -1599,13 +1863,13 @@ function writeLatestCliVersion(version, versionPath) {
|
|
|
1599
1863
|
const trimmed = version.trim();
|
|
1600
1864
|
if (trimmed.length === 0) return;
|
|
1601
1865
|
const resolved = versionPath || latestCliVersionPath();
|
|
1602
|
-
const dir =
|
|
1603
|
-
|
|
1604
|
-
|
|
1866
|
+
const dir = path4.dirname(resolved);
|
|
1867
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
1868
|
+
fs4.writeFileSync(resolved, trimmed, "utf-8");
|
|
1605
1869
|
}
|
|
1606
1870
|
function readLogTail(logPath, maxChars = 4e3) {
|
|
1607
1871
|
try {
|
|
1608
|
-
const content =
|
|
1872
|
+
const content = fs4.readFileSync(logPath, "utf-8");
|
|
1609
1873
|
if (content.length <= maxChars) return content;
|
|
1610
1874
|
return content.slice(-maxChars);
|
|
1611
1875
|
} catch (error) {
|
|
@@ -1644,6 +1908,10 @@ export {
|
|
|
1644
1908
|
buildClaudeArgs,
|
|
1645
1909
|
runClaudeCodeBridgeStartupProbe,
|
|
1646
1910
|
createClaudeCodeBridgeRunner,
|
|
1911
|
+
isClaudeSdkAvailableInEnv,
|
|
1912
|
+
isClaudeSdkImportable,
|
|
1913
|
+
runClaudeSdkBridgeStartupProbe,
|
|
1914
|
+
createClaudeSdkBridgeRunner,
|
|
1647
1915
|
isOpenClawAvailable,
|
|
1648
1916
|
resolveOpenClawRuntime,
|
|
1649
1917
|
runOpenClawBridgeStartupProbe,
|