negotium 0.2.13 → 0.2.14
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/agent-helpers.js +13 -12
- package/dist/agent-helpers.js.map +6 -6
- package/dist/background-bash.js +11 -11
- package/dist/background-bash.js.map +4 -4
- package/dist/browser-runtime.js +2 -3
- package/dist/browser-runtime.js.map +3 -3
- package/dist/{chunk-rnsnhcye.js → chunk-5g5a63vv.js} +11 -11
- package/dist/{chunk-rnsnhcye.js.map → chunk-5g5a63vv.js.map} +4 -4
- package/dist/hosted-agent.js +12 -12
- package/dist/hosted-agent.js.map +5 -5
- package/dist/main.js +582 -357
- package/dist/main.js.map +12 -11
- package/dist/mcp-factories.js +13 -12
- package/dist/mcp-factories.js.map +6 -6
- package/dist/mcp-servers.js +3 -2
- package/dist/mcp-servers.js.map +3 -3
- package/dist/prompts.js +2 -3
- package/dist/prompts.js.map +3 -3
- package/dist/query-runtime.js +2 -3
- package/dist/query-runtime.js.map +3 -3
- package/dist/registry.js +3 -3
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/index.ts +9 -0
- package/dist/runtime/src/node-host.ts +9 -0
- package/dist/runtime/src/platform/background-bash/manager.ts +30 -22
- package/dist/runtime/src/platform/config.ts +8 -7
- package/dist/runtime/src/runtime/bashrs-completions.ts +74 -14
- package/dist/runtime/src/runtime/turn-runner.ts +6 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +2 -3
- package/dist/runtime-helpers.js.map +3 -3
- package/dist/types/apps/negotium/src/mcp-servers.d.ts +16 -3
- package/dist/types/packages/core/src/platform/background-bash/manager.d.ts +6 -1
- package/dist/types/packages/core/src/platform/config.d.ts +8 -6
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +2 -3
- package/dist/vault.js.map +3 -3
- package/install-bash-rs.mjs +5 -5
- package/package.json +1 -1
- package/dist/runtime/src/mcp/background-bash-server.ts +0 -756
package/dist/main.js
CHANGED
|
@@ -263,7 +263,7 @@ function resolveDefaultModel(agent, registryDefaultModel) {
|
|
|
263
263
|
function codexAuthFilePath() {
|
|
264
264
|
return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
|
|
265
265
|
}
|
|
266
|
-
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.19", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.
|
|
266
|
+
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.19", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.5", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, BASHRS_SPILL_ROOT, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
|
|
267
267
|
var init_config = __esm(() => {
|
|
268
268
|
init_config_helpers();
|
|
269
269
|
init_logger();
|
|
@@ -300,7 +300,6 @@ var init_config = __esm(() => {
|
|
|
300
300
|
COMPACTION_LOG_SERVER = resolve(PROJECT_ROOT, "src/mcp/compaction-log-server.ts");
|
|
301
301
|
SYSTEM_HEALTH_SERVER = resolve(PROJECT_ROOT, "src/mcp/system-health-server.ts");
|
|
302
302
|
AGENT_HEALTH_SERVER = resolve(PROJECT_ROOT, "src/mcp/agent-health-server.ts");
|
|
303
|
-
BACKGROUND_BASH_SERVER = resolve(PROJECT_ROOT, "src/mcp/background-bash-server.ts");
|
|
304
303
|
VAULT_SERVER = resolve(PROJECT_ROOT, "src/mcp/vault-server.ts");
|
|
305
304
|
BG_BASH_BASE_PORT = parsePortEnv(process.env.BG_BASH_BASE_PORT, 9700);
|
|
306
305
|
BG_BASH_MAX_PORT = parsePortEnv(process.env.BG_BASH_MAX_PORT, 9799);
|
|
@@ -1573,7 +1572,7 @@ var exports_version = {};
|
|
|
1573
1572
|
__export(exports_version, {
|
|
1574
1573
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
1575
1574
|
});
|
|
1576
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
1575
|
+
var NEGOTIUM_VERSION = "0.2.14";
|
|
1577
1576
|
|
|
1578
1577
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
1579
1578
|
import { spawn } from "child_process";
|
|
@@ -2117,7 +2116,7 @@ function createBackgroundBashManager(options = {}) {
|
|
|
2117
2116
|
const knownContexts = new Map;
|
|
2118
2117
|
const runtimeCapability = options.capability ?? randomBytes3(32).toString("hex");
|
|
2119
2118
|
const runtimeServerId = options.serverId ?? randomBytes3(16).toString("hex");
|
|
2120
|
-
const
|
|
2119
|
+
const bashRsBin = options.bashRsBin ?? BASH_RS_BIN;
|
|
2121
2120
|
const basePort = options.basePort ?? BG_BASH_BASE_PORT;
|
|
2122
2121
|
const maxPort = options.maxPort ?? BG_BASH_MAX_PORT;
|
|
2123
2122
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -2154,11 +2153,10 @@ function createBackgroundBashManager(options = {}) {
|
|
|
2154
2153
|
const body = await response.text();
|
|
2155
2154
|
try {
|
|
2156
2155
|
const parsed = JSON.parse(body);
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
}
|
|
2161
|
-
return body === runtimeServerId;
|
|
2156
|
+
return Boolean(parsed) && typeof parsed === "object" && parsed.instance_id === runtimeServerId;
|
|
2157
|
+
} catch {
|
|
2158
|
+
return false;
|
|
2159
|
+
}
|
|
2162
2160
|
} catch {
|
|
2163
2161
|
return false;
|
|
2164
2162
|
}
|
|
@@ -2176,9 +2174,11 @@ function createBackgroundBashManager(options = {}) {
|
|
|
2176
2174
|
logger.info({ key, port: instance.port }, "background-bash server killed");
|
|
2177
2175
|
}
|
|
2178
2176
|
async function spawnServer(key, reservedPort, excludedPorts = new Set) {
|
|
2177
|
+
if (!bashRsBin) {
|
|
2178
|
+
throw new Error(`background-bash requires the bash-rs ${BASH_RS_VERSION} binary; run install-bash-rs.mjs (or set NEGOTIUM_BASH_RS_BIN)`);
|
|
2179
|
+
}
|
|
2179
2180
|
const port = reservedPort ?? await allocatePort(excludedPorts);
|
|
2180
|
-
const
|
|
2181
|
-
const process2 = spawnImpl(command, args, {
|
|
2181
|
+
const process2 = spawnImpl(bashRsBin, [String(port)], {
|
|
2182
2182
|
stdio: "ignore",
|
|
2183
2183
|
detached: false,
|
|
2184
2184
|
env: {
|
|
@@ -18642,6 +18642,7 @@ function startAiTurn(params) {
|
|
|
18642
18642
|
bgBashPort = await ensureBgBash(userId, topic.id);
|
|
18643
18643
|
} catch (err2) {
|
|
18644
18644
|
logger.warn({ topicId, err: err2 }, "ai: ensureBgBash failed \u2014 proceeding without background bash tools");
|
|
18645
|
+
turnReminders.push("<system-reminder>Background bash tools are UNAVAILABLE this turn. The `background_bash_*` tools could not be prepared, most often because the bash-rs binary is not installed on this host. Do not attempt to call them; run short commands in the foreground instead, and tell the user if the work genuinely needs a background job.</system-reminder>");
|
|
18645
18646
|
}
|
|
18646
18647
|
}
|
|
18647
18648
|
if (playwrightRequested && !browserProfileOwner) {
|
|
@@ -20984,6 +20985,276 @@ var init_node_plugins = __esm(() => {
|
|
|
20984
20985
|
plugins = [];
|
|
20985
20986
|
});
|
|
20986
20987
|
|
|
20988
|
+
// ../../packages/core/src/outbox/utils.ts
|
|
20989
|
+
import { mkdirSync as mkdirSync22, watch } from "fs";
|
|
20990
|
+
function createOutboxWatchOps(host) {
|
|
20991
|
+
function debouncedFlush(fn, label, delayMs) {
|
|
20992
|
+
let timer = null;
|
|
20993
|
+
let running = false;
|
|
20994
|
+
let pending = false;
|
|
20995
|
+
async function run() {
|
|
20996
|
+
if (running) {
|
|
20997
|
+
pending = true;
|
|
20998
|
+
return;
|
|
20999
|
+
}
|
|
21000
|
+
while (true) {
|
|
21001
|
+
running = true;
|
|
21002
|
+
pending = false;
|
|
21003
|
+
try {
|
|
21004
|
+
await fn();
|
|
21005
|
+
} catch (e) {
|
|
21006
|
+
host.logger.error({ err: e }, `${label}: Unhandled error`);
|
|
21007
|
+
} finally {
|
|
21008
|
+
running = false;
|
|
21009
|
+
}
|
|
21010
|
+
if (!pending)
|
|
21011
|
+
break;
|
|
21012
|
+
}
|
|
21013
|
+
}
|
|
21014
|
+
return () => {
|
|
21015
|
+
if (timer)
|
|
21016
|
+
clearTimeout(timer);
|
|
21017
|
+
timer = setTimeout(() => {
|
|
21018
|
+
timer = null;
|
|
21019
|
+
run();
|
|
21020
|
+
}, delayMs);
|
|
21021
|
+
};
|
|
21022
|
+
}
|
|
21023
|
+
function watchDir(dir, onChange) {
|
|
21024
|
+
try {
|
|
21025
|
+
mkdirSync22(dir, { recursive: true });
|
|
21026
|
+
const watcher = watch(dir, { recursive: true }, () => onChange());
|
|
21027
|
+
watcher.on("error", (e) => {
|
|
21028
|
+
host.logger.warn({ err: e, dir }, "outbox: fs.watch error");
|
|
21029
|
+
});
|
|
21030
|
+
return watcher;
|
|
21031
|
+
} catch (e) {
|
|
21032
|
+
host.logger.warn({ err: e, dir }, "outbox: Failed to watch dir");
|
|
21033
|
+
return null;
|
|
21034
|
+
}
|
|
21035
|
+
}
|
|
21036
|
+
return { debouncedFlush, watchDir };
|
|
21037
|
+
}
|
|
21038
|
+
var FALLBACK_INTERVAL_MS = 5000, defaultWatchOps, debouncedFlush, watchDir;
|
|
21039
|
+
var init_utils = __esm(() => {
|
|
21040
|
+
init_logger();
|
|
21041
|
+
defaultWatchOps = createOutboxWatchOps({ logger });
|
|
21042
|
+
debouncedFlush = defaultWatchOps.debouncedFlush;
|
|
21043
|
+
watchDir = defaultWatchOps.watchDir;
|
|
21044
|
+
});
|
|
21045
|
+
|
|
21046
|
+
// ../../packages/core/src/runtime/bashrs-completions.ts
|
|
21047
|
+
import {
|
|
21048
|
+
closeSync as closeSync3,
|
|
21049
|
+
openSync as openSync3,
|
|
21050
|
+
readdirSync as readdirSync7,
|
|
21051
|
+
readFileSync as readFileSync18,
|
|
21052
|
+
readSync,
|
|
21053
|
+
renameSync as renameSync9,
|
|
21054
|
+
rmSync as rmSync8,
|
|
21055
|
+
statSync as statSync12
|
|
21056
|
+
} from "fs";
|
|
21057
|
+
import { join as join31 } from "path";
|
|
21058
|
+
function setBashrsCompletionSink(sink) {
|
|
21059
|
+
completionSink = sink ?? defaultSink;
|
|
21060
|
+
}
|
|
21061
|
+
function isJobResult(value) {
|
|
21062
|
+
if (!value || typeof value !== "object")
|
|
21063
|
+
return false;
|
|
21064
|
+
const v = value;
|
|
21065
|
+
return typeof v.bash_id === "string" && typeof v.owner === "string";
|
|
21066
|
+
}
|
|
21067
|
+
function readTail(filePath) {
|
|
21068
|
+
try {
|
|
21069
|
+
const { size } = statSync12(filePath);
|
|
21070
|
+
const fd = openSync3(filePath, "r");
|
|
21071
|
+
try {
|
|
21072
|
+
const start = Math.max(0, size - TAIL_BYTES);
|
|
21073
|
+
const buf = Buffer.alloc(size - start);
|
|
21074
|
+
readSync(fd, buf, 0, buf.length, start);
|
|
21075
|
+
return { text: buf.toString("utf8"), truncated: start > 0 };
|
|
21076
|
+
} finally {
|
|
21077
|
+
closeSync3(fd);
|
|
21078
|
+
}
|
|
21079
|
+
} catch {
|
|
21080
|
+
return { text: "", truncated: false };
|
|
21081
|
+
}
|
|
21082
|
+
}
|
|
21083
|
+
function buildMessage(dir, result) {
|
|
21084
|
+
const stdout = readTail(join31(dir, "stdout.log"));
|
|
21085
|
+
const stderr = readTail(join31(dir, "stderr.log"));
|
|
21086
|
+
const parts = [];
|
|
21087
|
+
if (stdout.text.trim() || stdout.truncated) {
|
|
21088
|
+
parts.push(`stdout${stdout.truncated ? ` (truncated, full output: ${join31(dir, "stdout.log")})` : ""}:
|
|
21089
|
+
${stdout.text.trim()}`);
|
|
21090
|
+
}
|
|
21091
|
+
if (stderr.text.trim() || stderr.truncated) {
|
|
21092
|
+
parts.push(`stderr${stderr.truncated ? ` (truncated, full output: ${join31(dir, "stderr.log")})` : ""}:
|
|
21093
|
+
${stderr.text.trim()}`);
|
|
21094
|
+
}
|
|
21095
|
+
const header = watchHeader(result) ?? `[background_bash ${result.bash_id} finished]`;
|
|
21096
|
+
const exitLine = result.unknown ? "exit code: unknown (bash-rs restarted while this job was running)" : `exit code: ${result.exit_code ?? "unknown"}`;
|
|
21097
|
+
return `${header}
|
|
21098
|
+
${exitLine}
|
|
21099
|
+
${parts.join(`
|
|
21100
|
+
`) || "(no output)"}`;
|
|
21101
|
+
}
|
|
21102
|
+
function watchHeader(result) {
|
|
21103
|
+
if (result.matched_line) {
|
|
21104
|
+
return `[background_bash_watch ${result.bash_id} matched]
|
|
21105
|
+
matched line: ${result.matched_line.slice(0, 500)}`;
|
|
21106
|
+
}
|
|
21107
|
+
if (result.watch_outcome === "timeout") {
|
|
21108
|
+
return `[background_bash_watch ${result.bash_id} timed out without a match]`;
|
|
21109
|
+
}
|
|
21110
|
+
if (result.watch_outcome === "exited") {
|
|
21111
|
+
return `[background_bash_watch ${result.bash_id} exited before matching]`;
|
|
21112
|
+
}
|
|
21113
|
+
return null;
|
|
21114
|
+
}
|
|
21115
|
+
function parseOwner(owner) {
|
|
21116
|
+
const nul = owner.indexOf("\x00");
|
|
21117
|
+
if (nul < 0)
|
|
21118
|
+
return null;
|
|
21119
|
+
const userId = owner.slice(0, nul);
|
|
21120
|
+
const topicId = owner.slice(nul + 1);
|
|
21121
|
+
if (!userId || !topicId)
|
|
21122
|
+
return null;
|
|
21123
|
+
return { userId, topicId };
|
|
21124
|
+
}
|
|
21125
|
+
function injectedMarker(dir) {
|
|
21126
|
+
return join31(dir, "result.json.injected");
|
|
21127
|
+
}
|
|
21128
|
+
async function flushBashrsCompletions() {
|
|
21129
|
+
let entries;
|
|
21130
|
+
try {
|
|
21131
|
+
entries = readdirSync7(BASHRS_SPILL_ROOT);
|
|
21132
|
+
} catch {
|
|
21133
|
+
return;
|
|
21134
|
+
}
|
|
21135
|
+
const now = Date.now();
|
|
21136
|
+
for (const bashId of entries) {
|
|
21137
|
+
const dir = join31(BASHRS_SPILL_ROOT, bashId);
|
|
21138
|
+
const resultPath = join31(dir, "result.json");
|
|
21139
|
+
const marker = injectedMarker(dir);
|
|
21140
|
+
try {
|
|
21141
|
+
const markerStat = statSync12(marker);
|
|
21142
|
+
if (now - markerStat.mtimeMs > RETENTION_MS) {
|
|
21143
|
+
rmSync8(dir, { recursive: true, force: true });
|
|
21144
|
+
}
|
|
21145
|
+
continue;
|
|
21146
|
+
} catch {}
|
|
21147
|
+
let raw;
|
|
21148
|
+
try {
|
|
21149
|
+
raw = readFileSync18(resultPath, "utf8");
|
|
21150
|
+
} catch {
|
|
21151
|
+
continue;
|
|
21152
|
+
}
|
|
21153
|
+
let result;
|
|
21154
|
+
try {
|
|
21155
|
+
result = JSON.parse(raw);
|
|
21156
|
+
} catch (err2) {
|
|
21157
|
+
logger.warn({ err: err2, dir }, "bashrs-completions: corrupt result.json, skipping");
|
|
21158
|
+
continue;
|
|
21159
|
+
}
|
|
21160
|
+
if (!isJobResult(result)) {
|
|
21161
|
+
logger.warn({ dir }, "bashrs-completions: result.json missing bash_id/owner, skipping");
|
|
21162
|
+
continue;
|
|
21163
|
+
}
|
|
21164
|
+
const parsed = parseOwner(result.owner);
|
|
21165
|
+
if (!parsed) {
|
|
21166
|
+
continue;
|
|
21167
|
+
}
|
|
21168
|
+
try {
|
|
21169
|
+
completionSink({
|
|
21170
|
+
userId: parsed.userId,
|
|
21171
|
+
topicId: parsed.topicId,
|
|
21172
|
+
bashId: result.bash_id,
|
|
21173
|
+
message: buildMessage(dir, result)
|
|
21174
|
+
});
|
|
21175
|
+
renameSync9(resultPath, marker);
|
|
21176
|
+
logger.info({ bashId: result.bash_id, userId: parsed.userId, topicId: parsed.topicId }, "bashrs-completions: delivered");
|
|
21177
|
+
} catch (err2) {
|
|
21178
|
+
logger.warn({ err: err2, dir }, "bashrs-completions: delivery failed, will retry");
|
|
21179
|
+
}
|
|
21180
|
+
}
|
|
21181
|
+
}
|
|
21182
|
+
function stopLeaderResources() {
|
|
21183
|
+
if (watcher) {
|
|
21184
|
+
watcher.close();
|
|
21185
|
+
watcher = null;
|
|
21186
|
+
}
|
|
21187
|
+
if (fallbackTimer) {
|
|
21188
|
+
clearInterval(fallbackTimer);
|
|
21189
|
+
fallbackTimer = null;
|
|
21190
|
+
}
|
|
21191
|
+
debouncedTrigger = null;
|
|
21192
|
+
}
|
|
21193
|
+
function tryBecomeLeader() {
|
|
21194
|
+
if (!workerStarted || workerLease)
|
|
21195
|
+
return;
|
|
21196
|
+
const acquired = acquireRuntimeProcessLease(PROCESS_ROLE, {
|
|
21197
|
+
onLost: () => {
|
|
21198
|
+
if (workerLease !== acquired)
|
|
21199
|
+
return;
|
|
21200
|
+
workerLease = null;
|
|
21201
|
+
stopLeaderResources();
|
|
21202
|
+
logger.warn("bashrs-completions: worker leadership lost");
|
|
21203
|
+
}
|
|
21204
|
+
});
|
|
21205
|
+
if (!acquired)
|
|
21206
|
+
return;
|
|
21207
|
+
workerLease = acquired;
|
|
21208
|
+
debouncedTrigger = debouncedFlush(flushBashrsCompletions, "bashrs-completions", 200);
|
|
21209
|
+
watcher = watchDir(BASHRS_SPILL_ROOT, () => debouncedTrigger?.());
|
|
21210
|
+
fallbackTimer = setInterval(() => debouncedTrigger?.(), FALLBACK_INTERVAL_MS);
|
|
21211
|
+
fallbackTimer.unref?.();
|
|
21212
|
+
logger.info({ dir: BASHRS_SPILL_ROOT, role: PROCESS_ROLE }, "bashrs-completions: worker leadership acquired");
|
|
21213
|
+
flushBashrsCompletions();
|
|
21214
|
+
}
|
|
21215
|
+
function startBashrsCompletionsWorker() {
|
|
21216
|
+
if (workerStarted)
|
|
21217
|
+
return () => {};
|
|
21218
|
+
workerStarted = true;
|
|
21219
|
+
tryBecomeLeader();
|
|
21220
|
+
leadershipTimer = setInterval(tryBecomeLeader, PROCESS_LEASE_HEARTBEAT_MS);
|
|
21221
|
+
leadershipTimer.unref?.();
|
|
21222
|
+
return () => {
|
|
21223
|
+
if (!workerStarted)
|
|
21224
|
+
return;
|
|
21225
|
+
workerStarted = false;
|
|
21226
|
+
if (leadershipTimer) {
|
|
21227
|
+
clearInterval(leadershipTimer);
|
|
21228
|
+
leadershipTimer = null;
|
|
21229
|
+
}
|
|
21230
|
+
stopLeaderResources();
|
|
21231
|
+
workerLease?.stop();
|
|
21232
|
+
workerLease = null;
|
|
21233
|
+
logger.info("bashrs-completions: worker stopped");
|
|
21234
|
+
};
|
|
21235
|
+
}
|
|
21236
|
+
var defaultSink = ({ userId, topicId, bashId, message }) => {
|
|
21237
|
+
appendJsonlEntry(sessionInboxPath(userId, topicId), {
|
|
21238
|
+
type: "tell",
|
|
21239
|
+
from: "__bg_bash__",
|
|
21240
|
+
message,
|
|
21241
|
+
depth: 0,
|
|
21242
|
+
requestId: bashId,
|
|
21243
|
+
timestamp: new Date().toISOString()
|
|
21244
|
+
});
|
|
21245
|
+
}, completionSink, PROCESS_ROLE = "worker:bashrs-completions", RETENTION_MS, TAIL_BYTES, watcher = null, fallbackTimer = null, debouncedTrigger = null, leadershipTimer = null, workerLease = null, workerStarted = false;
|
|
21246
|
+
var init_bashrs_completions = __esm(async () => {
|
|
21247
|
+
init_utils();
|
|
21248
|
+
init_config();
|
|
21249
|
+
init_jsonl();
|
|
21250
|
+
init_logger();
|
|
21251
|
+
init_session_inbox_path();
|
|
21252
|
+
await init_runtime_process_leases();
|
|
21253
|
+
completionSink = defaultSink;
|
|
21254
|
+
RETENTION_MS = 15 * 60000;
|
|
21255
|
+
TAIL_BYTES = 8 * 1024;
|
|
21256
|
+
});
|
|
21257
|
+
|
|
20987
21258
|
// ../../packages/core/src/runtime/delivery-ack.ts
|
|
20988
21259
|
function signalForMessage(payload, messageId) {
|
|
20989
21260
|
if (!payload || typeof payload !== "object")
|
|
@@ -21070,7 +21341,7 @@ function renderTurnFooter(msg) {
|
|
|
21070
21341
|
|
|
21071
21342
|
// ../../packages/core/src/outbox/file-ops.ts
|
|
21072
21343
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
21073
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync22, readFileSync as
|
|
21344
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync22, readFileSync as readFileSync19, renameSync as renameSync10, unlinkSync as unlinkSync17 } from "fs";
|
|
21074
21345
|
function host() {
|
|
21075
21346
|
return hostContext.getStore() ?? defaultHost2;
|
|
21076
21347
|
}
|
|
@@ -21097,7 +21368,7 @@ function drainOutboxFile(filePath, label) {
|
|
|
21097
21368
|
else
|
|
21098
21369
|
host().logger.info(logCtx, logMsg);
|
|
21099
21370
|
try {
|
|
21100
|
-
const leftover =
|
|
21371
|
+
const leftover = readFileSync19(processingPath, "utf-8");
|
|
21101
21372
|
if (leftover)
|
|
21102
21373
|
appendFileSync2(filePath, leftover.endsWith(`
|
|
21103
21374
|
`) ? leftover : `${leftover}
|
|
@@ -21111,7 +21382,7 @@ function drainOutboxFile(filePath, label) {
|
|
|
21111
21382
|
if (!existsSync22(filePath))
|
|
21112
21383
|
return null;
|
|
21113
21384
|
try {
|
|
21114
|
-
|
|
21385
|
+
renameSync10(filePath, processingPath);
|
|
21115
21386
|
} catch (e) {
|
|
21116
21387
|
host().logger.warn({ err: e, filePath }, `${label}: failed to rename for processing`);
|
|
21117
21388
|
return null;
|
|
@@ -21159,68 +21430,10 @@ var init_file_ops = __esm(() => {
|
|
|
21159
21430
|
hostContext = new AsyncLocalStorage2;
|
|
21160
21431
|
});
|
|
21161
21432
|
|
|
21162
|
-
// ../../packages/core/src/outbox/utils.ts
|
|
21163
|
-
import { mkdirSync as mkdirSync22, watch } from "fs";
|
|
21164
|
-
function createOutboxWatchOps(host2) {
|
|
21165
|
-
function debouncedFlush(fn, label, delayMs) {
|
|
21166
|
-
let timer = null;
|
|
21167
|
-
let running = false;
|
|
21168
|
-
let pending = false;
|
|
21169
|
-
async function run() {
|
|
21170
|
-
if (running) {
|
|
21171
|
-
pending = true;
|
|
21172
|
-
return;
|
|
21173
|
-
}
|
|
21174
|
-
while (true) {
|
|
21175
|
-
running = true;
|
|
21176
|
-
pending = false;
|
|
21177
|
-
try {
|
|
21178
|
-
await fn();
|
|
21179
|
-
} catch (e) {
|
|
21180
|
-
host2.logger.error({ err: e }, `${label}: Unhandled error`);
|
|
21181
|
-
} finally {
|
|
21182
|
-
running = false;
|
|
21183
|
-
}
|
|
21184
|
-
if (!pending)
|
|
21185
|
-
break;
|
|
21186
|
-
}
|
|
21187
|
-
}
|
|
21188
|
-
return () => {
|
|
21189
|
-
if (timer)
|
|
21190
|
-
clearTimeout(timer);
|
|
21191
|
-
timer = setTimeout(() => {
|
|
21192
|
-
timer = null;
|
|
21193
|
-
run();
|
|
21194
|
-
}, delayMs);
|
|
21195
|
-
};
|
|
21196
|
-
}
|
|
21197
|
-
function watchDir(dir, onChange) {
|
|
21198
|
-
try {
|
|
21199
|
-
mkdirSync22(dir, { recursive: true });
|
|
21200
|
-
const watcher = watch(dir, { recursive: true }, () => onChange());
|
|
21201
|
-
watcher.on("error", (e) => {
|
|
21202
|
-
host2.logger.warn({ err: e, dir }, "outbox: fs.watch error");
|
|
21203
|
-
});
|
|
21204
|
-
return watcher;
|
|
21205
|
-
} catch (e) {
|
|
21206
|
-
host2.logger.warn({ err: e, dir }, "outbox: Failed to watch dir");
|
|
21207
|
-
return null;
|
|
21208
|
-
}
|
|
21209
|
-
}
|
|
21210
|
-
return { debouncedFlush, watchDir };
|
|
21211
|
-
}
|
|
21212
|
-
var FALLBACK_INTERVAL_MS = 5000, defaultWatchOps, debouncedFlush, watchDir;
|
|
21213
|
-
var init_utils = __esm(() => {
|
|
21214
|
-
init_logger();
|
|
21215
|
-
defaultWatchOps = createOutboxWatchOps({ logger });
|
|
21216
|
-
debouncedFlush = defaultWatchOps.debouncedFlush;
|
|
21217
|
-
watchDir = defaultWatchOps.watchDir;
|
|
21218
|
-
});
|
|
21219
|
-
|
|
21220
21433
|
// ../../packages/core/src/runtime/inbox.ts
|
|
21221
21434
|
import { createHash as createHash8, randomUUID as randomUUID20 } from "crypto";
|
|
21222
|
-
import { readdirSync as
|
|
21223
|
-
import { join as
|
|
21435
|
+
import { readdirSync as readdirSync8, statSync as statSync13, writeFileSync as writeFileSync16 } from "fs";
|
|
21436
|
+
import { join as join32 } from "path";
|
|
21224
21437
|
async function createAskForkPlan(options) {
|
|
21225
21438
|
const snapshot = structuredClone(options.entries);
|
|
21226
21439
|
const prepareSession = async () => options.synthesize(structuredClone(snapshot));
|
|
@@ -21340,23 +21553,23 @@ async function flushSessionInbox() {
|
|
|
21340
21553
|
sweepScheduledSessionInbox();
|
|
21341
21554
|
let userDirs;
|
|
21342
21555
|
try {
|
|
21343
|
-
userDirs =
|
|
21556
|
+
userDirs = readdirSync8(SESSION_INBOX_DIR);
|
|
21344
21557
|
} catch {
|
|
21345
21558
|
return;
|
|
21346
21559
|
}
|
|
21347
21560
|
for (const uid of userDirs) {
|
|
21348
|
-
const userInboxDir =
|
|
21561
|
+
const userInboxDir = join32(SESSION_INBOX_DIR, uid);
|
|
21349
21562
|
let entries;
|
|
21350
21563
|
try {
|
|
21351
|
-
entries =
|
|
21564
|
+
entries = readdirSync8(userInboxDir);
|
|
21352
21565
|
} catch {
|
|
21353
21566
|
continue;
|
|
21354
21567
|
}
|
|
21355
21568
|
for (const entry of entries) {
|
|
21356
|
-
const entryPath =
|
|
21569
|
+
const entryPath = join32(userInboxDir, entry);
|
|
21357
21570
|
let isDir = false;
|
|
21358
21571
|
try {
|
|
21359
|
-
isDir =
|
|
21572
|
+
isDir = statSync13(entryPath).isDirectory();
|
|
21360
21573
|
} catch {
|
|
21361
21574
|
continue;
|
|
21362
21575
|
}
|
|
@@ -21438,15 +21651,15 @@ ${schedule.message}`, topic.agent, {
|
|
|
21438
21651
|
function sweepScheduledSessionInbox(nowMs = Date.now()) {
|
|
21439
21652
|
let userDirs;
|
|
21440
21653
|
try {
|
|
21441
|
-
userDirs =
|
|
21654
|
+
userDirs = readdirSync8(SESSION_INBOX_DIR);
|
|
21442
21655
|
} catch {
|
|
21443
21656
|
return;
|
|
21444
21657
|
}
|
|
21445
21658
|
for (const userId of userDirs) {
|
|
21446
|
-
const userInboxDir =
|
|
21659
|
+
const userInboxDir = join32(SESSION_INBOX_DIR, userId);
|
|
21447
21660
|
let files;
|
|
21448
21661
|
try {
|
|
21449
|
-
files =
|
|
21662
|
+
files = readdirSync8(userInboxDir);
|
|
21450
21663
|
} catch {
|
|
21451
21664
|
continue;
|
|
21452
21665
|
}
|
|
@@ -21455,7 +21668,7 @@ function sweepScheduledSessionInbox(nowMs = Date.now()) {
|
|
|
21455
21668
|
const topicId = topicIdFromScheduledSessionInboxFileName(file);
|
|
21456
21669
|
if (!topicId)
|
|
21457
21670
|
continue;
|
|
21458
|
-
const schedulePath =
|
|
21671
|
+
const schedulePath = join32(userInboxDir, file);
|
|
21459
21672
|
const hasProcessingClaim = files.includes(`${file}.processing`);
|
|
21460
21673
|
if (!hasProcessingClaim && !scheduledFileNeedsClaim(schedulePath, nowMs))
|
|
21461
21674
|
continue;
|
|
@@ -21809,62 +22022,62 @@ ${entry.message}
|
|
|
21809
22022
|
});
|
|
21810
22023
|
logger.info({ topicName, from: entry.from, requestId, callerTopicId }, "session-inbox: ask delivered");
|
|
21811
22024
|
}
|
|
21812
|
-
function
|
|
21813
|
-
if (
|
|
21814
|
-
|
|
21815
|
-
|
|
22025
|
+
function stopLeaderResources2() {
|
|
22026
|
+
if (watcher2) {
|
|
22027
|
+
watcher2.close();
|
|
22028
|
+
watcher2 = null;
|
|
21816
22029
|
}
|
|
21817
|
-
if (
|
|
21818
|
-
clearInterval(
|
|
21819
|
-
|
|
22030
|
+
if (fallbackTimer2) {
|
|
22031
|
+
clearInterval(fallbackTimer2);
|
|
22032
|
+
fallbackTimer2 = null;
|
|
21820
22033
|
}
|
|
21821
|
-
|
|
22034
|
+
debouncedTrigger2 = null;
|
|
21822
22035
|
}
|
|
21823
22036
|
function tryBecomeSessionInboxLeader() {
|
|
21824
|
-
if (!
|
|
22037
|
+
if (!workerStarted2 || workerLease2)
|
|
21825
22038
|
return;
|
|
21826
22039
|
let acquired = null;
|
|
21827
22040
|
acquired = acquireRuntimeProcessLease(SESSION_INBOX_PROCESS_ROLE, {
|
|
21828
22041
|
onLost: () => {
|
|
21829
|
-
if (
|
|
22042
|
+
if (workerLease2 !== acquired)
|
|
21830
22043
|
return;
|
|
21831
|
-
|
|
21832
|
-
|
|
22044
|
+
workerLease2 = null;
|
|
22045
|
+
stopLeaderResources2();
|
|
21833
22046
|
logger.warn("session-inbox: worker leadership lost");
|
|
21834
22047
|
}
|
|
21835
22048
|
});
|
|
21836
22049
|
if (!acquired)
|
|
21837
22050
|
return;
|
|
21838
|
-
|
|
21839
|
-
|
|
21840
|
-
|
|
21841
|
-
|
|
21842
|
-
|
|
22051
|
+
workerLease2 = acquired;
|
|
22052
|
+
debouncedTrigger2 = debouncedFlush(flushSessionInbox, "session-inbox", 200);
|
|
22053
|
+
watcher2 = watchDir(SESSION_INBOX_DIR, () => debouncedTrigger2?.());
|
|
22054
|
+
fallbackTimer2 = setInterval(() => debouncedTrigger2?.(), FALLBACK_INTERVAL_MS);
|
|
22055
|
+
fallbackTimer2.unref?.();
|
|
21843
22056
|
logger.info({ dir: SESSION_INBOX_DIR, role: SESSION_INBOX_PROCESS_ROLE }, "session-inbox: worker leadership acquired");
|
|
21844
22057
|
flushSessionInbox();
|
|
21845
22058
|
}
|
|
21846
22059
|
function startSessionInboxWorker() {
|
|
21847
|
-
if (
|
|
22060
|
+
if (workerStarted2)
|
|
21848
22061
|
return () => {};
|
|
21849
|
-
|
|
22062
|
+
workerStarted2 = true;
|
|
21850
22063
|
tryBecomeSessionInboxLeader();
|
|
21851
|
-
|
|
21852
|
-
|
|
22064
|
+
leadershipTimer2 = setInterval(tryBecomeSessionInboxLeader, PROCESS_LEASE_HEARTBEAT_MS);
|
|
22065
|
+
leadershipTimer2.unref?.();
|
|
21853
22066
|
return () => {
|
|
21854
|
-
if (!
|
|
22067
|
+
if (!workerStarted2)
|
|
21855
22068
|
return;
|
|
21856
|
-
|
|
21857
|
-
if (
|
|
21858
|
-
clearInterval(
|
|
21859
|
-
|
|
22069
|
+
workerStarted2 = false;
|
|
22070
|
+
if (leadershipTimer2) {
|
|
22071
|
+
clearInterval(leadershipTimer2);
|
|
22072
|
+
leadershipTimer2 = null;
|
|
21860
22073
|
}
|
|
21861
|
-
|
|
21862
|
-
|
|
21863
|
-
|
|
22074
|
+
stopLeaderResources2();
|
|
22075
|
+
workerLease2?.stop();
|
|
22076
|
+
workerLease2 = null;
|
|
21864
22077
|
logger.info("session-inbox: worker stopped");
|
|
21865
22078
|
};
|
|
21866
22079
|
}
|
|
21867
|
-
var topicWorkerBusy,
|
|
22080
|
+
var topicWorkerBusy, watcher2 = null, fallbackTimer2 = null, debouncedTrigger2 = null, leadershipTimer2 = null, workerLease2 = null, workerStarted2 = false, SESSION_INBOX_PROCESS_ROLE = "worker:session-inbox";
|
|
21868
22081
|
var init_inbox = __esm(async () => {
|
|
21869
22082
|
init_file_ops();
|
|
21870
22083
|
init_utils();
|
|
@@ -21916,6 +22129,7 @@ __export(exports_src, {
|
|
|
21916
22129
|
startSessionInboxWorker: () => startSessionInboxWorker,
|
|
21917
22130
|
startNegotiumNodeModules: () => startNegotiumNodeModules,
|
|
21918
22131
|
startDurableTurnRequestWorker: () => startDurableTurnRequestWorker,
|
|
22132
|
+
startBashrsCompletionsWorker: () => startBashrsCompletionsWorker,
|
|
21919
22133
|
startAskUserQuestionGateOwner: () => startAskUserQuestionGateOwner,
|
|
21920
22134
|
startAiTurn: () => startAiTurn,
|
|
21921
22135
|
setTopicSessionId: () => setTopicSessionId,
|
|
@@ -21924,6 +22138,7 @@ __export(exports_src, {
|
|
|
21924
22138
|
setPlaywrightUnavailableNotifier: () => setPlaywrightUnavailableNotifier,
|
|
21925
22139
|
setNodeMcpServers: () => setNodeMcpServers,
|
|
21926
22140
|
setFileHooks: () => setFileHooks,
|
|
22141
|
+
setBashrsCompletionSink: () => setBashrsCompletionSink,
|
|
21927
22142
|
setApiTopicConfig: () => setApiTopicConfig,
|
|
21928
22143
|
sessionInboxPath: () => sessionInboxPath,
|
|
21929
22144
|
selectableModel: () => selectableModel,
|
|
@@ -22016,6 +22231,7 @@ __export(exports_src, {
|
|
|
22016
22231
|
forkAgentSession: () => forkAgentSession,
|
|
22017
22232
|
flushSessionInbox: () => flushSessionInbox,
|
|
22018
22233
|
flushPeerRuntimeEvents: () => flushPeerRuntimeEvents,
|
|
22234
|
+
flushBashrsCompletions: () => flushBashrsCompletions,
|
|
22019
22235
|
findTopicTitleConflict: () => findTopicTitleConflict,
|
|
22020
22236
|
fileHooks: () => fileHooks,
|
|
22021
22237
|
failInterruptedRemoteAskCallbacks: () => failInterruptedRemoteAskCallbacks,
|
|
@@ -22158,6 +22374,7 @@ var init_src = __esm(async () => {
|
|
|
22158
22374
|
init_active_rooms(),
|
|
22159
22375
|
init_ask_callbacks(),
|
|
22160
22376
|
init_background_sessions(),
|
|
22377
|
+
init_bashrs_completions(),
|
|
22161
22378
|
init_delivery_ack(),
|
|
22162
22379
|
init_inbox(),
|
|
22163
22380
|
init_turn_runner(),
|
|
@@ -22181,11 +22398,11 @@ var init_src = __esm(async () => {
|
|
|
22181
22398
|
});
|
|
22182
22399
|
|
|
22183
22400
|
// ../../packages/core/src/storage/conversation-migration.ts
|
|
22184
|
-
import { copyFileSync as copyFileSync3, existsSync as existsSync23, mkdirSync as mkdirSync23, readFileSync as
|
|
22185
|
-
import { dirname as dirname15, join as
|
|
22401
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync23, mkdirSync as mkdirSync23, readFileSync as readFileSync20 } from "fs";
|
|
22402
|
+
import { dirname as dirname15, join as join33 } from "path";
|
|
22186
22403
|
function readEntries(path) {
|
|
22187
22404
|
const entries = [];
|
|
22188
|
-
for (const [index, line] of
|
|
22405
|
+
for (const [index, line] of readFileSync20(path, "utf8").split(`
|
|
22189
22406
|
`).entries()) {
|
|
22190
22407
|
if (!line.trim())
|
|
22191
22408
|
continue;
|
|
@@ -22249,7 +22466,7 @@ function migrateLegacyCompactedConversations() {
|
|
|
22249
22466
|
result.skipped++;
|
|
22250
22467
|
continue;
|
|
22251
22468
|
}
|
|
22252
|
-
const backupPath =
|
|
22469
|
+
const backupPath = join33(resolveStorageDataDir(), "conversation-migration-backups", MIGRATION_NAME, userId, `${sanitizeTopicName(topic.title, true)}.jsonl`);
|
|
22253
22470
|
const sourcePath = existsSync23(backupPath) ? backupPath : rawPath;
|
|
22254
22471
|
const legacyEntries = readEntries(sourcePath);
|
|
22255
22472
|
const compactIndex = compactionEntryIndex(legacyEntries);
|
|
@@ -22308,11 +22525,13 @@ __export(exports_node_host, {
|
|
|
22308
22525
|
startSessionInboxWorker: () => startSessionInboxWorker,
|
|
22309
22526
|
startNegotiumNodeModules: () => startNegotiumNodeModules,
|
|
22310
22527
|
startDurableTurnRequestWorker: () => startDurableTurnRequestWorker,
|
|
22528
|
+
startBashrsCompletionsWorker: () => startBashrsCompletionsWorker,
|
|
22311
22529
|
startAskUserQuestionGateOwner: () => startAskUserQuestionGateOwner,
|
|
22312
22530
|
startAiTurn: () => startAiTurn,
|
|
22313
22531
|
setRuntimeMcpPort: () => setRuntimeMcpPort,
|
|
22314
22532
|
setNodeMcpServers: () => setNodeMcpServers,
|
|
22315
22533
|
setFileHooks: () => setFileHooks,
|
|
22534
|
+
setBashrsCompletionSink: () => setBashrsCompletionSink,
|
|
22316
22535
|
saveVaultEntry: () => saveVaultEntry,
|
|
22317
22536
|
runtimeBus: () => runtimeBus,
|
|
22318
22537
|
runShutdown: () => runShutdown,
|
|
@@ -22335,6 +22554,7 @@ __export(exports_node_host, {
|
|
|
22335
22554
|
isParticipant: () => isParticipant,
|
|
22336
22555
|
getVisibleTopics: () => getVisibleTopics,
|
|
22337
22556
|
getTopic: () => getTopic,
|
|
22557
|
+
flushBashrsCompletions: () => flushBashrsCompletions,
|
|
22338
22558
|
executeVaultCommand: () => executeVaultCommand,
|
|
22339
22559
|
ensurePersonalGeneral: () => ensurePersonalGeneral,
|
|
22340
22560
|
deleteVaultEntry: () => deleteVaultEntry,
|
|
@@ -22380,6 +22600,7 @@ var init_node_host = __esm(async () => {
|
|
|
22380
22600
|
init_manager2(),
|
|
22381
22601
|
init_active_rooms(),
|
|
22382
22602
|
init_background_sessions(),
|
|
22603
|
+
init_bashrs_completions(),
|
|
22383
22604
|
init_inbox(),
|
|
22384
22605
|
init_turn_runner(),
|
|
22385
22606
|
init_api_messages(),
|
|
@@ -22393,7 +22614,7 @@ var init_node_host = __esm(async () => {
|
|
|
22393
22614
|
});
|
|
22394
22615
|
|
|
22395
22616
|
// ../../packages/core/src/agents/mcp-tools/inline-assets.ts
|
|
22396
|
-
import { existsSync as existsSync24, readFileSync as
|
|
22617
|
+
import { existsSync as existsSync24, readFileSync as readFileSync21, statSync as statSync14 } from "fs";
|
|
22397
22618
|
import { extname as extname2, isAbsolute as isAbsolute6, resolve as resolve16 } from "path";
|
|
22398
22619
|
function isNonLocal(ref) {
|
|
22399
22620
|
return /^(?:[a-z][a-z0-9+.-]*:|\/\/|#)/i.test(ref.trim());
|
|
@@ -22421,12 +22642,12 @@ function inlineLocalAssets(html, options) {
|
|
|
22421
22642
|
const abs = isAbsolute6(relPath) ? relPath : resolve16(baseDir, relPath);
|
|
22422
22643
|
let bytes;
|
|
22423
22644
|
try {
|
|
22424
|
-
if (!existsSync24(abs) || !
|
|
22645
|
+
if (!existsSync24(abs) || !statSync14(abs).isFile()) {
|
|
22425
22646
|
unresolved.push(ref);
|
|
22426
22647
|
cache.set(ref, null);
|
|
22427
22648
|
return null;
|
|
22428
22649
|
}
|
|
22429
|
-
bytes =
|
|
22650
|
+
bytes = statSync14(abs).size;
|
|
22430
22651
|
} catch {
|
|
22431
22652
|
unresolved.push(ref);
|
|
22432
22653
|
cache.set(ref, null);
|
|
@@ -22446,7 +22667,7 @@ function inlineLocalAssets(html, options) {
|
|
|
22446
22667
|
let uri;
|
|
22447
22668
|
try {
|
|
22448
22669
|
const mime = MIME_BY_EXT[extname2(abs).toLowerCase()] ?? "application/octet-stream";
|
|
22449
|
-
uri = `data:${mime};base64,${
|
|
22670
|
+
uri = `data:${mime};base64,${readFileSync21(abs).toString("base64")}`;
|
|
22450
22671
|
} catch {
|
|
22451
22672
|
unresolved.push(ref);
|
|
22452
22673
|
cache.set(ref, null);
|
|
@@ -23232,8 +23453,8 @@ __export(exports_agent_health, {
|
|
|
23232
23453
|
createAgentHealthMcpServer: () => createAgentHealthMcpServer
|
|
23233
23454
|
});
|
|
23234
23455
|
import { spawn as spawn6 } from "child_process";
|
|
23235
|
-
import { existsSync as existsSync25, readdirSync as
|
|
23236
|
-
import { join as
|
|
23456
|
+
import { existsSync as existsSync25, readdirSync as readdirSync9 } from "fs";
|
|
23457
|
+
import { join as join34 } from "path";
|
|
23237
23458
|
import { McpServer as McpServer4 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
23238
23459
|
import { z as z9 } from "zod";
|
|
23239
23460
|
function signalProcessTree2(child, signal) {
|
|
@@ -23477,12 +23698,12 @@ ${results.every((result) => result.ok) ? "All agents healthy" : "Some agents fai
|
|
|
23477
23698
|
server.tool("list_active_queries", "\uD604\uC7AC \uC0AC\uC6A9\uC790 \uBC94\uC704\uC5D0\uC11C \uC2E4\uD589 \uC911\uC778 \uD1A0\uD53D \uCFFC\uB9AC \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.", {}, async () => {
|
|
23478
23699
|
if (!context.userId)
|
|
23479
23700
|
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC870\uD68C \uBD88\uAC00 (user context \uC5C6\uC74C)");
|
|
23480
|
-
const stateDir =
|
|
23701
|
+
const stateDir = join34(USERS_LOG_DIR, context.userId, "active-queries");
|
|
23481
23702
|
if (!existsSync25(stateDir))
|
|
23482
23703
|
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC5C6\uC74C");
|
|
23483
23704
|
let files;
|
|
23484
23705
|
try {
|
|
23485
|
-
files =
|
|
23706
|
+
files = readdirSync9(stateDir);
|
|
23486
23707
|
} catch {
|
|
23487
23708
|
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC5C6\uC74C");
|
|
23488
23709
|
}
|
|
@@ -23490,7 +23711,7 @@ ${results.every((result) => result.ok) ? "All agents healthy" : "Some agents fai
|
|
|
23490
23711
|
const entries = files.flatMap((file) => {
|
|
23491
23712
|
if (!file.endsWith(".json"))
|
|
23492
23713
|
return [];
|
|
23493
|
-
const state = readJsonFile(
|
|
23714
|
+
const state = readJsonFile(join34(stateDir, file));
|
|
23494
23715
|
if (!state)
|
|
23495
23716
|
return [];
|
|
23496
23717
|
const sinceMs = new Date(state.since).getTime();
|
|
@@ -23726,7 +23947,7 @@ var exports_default_host = {};
|
|
|
23726
23947
|
__export(exports_default_host, {
|
|
23727
23948
|
createDefaultSessionCommMcpHost: () => createDefaultSessionCommMcpHost
|
|
23728
23949
|
});
|
|
23729
|
-
import { basename as basename6, join as
|
|
23950
|
+
import { basename as basename6, join as join35 } from "path";
|
|
23730
23951
|
function ok2(text2) {
|
|
23731
23952
|
return { content: [{ type: "text", text: text2 }] };
|
|
23732
23953
|
}
|
|
@@ -23768,10 +23989,10 @@ function remoteTarget(context, to) {
|
|
|
23768
23989
|
return { node: to.slice(0, slash), topic: to.slice(slash + 1) };
|
|
23769
23990
|
}
|
|
23770
23991
|
function activeQuery(context, topicId, title) {
|
|
23771
|
-
const dir =
|
|
23772
|
-
const candidates = [
|
|
23992
|
+
const dir = join35(USERS_LOG_DIR, context.userId, "active-queries");
|
|
23993
|
+
const candidates = [join35(dir, `${sanitizeId(topicId)}.json`)];
|
|
23773
23994
|
if (title && basename6(title) === title && title !== "." && title !== "..") {
|
|
23774
|
-
candidates.push(
|
|
23995
|
+
candidates.push(join35(dir, `${title}.json`));
|
|
23775
23996
|
}
|
|
23776
23997
|
for (const path of candidates) {
|
|
23777
23998
|
const state = readJsonFile(path);
|
|
@@ -24421,18 +24642,18 @@ __export(exports_wiki_server, {
|
|
|
24421
24642
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
24422
24643
|
import { randomUUID as randomUUID21 } from "crypto";
|
|
24423
24644
|
import {
|
|
24424
|
-
closeSync as
|
|
24645
|
+
closeSync as closeSync4,
|
|
24425
24646
|
existsSync as existsSync26,
|
|
24426
24647
|
mkdirSync as mkdirSync24,
|
|
24427
|
-
openSync as
|
|
24428
|
-
readdirSync as
|
|
24429
|
-
readFileSync as
|
|
24430
|
-
renameSync as
|
|
24431
|
-
statSync as
|
|
24648
|
+
openSync as openSync4,
|
|
24649
|
+
readdirSync as readdirSync10,
|
|
24650
|
+
readFileSync as readFileSync22,
|
|
24651
|
+
renameSync as renameSync11,
|
|
24652
|
+
statSync as statSync15,
|
|
24432
24653
|
unlinkSync as unlinkSync18,
|
|
24433
24654
|
writeFileSync as writeFileSync17
|
|
24434
24655
|
} from "fs";
|
|
24435
|
-
import { basename as basename7, dirname as dirname16, join as
|
|
24656
|
+
import { basename as basename7, dirname as dirname16, join as join36, resolve as resolve17 } from "path";
|
|
24436
24657
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
24437
24658
|
import { StdioServerTransport as StdioServerTransport2 } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
24438
24659
|
import {
|
|
@@ -24466,20 +24687,20 @@ function acquireRecoveryGuard(lockPath) {
|
|
|
24466
24687
|
const deadline = Date.now() + FILE_LOCK_TIMEOUT_MS;
|
|
24467
24688
|
while (true) {
|
|
24468
24689
|
try {
|
|
24469
|
-
const fd =
|
|
24690
|
+
const fd = openSync4(guardPath, "wx");
|
|
24470
24691
|
try {
|
|
24471
24692
|
writeFileSync17(fd, ownerToken, "utf-8");
|
|
24472
24693
|
} catch (error2) {
|
|
24473
|
-
|
|
24694
|
+
closeSync4(fd);
|
|
24474
24695
|
try {
|
|
24475
24696
|
unlinkSync18(guardPath);
|
|
24476
24697
|
} catch {}
|
|
24477
24698
|
throw error2;
|
|
24478
24699
|
}
|
|
24479
24700
|
return () => {
|
|
24480
|
-
|
|
24701
|
+
closeSync4(fd);
|
|
24481
24702
|
try {
|
|
24482
|
-
if (
|
|
24703
|
+
if (readFileSync22(guardPath, "utf-8") === ownerToken)
|
|
24483
24704
|
unlinkSync18(guardPath);
|
|
24484
24705
|
} catch {}
|
|
24485
24706
|
};
|
|
@@ -24499,21 +24720,21 @@ function acquireFileLock(path) {
|
|
|
24499
24720
|
const deadline = Date.now() + FILE_LOCK_TIMEOUT_MS;
|
|
24500
24721
|
while (true) {
|
|
24501
24722
|
try {
|
|
24502
|
-
const fd =
|
|
24723
|
+
const fd = openSync4(lockPath, "wx");
|
|
24503
24724
|
try {
|
|
24504
24725
|
writeFileSync17(fd, ownerToken, "utf-8");
|
|
24505
24726
|
} catch (error2) {
|
|
24506
|
-
|
|
24727
|
+
closeSync4(fd);
|
|
24507
24728
|
try {
|
|
24508
24729
|
unlinkSync18(lockPath);
|
|
24509
24730
|
} catch {}
|
|
24510
24731
|
throw error2;
|
|
24511
24732
|
}
|
|
24512
24733
|
return () => {
|
|
24513
|
-
|
|
24734
|
+
closeSync4(fd);
|
|
24514
24735
|
const releaseGuard = acquireRecoveryGuard(lockPath);
|
|
24515
24736
|
try {
|
|
24516
|
-
if (
|
|
24737
|
+
if (readFileSync22(lockPath, "utf-8") === ownerToken)
|
|
24517
24738
|
unlinkSync18(lockPath);
|
|
24518
24739
|
} catch {} finally {
|
|
24519
24740
|
releaseGuard();
|
|
@@ -24525,8 +24746,8 @@ function acquireFileLock(path) {
|
|
|
24525
24746
|
const releaseGuard = acquireRecoveryGuard(lockPath);
|
|
24526
24747
|
try {
|
|
24527
24748
|
try {
|
|
24528
|
-
const staleToken =
|
|
24529
|
-
if (Date.now() -
|
|
24749
|
+
const staleToken = readFileSync22(lockPath, "utf-8");
|
|
24750
|
+
if (Date.now() - statSync15(lockPath).mtimeMs > FILE_LOCK_STALE_MS && readFileSync22(lockPath, "utf-8") === staleToken) {
|
|
24530
24751
|
unlinkSync18(lockPath);
|
|
24531
24752
|
continue;
|
|
24532
24753
|
}
|
|
@@ -24547,7 +24768,7 @@ function atomicWriteFile(path, content) {
|
|
|
24547
24768
|
const temporaryPath = `${path}.tmp.${process.pid}.${Date.now()}`;
|
|
24548
24769
|
writeFileSync17(temporaryPath, content, "utf-8");
|
|
24549
24770
|
try {
|
|
24550
|
-
|
|
24771
|
+
renameSync11(temporaryPath, path);
|
|
24551
24772
|
} catch (error2) {
|
|
24552
24773
|
try {
|
|
24553
24774
|
unlinkSync18(temporaryPath);
|
|
@@ -24579,17 +24800,17 @@ function wikiQuery(args) {
|
|
|
24579
24800
|
function scan(dir, label) {
|
|
24580
24801
|
ensureDir(dir);
|
|
24581
24802
|
try {
|
|
24582
|
-
for (const entry of
|
|
24803
|
+
for (const entry of readdirSync10(dir, { withFileTypes: true })) {
|
|
24583
24804
|
if (entry.isDirectory()) {
|
|
24584
|
-
const sub =
|
|
24805
|
+
const sub = join36(dir, entry.name);
|
|
24585
24806
|
if (label === "articles" || label === "skills") {
|
|
24586
24807
|
try {
|
|
24587
|
-
for (const f of
|
|
24808
|
+
for (const f of readdirSync10(sub, { withFileTypes: true })) {
|
|
24588
24809
|
if (!f.isFile() || !f.name.endsWith(".md"))
|
|
24589
24810
|
continue;
|
|
24590
|
-
const fp =
|
|
24811
|
+
const fp = join36(sub, f.name);
|
|
24591
24812
|
try {
|
|
24592
|
-
const text2 =
|
|
24813
|
+
const text2 = readFileSync22(fp, "utf-8");
|
|
24593
24814
|
scored.push({
|
|
24594
24815
|
score: scoreMatch(text2),
|
|
24595
24816
|
path: `${label}/${entry.name}/${f.name}`,
|
|
@@ -24600,9 +24821,9 @@ function wikiQuery(args) {
|
|
|
24600
24821
|
} catch {}
|
|
24601
24822
|
}
|
|
24602
24823
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
24603
|
-
const fp =
|
|
24824
|
+
const fp = join36(dir, entry.name);
|
|
24604
24825
|
try {
|
|
24605
|
-
const text2 =
|
|
24826
|
+
const text2 = readFileSync22(fp, "utf-8");
|
|
24606
24827
|
scored.push({
|
|
24607
24828
|
score: scoreMatch(text2),
|
|
24608
24829
|
path: `${label}/${entry.name}`,
|
|
@@ -24710,18 +24931,18 @@ function wikiLastConversation(args) {
|
|
|
24710
24931
|
const name = slugify(topicNameFrom(rawTopic));
|
|
24711
24932
|
const archiveDir = resolve17(runtime().archiveDir, name);
|
|
24712
24933
|
try {
|
|
24713
|
-
let files = existsSync26(archiveDir) ?
|
|
24934
|
+
let files = existsSync26(archiveDir) ? readdirSync10(archiveDir).filter((f) => f.endsWith(".jsonl")).sort().reverse() : [];
|
|
24714
24935
|
if (files.length === 0) {
|
|
24715
|
-
files = existsSync26(runtime().archiveDir) ?
|
|
24936
|
+
files = existsSync26(runtime().archiveDir) ? readdirSync10(runtime().archiveDir).filter((f) => f.startsWith(name) && f.endsWith(".jsonl")).sort().reverse() : [];
|
|
24716
24937
|
}
|
|
24717
24938
|
if (files.length === 0) {
|
|
24718
24939
|
return {
|
|
24719
24940
|
content: [{ type: "text", text: `No archive found for topic: ${rawTopic}` }]
|
|
24720
24941
|
};
|
|
24721
24942
|
}
|
|
24722
|
-
const actualPath = files[0].includes("/") ? files[0] : resolve17(existsSync26(archiveDir) &&
|
|
24943
|
+
const actualPath = files[0].includes("/") ? files[0] : resolve17(existsSync26(archiveDir) && readdirSync10(archiveDir).includes(files[0]) ? archiveDir : runtime().archiveDir, files[0]);
|
|
24723
24944
|
try {
|
|
24724
|
-
const raw =
|
|
24945
|
+
const raw = readFileSync22(actualPath, "utf-8");
|
|
24725
24946
|
const lines = raw.trim().split(`
|
|
24726
24947
|
`).filter(Boolean);
|
|
24727
24948
|
const turns2 = [];
|
|
@@ -24787,14 +25008,14 @@ function skillQuery(args) {
|
|
|
24787
25008
|
ensureDir(runtime().skillsDir);
|
|
24788
25009
|
const matches = [];
|
|
24789
25010
|
try {
|
|
24790
|
-
for (const entry of
|
|
25011
|
+
for (const entry of readdirSync10(runtime().skillsDir, {
|
|
24791
25012
|
withFileTypes: true
|
|
24792
25013
|
})) {
|
|
24793
25014
|
if (!entry.isDirectory())
|
|
24794
25015
|
continue;
|
|
24795
25016
|
const skillFile = resolve17(runtime().skillsDir, entry.name, "skill.md");
|
|
24796
25017
|
try {
|
|
24797
|
-
const text2 =
|
|
25018
|
+
const text2 = readFileSync22(skillFile, "utf-8");
|
|
24798
25019
|
const lower = text2.toLowerCase();
|
|
24799
25020
|
let score = 0;
|
|
24800
25021
|
for (const w of query2.split(/\s+/).filter(Boolean)) {
|
|
@@ -24865,7 +25086,7 @@ ${fresh.join(`
|
|
|
24865
25086
|
const skillPath = resolve17(skillDir, "skill.md");
|
|
24866
25087
|
let finalContent = content;
|
|
24867
25088
|
try {
|
|
24868
|
-
const existing =
|
|
25089
|
+
const existing = readFileSync22(skillPath, "utf-8");
|
|
24869
25090
|
finalContent = mergeGotchas(content, extractGotchas(existing));
|
|
24870
25091
|
} catch {}
|
|
24871
25092
|
writeFileSync17(skillPath, finalContent, "utf-8");
|
|
@@ -24913,7 +25134,7 @@ function saveWikiEntry(args) {
|
|
|
24913
25134
|
if (topicId && setTopicBrief2) {
|
|
24914
25135
|
try {
|
|
24915
25136
|
const briefPath = resolve17(runtime().topicsDir, `${fileSlug}.md`);
|
|
24916
|
-
let briefMd = existsSync26(briefPath) ?
|
|
25137
|
+
let briefMd = existsSync26(briefPath) ? readFileSync22(briefPath, "utf-8") : undefined;
|
|
24917
25138
|
if (briefMd === undefined && getTopicBrief2 && !getTopicBrief2(fileSlug)?.briefMd) {
|
|
24918
25139
|
const legacy = getTopicBrief2(topicId)?.briefMd;
|
|
24919
25140
|
if (legacy)
|
|
@@ -24990,7 +25211,7 @@ function indexUpsert(args) {
|
|
|
24990
25211
|
try {
|
|
24991
25212
|
let index;
|
|
24992
25213
|
try {
|
|
24993
|
-
index =
|
|
25214
|
+
index = readFileSync22(indexPath, "utf-8");
|
|
24994
25215
|
} catch {
|
|
24995
25216
|
index = "";
|
|
24996
25217
|
}
|
|
@@ -25277,13 +25498,13 @@ __export(exports_activity_log, {
|
|
|
25277
25498
|
import {
|
|
25278
25499
|
existsSync as existsSync27,
|
|
25279
25500
|
mkdirSync as mkdirSync25,
|
|
25280
|
-
readdirSync as
|
|
25281
|
-
renameSync as
|
|
25282
|
-
statSync as
|
|
25501
|
+
readdirSync as readdirSync11,
|
|
25502
|
+
renameSync as renameSync12,
|
|
25503
|
+
statSync as statSync16,
|
|
25283
25504
|
unlinkSync as unlinkSync19,
|
|
25284
25505
|
writeFileSync as writeFileSync18
|
|
25285
25506
|
} from "fs";
|
|
25286
|
-
import { basename as basename8, join as
|
|
25507
|
+
import { basename as basename8, join as join37 } from "path";
|
|
25287
25508
|
function startLogRotation() {
|
|
25288
25509
|
if (rotationTimer)
|
|
25289
25510
|
return;
|
|
@@ -25297,12 +25518,12 @@ function writeLog(entry) {
|
|
|
25297
25518
|
mkdirSync25(logDir, { recursive: true });
|
|
25298
25519
|
const safeSession = sanitizeTopicName(entry.session);
|
|
25299
25520
|
const sidShort = entry.sessionId ? entry.sessionId.slice(0, 8) : "new";
|
|
25300
|
-
const file =
|
|
25521
|
+
const file = join37(logDir, `${entry.userId}_${safeSession}_${sidShort}.jsonl`);
|
|
25301
25522
|
try {
|
|
25302
|
-
const stat =
|
|
25523
|
+
const stat = statSync16(file);
|
|
25303
25524
|
if (stat.size >= MAX_FILE_SIZE) {
|
|
25304
25525
|
const rotated = file.replace(/\.jsonl$/, `.${Date.now()}.jsonl`);
|
|
25305
|
-
|
|
25526
|
+
renameSync12(file, rotated);
|
|
25306
25527
|
}
|
|
25307
25528
|
} catch {}
|
|
25308
25529
|
try {
|
|
@@ -25315,9 +25536,9 @@ function rotateOldLogs() {
|
|
|
25315
25536
|
const logDir = resolveStorageLogDir();
|
|
25316
25537
|
mkdirSync25(logDir, { recursive: true });
|
|
25317
25538
|
try {
|
|
25318
|
-
const files =
|
|
25539
|
+
const files = readdirSync11(logDir).filter((f) => f.endsWith(".jsonl")).map((f) => {
|
|
25319
25540
|
try {
|
|
25320
|
-
const stat =
|
|
25541
|
+
const stat = statSync16(join37(logDir, f));
|
|
25321
25542
|
return { name: f, size: stat.size, mtimeMs: stat.mtimeMs };
|
|
25322
25543
|
} catch {
|
|
25323
25544
|
return null;
|
|
@@ -25333,7 +25554,7 @@ function rotateOldLogs() {
|
|
|
25333
25554
|
if (freed >= toFree)
|
|
25334
25555
|
break;
|
|
25335
25556
|
try {
|
|
25336
|
-
unlinkSync19(
|
|
25557
|
+
unlinkSync19(join37(logDir, file.name));
|
|
25337
25558
|
freed += file.size;
|
|
25338
25559
|
logger.info({ file: file.name, sizeKB: (file.size / 1024).toFixed(0) }, "Rotated out old log");
|
|
25339
25560
|
} catch (e) {
|
|
@@ -25345,9 +25566,9 @@ function rotateOldLogs() {
|
|
|
25345
25566
|
}
|
|
25346
25567
|
}
|
|
25347
25568
|
function writeSentFileLog(entry) {
|
|
25348
|
-
const dir =
|
|
25569
|
+
const dir = join37(resolveStorageUsersLogDir(), String(entry.userId));
|
|
25349
25570
|
mkdirSync25(dir, { recursive: true });
|
|
25350
|
-
const file =
|
|
25571
|
+
const file = join37(dir, "sent-files.jsonl");
|
|
25351
25572
|
try {
|
|
25352
25573
|
appendJsonlEntry(file, { ...entry, fileName: basename8(entry.filePath) });
|
|
25353
25574
|
} catch (e) {
|
|
@@ -25358,7 +25579,7 @@ function entryMatchesTopic(e, topicName) {
|
|
|
25358
25579
|
return e.topicName === topicName;
|
|
25359
25580
|
}
|
|
25360
25581
|
function readSentFilesForTopic(userId, topicName) {
|
|
25361
|
-
const file =
|
|
25582
|
+
const file = join37(resolveStorageUsersLogDir(), String(userId), "sent-files.jsonl");
|
|
25362
25583
|
if (!existsSync27(file))
|
|
25363
25584
|
return [];
|
|
25364
25585
|
try {
|
|
@@ -25369,7 +25590,7 @@ function readSentFilesForTopic(userId, topicName) {
|
|
|
25369
25590
|
}
|
|
25370
25591
|
}
|
|
25371
25592
|
function removeSentFilesForTopic(userId, topicName) {
|
|
25372
|
-
const file =
|
|
25593
|
+
const file = join37(resolveStorageUsersLogDir(), String(userId), "sent-files.jsonl");
|
|
25373
25594
|
if (!existsSync27(file))
|
|
25374
25595
|
return;
|
|
25375
25596
|
try {
|
|
@@ -26329,7 +26550,7 @@ var init_sse_transport = () => {};
|
|
|
26329
26550
|
|
|
26330
26551
|
// ../../packages/mcp/src/server.ts
|
|
26331
26552
|
import { createHash as createHash9, randomUUID as randomUUID23 } from "crypto";
|
|
26332
|
-
import { realpathSync as realpathSync6, statSync as
|
|
26553
|
+
import { realpathSync as realpathSync6, statSync as statSync17 } from "fs";
|
|
26333
26554
|
import { basename as basename9, extname as extname3, resolve as resolve19 } from "path";
|
|
26334
26555
|
import { McpServer as McpServer7 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
26335
26556
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
@@ -26366,7 +26587,7 @@ function localFileInfo(ctx, filePath) {
|
|
|
26366
26587
|
return { error: "Access denied. Path matches the sensitive-file blacklist." };
|
|
26367
26588
|
}
|
|
26368
26589
|
try {
|
|
26369
|
-
const stats =
|
|
26590
|
+
const stats = statSync17(normalizedPath);
|
|
26370
26591
|
if (!stats.isFile())
|
|
26371
26592
|
return { error: `${filePath} is not a file` };
|
|
26372
26593
|
return {
|
|
@@ -26893,7 +27114,7 @@ var init_spec = __esm(() => {
|
|
|
26893
27114
|
});
|
|
26894
27115
|
|
|
26895
27116
|
// ../../packages/mcp-host/src/manifest.ts
|
|
26896
|
-
import { existsSync as existsSync28, mkdirSync as mkdirSync26, readFileSync as
|
|
27117
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync26, readFileSync as readFileSync23, renameSync as renameSync13, writeFileSync as writeFileSync19 } from "fs";
|
|
26897
27118
|
import { dirname as dirname17 } from "path";
|
|
26898
27119
|
import { z as z14 } from "zod";
|
|
26899
27120
|
|
|
@@ -26942,7 +27163,7 @@ class McpManifest {
|
|
|
26942
27163
|
return;
|
|
26943
27164
|
let parsed;
|
|
26944
27165
|
try {
|
|
26945
|
-
parsed = manifestFileSchema.parse(JSON.parse(
|
|
27166
|
+
parsed = manifestFileSchema.parse(JSON.parse(readFileSync23(this.file, "utf8")));
|
|
26946
27167
|
} catch (e) {
|
|
26947
27168
|
throw new Error(`Invalid MCP manifest at ${this.file}: ${e instanceof Error ? e.message : String(e)}`);
|
|
26948
27169
|
}
|
|
@@ -26962,7 +27183,7 @@ class McpManifest {
|
|
|
26962
27183
|
const tmp = `${this.file}.tmp-${process.pid}`;
|
|
26963
27184
|
writeFileSync19(tmp, `${JSON.stringify(payload, null, 2)}
|
|
26964
27185
|
`);
|
|
26965
|
-
|
|
27186
|
+
renameSync13(tmp, this.file);
|
|
26966
27187
|
}
|
|
26967
27188
|
}
|
|
26968
27189
|
var manifestEntrySchema, manifestFileSchema;
|
|
@@ -26991,14 +27212,14 @@ function sanitizePathComponent(name) {
|
|
|
26991
27212
|
import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
|
|
26992
27213
|
import {
|
|
26993
27214
|
mkdirSync as mkdirSync27,
|
|
26994
|
-
readdirSync as
|
|
26995
|
-
readFileSync as
|
|
26996
|
-
renameSync as
|
|
27215
|
+
readdirSync as readdirSync12,
|
|
27216
|
+
readFileSync as readFileSync24,
|
|
27217
|
+
renameSync as renameSync14,
|
|
26997
27218
|
unlinkSync as unlinkSync20,
|
|
26998
27219
|
writeFileSync as writeFileSync20
|
|
26999
27220
|
} from "fs";
|
|
27000
27221
|
import { connect, createServer as createServer3 } from "net";
|
|
27001
|
-
import { join as
|
|
27222
|
+
import { join as join38 } from "path";
|
|
27002
27223
|
function regKey(key, instanceKey) {
|
|
27003
27224
|
return `${key}\x00${instanceKey}`;
|
|
27004
27225
|
}
|
|
@@ -27292,7 +27513,7 @@ class McpHost {
|
|
|
27292
27513
|
const claims = new Map;
|
|
27293
27514
|
let files;
|
|
27294
27515
|
try {
|
|
27295
|
-
files =
|
|
27516
|
+
files = readdirSync12(this.portsDir);
|
|
27296
27517
|
} catch {
|
|
27297
27518
|
return claims;
|
|
27298
27519
|
}
|
|
@@ -27300,7 +27521,7 @@ class McpHost {
|
|
|
27300
27521
|
if (file.includes(".tmp-"))
|
|
27301
27522
|
continue;
|
|
27302
27523
|
try {
|
|
27303
|
-
const port = Number.parseInt(
|
|
27524
|
+
const port = Number.parseInt(readFileSync24(join38(this.portsDir, file), "utf8").trim(), 10);
|
|
27304
27525
|
if (!Number.isNaN(port))
|
|
27305
27526
|
claims.set(file, port);
|
|
27306
27527
|
} catch {}
|
|
@@ -27310,17 +27531,17 @@ class McpHost {
|
|
|
27310
27531
|
writePortFile(fileName, port) {
|
|
27311
27532
|
try {
|
|
27312
27533
|
mkdirSync27(this.portsDir, { recursive: true });
|
|
27313
|
-
const file =
|
|
27534
|
+
const file = join38(this.portsDir, fileName);
|
|
27314
27535
|
const tmp = `${file}.tmp-${process.pid}`;
|
|
27315
27536
|
writeFileSync20(tmp, String(port));
|
|
27316
|
-
|
|
27537
|
+
renameSync14(tmp, file);
|
|
27317
27538
|
} catch (e) {
|
|
27318
27539
|
this.log("warn", "Failed to write MCP port file", { fileName, port, err: String(e) });
|
|
27319
27540
|
}
|
|
27320
27541
|
}
|
|
27321
27542
|
deletePortFile(fileName) {
|
|
27322
27543
|
try {
|
|
27323
|
-
unlinkSync20(
|
|
27544
|
+
unlinkSync20(join38(this.portsDir, fileName));
|
|
27324
27545
|
} catch {}
|
|
27325
27546
|
}
|
|
27326
27547
|
cleanupRunning(rkey, inst) {
|
|
@@ -27427,12 +27648,12 @@ import {
|
|
|
27427
27648
|
copyFileSync as copyFileSync4,
|
|
27428
27649
|
existsSync as existsSync29,
|
|
27429
27650
|
mkdirSync as mkdirSync28,
|
|
27430
|
-
readFileSync as
|
|
27431
|
-
rmSync as
|
|
27432
|
-
statSync as
|
|
27651
|
+
readFileSync as readFileSync25,
|
|
27652
|
+
rmSync as rmSync9,
|
|
27653
|
+
statSync as statSync18,
|
|
27433
27654
|
writeFileSync as writeFileSync21
|
|
27434
27655
|
} from "fs";
|
|
27435
|
-
import { basename as basename10, extname as extname4, join as
|
|
27656
|
+
import { basename as basename10, extname as extname4, join as join39 } from "path";
|
|
27436
27657
|
function safeExtension(filename) {
|
|
27437
27658
|
const extension = extname4(basename10(filename));
|
|
27438
27659
|
return /^\.[A-Za-z0-9]{1,16}$/.test(extension) ? extension.toLowerCase() : "";
|
|
@@ -27450,20 +27671,20 @@ function contentDisposition(filename) {
|
|
|
27450
27671
|
|
|
27451
27672
|
class NodeFileStore {
|
|
27452
27673
|
uploadDir;
|
|
27453
|
-
constructor(uploadDir =
|
|
27674
|
+
constructor(uploadDir = join39(DATA_DIR, "uploads")) {
|
|
27454
27675
|
this.uploadDir = uploadDir;
|
|
27455
27676
|
}
|
|
27456
27677
|
#ensureDir() {
|
|
27457
27678
|
mkdirSync28(this.uploadDir, { recursive: true });
|
|
27458
27679
|
}
|
|
27459
27680
|
#metadataPath(fileId) {
|
|
27460
|
-
return
|
|
27681
|
+
return join39(this.uploadDir, `${fileId}.meta.json`);
|
|
27461
27682
|
}
|
|
27462
27683
|
#metadata(fileId) {
|
|
27463
27684
|
if (!FILE_ID_RE.test(fileId))
|
|
27464
27685
|
return null;
|
|
27465
27686
|
try {
|
|
27466
|
-
const parsed = JSON.parse(
|
|
27687
|
+
const parsed = JSON.parse(readFileSync25(this.#metadataPath(fileId), "utf8"));
|
|
27467
27688
|
if (typeof parsed.filename !== "string" || typeof parsed.mimeType !== "string" || typeof parsed.sizeBytes !== "number" || typeof parsed.savedName !== "string") {
|
|
27468
27689
|
return null;
|
|
27469
27690
|
}
|
|
@@ -27486,7 +27707,7 @@ class NodeFileStore {
|
|
|
27486
27707
|
hooks = {
|
|
27487
27708
|
resolveAttachmentByFileId: (fileId) => {
|
|
27488
27709
|
const metadata = this.#metadata(fileId);
|
|
27489
|
-
if (!metadata || !existsSync29(
|
|
27710
|
+
if (!metadata || !existsSync29(join39(this.uploadDir, metadata.savedName)))
|
|
27490
27711
|
return null;
|
|
27491
27712
|
return this.#attachment(fileId, metadata);
|
|
27492
27713
|
},
|
|
@@ -27494,7 +27715,7 @@ class NodeFileStore {
|
|
|
27494
27715
|
const metadata = this.#metadata(fileId);
|
|
27495
27716
|
if (!metadata)
|
|
27496
27717
|
return null;
|
|
27497
|
-
const path =
|
|
27718
|
+
const path = join39(this.uploadDir, metadata.savedName);
|
|
27498
27719
|
return existsSync29(path) ? path : null;
|
|
27499
27720
|
},
|
|
27500
27721
|
storeLocalFileAsUpload: (absPath, access = {}) => this.store(absPath, access),
|
|
@@ -27505,9 +27726,9 @@ class NodeFileStore {
|
|
|
27505
27726
|
const fileId = randomUUID24();
|
|
27506
27727
|
const extension = safeExtension(absPath);
|
|
27507
27728
|
const savedName = `${fileId}${extension}`;
|
|
27508
|
-
const savedPath =
|
|
27729
|
+
const savedPath = join39(this.uploadDir, savedName);
|
|
27509
27730
|
try {
|
|
27510
|
-
const stats =
|
|
27731
|
+
const stats = statSync18(absPath);
|
|
27511
27732
|
if (!stats.isFile() || stats.size > MAX_UPLOAD_BYTES)
|
|
27512
27733
|
return null;
|
|
27513
27734
|
const metadata = {
|
|
@@ -27523,8 +27744,8 @@ class NodeFileStore {
|
|
|
27523
27744
|
writeFileSync21(this.#metadataPath(fileId), JSON.stringify(metadata), { mode: 384 });
|
|
27524
27745
|
return this.#attachment(fileId, metadata);
|
|
27525
27746
|
} catch (error2) {
|
|
27526
|
-
|
|
27527
|
-
|
|
27747
|
+
rmSync9(savedPath, { force: true });
|
|
27748
|
+
rmSync9(this.#metadataPath(fileId), { force: true });
|
|
27528
27749
|
logger.warn({ err: error2, absPath }, "node files: failed to store local upload");
|
|
27529
27750
|
return null;
|
|
27530
27751
|
}
|
|
@@ -27537,7 +27758,7 @@ class NodeFileStore {
|
|
|
27537
27758
|
const allowed = metadata.visibility === "workspace" || metadata.ownerUserId === userId || Boolean(topic && isParticipant(topic, userId));
|
|
27538
27759
|
if (!allowed)
|
|
27539
27760
|
return null;
|
|
27540
|
-
const path =
|
|
27761
|
+
const path = join39(this.uploadDir, metadata.savedName);
|
|
27541
27762
|
if (!existsSync29(path))
|
|
27542
27763
|
return null;
|
|
27543
27764
|
return new Response(Bun.file(path), {
|
|
@@ -27556,8 +27777,8 @@ class NodeFileStore {
|
|
|
27556
27777
|
const metadata = this.#metadata(fileId);
|
|
27557
27778
|
if (metadata?.topicId !== topicId)
|
|
27558
27779
|
continue;
|
|
27559
|
-
|
|
27560
|
-
|
|
27780
|
+
rmSync9(join39(this.uploadDir, metadata.savedName), { force: true });
|
|
27781
|
+
rmSync9(this.#metadataPath(fileId), { force: true });
|
|
27561
27782
|
}
|
|
27562
27783
|
}
|
|
27563
27784
|
}
|
|
@@ -27710,8 +27931,8 @@ import {
|
|
|
27710
27931
|
chmodSync as chmodSync5,
|
|
27711
27932
|
existsSync as existsSync30,
|
|
27712
27933
|
mkdirSync as mkdirSync29,
|
|
27713
|
-
readFileSync as
|
|
27714
|
-
renameSync as
|
|
27934
|
+
readFileSync as readFileSync26,
|
|
27935
|
+
renameSync as renameSync15,
|
|
27715
27936
|
unlinkSync as unlinkSync21,
|
|
27716
27937
|
writeFileSync as writeFileSync22
|
|
27717
27938
|
} from "fs";
|
|
@@ -28212,7 +28433,7 @@ function writeNodeDaemonInfo(port, startedAt) {
|
|
|
28212
28433
|
writeFileSync22(temporary, `${JSON.stringify(info, null, 2)}
|
|
28213
28434
|
`, { mode: 384 });
|
|
28214
28435
|
chmodSync5(temporary, 384);
|
|
28215
|
-
|
|
28436
|
+
renameSync15(temporary, NODE_DAEMON_INFO_PATH);
|
|
28216
28437
|
chmodSync5(NODE_DAEMON_INFO_PATH, 384);
|
|
28217
28438
|
return info;
|
|
28218
28439
|
}
|
|
@@ -28220,7 +28441,7 @@ function readNodeDaemonInfo() {
|
|
|
28220
28441
|
if (!existsSync30(NODE_DAEMON_INFO_PATH))
|
|
28221
28442
|
return null;
|
|
28222
28443
|
try {
|
|
28223
|
-
const value = JSON.parse(
|
|
28444
|
+
const value = JSON.parse(readFileSync26(NODE_DAEMON_INFO_PATH, "utf8"));
|
|
28224
28445
|
if (value?.schemaVersion !== 1 || value.stateDir !== STATE_DIR || !Number.isInteger(value.protocolVersion) || !Number.isInteger(value.pid) || !Number.isInteger(value.port) || value.port <= 0) {
|
|
28225
28446
|
return null;
|
|
28226
28447
|
}
|
|
@@ -28508,7 +28729,7 @@ var init_schedule = __esm(() => {
|
|
|
28508
28729
|
|
|
28509
28730
|
// ../../packages/module-cron/src/scripts.ts
|
|
28510
28731
|
import { spawn as spawn9 } from "child_process";
|
|
28511
|
-
import { existsSync as existsSync31, mkdirSync as mkdirSync30, readdirSync as
|
|
28732
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync30, readdirSync as readdirSync13 } from "fs";
|
|
28512
28733
|
import { resolve as resolve22, sep as sep2 } from "path";
|
|
28513
28734
|
function validateCronScriptName(script) {
|
|
28514
28735
|
if (!/^[A-Za-z0-9_][A-Za-z0-9_.-]*\.py$/.test(script) || script.includes("..") || script.includes("/") || script.includes("\\")) {
|
|
@@ -28527,7 +28748,7 @@ function resolveCronScriptPath(script) {
|
|
|
28527
28748
|
}
|
|
28528
28749
|
function listCronScripts() {
|
|
28529
28750
|
mkdirSync30(CRON_JOBS_DIR, { recursive: true });
|
|
28530
|
-
return
|
|
28751
|
+
return readdirSync13(CRON_JOBS_DIR, { withFileTypes: true }).filter((entry) => entry.isFile() && validateCronScriptName(entry.name).ok).map((entry) => entry.name).sort();
|
|
28531
28752
|
}
|
|
28532
28753
|
function cronScriptExists(script) {
|
|
28533
28754
|
try {
|
|
@@ -30209,6 +30430,7 @@ function startNode(opts = {}) {
|
|
|
30209
30430
|
setRuntimeMcpPort(port);
|
|
30210
30431
|
const stopTurnRequests = startDurableTurnRequestWorker();
|
|
30211
30432
|
const stopInbox = startSessionInboxWorker();
|
|
30433
|
+
const stopBashrsCompletions = startBashrsCompletionsWorker();
|
|
30212
30434
|
let modules;
|
|
30213
30435
|
try {
|
|
30214
30436
|
modules = startNegotiumNodeModules(opts.modules ?? [], {
|
|
@@ -30222,6 +30444,7 @@ function startNode(opts = {}) {
|
|
|
30222
30444
|
} catch (error2) {
|
|
30223
30445
|
stopTurnRequests();
|
|
30224
30446
|
stopInbox();
|
|
30447
|
+
stopBashrsCompletions();
|
|
30225
30448
|
server.stop(true);
|
|
30226
30449
|
processLease?.stop();
|
|
30227
30450
|
stopAskUserQuestionGateOwner();
|
|
@@ -30241,6 +30464,7 @@ function startNode(opts = {}) {
|
|
|
30241
30464
|
stopSweeper();
|
|
30242
30465
|
stopTurnRequests();
|
|
30243
30466
|
stopInbox();
|
|
30467
|
+
stopBashrsCompletions();
|
|
30244
30468
|
server.stop(true);
|
|
30245
30469
|
processLease?.stop();
|
|
30246
30470
|
stopAskUserQuestionGateOwner();
|
|
@@ -30252,6 +30476,7 @@ function startNode(opts = {}) {
|
|
|
30252
30476
|
onShutdown("node-server", 130, () => {
|
|
30253
30477
|
stopTurnRequests();
|
|
30254
30478
|
stopInbox();
|
|
30479
|
+
stopBashrsCompletions();
|
|
30255
30480
|
server.stop(true);
|
|
30256
30481
|
});
|
|
30257
30482
|
if (advertised) {
|
|
@@ -30469,9 +30694,9 @@ var init_commands = __esm(() => {
|
|
|
30469
30694
|
|
|
30470
30695
|
// ../../adapters/terminal/src/path-suggest.ts
|
|
30471
30696
|
import { execFile as execFile3 } from "child_process";
|
|
30472
|
-
import { existsSync as existsSync33, readdirSync as
|
|
30697
|
+
import { existsSync as existsSync33, readdirSync as readdirSync14, statSync as statSync19 } from "fs";
|
|
30473
30698
|
import { homedir as homedir10 } from "os";
|
|
30474
|
-
import { basename as basename11, dirname as dirname19, join as
|
|
30699
|
+
import { basename as basename11, dirname as dirname19, join as join40, sep as sep3 } from "path";
|
|
30475
30700
|
import { promisify as promisify3 } from "util";
|
|
30476
30701
|
function indexRecursivePaths(files) {
|
|
30477
30702
|
const paths = [];
|
|
@@ -30572,11 +30797,11 @@ function resolveFragment(frag) {
|
|
|
30572
30797
|
else if (frag === "~/")
|
|
30573
30798
|
path = home;
|
|
30574
30799
|
else if (frag.startsWith("~/"))
|
|
30575
|
-
path =
|
|
30800
|
+
path = join40(home, frag.slice(2));
|
|
30576
30801
|
else if (frag.startsWith("/"))
|
|
30577
30802
|
path = frag;
|
|
30578
30803
|
else
|
|
30579
|
-
path =
|
|
30804
|
+
path = join40(home, frag);
|
|
30580
30805
|
if (frag.endsWith("/") || frag === "" || frag === "~") {
|
|
30581
30806
|
return { dir: path, prefix: "" };
|
|
30582
30807
|
}
|
|
@@ -30605,7 +30830,7 @@ function rankAndSlice(dir, candidates) {
|
|
|
30605
30830
|
});
|
|
30606
30831
|
return candidates.slice(0, MAX_SUGGESTIONS).map(({ relPath, isDir }) => ({
|
|
30607
30832
|
label: `${relPath}${isDir ? "/" : ""}`,
|
|
30608
|
-
value: toToken(
|
|
30833
|
+
value: toToken(join40(dir, relPath), isDir),
|
|
30609
30834
|
isDir
|
|
30610
30835
|
}));
|
|
30611
30836
|
}
|
|
@@ -30652,7 +30877,7 @@ async function warmPathSuggestions(lineText, col, loader = listFilesWithRipgrep)
|
|
|
30652
30877
|
return false;
|
|
30653
30878
|
const { dir } = resolveFragment(token.frag);
|
|
30654
30879
|
try {
|
|
30655
|
-
if (!
|
|
30880
|
+
if (!statSync19(dir).isDirectory())
|
|
30656
30881
|
return false;
|
|
30657
30882
|
} catch {
|
|
30658
30883
|
return false;
|
|
@@ -30666,7 +30891,7 @@ function pathSuggestions(lineText, col) {
|
|
|
30666
30891
|
const { dir, prefix } = resolveFragment(token.frag);
|
|
30667
30892
|
let entries;
|
|
30668
30893
|
try {
|
|
30669
|
-
entries =
|
|
30894
|
+
entries = readdirSync14(dir, { withFileTypes: true });
|
|
30670
30895
|
} catch {
|
|
30671
30896
|
return { start: token.start, end: col, items: [], truncated: 0, searching: false };
|
|
30672
30897
|
}
|
|
@@ -30684,7 +30909,7 @@ function pathSuggestions(lineText, col) {
|
|
|
30684
30909
|
let isDir = entry.isDirectory();
|
|
30685
30910
|
if (!isDir && entry.isSymbolicLink()) {
|
|
30686
30911
|
try {
|
|
30687
|
-
isDir =
|
|
30912
|
+
isDir = statSync19(join40(dir, entry.name)).isDirectory();
|
|
30688
30913
|
} catch {}
|
|
30689
30914
|
}
|
|
30690
30915
|
return {
|
|
@@ -30711,10 +30936,10 @@ function fragmentToAbsolutePath(frag) {
|
|
|
30711
30936
|
if (frag === "~" || frag === "~/")
|
|
30712
30937
|
return home;
|
|
30713
30938
|
if (frag.startsWith("~/"))
|
|
30714
|
-
return
|
|
30939
|
+
return join40(home, frag.slice(2));
|
|
30715
30940
|
if (frag.startsWith("/"))
|
|
30716
30941
|
return frag;
|
|
30717
|
-
return
|
|
30942
|
+
return join40(home, frag);
|
|
30718
30943
|
}
|
|
30719
30944
|
function fragmentResolves(frag) {
|
|
30720
30945
|
try {
|
|
@@ -37590,7 +37815,7 @@ var init_commands2 = __esm(async () => {
|
|
|
37590
37815
|
// ../../adapters/telegram/src/mapping-store.ts
|
|
37591
37816
|
import { Database as Database2 } from "bun:sqlite";
|
|
37592
37817
|
import { mkdirSync as mkdirSync31 } from "fs";
|
|
37593
|
-
import { dirname as dirname20, join as
|
|
37818
|
+
import { dirname as dirname20, join as join41 } from "path";
|
|
37594
37819
|
function outboxRowToEntry(row) {
|
|
37595
37820
|
return {
|
|
37596
37821
|
id: row.id,
|
|
@@ -37656,7 +37881,7 @@ function migrateOutboxSchema(db4) {
|
|
|
37656
37881
|
db4.run("CREATE INDEX IF NOT EXISTS idx_telegram_outbox_runtime_message ON outbox(runtime_message_id)");
|
|
37657
37882
|
}
|
|
37658
37883
|
function openMappingStore(path) {
|
|
37659
|
-
const dbPath = path ??
|
|
37884
|
+
const dbPath = path ?? join41(DATA_DIR, "adapter-telegram.db");
|
|
37660
37885
|
if (dbPath !== ":memory:")
|
|
37661
37886
|
mkdirSync31(dirname20(dbPath), { recursive: true });
|
|
37662
37887
|
const db4 = new Database2(dbPath);
|
|
@@ -39521,8 +39746,8 @@ __export(exports_central, {
|
|
|
39521
39746
|
listPeerNodes: () => listPeerNodes,
|
|
39522
39747
|
configureOtiumCentral: () => configureOtiumCentral
|
|
39523
39748
|
});
|
|
39524
|
-
function configureOtiumCentral(
|
|
39525
|
-
joinConfig =
|
|
39749
|
+
function configureOtiumCentral(join42) {
|
|
39750
|
+
joinConfig = join42;
|
|
39526
39751
|
resetPeerCentralCaches();
|
|
39527
39752
|
}
|
|
39528
39753
|
function otiumCentralConfig() {
|
|
@@ -39678,17 +39903,17 @@ __export(exports_join, {
|
|
|
39678
39903
|
import { createHash as createHash10, randomUUID as randomUUID27 } from "crypto";
|
|
39679
39904
|
import {
|
|
39680
39905
|
chmodSync as chmodSync6,
|
|
39681
|
-
closeSync as
|
|
39906
|
+
closeSync as closeSync5,
|
|
39682
39907
|
existsSync as existsSync35,
|
|
39683
39908
|
fsyncSync as fsyncSync2,
|
|
39684
39909
|
linkSync,
|
|
39685
39910
|
lstatSync,
|
|
39686
39911
|
mkdirSync as mkdirSync32,
|
|
39687
|
-
openSync as
|
|
39688
|
-
readFileSync as
|
|
39689
|
-
renameSync as
|
|
39690
|
-
rmSync as
|
|
39691
|
-
statSync as
|
|
39912
|
+
openSync as openSync5,
|
|
39913
|
+
readFileSync as readFileSync27,
|
|
39914
|
+
renameSync as renameSync16,
|
|
39915
|
+
rmSync as rmSync10,
|
|
39916
|
+
statSync as statSync20,
|
|
39692
39917
|
unlinkSync as unlinkSync22,
|
|
39693
39918
|
writeFileSync as writeFileSync23
|
|
39694
39919
|
} from "fs";
|
|
@@ -39773,27 +39998,27 @@ function withJoinCredentialLock(operation) {
|
|
|
39773
39998
|
created = true;
|
|
39774
39999
|
writeFileSync23(ownerPath, `${JSON.stringify(owner)}
|
|
39775
40000
|
`, { mode: 384 });
|
|
39776
|
-
const ownerFd =
|
|
40001
|
+
const ownerFd = openSync5(ownerPath, "r");
|
|
39777
40002
|
try {
|
|
39778
40003
|
fsyncSync2(ownerFd);
|
|
39779
40004
|
} finally {
|
|
39780
|
-
|
|
40005
|
+
closeSync5(ownerFd);
|
|
39781
40006
|
}
|
|
39782
40007
|
break;
|
|
39783
40008
|
} catch (error2) {
|
|
39784
40009
|
if (created) {
|
|
39785
|
-
|
|
40010
|
+
rmSync10(lockPath, { recursive: true, force: true });
|
|
39786
40011
|
throw error2;
|
|
39787
40012
|
}
|
|
39788
40013
|
if (error2.code !== "EEXIST")
|
|
39789
40014
|
throw error2;
|
|
39790
40015
|
let current3 = null;
|
|
39791
40016
|
try {
|
|
39792
|
-
current3 = JSON.parse(
|
|
40017
|
+
current3 = JSON.parse(readFileSync27(ownerPath, "utf8"));
|
|
39793
40018
|
} catch {}
|
|
39794
40019
|
let ageMs;
|
|
39795
40020
|
try {
|
|
39796
|
-
ageMs = Date.now() -
|
|
40021
|
+
ageMs = Date.now() - statSync20(lockPath).mtimeMs;
|
|
39797
40022
|
} catch (statError) {
|
|
39798
40023
|
if (statError.code === "ENOENT")
|
|
39799
40024
|
continue;
|
|
@@ -39807,8 +40032,8 @@ function withJoinCredentialLock(operation) {
|
|
|
39807
40032
|
}
|
|
39808
40033
|
const stalePath = `${lockPath}.stale.${process.pid}.${randomUUID27()}`;
|
|
39809
40034
|
try {
|
|
39810
|
-
|
|
39811
|
-
|
|
40035
|
+
renameSync16(lockPath, stalePath);
|
|
40036
|
+
rmSync10(stalePath, { recursive: true, force: true });
|
|
39812
40037
|
} catch (staleError) {
|
|
39813
40038
|
if (staleError.code !== "ENOENT")
|
|
39814
40039
|
throw staleError;
|
|
@@ -39819,9 +40044,9 @@ function withJoinCredentialLock(operation) {
|
|
|
39819
40044
|
return operation();
|
|
39820
40045
|
} finally {
|
|
39821
40046
|
try {
|
|
39822
|
-
const current3 = JSON.parse(
|
|
40047
|
+
const current3 = JSON.parse(readFileSync27(ownerPath, "utf8"));
|
|
39823
40048
|
if (current3.pid === owner.pid && current3.token === owner.token) {
|
|
39824
|
-
|
|
40049
|
+
rmSync10(lockPath, { recursive: true, force: true });
|
|
39825
40050
|
}
|
|
39826
40051
|
} catch {}
|
|
39827
40052
|
}
|
|
@@ -39829,39 +40054,39 @@ function withJoinCredentialLock(operation) {
|
|
|
39829
40054
|
function joinsEqual(left, right) {
|
|
39830
40055
|
return left.central === right.central && left.relay === right.relay && left.cellId === right.cellId && left.secret === right.secret;
|
|
39831
40056
|
}
|
|
39832
|
-
function normalizedJoin(
|
|
40057
|
+
function normalizedJoin(join42) {
|
|
39833
40058
|
return normalizeJoin({
|
|
39834
|
-
v:
|
|
39835
|
-
central:
|
|
39836
|
-
relay:
|
|
39837
|
-
cellId:
|
|
39838
|
-
secret:
|
|
40059
|
+
v: join42.v,
|
|
40060
|
+
central: join42.central,
|
|
40061
|
+
relay: join42.relay,
|
|
40062
|
+
cellId: join42.cellId,
|
|
40063
|
+
secret: join42.secret
|
|
39839
40064
|
});
|
|
39840
40065
|
}
|
|
39841
|
-
function joinCredentialDigest(
|
|
39842
|
-
return createHash10("sha256").update(JSON.stringify(normalizedJoin(
|
|
40066
|
+
function joinCredentialDigest(join42) {
|
|
40067
|
+
return createHash10("sha256").update(JSON.stringify(normalizedJoin(join42))).digest("base64url");
|
|
39843
40068
|
}
|
|
39844
40069
|
function readPersistedJoin(path = joinFilePath()) {
|
|
39845
40070
|
if (!existsSync35(path))
|
|
39846
40071
|
return null;
|
|
39847
|
-
const parsed = JSON.parse(
|
|
40072
|
+
const parsed = JSON.parse(readFileSync27(path, "utf-8"));
|
|
39848
40073
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
39849
40074
|
throw new Error("persisted join credentials are not a JSON object");
|
|
39850
40075
|
}
|
|
39851
40076
|
return normalizeJoin(parsed);
|
|
39852
40077
|
}
|
|
39853
|
-
function isJoinPersisted(
|
|
40078
|
+
function isJoinPersisted(join42) {
|
|
39854
40079
|
try {
|
|
39855
40080
|
const persisted = readPersistedJoin();
|
|
39856
|
-
return persisted !== null && joinsEqual(persisted, normalizedJoin(
|
|
40081
|
+
return persisted !== null && joinsEqual(persisted, normalizedJoin(join42));
|
|
39857
40082
|
} catch {
|
|
39858
40083
|
return false;
|
|
39859
40084
|
}
|
|
39860
40085
|
}
|
|
39861
|
-
function saveJoinWhileLocked(
|
|
40086
|
+
function saveJoinWhileLocked(join42, options = {}) {
|
|
39862
40087
|
const path = joinFilePath();
|
|
39863
40088
|
const directory = dirname21(path);
|
|
39864
|
-
const normalized = normalizedJoin(
|
|
40089
|
+
const normalized = normalizedJoin(join42);
|
|
39865
40090
|
mkdirSync32(directory, { recursive: true });
|
|
39866
40091
|
if (existsSync35(path)) {
|
|
39867
40092
|
if (lstatSync(path).isSymbolicLink()) {
|
|
@@ -39877,17 +40102,17 @@ function saveJoinWhileLocked(join41, options = {}) {
|
|
|
39877
40102
|
}
|
|
39878
40103
|
if (existing && joinsEqual(existing, normalized)) {
|
|
39879
40104
|
chmodSync6(path, 384);
|
|
39880
|
-
const fileFd =
|
|
40105
|
+
const fileFd = openSync5(path, "r");
|
|
39881
40106
|
try {
|
|
39882
40107
|
fsyncSync2(fileFd);
|
|
39883
40108
|
} finally {
|
|
39884
|
-
|
|
40109
|
+
closeSync5(fileFd);
|
|
39885
40110
|
}
|
|
39886
|
-
const directoryFd =
|
|
40111
|
+
const directoryFd = openSync5(directory, "r");
|
|
39887
40112
|
try {
|
|
39888
40113
|
fsyncSync2(directoryFd);
|
|
39889
40114
|
} finally {
|
|
39890
|
-
|
|
40115
|
+
closeSync5(directoryFd);
|
|
39891
40116
|
}
|
|
39892
40117
|
return path;
|
|
39893
40118
|
}
|
|
@@ -39898,36 +40123,36 @@ function saveJoinWhileLocked(join41, options = {}) {
|
|
|
39898
40123
|
const temporaryPath = resolve23(directory, `.otium-join.json.${process.pid}.${randomUUID27()}.tmp`);
|
|
39899
40124
|
let fd;
|
|
39900
40125
|
try {
|
|
39901
|
-
fd =
|
|
40126
|
+
fd = openSync5(temporaryPath, "wx", 384);
|
|
39902
40127
|
writeFileSync23(fd, `${JSON.stringify(normalized, null, 2)}
|
|
39903
40128
|
`, "utf8");
|
|
39904
40129
|
fsyncSync2(fd);
|
|
39905
|
-
|
|
40130
|
+
closeSync5(fd);
|
|
39906
40131
|
fd = undefined;
|
|
39907
40132
|
if (options.replaceExisting) {
|
|
39908
|
-
|
|
40133
|
+
renameSync16(temporaryPath, path);
|
|
39909
40134
|
} else {
|
|
39910
40135
|
linkSync(temporaryPath, path);
|
|
39911
40136
|
unlinkSync22(temporaryPath);
|
|
39912
40137
|
}
|
|
39913
40138
|
chmodSync6(path, 384);
|
|
39914
|
-
const directoryFd =
|
|
40139
|
+
const directoryFd = openSync5(directory, "r");
|
|
39915
40140
|
try {
|
|
39916
40141
|
fsyncSync2(directoryFd);
|
|
39917
40142
|
} finally {
|
|
39918
|
-
|
|
40143
|
+
closeSync5(directoryFd);
|
|
39919
40144
|
}
|
|
39920
40145
|
} catch (error2) {
|
|
39921
40146
|
if (fd !== undefined)
|
|
39922
|
-
|
|
40147
|
+
closeSync5(fd);
|
|
39923
40148
|
if (existsSync35(temporaryPath))
|
|
39924
40149
|
unlinkSync22(temporaryPath);
|
|
39925
40150
|
throw error2;
|
|
39926
40151
|
}
|
|
39927
40152
|
return path;
|
|
39928
40153
|
}
|
|
39929
|
-
function saveJoin(
|
|
39930
|
-
return withJoinCredentialLock(() => saveJoinWhileLocked(
|
|
40154
|
+
function saveJoin(join42, options = {}) {
|
|
40155
|
+
return withJoinCredentialLock(() => saveJoinWhileLocked(join42, options));
|
|
39931
40156
|
}
|
|
39932
40157
|
function removeJoin() {
|
|
39933
40158
|
return withJoinCredentialLock(() => {
|
|
@@ -39938,11 +40163,11 @@ function removeJoin() {
|
|
|
39938
40163
|
throw new Error(`refusing to remove symlinked Otium join file at ${path}`);
|
|
39939
40164
|
}
|
|
39940
40165
|
unlinkSync22(path);
|
|
39941
|
-
const directoryFd =
|
|
40166
|
+
const directoryFd = openSync5(dirname21(path), "r");
|
|
39942
40167
|
try {
|
|
39943
40168
|
fsyncSync2(directoryFd);
|
|
39944
40169
|
} finally {
|
|
39945
|
-
|
|
40170
|
+
closeSync5(directoryFd);
|
|
39946
40171
|
}
|
|
39947
40172
|
return true;
|
|
39948
40173
|
});
|
|
@@ -39967,7 +40192,7 @@ function loadJoin() {
|
|
|
39967
40192
|
if (!existsSync35(path))
|
|
39968
40193
|
return null;
|
|
39969
40194
|
try {
|
|
39970
|
-
const parsed = JSON.parse(
|
|
40195
|
+
const parsed = JSON.parse(readFileSync27(path, "utf-8"));
|
|
39971
40196
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
39972
40197
|
return null;
|
|
39973
40198
|
return normalizeJoin(parsed);
|
|
@@ -40944,8 +41169,8 @@ var init_event_backflow = __esm(async () => {
|
|
|
40944
41169
|
|
|
40945
41170
|
// ../../adapters/otium/src/peer-files.ts
|
|
40946
41171
|
import { randomUUID as randomUUID29 } from "crypto";
|
|
40947
|
-
import { copyFileSync as copyFileSync5, mkdirSync as mkdirSync33, rmSync as
|
|
40948
|
-
import { basename as basename13, extname as extname6, join as
|
|
41172
|
+
import { copyFileSync as copyFileSync5, mkdirSync as mkdirSync33, rmSync as rmSync11, statSync as statSync21 } from "fs";
|
|
41173
|
+
import { basename as basename13, extname as extname6, join as join42 } from "path";
|
|
40949
41174
|
function fileType(mimeType) {
|
|
40950
41175
|
if (mimeType.startsWith("image/"))
|
|
40951
41176
|
return "image";
|
|
@@ -41015,21 +41240,21 @@ function recordFile(args) {
|
|
|
41015
41240
|
function insertLocalFile(args) {
|
|
41016
41241
|
const id = randomUUID29();
|
|
41017
41242
|
mkdirSync33(PEER_FILES_DIR, { recursive: true });
|
|
41018
|
-
const path =
|
|
41243
|
+
const path = join42(PEER_FILES_DIR, `${id}-${safeFilename(args.filename)}`);
|
|
41019
41244
|
copyFileSync5(args.sourcePath, path);
|
|
41020
|
-
return recordFile({ id, path, sizeBytes:
|
|
41245
|
+
return recordFile({ id, path, sizeBytes: statSync21(path).size, ...args });
|
|
41021
41246
|
}
|
|
41022
41247
|
function deletePeerFilesForTopic(topicId) {
|
|
41023
41248
|
const rows = db.query("SELECT path FROM otium_peer_files WHERE topic_id = ?").all(topicId);
|
|
41024
41249
|
db.run("DELETE FROM otium_peer_files WHERE topic_id = ?", [topicId]);
|
|
41025
41250
|
for (const row of rows)
|
|
41026
|
-
|
|
41251
|
+
rmSync11(row.path, { force: true });
|
|
41027
41252
|
}
|
|
41028
41253
|
async function storePeerInputFile(file, access) {
|
|
41029
41254
|
const id = randomUUID29();
|
|
41030
41255
|
mkdirSync33(PEER_FILES_DIR, { recursive: true });
|
|
41031
41256
|
const filename = file.name || "upload";
|
|
41032
|
-
const path =
|
|
41257
|
+
const path = join42(PEER_FILES_DIR, `${id}-${safeFilename(filename)}`);
|
|
41033
41258
|
const sizeBytes = await Bun.write(path, file);
|
|
41034
41259
|
return recordFile({
|
|
41035
41260
|
id,
|
|
@@ -41076,7 +41301,7 @@ function installPeerFileHooks() {
|
|
|
41076
41301
|
var PEER_FILES_DIR;
|
|
41077
41302
|
var init_peer_files = __esm(async () => {
|
|
41078
41303
|
await init_src();
|
|
41079
|
-
PEER_FILES_DIR =
|
|
41304
|
+
PEER_FILES_DIR = join42(DATA_DIR, "otium-peer-files");
|
|
41080
41305
|
db.exec(`
|
|
41081
41306
|
CREATE TABLE IF NOT EXISTS otium_peer_files (
|
|
41082
41307
|
id TEXT PRIMARY KEY,
|
|
@@ -41780,7 +42005,7 @@ function messageEnvelope(message) {
|
|
|
41780
42005
|
...message.kind ? { kind: message.kind } : {}
|
|
41781
42006
|
};
|
|
41782
42007
|
}
|
|
41783
|
-
async function publishTopic(
|
|
42008
|
+
async function publishTopic(join43, topicId, node) {
|
|
41784
42009
|
const topic = getTopic(topicId);
|
|
41785
42010
|
if (!topic || topic.kind !== "agent" || !topic.agent || !isTopicShared(topic) || !topic.visibility || topic.visibility === "hidden" || isMirrorTopic(topicId))
|
|
41786
42011
|
return;
|
|
@@ -41828,10 +42053,10 @@ async function publishTopic(join42, topicId, node) {
|
|
|
41828
42053
|
}
|
|
41829
42054
|
} catch (error2) {
|
|
41830
42055
|
logger.warn({ error: error2, topicId }, "otium: shared topic publish deferred");
|
|
41831
|
-
setTimeout(() => void reconcileTopic(
|
|
42056
|
+
setTimeout(() => void reconcileTopic(join43, topicId), RETRY_MS).unref?.();
|
|
41832
42057
|
}
|
|
41833
42058
|
}
|
|
41834
|
-
async function unpublishTopic(
|
|
42059
|
+
async function unpublishTopic(join43, topicId, node) {
|
|
41835
42060
|
const state2 = getSharedTopicState(topicId);
|
|
41836
42061
|
if (!state2)
|
|
41837
42062
|
return;
|
|
@@ -41847,26 +42072,26 @@ async function unpublishTopic(join42, topicId, node) {
|
|
|
41847
42072
|
deleteSharedTopicState(topicId);
|
|
41848
42073
|
} catch (error2) {
|
|
41849
42074
|
logger.warn({ error: error2, topicId }, "otium: shared topic unpublish deferred");
|
|
41850
|
-
setTimeout(() => void reconcileTopic(
|
|
42075
|
+
setTimeout(() => void reconcileTopic(join43, topicId), RETRY_MS).unref?.();
|
|
41851
42076
|
}
|
|
41852
42077
|
}
|
|
41853
|
-
async function reconcileTopic(
|
|
42078
|
+
async function reconcileTopic(join43, topicId, explicit = false) {
|
|
41854
42079
|
if (!otiumCentralConfig())
|
|
41855
42080
|
return;
|
|
41856
|
-
if (!explicit && isPeerDetached(
|
|
42081
|
+
if (!explicit && isPeerDetached(join43.cellId))
|
|
41857
42082
|
return;
|
|
41858
42083
|
const target = (await listPeerNodes()).find((node) => node.isPrimary) ?? null;
|
|
41859
42084
|
if (!target)
|
|
41860
42085
|
return;
|
|
41861
42086
|
const topic = getTopic(topicId);
|
|
41862
42087
|
if (topic?.kind === "agent" && topic.agent && isTopicShared(topic) && topic.visibility !== "hidden" && !isMirrorTopic(topicId))
|
|
41863
|
-
return publishTopic(
|
|
41864
|
-
return unpublishTopic(
|
|
42088
|
+
return publishTopic(join43, topicId, target);
|
|
42089
|
+
return unpublishTopic(join43, topicId, target);
|
|
41865
42090
|
}
|
|
41866
|
-
function disconnectSharedTopics(
|
|
42091
|
+
function disconnectSharedTopics(join43) {
|
|
41867
42092
|
const states = listSharedTopicStates();
|
|
41868
42093
|
const hubPromise = listPeerNodes({ fresh: true }).then((nodes) => nodes.find((node) => node.isPrimary) ?? null, () => null);
|
|
41869
|
-
const updated = downgradeSharedTopicsLocally(
|
|
42094
|
+
const updated = downgradeSharedTopicsLocally(join43.cellId);
|
|
41870
42095
|
for (const topicId of updated)
|
|
41871
42096
|
WsHub.get().broadcastTopicUpdated(topicId);
|
|
41872
42097
|
const deletions = states.map(async (state2) => {
|
|
@@ -41889,16 +42114,16 @@ function downgradeSharedTopicsForHub(hubNodeId) {
|
|
|
41889
42114
|
WsHub.get().broadcastTopicUpdated(topicId);
|
|
41890
42115
|
return updated.length;
|
|
41891
42116
|
}
|
|
41892
|
-
async function checkPeerAttachment(
|
|
42117
|
+
async function checkPeerAttachment(join43) {
|
|
41893
42118
|
const nodes = await listPeerNodes({ fresh: true });
|
|
41894
|
-
if (nodes.some((node) => node.cellId ===
|
|
42119
|
+
if (nodes.some((node) => node.cellId === join43.cellId))
|
|
41895
42120
|
return true;
|
|
41896
|
-
downgradeSharedTopicsForHub(
|
|
42121
|
+
downgradeSharedTopicsForHub(join43.cellId);
|
|
41897
42122
|
return false;
|
|
41898
42123
|
}
|
|
41899
|
-
function startSharedTopicSync(
|
|
42124
|
+
function startSharedTopicSync(join43) {
|
|
41900
42125
|
let stopped = false;
|
|
41901
|
-
let detached = isPeerDetached(
|
|
42126
|
+
let detached = isPeerDetached(join43.cellId);
|
|
41902
42127
|
const queue = new Set;
|
|
41903
42128
|
const schedule = (topicId, explicit = false) => {
|
|
41904
42129
|
if (stopped || queue.has(topicId))
|
|
@@ -41907,7 +42132,7 @@ function startSharedTopicSync(join42) {
|
|
|
41907
42132
|
queueMicrotask(async () => {
|
|
41908
42133
|
queue.delete(topicId);
|
|
41909
42134
|
try {
|
|
41910
|
-
await reconcileTopic(
|
|
42135
|
+
await reconcileTopic(join43, topicId, explicit);
|
|
41911
42136
|
} catch (error2) {
|
|
41912
42137
|
logger.warn({ error: error2, topicId }, "otium: shared topic reconciliation failed");
|
|
41913
42138
|
}
|
|
@@ -41921,7 +42146,7 @@ function startSharedTopicSync(join42) {
|
|
|
41921
42146
|
if (stopped || detached)
|
|
41922
42147
|
return;
|
|
41923
42148
|
try {
|
|
41924
|
-
if (!await checkPeerAttachment(
|
|
42149
|
+
if (!await checkPeerAttachment(join43))
|
|
41925
42150
|
detached = true;
|
|
41926
42151
|
} catch {}
|
|
41927
42152
|
}, 30000);
|
|
@@ -41933,7 +42158,7 @@ function startSharedTopicSync(join42) {
|
|
|
41933
42158
|
const message = event.payload;
|
|
41934
42159
|
if (!message.sourceNode) {
|
|
41935
42160
|
schedule(event.topicId);
|
|
41936
|
-
forwardSharedTopicMessage(
|
|
42161
|
+
forwardSharedTopicMessage(join43, message).catch((error2) => logger.warn({ error: error2, topicId: event.topicId }, "otium: shared message deferred"));
|
|
41937
42162
|
}
|
|
41938
42163
|
}
|
|
41939
42164
|
});
|
|
@@ -42684,14 +42909,14 @@ import {
|
|
|
42684
42909
|
} from "crypto";
|
|
42685
42910
|
import {
|
|
42686
42911
|
chmodSync as chmodSync7,
|
|
42687
|
-
closeSync as
|
|
42912
|
+
closeSync as closeSync6,
|
|
42688
42913
|
existsSync as existsSync37,
|
|
42689
42914
|
fsyncSync as fsyncSync3,
|
|
42690
42915
|
linkSync as linkSync2,
|
|
42691
42916
|
mkdirSync as mkdirSync34,
|
|
42692
|
-
openSync as
|
|
42693
|
-
readFileSync as
|
|
42694
|
-
renameSync as
|
|
42917
|
+
openSync as openSync6,
|
|
42918
|
+
readFileSync as readFileSync28,
|
|
42919
|
+
renameSync as renameSync17,
|
|
42695
42920
|
unlinkSync as unlinkSync23,
|
|
42696
42921
|
writeFileSync as writeFileSync24
|
|
42697
42922
|
} from "fs";
|
|
@@ -42723,7 +42948,7 @@ function isEnrollmentPending(invite) {
|
|
|
42723
42948
|
if (!existsSync37(path))
|
|
42724
42949
|
return false;
|
|
42725
42950
|
try {
|
|
42726
|
-
const saved = JSON.parse(
|
|
42951
|
+
const saved = JSON.parse(readFileSync28(path, "utf8"));
|
|
42727
42952
|
return saved.central === invite.central && saved.token === invite.token;
|
|
42728
42953
|
} catch {
|
|
42729
42954
|
return false;
|
|
@@ -42732,7 +42957,7 @@ function isEnrollmentPending(invite) {
|
|
|
42732
42957
|
function loadOrCreatePending(invite, nodeName) {
|
|
42733
42958
|
const path = pendingEnrollmentPath();
|
|
42734
42959
|
if (existsSync37(path)) {
|
|
42735
|
-
const saved = JSON.parse(
|
|
42960
|
+
const saved = JSON.parse(readFileSync28(path, "utf8"));
|
|
42736
42961
|
if (saved.central === invite.central && saved.token === invite.token)
|
|
42737
42962
|
return saved;
|
|
42738
42963
|
throw new Error(`another Otium enrollment is pending at ${path}`);
|
|
@@ -42749,28 +42974,28 @@ function loadOrCreatePending(invite, nodeName) {
|
|
|
42749
42974
|
const temporaryPath = resolve25(dirname22(path), `.otium-enrollment-pending.json.${process.pid}.${randomUUID31()}.tmp`);
|
|
42750
42975
|
let fd;
|
|
42751
42976
|
try {
|
|
42752
|
-
fd =
|
|
42977
|
+
fd = openSync6(temporaryPath, "wx", 384);
|
|
42753
42978
|
writeFileSync24(fd, `${JSON.stringify(pending2, null, 2)}
|
|
42754
42979
|
`, "utf8");
|
|
42755
42980
|
fsyncSync3(fd);
|
|
42756
|
-
|
|
42981
|
+
closeSync6(fd);
|
|
42757
42982
|
fd = undefined;
|
|
42758
42983
|
linkSync2(temporaryPath, path);
|
|
42759
42984
|
unlinkSync23(temporaryPath);
|
|
42760
42985
|
chmodSync7(path, 384);
|
|
42761
|
-
const directoryFd =
|
|
42986
|
+
const directoryFd = openSync6(dirname22(path), "r");
|
|
42762
42987
|
try {
|
|
42763
42988
|
fsyncSync3(directoryFd);
|
|
42764
42989
|
} finally {
|
|
42765
|
-
|
|
42990
|
+
closeSync6(directoryFd);
|
|
42766
42991
|
}
|
|
42767
42992
|
} catch (error2) {
|
|
42768
42993
|
if (fd !== undefined)
|
|
42769
|
-
|
|
42994
|
+
closeSync6(fd);
|
|
42770
42995
|
if (existsSync37(temporaryPath))
|
|
42771
42996
|
unlinkSync23(temporaryPath);
|
|
42772
42997
|
if (error2.code === "EEXIST" && existsSync37(path)) {
|
|
42773
|
-
const saved = JSON.parse(
|
|
42998
|
+
const saved = JSON.parse(readFileSync28(path, "utf8"));
|
|
42774
42999
|
if (saved.central === invite.central && saved.token === invite.token)
|
|
42775
43000
|
return saved;
|
|
42776
43001
|
}
|
|
@@ -42784,34 +43009,34 @@ function replacePendingEnrollment(pending2) {
|
|
|
42784
43009
|
const temporaryPath = resolve25(directory, `.otium-enrollment-pending.json.${process.pid}.${randomUUID31()}.tmp`);
|
|
42785
43010
|
let fd;
|
|
42786
43011
|
try {
|
|
42787
|
-
fd =
|
|
43012
|
+
fd = openSync6(temporaryPath, "wx", 384);
|
|
42788
43013
|
writeFileSync24(fd, `${JSON.stringify(pending2, null, 2)}
|
|
42789
43014
|
`, "utf8");
|
|
42790
43015
|
fsyncSync3(fd);
|
|
42791
|
-
|
|
43016
|
+
closeSync6(fd);
|
|
42792
43017
|
fd = undefined;
|
|
42793
|
-
|
|
42794
|
-
const directoryFd =
|
|
43018
|
+
renameSync17(temporaryPath, path);
|
|
43019
|
+
const directoryFd = openSync6(directory, "r");
|
|
42795
43020
|
try {
|
|
42796
43021
|
fsyncSync3(directoryFd);
|
|
42797
43022
|
} finally {
|
|
42798
|
-
|
|
43023
|
+
closeSync6(directoryFd);
|
|
42799
43024
|
}
|
|
42800
43025
|
} catch (error2) {
|
|
42801
43026
|
if (fd !== undefined)
|
|
42802
|
-
|
|
43027
|
+
closeSync6(fd);
|
|
42803
43028
|
if (existsSync37(temporaryPath))
|
|
42804
43029
|
unlinkSync23(temporaryPath);
|
|
42805
43030
|
throw error2;
|
|
42806
43031
|
}
|
|
42807
43032
|
}
|
|
42808
|
-
function recordClaimedCredential(pending2,
|
|
43033
|
+
function recordClaimedCredential(pending2, join43) {
|
|
42809
43034
|
withJoinCredentialLock(() => {
|
|
42810
|
-
const current3 = JSON.parse(
|
|
43035
|
+
const current3 = JSON.parse(readFileSync28(pendingEnrollmentPath(), "utf8"));
|
|
42811
43036
|
if (current3.central !== pending2.central || current3.token !== pending2.token || current3.idempotencyKey !== pending2.idempotencyKey || current3.publicKey !== pending2.publicKey) {
|
|
42812
43037
|
throw new Error("pending Otium enrollment changed while its claim was in flight");
|
|
42813
43038
|
}
|
|
42814
|
-
const claimed = { digest: joinCredentialDigest(
|
|
43039
|
+
const claimed = { digest: joinCredentialDigest(join43), cellId: join43.cellId };
|
|
42815
43040
|
if (current3.claimed && (current3.claimed.digest !== claimed.digest || current3.claimed.cellId !== claimed.cellId)) {
|
|
42816
43041
|
throw new Error("central returned different credentials for an idempotent enrollment claim");
|
|
42817
43042
|
}
|
|
@@ -42869,40 +43094,40 @@ async function claimEnrollment(invite, nodeName) {
|
|
|
42869
43094
|
const secret = openCredential(credential, pending2.privateKey);
|
|
42870
43095
|
if (!secret.startsWith("rcs_"))
|
|
42871
43096
|
throw new Error("central returned an invalid runtime credential");
|
|
42872
|
-
const
|
|
43097
|
+
const join43 = {
|
|
42873
43098
|
v: 2,
|
|
42874
43099
|
central: invite.central,
|
|
42875
43100
|
relay: String(response.relayUrl),
|
|
42876
43101
|
cellId: String(response.cell?.id),
|
|
42877
43102
|
secret
|
|
42878
43103
|
};
|
|
42879
|
-
if (!
|
|
43104
|
+
if (!join43.relay || !join43.cellId || join43.cellId === "undefined") {
|
|
42880
43105
|
throw new Error("central returned an incomplete enrollment response");
|
|
42881
43106
|
}
|
|
42882
|
-
assertSecureRelayUrl(
|
|
42883
|
-
recordClaimedCredential(pending2,
|
|
42884
|
-
return
|
|
43107
|
+
assertSecureRelayUrl(join43.relay);
|
|
43108
|
+
recordClaimedCredential(pending2, join43);
|
|
43109
|
+
return join43;
|
|
42885
43110
|
}
|
|
42886
|
-
function commitEnrollment(
|
|
43111
|
+
function commitEnrollment(join43, options = {}) {
|
|
42887
43112
|
return withJoinCredentialLock(() => {
|
|
42888
43113
|
const pendingPath = pendingEnrollmentPath();
|
|
42889
|
-
const pending2 = existsSync37(pendingPath) ? JSON.parse(
|
|
42890
|
-
const digest = joinCredentialDigest(
|
|
42891
|
-
if (pending2 && (!pending2.claimed || pending2.claimed.digest !== digest || pending2.claimed.cellId !==
|
|
43114
|
+
const pending2 = existsSync37(pendingPath) ? JSON.parse(readFileSync28(pendingPath, "utf8")) : null;
|
|
43115
|
+
const digest = joinCredentialDigest(join43);
|
|
43116
|
+
if (pending2 && (!pending2.claimed || pending2.claimed.digest !== digest || pending2.claimed.cellId !== join43.cellId)) {
|
|
42892
43117
|
throw new Error(`pending Otium enrollment at ${pendingPath} does not match these credentials`);
|
|
42893
43118
|
}
|
|
42894
|
-
const path = saveJoinWhileLocked(
|
|
42895
|
-
if (!isJoinPersisted(
|
|
43119
|
+
const path = saveJoinWhileLocked(join43, options);
|
|
43120
|
+
if (!isJoinPersisted(join43)) {
|
|
42896
43121
|
throw new Error("Otium join credentials were not durably persisted");
|
|
42897
43122
|
}
|
|
42898
43123
|
if (!pending2)
|
|
42899
43124
|
return path;
|
|
42900
43125
|
unlinkSync23(pendingPath);
|
|
42901
|
-
const directoryFd =
|
|
43126
|
+
const directoryFd = openSync6(dirname22(pendingPath), "r");
|
|
42902
43127
|
try {
|
|
42903
43128
|
fsyncSync3(directoryFd);
|
|
42904
43129
|
} finally {
|
|
42905
|
-
|
|
43130
|
+
closeSync6(directoryFd);
|
|
42906
43131
|
}
|
|
42907
43132
|
return path;
|
|
42908
43133
|
});
|
|
@@ -43783,14 +44008,14 @@ var init_peer_server = __esm(async () => {
|
|
|
43783
44008
|
|
|
43784
44009
|
// ../../adapters/otium/src/index.ts
|
|
43785
44010
|
function startOtiumNodeRuntime(options) {
|
|
43786
|
-
const { join:
|
|
43787
|
-
configureOtiumCentral(
|
|
44011
|
+
const { join: join43 } = options;
|
|
44012
|
+
configureOtiumCentral(join43);
|
|
43788
44013
|
const failed = failInterruptedPeerTurnRequestsOnStartup();
|
|
43789
44014
|
if (failed > 0) {
|
|
43790
44015
|
logger.warn({ failed }, "otium: failed interrupted peer turns from previous process");
|
|
43791
44016
|
}
|
|
43792
44017
|
const stopBackflow = startEventBackflow();
|
|
43793
|
-
const stopSharedTopicSync = startSharedTopicSync(
|
|
44018
|
+
const stopSharedTopicSync = startSharedTopicSync(join43);
|
|
43794
44019
|
const unregisterRuntimeBridge = registerPeerRuntimeBridge(otiumPeerRuntimeBridge);
|
|
43795
44020
|
const unregisterSessionBridge = registerPeerSessionBridge(otiumPeerSessionBridge);
|
|
43796
44021
|
const sessionBridgeIpc = startPeerSessionBridgeIpc(otiumPeerSessionBridge);
|
|
@@ -43811,7 +44036,7 @@ function startOtiumNodeRuntime(options) {
|
|
|
43811
44036
|
}
|
|
43812
44037
|
});
|
|
43813
44038
|
let stopped = false;
|
|
43814
|
-
logger.info({ central:
|
|
44039
|
+
logger.info({ central: join43.central, cellId: join43.cellId }, "otium: worker mode enabled");
|
|
43815
44040
|
selfPeerNode().then((self) => {
|
|
43816
44041
|
if (self) {
|
|
43817
44042
|
logger.info({ nodeName: self.nodeName, baseUrl: self.baseUrl }, "otium: attached to workspace");
|
|
@@ -43821,7 +44046,7 @@ function startOtiumNodeRuntime(options) {
|
|
|
43821
44046
|
});
|
|
43822
44047
|
return {
|
|
43823
44048
|
name: "otium",
|
|
43824
|
-
join:
|
|
44049
|
+
join: join43,
|
|
43825
44050
|
stop: () => {
|
|
43826
44051
|
if (stopped)
|
|
43827
44052
|
return;
|
|
@@ -43943,10 +44168,10 @@ async function handleOtiumAdapterControlRequest(req) {
|
|
|
43943
44168
|
return await handleOtiumPeerRequest(new Request(peerUrl.toString(), { method: req.method, headers, body, signal: req.signal })) ?? Response.json({ ok: false, error: "Otium route not found" }, { status: 404 });
|
|
43944
44169
|
}
|
|
43945
44170
|
function mountConfiguredOtiumNodeRuntime() {
|
|
43946
|
-
const
|
|
43947
|
-
if (!
|
|
44171
|
+
const join43 = loadJoin();
|
|
44172
|
+
if (!join43)
|
|
43948
44173
|
return null;
|
|
43949
|
-
const runtime2 = startOtiumNodeRuntime({ join:
|
|
44174
|
+
const runtime2 = startOtiumNodeRuntime({ join: join43 });
|
|
43950
44175
|
registerNodeRequestHandler("otium-adapter-control", handleOtiumAdapterControlRequest);
|
|
43951
44176
|
let stopped = false;
|
|
43952
44177
|
return {
|
|
@@ -43997,11 +44222,11 @@ async function joinCommand(args) {
|
|
|
43997
44222
|
process.exitCode = 1;
|
|
43998
44223
|
return;
|
|
43999
44224
|
}
|
|
44000
|
-
let
|
|
44225
|
+
let join43;
|
|
44001
44226
|
let productionEnrollment = false;
|
|
44002
44227
|
if (args.includes("--legacy")) {
|
|
44003
44228
|
try {
|
|
44004
|
-
|
|
44229
|
+
join43 = parseInviteCode(code);
|
|
44005
44230
|
} catch (err2) {
|
|
44006
44231
|
console.error(`invalid legacy invite code: ${err2 instanceof Error ? err2.message : err2}`);
|
|
44007
44232
|
process.exitCode = 1;
|
|
@@ -44028,7 +44253,7 @@ async function joinCommand(args) {
|
|
|
44028
44253
|
return;
|
|
44029
44254
|
}
|
|
44030
44255
|
}
|
|
44031
|
-
|
|
44256
|
+
join43 = await claimEnrollment(invite, nodeName);
|
|
44032
44257
|
productionEnrollment = true;
|
|
44033
44258
|
} catch (err2) {
|
|
44034
44259
|
console.error(`enrollment failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
@@ -44039,16 +44264,16 @@ async function joinCommand(args) {
|
|
|
44039
44264
|
let path;
|
|
44040
44265
|
try {
|
|
44041
44266
|
const saveOptions = { replaceExisting: args.includes("--replace") };
|
|
44042
|
-
path = productionEnrollment ? commitEnrollment(
|
|
44267
|
+
path = productionEnrollment ? commitEnrollment(join43, saveOptions) : saveJoin(join43, saveOptions);
|
|
44043
44268
|
} catch (err2) {
|
|
44044
44269
|
console.error(`could not save join credentials: ${err2 instanceof Error ? err2.message : err2}`);
|
|
44045
44270
|
process.exitCode = 1;
|
|
44046
44271
|
return;
|
|
44047
44272
|
}
|
|
44048
44273
|
console.log(`otium join credentials saved to ${path}`);
|
|
44049
|
-
console.log(` central: ${
|
|
44050
|
-
console.log(` cellId: ${
|
|
44051
|
-
configureOtiumCentral(
|
|
44274
|
+
console.log(` central: ${join43.central}`);
|
|
44275
|
+
console.log(` cellId: ${join43.cellId}`);
|
|
44276
|
+
configureOtiumCentral(join43);
|
|
44052
44277
|
try {
|
|
44053
44278
|
const self = await selfPeerNode();
|
|
44054
44279
|
if (self) {
|
|
@@ -44103,8 +44328,8 @@ async function proxyOtiumPeerRequest(req, dependencies = {}) {
|
|
|
44103
44328
|
}
|
|
44104
44329
|
}
|
|
44105
44330
|
async function runOtiumSidecar(options) {
|
|
44106
|
-
const
|
|
44107
|
-
if (!
|
|
44331
|
+
const join43 = loadJoin();
|
|
44332
|
+
if (!join43) {
|
|
44108
44333
|
throw new Error("not joined to an Otium workspace \u2014 run `negotium otium join <code>` first");
|
|
44109
44334
|
}
|
|
44110
44335
|
const initialNode = await inspectNodeDaemon();
|
|
@@ -44136,10 +44361,10 @@ async function runOtiumSidecar(options) {
|
|
|
44136
44361
|
lease.stop();
|
|
44137
44362
|
throw error2;
|
|
44138
44363
|
}
|
|
44139
|
-
const selectedRelay = options.relayUrl?.trim() ||
|
|
44364
|
+
const selectedRelay = options.relayUrl?.trim() || join43.relay || process.env.OTIUM_RELAY_URL?.trim();
|
|
44140
44365
|
const tunnel = selectedRelay ? new TunnelClient({
|
|
44141
44366
|
relayUrl: selectedRelay,
|
|
44142
|
-
token:
|
|
44367
|
+
token: join43.secret,
|
|
44143
44368
|
targetOrigin: `http://127.0.0.1:${server.port}`,
|
|
44144
44369
|
nodeVersion: `negotium@${NEGOTIUM_VERSION}`,
|
|
44145
44370
|
logger
|
|
@@ -44230,10 +44455,10 @@ async function resolveHostNodeId(explicit) {
|
|
|
44230
44455
|
init_central().then(() => exports_central),
|
|
44231
44456
|
init_join().then(() => exports_join)
|
|
44232
44457
|
]);
|
|
44233
|
-
const
|
|
44234
|
-
if (!
|
|
44458
|
+
const join43 = loadJoin2();
|
|
44459
|
+
if (!join43)
|
|
44235
44460
|
throw new Error("not joined to an Otium workspace; pass --host-node or join first");
|
|
44236
|
-
configureOtiumCentral2(
|
|
44461
|
+
configureOtiumCentral2(join43);
|
|
44237
44462
|
try {
|
|
44238
44463
|
const nodes = await listPeerNodes2({ fresh: true });
|
|
44239
44464
|
const primary = nodes.find((node) => node.isPrimary && !node.self) ?? nodes.find((node) => node.isPrimary);
|
|
@@ -44304,12 +44529,12 @@ async function runOtiumCli(args = process.argv.slice(2)) {
|
|
|
44304
44529
|
const { configureOtiumCentral: configureOtiumCentral2 } = await init_central().then(() => exports_central);
|
|
44305
44530
|
const { loadJoin: loadJoin2, removeJoin: removeJoin2 } = await init_join().then(() => exports_join);
|
|
44306
44531
|
const { disconnectSharedTopics: disconnectSharedTopics2 } = await init_shared_topic_sync().then(() => exports_shared_topic_sync);
|
|
44307
|
-
const
|
|
44308
|
-
if (!
|
|
44532
|
+
const join43 = loadJoin2();
|
|
44533
|
+
if (!join43)
|
|
44309
44534
|
throw new Error("not joined to an Otium workspace");
|
|
44310
|
-
configureOtiumCentral2(
|
|
44535
|
+
configureOtiumCentral2(join43);
|
|
44311
44536
|
try {
|
|
44312
|
-
await disconnectSharedTopics2(
|
|
44537
|
+
await disconnectSharedTopics2(join43);
|
|
44313
44538
|
removeJoin2();
|
|
44314
44539
|
} finally {
|
|
44315
44540
|
configureOtiumCentral2(null);
|
|
@@ -45086,4 +45311,4 @@ switch (command) {
|
|
|
45086
45311
|
}
|
|
45087
45312
|
}
|
|
45088
45313
|
|
|
45089
|
-
//# debugId=
|
|
45314
|
+
//# debugId=C6B36BE30E72B26A64756E2164756E21
|