negotium 0.1.25 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/agent-helpers.js +2 -2
- package/dist/agent-helpers.js.map +2 -2
- package/dist/cron.js +93 -38
- package/dist/cron.js.map +6 -5
- package/dist/hosted-agent.js +2 -2
- package/dist/hosted-agent.js.map +2 -2
- package/dist/main.js +149 -94
- package/dist/main.js.map +6 -5
- package/dist/runtime/src/platform/playwright/headed-launch.ts +61 -0
- package/dist/runtime/src/platform/playwright/manager.ts +39 -9
- package/dist/runtime/src/version.ts +1 -1
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -3728,7 +3728,7 @@ var init_claude_provider = __esm(async () => {
|
|
|
3728
3728
|
});
|
|
3729
3729
|
|
|
3730
3730
|
// ../../packages/core/src/version.ts
|
|
3731
|
-
var NEGOTIUM_VERSION = "0.1.
|
|
3731
|
+
var NEGOTIUM_VERSION = "0.1.26";
|
|
3732
3732
|
|
|
3733
3733
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
3734
3734
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -6747,6 +6747,38 @@ var init_self_schedules = __esm(async () => {
|
|
|
6747
6747
|
`);
|
|
6748
6748
|
});
|
|
6749
6749
|
|
|
6750
|
+
// ../../packages/core/src/platform/playwright/headed-launch.ts
|
|
6751
|
+
import { accessSync, constants } from "fs";
|
|
6752
|
+
import { delimiter, isAbsolute, resolve as resolve5 } from "path";
|
|
6753
|
+
function findExecutableOnPath(command, environment = process.env) {
|
|
6754
|
+
const candidates = isAbsolute(command) ? [command] : (environment.PATH ?? "").split(delimiter).filter(Boolean).map((directory) => resolve5(directory, command));
|
|
6755
|
+
for (const candidate of candidates) {
|
|
6756
|
+
try {
|
|
6757
|
+
accessSync(candidate, constants.X_OK);
|
|
6758
|
+
return candidate;
|
|
6759
|
+
} catch {}
|
|
6760
|
+
}
|
|
6761
|
+
return null;
|
|
6762
|
+
}
|
|
6763
|
+
function resolveHeadedPlaywrightSpawn(command, args, options = {}) {
|
|
6764
|
+
const platform2 = options.platform ?? process.platform;
|
|
6765
|
+
const environment = options.environment ?? process.env;
|
|
6766
|
+
const hasDisplay = Boolean(environment.DISPLAY?.trim() || environment.WAYLAND_DISPLAY?.trim());
|
|
6767
|
+
if (platform2 !== "linux" || hasDisplay) {
|
|
6768
|
+
return { command, args: [...args], virtualDisplay: false };
|
|
6769
|
+
}
|
|
6770
|
+
const xvfbRun = (options.findExecutable ?? findExecutableOnPath)("xvfb-run", environment);
|
|
6771
|
+
if (!xvfbRun) {
|
|
6772
|
+
throw new Error("Headed Playwright on Linux requires DISPLAY/WAYLAND_DISPLAY or xvfb-run; install Xvfb and ensure xvfb-run is on PATH");
|
|
6773
|
+
}
|
|
6774
|
+
return {
|
|
6775
|
+
command: xvfbRun,
|
|
6776
|
+
args: ["-a", "-s", "-screen 0 1440x1000x24", command, ...args],
|
|
6777
|
+
virtualDisplay: true
|
|
6778
|
+
};
|
|
6779
|
+
}
|
|
6780
|
+
var init_headed_launch = () => {};
|
|
6781
|
+
|
|
6750
6782
|
// ../../packages/core/src/storage/browser-profiles.ts
|
|
6751
6783
|
function normalizeBrowserProfileName(name) {
|
|
6752
6784
|
const value = name.trim().toLowerCase();
|
|
@@ -6916,7 +6948,7 @@ async function waitForRuntimeProcessLease(role, options = {}) {
|
|
|
6916
6948
|
const remaining = deadline - Date.now();
|
|
6917
6949
|
if (remaining <= 0)
|
|
6918
6950
|
return null;
|
|
6919
|
-
await new Promise((
|
|
6951
|
+
await new Promise((resolve6) => setTimeout(resolve6, Math.min(interval, remaining)));
|
|
6920
6952
|
}
|
|
6921
6953
|
}
|
|
6922
6954
|
async function waitForRequiredRuntimeProcessLease(role, options = {}) {
|
|
@@ -6957,7 +6989,7 @@ import {
|
|
|
6957
6989
|
unlinkSync as unlinkSync10,
|
|
6958
6990
|
writeFileSync as writeFileSync7
|
|
6959
6991
|
} from "fs";
|
|
6960
|
-
import { dirname as dirname8, join as join14, resolve as
|
|
6992
|
+
import { dirname as dirname8, join as join14, resolve as resolve6 } from "path";
|
|
6961
6993
|
function makeInstanceKey(userId, topic) {
|
|
6962
6994
|
if (!topic)
|
|
6963
6995
|
return makeBrowserProfileInstanceKey(userId, "default");
|
|
@@ -6975,7 +7007,7 @@ function migrateLegacyTopicProfile(ownerId, topic) {
|
|
|
6975
7007
|
const current2 = getTopicBrowserProfile(topic);
|
|
6976
7008
|
if (current2 !== "default" || !hasBrowserProfileTopic(topic))
|
|
6977
7009
|
return current2;
|
|
6978
|
-
const legacyDir =
|
|
7010
|
+
const legacyDir = resolve6(BROWSER_PROFILES_DIR, sanitizeTopicName(topic));
|
|
6979
7011
|
if (!existsSync13(legacyDir))
|
|
6980
7012
|
return current2;
|
|
6981
7013
|
const profile = legacyBrowserProfileName(topic);
|
|
@@ -7179,11 +7211,11 @@ async function killPlaywrightOnPort(port, expectedUserDataDir) {
|
|
|
7179
7211
|
}
|
|
7180
7212
|
function browserProcessMatchesExpectedProfile(cmdline, expectedUserDataDir) {
|
|
7181
7213
|
const actualUserDataDir = extractUserDataDirArg(cmdline);
|
|
7182
|
-
return actualUserDataDir !== null &&
|
|
7214
|
+
return actualUserDataDir !== null && resolve6(actualUserDataDir) === resolve6(expectedUserDataDir);
|
|
7183
7215
|
}
|
|
7184
7216
|
function killBrowserProcsForUserDataDir(userDataDir) {
|
|
7185
|
-
const target =
|
|
7186
|
-
if (!target.startsWith(
|
|
7217
|
+
const target = resolve6(userDataDir);
|
|
7218
|
+
if (!target.startsWith(resolve6(BROWSER_PROFILES_DIR)))
|
|
7187
7219
|
return;
|
|
7188
7220
|
let pids;
|
|
7189
7221
|
try {
|
|
@@ -7203,7 +7235,7 @@ function killBrowserProcsForUserDataDir(userDataDir) {
|
|
|
7203
7235
|
stdio: "pipe"
|
|
7204
7236
|
}).toString().trim();
|
|
7205
7237
|
const argDir = extractUserDataDirArg(cmdline);
|
|
7206
|
-
if (!argDir ||
|
|
7238
|
+
if (!argDir || resolve6(argDir) !== target)
|
|
7207
7239
|
continue;
|
|
7208
7240
|
killProcessTreeChildren(pidNum);
|
|
7209
7241
|
process.kill(pidNum, "SIGKILL");
|
|
@@ -7214,13 +7246,13 @@ function killBrowserProcsForUserDataDir(userDataDir) {
|
|
|
7214
7246
|
}
|
|
7215
7247
|
}
|
|
7216
7248
|
function selectOrphanBrowserPids(procs, liveUserDataDirs, profileRoot, selfPid) {
|
|
7217
|
-
const root =
|
|
7218
|
-
const live = new Set([...liveUserDataDirs].map((d) =>
|
|
7249
|
+
const root = resolve6(profileRoot);
|
|
7250
|
+
const live = new Set([...liveUserDataDirs].map((d) => resolve6(d)));
|
|
7219
7251
|
const out = [];
|
|
7220
7252
|
for (const { pid, userDataDir } of procs) {
|
|
7221
7253
|
if (pid === selfPid || !userDataDir)
|
|
7222
7254
|
continue;
|
|
7223
|
-
const dir =
|
|
7255
|
+
const dir = resolve6(userDataDir);
|
|
7224
7256
|
if (!dir.startsWith(root))
|
|
7225
7257
|
continue;
|
|
7226
7258
|
if (live.has(dir))
|
|
@@ -7236,7 +7268,7 @@ function reapOrphanBrowsers() {
|
|
|
7236
7268
|
const daemonLease = getRuntimeProcessLease("node-daemon", Date.now(), Number.POSITIVE_INFINITY);
|
|
7237
7269
|
if (!isBrowserJanitorOwner(daemonLease?.pid ?? null, process.pid))
|
|
7238
7270
|
return;
|
|
7239
|
-
const profileRoot =
|
|
7271
|
+
const profileRoot = resolve6(BROWSER_PROFILES_DIR);
|
|
7240
7272
|
let pids;
|
|
7241
7273
|
try {
|
|
7242
7274
|
pids = execFileSync4("pgrep", ["-f", "--", profileRoot], { stdio: "pipe" }).toString().trim();
|
|
@@ -7289,7 +7321,7 @@ function cleanSingletonFiles(userDataDir) {
|
|
|
7289
7321
|
for (const f of files) {
|
|
7290
7322
|
if (f.startsWith("Singleton")) {
|
|
7291
7323
|
try {
|
|
7292
|
-
unlinkSync10(
|
|
7324
|
+
unlinkSync10(resolve6(userDataDir, f));
|
|
7293
7325
|
logger.info({ file: f, userDataDir }, "Removed stale Singleton file");
|
|
7294
7326
|
} catch (e) {
|
|
7295
7327
|
logger.warn({ err: e, file: f }, "Failed to remove stale Chrome Singleton file");
|
|
@@ -7325,7 +7357,7 @@ function ownerDirectory(ownerId) {
|
|
|
7325
7357
|
return `${sanitizeTopicName(ownerId).slice(0, 24)}_${digest}`;
|
|
7326
7358
|
}
|
|
7327
7359
|
function resolveProfileDir(ownerId, profile) {
|
|
7328
|
-
return
|
|
7360
|
+
return resolve6(BROWSER_PROFILES_DIR, "profiles", ownerDirectory(ownerId), profile);
|
|
7329
7361
|
}
|
|
7330
7362
|
function resolveUserDataDir(instanceKey) {
|
|
7331
7363
|
const { ownerId, profile } = parseInstanceKey(instanceKey);
|
|
@@ -7383,11 +7415,25 @@ async function spawnPlaywright(instanceKey, userId, reservedPort, browserBin = P
|
|
|
7383
7415
|
}
|
|
7384
7416
|
const command = browserBin.endsWith(".mjs") ? process.execPath : browserBin;
|
|
7385
7417
|
const args = browserBin.endsWith(".mjs") ? [browserBin, ...mcpArgs] : mcpArgs;
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7390
|
-
|
|
7418
|
+
let spawnSpec;
|
|
7419
|
+
try {
|
|
7420
|
+
spawnSpec = resolveHeadedPlaywrightSpawn(command, args, { environment: childEnv });
|
|
7421
|
+
} catch (err) {
|
|
7422
|
+
releasePort(port);
|
|
7423
|
+
throw err;
|
|
7424
|
+
}
|
|
7425
|
+
let proc;
|
|
7426
|
+
try {
|
|
7427
|
+
proc = spawn4(spawnSpec.command, spawnSpec.args, {
|
|
7428
|
+
stdio: "ignore",
|
|
7429
|
+
detached: false,
|
|
7430
|
+
env: childEnv
|
|
7431
|
+
});
|
|
7432
|
+
} catch (err) {
|
|
7433
|
+
releasePort(port);
|
|
7434
|
+
throw err;
|
|
7435
|
+
}
|
|
7436
|
+
const spawnError = waitForChildProcessSpawnError(proc);
|
|
7391
7437
|
const reapCrashedBrowser = () => {
|
|
7392
7438
|
const userDataDir2 = resolveUserDataDir(instanceKey);
|
|
7393
7439
|
killBrowserProcsForUserDataDir(userDataDir2);
|
|
@@ -7420,7 +7466,10 @@ async function spawnPlaywright(instanceKey, userId, reservedPort, browserBin = P
|
|
|
7420
7466
|
lastUsedAt: now,
|
|
7421
7467
|
capability
|
|
7422
7468
|
});
|
|
7423
|
-
const ready = await
|
|
7469
|
+
const ready = await Promise.race([
|
|
7470
|
+
(async () => await waitForServer(port, 1e4) && await supportsOwnerCleanup(port, capability))(),
|
|
7471
|
+
spawnError
|
|
7472
|
+
]);
|
|
7424
7473
|
if (!ready) {
|
|
7425
7474
|
const exitCode = proc.exitCode;
|
|
7426
7475
|
killInstance(instanceKey);
|
|
@@ -7431,7 +7480,7 @@ async function spawnPlaywright(instanceKey, userId, reservedPort, browserBin = P
|
|
|
7431
7480
|
throw new Error(`Playwright MCP failed health check after spawn on port ${port}` + (exitCode === null ? "" : ` (exitCode=${exitCode})`));
|
|
7432
7481
|
}
|
|
7433
7482
|
writePortFile(instanceKey, port);
|
|
7434
|
-
logger.info({ instanceKey, port, pid: proc.pid, ready }, "Playwright MCP started");
|
|
7483
|
+
logger.info({ instanceKey, port, pid: proc.pid, ready, virtualDisplay: spawnSpec.virtualDisplay }, "Playwright MCP started");
|
|
7435
7484
|
return port;
|
|
7436
7485
|
}
|
|
7437
7486
|
async function supportsOwnerCleanup(port, capability) {
|
|
@@ -7587,7 +7636,7 @@ async function cloneProfileForChild(opts) {
|
|
|
7587
7636
|
cleanSingletonFiles(dstDir);
|
|
7588
7637
|
for (const f of ["DevToolsActivePort", "LOCK"]) {
|
|
7589
7638
|
try {
|
|
7590
|
-
unlinkSync10(
|
|
7639
|
+
unlinkSync10(resolve6(dstDir, f));
|
|
7591
7640
|
} catch {}
|
|
7592
7641
|
}
|
|
7593
7642
|
logger.info({ srcKey, dstKey, srcDir, dstDir }, "Cloned Playwright profile for child topic");
|
|
@@ -7641,10 +7690,16 @@ function waitForChildProcessExit(proc, timeoutMs) {
|
|
|
7641
7690
|
finish(true);
|
|
7642
7691
|
});
|
|
7643
7692
|
}
|
|
7693
|
+
function waitForChildProcessSpawnError(proc) {
|
|
7694
|
+
return new Promise((_resolve, reject) => {
|
|
7695
|
+
proc.once("error", reject);
|
|
7696
|
+
});
|
|
7697
|
+
}
|
|
7644
7698
|
var BASE_PORT, MAX_PORT, MAX_IDLE_MS, instances, usedPorts, spawning, pinnedInstances, _onPlaywrightExit = null;
|
|
7645
7699
|
var init_manager2 = __esm(async () => {
|
|
7646
7700
|
init_config();
|
|
7647
7701
|
init_logger();
|
|
7702
|
+
init_headed_launch();
|
|
7648
7703
|
await init_browser_profiles();
|
|
7649
7704
|
await init_runtime_process_leases();
|
|
7650
7705
|
BASE_PORT = PLAYWRIGHT_BASE_PORT;
|
|
@@ -9022,9 +9077,9 @@ var init_runtime_turn_requests = __esm(async () => {
|
|
|
9022
9077
|
|
|
9023
9078
|
// ../../packages/core/src/prompts/builders.ts
|
|
9024
9079
|
import { readFileSync as readFileSync10 } from "fs";
|
|
9025
|
-
import { resolve as
|
|
9080
|
+
import { resolve as resolve7 } from "path";
|
|
9026
9081
|
function loadPrompt(filename, dir = SESSIONS_DIR) {
|
|
9027
|
-
const raw = readFileSync10(
|
|
9082
|
+
const raw = readFileSync10(resolve7(dir, filename), "utf-8");
|
|
9028
9083
|
return raw.replace(/\{\{RESOURCES_DIR\}\}/g, RESOURCES_DIR);
|
|
9029
9084
|
}
|
|
9030
9085
|
function replaceVars(template, vars) {
|
|
@@ -9067,7 +9122,7 @@ function visualDesignGuide() {
|
|
|
9067
9122
|
return _visualDesignGuide;
|
|
9068
9123
|
}
|
|
9069
9124
|
function loadAgentPrompt(filename) {
|
|
9070
|
-
const raw = readFileSync10(
|
|
9125
|
+
const raw = readFileSync10(resolve7(AGENTS_PROMPTS_DIR, filename), "utf-8");
|
|
9071
9126
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
9072
9127
|
if (!match)
|
|
9073
9128
|
throw new Error(`Agent prompt ${filename} is missing frontmatter`);
|
|
@@ -9267,8 +9322,8 @@ var init_builders = __esm(() => {
|
|
|
9267
9322
|
init_model_catalog();
|
|
9268
9323
|
init_config();
|
|
9269
9324
|
init_logger();
|
|
9270
|
-
PROMPTS_DIR =
|
|
9271
|
-
SESSIONS_DIR =
|
|
9325
|
+
PROMPTS_DIR = resolve7(PROJECT_ROOT, "src/prompts");
|
|
9326
|
+
SESSIONS_DIR = resolve7(PROMPTS_DIR, "sessions");
|
|
9272
9327
|
});
|
|
9273
9328
|
|
|
9274
9329
|
// ../../packages/core/src/storage/api-topic-brief.ts
|
|
@@ -10678,12 +10733,12 @@ var init_errors = __esm(() => {
|
|
|
10678
10733
|
|
|
10679
10734
|
// ../../packages/core/src/runtime/event-heartbeat.ts
|
|
10680
10735
|
function nextOrHeartbeat(pending, intervalMs) {
|
|
10681
|
-
return new Promise((
|
|
10682
|
-
const timer = setTimeout(() =>
|
|
10736
|
+
return new Promise((resolve8, reject) => {
|
|
10737
|
+
const timer = setTimeout(() => resolve8({ kind: "heartbeat" }), intervalMs);
|
|
10683
10738
|
timer.unref?.();
|
|
10684
10739
|
pending.then((result) => {
|
|
10685
10740
|
clearTimeout(timer);
|
|
10686
|
-
|
|
10741
|
+
resolve8({ kind: "event", result });
|
|
10687
10742
|
}, (error) => {
|
|
10688
10743
|
clearTimeout(timer);
|
|
10689
10744
|
reject(error);
|
|
@@ -11120,7 +11175,7 @@ var init_visual_html = __esm(() => {
|
|
|
11120
11175
|
|
|
11121
11176
|
// ../../packages/core/src/runtime/visuals.ts
|
|
11122
11177
|
import { realpathSync as realpathSync2 } from "fs";
|
|
11123
|
-
import { isAbsolute, resolve as
|
|
11178
|
+
import { isAbsolute as isAbsolute2, resolve as resolve8 } from "path";
|
|
11124
11179
|
function activeVisualHtmlForPrompt(html) {
|
|
11125
11180
|
if (html.length <= ACTIVE_VISUAL_PROMPT_MAX_CHARS) {
|
|
11126
11181
|
return { html, omittedChars: 0 };
|
|
@@ -11171,8 +11226,8 @@ function topicAllowsVisualFileId(topicId, fileId) {
|
|
|
11171
11226
|
return topicHasAttachmentFileId(topicId, fileId) || topicHasVisualFileId(topicId, fileId);
|
|
11172
11227
|
}
|
|
11173
11228
|
function isPathInside(baseDir, filePath) {
|
|
11174
|
-
const base =
|
|
11175
|
-
const normalized =
|
|
11229
|
+
const base = resolve8(baseDir);
|
|
11230
|
+
const normalized = resolve8(filePath);
|
|
11176
11231
|
try {
|
|
11177
11232
|
const realBase = realpathSync2(base);
|
|
11178
11233
|
const real = realpathSync2(normalized);
|
|
@@ -11234,7 +11289,7 @@ function resolveVisualMediaInput(topicId, input) {
|
|
|
11234
11289
|
}
|
|
11235
11290
|
const rawPath = input.file_path.trim();
|
|
11236
11291
|
const cwd = workspaceCwdFor(topicId);
|
|
11237
|
-
const candidate =
|
|
11292
|
+
const candidate = isAbsolute2(rawPath) ? rawPath : resolve8(cwd, rawPath);
|
|
11238
11293
|
if (!isPathInside(cwd, candidate)) {
|
|
11239
11294
|
return { error: "file_path must be inside the topic workspace" };
|
|
11240
11295
|
}
|
|
@@ -11948,7 +12003,7 @@ __export(exports_turn_runner, {
|
|
|
11948
12003
|
});
|
|
11949
12004
|
import { randomUUID as randomUUID13 } from "crypto";
|
|
11950
12005
|
import { mkdirSync as mkdirSync17, realpathSync as realpathSync3, statSync as statSync6 } from "fs";
|
|
11951
|
-
import { isAbsolute as
|
|
12006
|
+
import { isAbsolute as isAbsolute3, resolve as resolve9 } from "path";
|
|
11952
12007
|
function withDefaultPlaywright(configuredMcp, isManager) {
|
|
11953
12008
|
if (isManager)
|
|
11954
12009
|
return configuredMcp;
|
|
@@ -12292,7 +12347,7 @@ async function streamAgentEvents(topicId, topicTitle, queryId, events, control,
|
|
|
12292
12347
|
case "file":
|
|
12293
12348
|
if (!silent && peerBridge) {
|
|
12294
12349
|
const cwd = workspaceCwdFor(topicId);
|
|
12295
|
-
const path =
|
|
12350
|
+
const path = isAbsolute3(event.path) ? event.path : resolve9(cwd, event.path);
|
|
12296
12351
|
if (!isPathInside(cwd, path)) {
|
|
12297
12352
|
logger.warn({ topicId, path }, "peer output file is outside the topic workspace");
|
|
12298
12353
|
break;
|
|
@@ -14854,8 +14909,8 @@ async function waitForMemoryArchive(settled, timeoutMs) {
|
|
|
14854
14909
|
try {
|
|
14855
14910
|
return await Promise.race([
|
|
14856
14911
|
settled.then(() => true),
|
|
14857
|
-
new Promise((
|
|
14858
|
-
timer = setTimeout(() =>
|
|
14912
|
+
new Promise((resolve10) => {
|
|
14913
|
+
timer = setTimeout(() => resolve10(false), timeoutMs);
|
|
14859
14914
|
timer.unref?.();
|
|
14860
14915
|
})
|
|
14861
14916
|
]);
|
|
@@ -14901,8 +14956,8 @@ async function restartTopicSession(topicId, userId, reason = "topic-session-rest
|
|
|
14901
14956
|
return { text: fenceError, isError: true };
|
|
14902
14957
|
cancelIdleArchiveForTopic(topicId);
|
|
14903
14958
|
let settleMemoryArchive;
|
|
14904
|
-
const memoryArchiveSettled = new Promise((
|
|
14905
|
-
settleMemoryArchive =
|
|
14959
|
+
const memoryArchiveSettled = new Promise((resolve10) => {
|
|
14960
|
+
settleMemoryArchive = resolve10;
|
|
14906
14961
|
});
|
|
14907
14962
|
const archiveStatus = (options.archiveMemory ?? archiveActiveTopicForMemory)(topicId, userId, {
|
|
14908
14963
|
reason: "reset",
|
|
@@ -15940,8 +15995,8 @@ function prepareDeliveryAck(messageId, claimTimeoutMs, deliveryTimeoutMs) {
|
|
|
15940
15995
|
let finishPromise = () => {};
|
|
15941
15996
|
let timer;
|
|
15942
15997
|
let unsubscribe = () => {};
|
|
15943
|
-
const promise = new Promise((
|
|
15944
|
-
finishPromise =
|
|
15998
|
+
const promise = new Promise((resolve10) => {
|
|
15999
|
+
finishPromise = resolve10;
|
|
15945
16000
|
});
|
|
15946
16001
|
unsubscribe = runtimeBus().subscribe((event) => {
|
|
15947
16002
|
if (event.type !== "ai-status")
|
|
@@ -17303,7 +17358,7 @@ var init_sse_transport = () => {};
|
|
|
17303
17358
|
// ../../packages/mcp/src/server.ts
|
|
17304
17359
|
import { randomUUID as randomUUID20 } from "crypto";
|
|
17305
17360
|
import { realpathSync as realpathSync4, statSync as statSync8 } from "fs";
|
|
17306
|
-
import { basename as basename4, extname as extname2, resolve as
|
|
17361
|
+
import { basename as basename4, extname as extname2, resolve as resolve10 } from "path";
|
|
17307
17362
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
17308
17363
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
17309
17364
|
import { z as z6 } from "zod";
|
|
@@ -17317,8 +17372,8 @@ function requireTopicAccess(ctx) {
|
|
|
17317
17372
|
return { topic };
|
|
17318
17373
|
}
|
|
17319
17374
|
function isPathInside2(baseDir, filePath) {
|
|
17320
|
-
const cwd =
|
|
17321
|
-
const normalized =
|
|
17375
|
+
const cwd = resolve10(baseDir);
|
|
17376
|
+
const normalized = resolve10(filePath);
|
|
17322
17377
|
try {
|
|
17323
17378
|
const realCwd = realpathSync4(cwd);
|
|
17324
17379
|
const real = realpathSync4(normalized);
|
|
@@ -17334,7 +17389,7 @@ function localFileInfo(ctx, filePath) {
|
|
|
17334
17389
|
if (!isPathInside2(ctx.cwd, filePath)) {
|
|
17335
17390
|
return { error: "Access denied. File must be within the topic workspace." };
|
|
17336
17391
|
}
|
|
17337
|
-
const normalizedPath =
|
|
17392
|
+
const normalizedPath = resolve10(filePath);
|
|
17338
17393
|
if (isSensitivePath(normalizedPath)) {
|
|
17339
17394
|
return { error: "Access denied. Path matches the sensitive-file blacklist." };
|
|
17340
17395
|
}
|
|
@@ -17684,16 +17739,16 @@ var init_src2 = __esm(async () => {
|
|
|
17684
17739
|
|
|
17685
17740
|
// ../../packages/mcp-host/src/paths.ts
|
|
17686
17741
|
import { homedir as homedir9 } from "os";
|
|
17687
|
-
import { resolve as
|
|
17742
|
+
import { resolve as resolve11 } from "path";
|
|
17688
17743
|
function stateDir() {
|
|
17689
17744
|
const env = process.env.NEGOTIUM_STATE_DIR?.trim();
|
|
17690
|
-
return env ?
|
|
17745
|
+
return env ? resolve11(env) : resolve11(homedir9(), ".negotium");
|
|
17691
17746
|
}
|
|
17692
17747
|
function defaultPortsDir() {
|
|
17693
|
-
return
|
|
17748
|
+
return resolve11(stateDir(), "run", "mcp-ports");
|
|
17694
17749
|
}
|
|
17695
17750
|
function defaultManifestFile() {
|
|
17696
|
-
return
|
|
17751
|
+
return resolve11(stateDir(), "data", "mcp-manifest.json");
|
|
17697
17752
|
}
|
|
17698
17753
|
var init_paths = () => {};
|
|
17699
17754
|
|
|
@@ -17856,16 +17911,16 @@ function resolveInstanceKey(spec, instanceKey) {
|
|
|
17856
17911
|
return instanceKey;
|
|
17857
17912
|
}
|
|
17858
17913
|
function canBind(port) {
|
|
17859
|
-
return new Promise((
|
|
17914
|
+
return new Promise((resolve12) => {
|
|
17860
17915
|
const srv = createServer();
|
|
17861
|
-
srv.once("error", () =>
|
|
17916
|
+
srv.once("error", () => resolve12(false));
|
|
17862
17917
|
srv.listen({ port, host: "127.0.0.1", exclusive: true }, () => {
|
|
17863
|
-
srv.close(() =>
|
|
17918
|
+
srv.close(() => resolve12(true));
|
|
17864
17919
|
});
|
|
17865
17920
|
});
|
|
17866
17921
|
}
|
|
17867
17922
|
function tcpProbe(port, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
17868
|
-
return new Promise((
|
|
17923
|
+
return new Promise((resolve12) => {
|
|
17869
17924
|
const sock = connect({ port, host: "127.0.0.1" });
|
|
17870
17925
|
let settled = false;
|
|
17871
17926
|
const done = (ok2) => {
|
|
@@ -17873,7 +17928,7 @@ function tcpProbe(port, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
|
17873
17928
|
return;
|
|
17874
17929
|
settled = true;
|
|
17875
17930
|
sock.destroy();
|
|
17876
|
-
|
|
17931
|
+
resolve12(ok2);
|
|
17877
17932
|
};
|
|
17878
17933
|
sock.once("connect", () => done(true));
|
|
17879
17934
|
sock.once("error", () => done(false));
|
|
@@ -17901,12 +17956,12 @@ function killProcessTree(pid) {
|
|
|
17901
17956
|
function waitExit(proc, timeoutMs) {
|
|
17902
17957
|
if (proc.exitCode !== null || proc.signalCode !== null)
|
|
17903
17958
|
return Promise.resolve(true);
|
|
17904
|
-
return new Promise((
|
|
17905
|
-
const timer = setTimeout(() =>
|
|
17959
|
+
return new Promise((resolve12) => {
|
|
17960
|
+
const timer = setTimeout(() => resolve12(false), timeoutMs);
|
|
17906
17961
|
timer.unref?.();
|
|
17907
17962
|
const settle = () => {
|
|
17908
17963
|
clearTimeout(timer);
|
|
17909
|
-
|
|
17964
|
+
resolve12(true);
|
|
17910
17965
|
};
|
|
17911
17966
|
proc.once("exit", settle);
|
|
17912
17967
|
proc.once("error", settle);
|
|
@@ -18244,7 +18299,7 @@ var DEFAULT_READY_TIMEOUT_MS = 20000, READY_POLL_MS = 150, KILL_GRACE_MS = 5000,
|
|
|
18244
18299
|
fn(`[mcp-host] ${msg}`, ctx);
|
|
18245
18300
|
else
|
|
18246
18301
|
fn(`[mcp-host] ${msg}`);
|
|
18247
|
-
}, delay2 = (ms) => new Promise((
|
|
18302
|
+
}, delay2 = (ms) => new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
18248
18303
|
var init_manager3 = __esm(() => {
|
|
18249
18304
|
init_manifest();
|
|
18250
18305
|
init_paths();
|
|
@@ -18437,7 +18492,7 @@ import {
|
|
|
18437
18492
|
unlinkSync as unlinkSync17,
|
|
18438
18493
|
writeFileSync as writeFileSync17
|
|
18439
18494
|
} from "fs";
|
|
18440
|
-
import { dirname as dirname14, resolve as
|
|
18495
|
+
import { dirname as dirname14, resolve as resolve12 } from "path";
|
|
18441
18496
|
function jsonError(status, error) {
|
|
18442
18497
|
return Response.json({ ok: false, error }, { status });
|
|
18443
18498
|
}
|
|
@@ -19135,7 +19190,7 @@ var init_control = __esm(async () => {
|
|
|
19135
19190
|
await init_src();
|
|
19136
19191
|
await init_files();
|
|
19137
19192
|
NODE_RUNTIME_CONTRACT_BASE_PATH = `${NODE_CONTROL_BASE_PATH}/runtime/v1`;
|
|
19138
|
-
NODE_DAEMON_INFO_PATH =
|
|
19193
|
+
NODE_DAEMON_INFO_PATH = resolve12(RUN_DIR, "node-daemon.json");
|
|
19139
19194
|
NODE_VERSION = NEGOTIUM_VERSION;
|
|
19140
19195
|
});
|
|
19141
19196
|
|
|
@@ -19309,7 +19364,7 @@ var init_schedule = __esm(() => {
|
|
|
19309
19364
|
// ../../packages/module-cron/src/scripts.ts
|
|
19310
19365
|
import { spawn as spawn6 } from "child_process";
|
|
19311
19366
|
import { existsSync as existsSync21, mkdirSync as mkdirSync26, readdirSync as readdirSync8 } from "fs";
|
|
19312
|
-
import { resolve as
|
|
19367
|
+
import { resolve as resolve13, sep } from "path";
|
|
19313
19368
|
function validateCronScriptName(script) {
|
|
19314
19369
|
if (!/^[A-Za-z0-9_][A-Za-z0-9_.-]*\.py$/.test(script) || script.includes("..") || script.includes("/") || script.includes("\\")) {
|
|
19315
19370
|
return { ok: false, error: `script must be a plain .py filename under ${CRON_JOBS_DIR}` };
|
|
@@ -19320,7 +19375,7 @@ function resolveCronScriptPath(script) {
|
|
|
19320
19375
|
const valid = validateCronScriptName(script);
|
|
19321
19376
|
if (!valid.ok)
|
|
19322
19377
|
throw new Error(valid.error);
|
|
19323
|
-
const path =
|
|
19378
|
+
const path = resolve13(CRON_JOBS_DIR, script);
|
|
19324
19379
|
if (!path.startsWith(`${CRON_JOBS_DIR}${sep}`))
|
|
19325
19380
|
throw new Error("script path escaped jobs directory");
|
|
19326
19381
|
return path;
|
|
@@ -19436,7 +19491,7 @@ async function runCronPromptScript(options) {
|
|
|
19436
19491
|
var CRON_JOBS_DIR, DEFAULT_SCRIPT_TIMEOUT_MS, DEFAULT_OUTPUT_LIMIT_BYTES, KILL_GRACE_MS2 = 2500, CronScriptError;
|
|
19437
19492
|
var init_scripts = __esm(async () => {
|
|
19438
19493
|
await init_src();
|
|
19439
|
-
CRON_JOBS_DIR =
|
|
19494
|
+
CRON_JOBS_DIR = resolve13(process.env.NEGOTIUM_CRON_JOBS_DIR?.trim() || resolve13(WORKSPACE_DIR, "cron", "jobs"));
|
|
19440
19495
|
DEFAULT_SCRIPT_TIMEOUT_MS = 10 * 60000;
|
|
19441
19496
|
DEFAULT_OUTPUT_LIMIT_BYTES = 1024 * 1024;
|
|
19442
19497
|
CronScriptError = class CronScriptError extends Error {
|
|
@@ -20858,7 +20913,7 @@ __export(exports_src3, {
|
|
|
20858
20913
|
});
|
|
20859
20914
|
import { createServer as createServer2 } from "net";
|
|
20860
20915
|
async function availableLoopbackPort() {
|
|
20861
|
-
return new Promise((
|
|
20916
|
+
return new Promise((resolve14, reject) => {
|
|
20862
20917
|
const probe = createServer2();
|
|
20863
20918
|
probe.unref();
|
|
20864
20919
|
probe.once("error", reject);
|
|
@@ -20869,7 +20924,7 @@ async function availableLoopbackPort() {
|
|
|
20869
20924
|
if (error)
|
|
20870
20925
|
reject(error);
|
|
20871
20926
|
else if (port > 0)
|
|
20872
|
-
|
|
20927
|
+
resolve14(port);
|
|
20873
20928
|
else
|
|
20874
20929
|
reject(new Error("failed to allocate a loopback port"));
|
|
20875
20930
|
});
|
|
@@ -20989,8 +21044,8 @@ function startNode(opts = {}) {
|
|
|
20989
21044
|
const manifest = new McpManifest;
|
|
20990
21045
|
const stopSweeper = mcpHost.startSweeper();
|
|
20991
21046
|
let resolveCompleted;
|
|
20992
|
-
const completed = new Promise((
|
|
20993
|
-
resolveCompleted =
|
|
21047
|
+
const completed = new Promise((resolve14) => {
|
|
21048
|
+
resolveCompleted = resolve14;
|
|
20994
21049
|
});
|
|
20995
21050
|
let advertised = null;
|
|
20996
21051
|
try {
|
|
@@ -21064,7 +21119,7 @@ async function runNodeDaemon(opts = {}) {
|
|
|
21064
21119
|
singleton: true
|
|
21065
21120
|
});
|
|
21066
21121
|
await node.completed;
|
|
21067
|
-
await new Promise((
|
|
21122
|
+
await new Promise((resolve14) => setImmediate(resolve14));
|
|
21068
21123
|
process.exit(0);
|
|
21069
21124
|
}
|
|
21070
21125
|
var init_src5 = __esm(async () => {
|
|
@@ -23671,8 +23726,8 @@ class TerminalApp {
|
|
|
23671
23726
|
this.#refreshBackgroundSessions();
|
|
23672
23727
|
}, 1000);
|
|
23673
23728
|
this.#backgroundRefreshTimer.unref?.();
|
|
23674
|
-
await new Promise((
|
|
23675
|
-
this.#finishRun =
|
|
23729
|
+
await new Promise((resolve14) => {
|
|
23730
|
+
this.#finishRun = resolve14;
|
|
23676
23731
|
});
|
|
23677
23732
|
} finally {
|
|
23678
23733
|
this.#running = false;
|
|
@@ -25848,7 +25903,7 @@ function startTelegramAdapter(opts) {
|
|
|
25848
25903
|
attempt += 1;
|
|
25849
25904
|
const waitMs = Math.min(5000, 250 * 2 ** Math.min(attempt - 1, 5));
|
|
25850
25905
|
logger.warn({ err: err2, attempt, waitMs }, "telegram adapter: getMe failed while resolving onboarding identity; retrying");
|
|
25851
|
-
await new Promise((
|
|
25906
|
+
await new Promise((resolve14) => setTimeout(resolve14, waitMs));
|
|
25852
25907
|
}
|
|
25853
25908
|
}
|
|
25854
25909
|
return;
|
|
@@ -26325,14 +26380,14 @@ function startTelegramAdapter(opts) {
|
|
|
26325
26380
|
const sendQueues = new Map;
|
|
26326
26381
|
function enqueueSend(topicId, task) {
|
|
26327
26382
|
const prev = sendQueues.get(topicId) ?? Promise.resolve();
|
|
26328
|
-
const next = prev.then(() => new Promise((
|
|
26383
|
+
const next = prev.then(() => new Promise((resolve14) => {
|
|
26329
26384
|
const timer = setTimeout(() => {
|
|
26330
26385
|
logger.warn({ topicId, sendTimeoutMs }, "telegram adapter: send timed out \u2014 abandoning it and continuing the queue");
|
|
26331
|
-
|
|
26386
|
+
resolve14();
|
|
26332
26387
|
}, sendTimeoutMs);
|
|
26333
26388
|
task().catch((err2) => logger.warn({ err: err2, topicId }, "telegram adapter: send task failed")).finally(() => {
|
|
26334
26389
|
clearTimeout(timer);
|
|
26335
|
-
|
|
26390
|
+
resolve14();
|
|
26336
26391
|
});
|
|
26337
26392
|
}));
|
|
26338
26393
|
sendQueues.set(topicId, next);
|
|
@@ -26576,7 +26631,7 @@ ${suffix}`;
|
|
|
26576
26631
|
continue;
|
|
26577
26632
|
}
|
|
26578
26633
|
if (retryDelayMs > 0) {
|
|
26579
|
-
await new Promise((
|
|
26634
|
+
await new Promise((resolve14) => setTimeout(resolve14, retryDelayMs));
|
|
26580
26635
|
}
|
|
26581
26636
|
try {
|
|
26582
26637
|
await client.editMessageText(text2, editOptions);
|
|
@@ -26930,8 +26985,8 @@ ${caption}` : voiceText : caption;
|
|
|
26930
26985
|
return;
|
|
26931
26986
|
}
|
|
26932
26987
|
let releaseReady;
|
|
26933
|
-
const ready = new Promise((
|
|
26934
|
-
releaseReady =
|
|
26988
|
+
const ready = new Promise((resolve14) => {
|
|
26989
|
+
releaseReady = resolve14;
|
|
26935
26990
|
});
|
|
26936
26991
|
const entry = {
|
|
26937
26992
|
messages: [msg],
|
|
@@ -27500,8 +27555,8 @@ async function runTelegramCli(args = process.argv.slice(2)) {
|
|
|
27500
27555
|
onShutdown("telegram-channel", 100, () => channel.stop());
|
|
27501
27556
|
onShutdown("telegram-singleton", 90, () => singleton.stop());
|
|
27502
27557
|
let resolveCompleted;
|
|
27503
|
-
const completed = new Promise((
|
|
27504
|
-
resolveCompleted =
|
|
27558
|
+
const completed = new Promise((resolve14) => {
|
|
27559
|
+
resolveCompleted = resolve14;
|
|
27505
27560
|
});
|
|
27506
27561
|
onShutdown("telegram-completed", -100, resolveCompleted);
|
|
27507
27562
|
process.stdout.write(`negotium Telegram adapter connected to canonical node pid ${initialNode.info?.pid ?? "unknown"}
|
|
@@ -27698,9 +27753,9 @@ import {
|
|
|
27698
27753
|
unlinkSync as unlinkSync18,
|
|
27699
27754
|
writeFileSync as writeFileSync18
|
|
27700
27755
|
} from "fs";
|
|
27701
|
-
import { dirname as dirname17, resolve as
|
|
27756
|
+
import { dirname as dirname17, resolve as resolve14 } from "path";
|
|
27702
27757
|
function joinFilePath() {
|
|
27703
|
-
return
|
|
27758
|
+
return resolve14(DATA_DIR, "otium-join.json");
|
|
27704
27759
|
}
|
|
27705
27760
|
function isHttpUrl(value) {
|
|
27706
27761
|
return /^https?:\/\//.test(value);
|
|
@@ -27755,7 +27810,7 @@ function parseInviteCode(code) {
|
|
|
27755
27810
|
return normalizeJoin(parsed);
|
|
27756
27811
|
}
|
|
27757
27812
|
function joinLockPath() {
|
|
27758
|
-
return
|
|
27813
|
+
return resolve14(DATA_DIR, ".otium-join.lock");
|
|
27759
27814
|
}
|
|
27760
27815
|
function processIsAlive(pid) {
|
|
27761
27816
|
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
@@ -27769,7 +27824,7 @@ function processIsAlive(pid) {
|
|
|
27769
27824
|
}
|
|
27770
27825
|
function withJoinCredentialLock(operation) {
|
|
27771
27826
|
const lockPath = joinLockPath();
|
|
27772
|
-
const ownerPath =
|
|
27827
|
+
const ownerPath = resolve14(lockPath, "owner.json");
|
|
27773
27828
|
const owner = { pid: process.pid, token: randomUUID24() };
|
|
27774
27829
|
mkdirSync28(dirname17(lockPath), { recursive: true });
|
|
27775
27830
|
for (let attempt = 0;; attempt += 1) {
|
|
@@ -27901,7 +27956,7 @@ function saveJoinWhileLocked(join31, options = {}) {
|
|
|
27901
27956
|
throw new Error(`this node is already joined${existing ? ` as ${existing.cellId}` : " with an invalid join file"}; pass --replace to replace its credentials`);
|
|
27902
27957
|
}
|
|
27903
27958
|
}
|
|
27904
|
-
const temporaryPath =
|
|
27959
|
+
const temporaryPath = resolve14(directory, `.otium-join.json.${process.pid}.${randomUUID24()}.tmp`);
|
|
27905
27960
|
let fd;
|
|
27906
27961
|
try {
|
|
27907
27962
|
fd = openSync3(temporaryPath, "wx", 384);
|
|
@@ -28786,7 +28841,7 @@ function createTurnForwarder(opts) {
|
|
|
28786
28841
|
logger.warn({ requestId, seq, type: event.type, attempt, error: result.error }, "otium: peer event delivery to hub failed");
|
|
28787
28842
|
if (attempt < PEER_EVENT_MAX_ATTEMPTS) {
|
|
28788
28843
|
const delayMs = retryBaseMs * 2 ** (attempt - 1);
|
|
28789
|
-
await new Promise((
|
|
28844
|
+
await new Promise((resolve15) => setTimeout(resolve15, delayMs));
|
|
28790
28845
|
}
|
|
28791
28846
|
}
|
|
28792
28847
|
forwarder.deliveryBlocked = true;
|
|
@@ -30684,7 +30739,7 @@ import {
|
|
|
30684
30739
|
unlinkSync as unlinkSync19,
|
|
30685
30740
|
writeFileSync as writeFileSync19
|
|
30686
30741
|
} from "fs";
|
|
30687
|
-
import { dirname as dirname18, resolve as
|
|
30742
|
+
import { dirname as dirname18, resolve as resolve15 } from "path";
|
|
30688
30743
|
function parseEnrollmentInvite(code) {
|
|
30689
30744
|
let parsed;
|
|
30690
30745
|
try {
|
|
@@ -30705,7 +30760,7 @@ function parseEnrollmentInvite(code) {
|
|
|
30705
30760
|
return { v: 2, central, token };
|
|
30706
30761
|
}
|
|
30707
30762
|
function pendingEnrollmentPath() {
|
|
30708
|
-
return
|
|
30763
|
+
return resolve15(DATA_DIR, "otium-enrollment-pending.json");
|
|
30709
30764
|
}
|
|
30710
30765
|
function isEnrollmentPending(invite) {
|
|
30711
30766
|
const path = pendingEnrollmentPath();
|
|
@@ -30735,7 +30790,7 @@ function loadOrCreatePending(invite, nodeName) {
|
|
|
30735
30790
|
...nodeName ? { nodeName } : {}
|
|
30736
30791
|
};
|
|
30737
30792
|
mkdirSync30(dirname18(path), { recursive: true });
|
|
30738
|
-
const temporaryPath =
|
|
30793
|
+
const temporaryPath = resolve15(dirname18(path), `.otium-enrollment-pending.json.${process.pid}.${randomUUID28()}.tmp`);
|
|
30739
30794
|
let fd;
|
|
30740
30795
|
try {
|
|
30741
30796
|
fd = openSync4(temporaryPath, "wx", 384);
|
|
@@ -30770,7 +30825,7 @@ function loadOrCreatePending(invite, nodeName) {
|
|
|
30770
30825
|
function replacePendingEnrollment(pending2) {
|
|
30771
30826
|
const path = pendingEnrollmentPath();
|
|
30772
30827
|
const directory = dirname18(path);
|
|
30773
|
-
const temporaryPath =
|
|
30828
|
+
const temporaryPath = resolve15(directory, `.otium-enrollment-pending.json.${process.pid}.${randomUUID28()}.tmp`);
|
|
30774
30829
|
let fd;
|
|
30775
30830
|
try {
|
|
30776
30831
|
fd = openSync4(temporaryPath, "wx", 384);
|
|
@@ -32113,8 +32168,8 @@ async function runOtiumSidecar(options) {
|
|
|
32113
32168
|
}) : null;
|
|
32114
32169
|
tunnel?.start();
|
|
32115
32170
|
let resolveCompleted;
|
|
32116
|
-
const completed = new Promise((
|
|
32117
|
-
resolveCompleted =
|
|
32171
|
+
const completed = new Promise((resolve16) => {
|
|
32172
|
+
resolveCompleted = resolve16;
|
|
32118
32173
|
});
|
|
32119
32174
|
onShutdown("otium-sidecar-server", 130, () => server?.stop(true));
|
|
32120
32175
|
onShutdown("otium-sidecar-tunnel", 120, () => tunnel?.stop());
|
|
@@ -32906,7 +32961,7 @@ async function runCanonicalNode(port) {
|
|
|
32906
32961
|
});
|
|
32907
32962
|
console.log(`negotium node listening on 127.0.0.1:${node.port} (ctrl-c to stop)`);
|
|
32908
32963
|
await node.completed;
|
|
32909
|
-
await new Promise((
|
|
32964
|
+
await new Promise((resolve16) => setImmediate(resolve16));
|
|
32910
32965
|
process.exit(0);
|
|
32911
32966
|
}
|
|
32912
32967
|
async function stopAdapter(name) {
|
|
@@ -33036,4 +33091,4 @@ switch (command) {
|
|
|
33036
33091
|
}
|
|
33037
33092
|
}
|
|
33038
33093
|
|
|
33039
|
-
//# debugId=
|
|
33094
|
+
//# debugId=4312707E3B05EF9564756E2164756E21
|