negotium 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-helpers.js +165 -131
- package/dist/agent-helpers.js.map +5 -5
- package/dist/{chunk-zq2tcq4k.js → chunk-238qj1qy.js} +58 -22
- package/dist/{chunk-zq2tcq4k.js.map → chunk-238qj1qy.js.map} +5 -5
- package/dist/hosted-agent.js +74 -38
- package/dist/hosted-agent.js.map +6 -6
- package/dist/main.js +301 -267
- package/dist/main.js.map +5 -5
- package/dist/mcp-catalog.js +3 -2
- package/dist/mcp-catalog.js.map +3 -3
- package/dist/mcp-factories.js +147 -113
- package/dist/mcp-factories.js.map +5 -5
- package/dist/registry.js +3 -3
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/platform/mcp-catalog-policy.ts +5 -0
- package/dist/runtime/src/platform/mcp-config.ts +81 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/types/packages/core/src/platform/mcp-catalog-policy.d.ts +4 -0
- package/dist/types/packages/core/src/platform/mcp-config.d.ts +19 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1869,7 +1869,7 @@ var exports_version = {};
|
|
|
1869
1869
|
__export(exports_version, {
|
|
1870
1870
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
1871
1871
|
});
|
|
1872
|
-
var NEGOTIUM_VERSION = "0.4.
|
|
1872
|
+
var NEGOTIUM_VERSION = "0.4.2";
|
|
1873
1873
|
|
|
1874
1874
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
1875
1875
|
import { spawn } from "child_process";
|
|
@@ -2654,7 +2654,8 @@ var init_mcp_catalog_policy = __esm(() => {
|
|
|
2654
2654
|
"system-health": { scopes: ["dm", "forum", "manager", "cron"], forumRequired: true },
|
|
2655
2655
|
"background-bash": { scopes: ["forum"], forumRequired: true },
|
|
2656
2656
|
"agent-health": { scopes: ["forum", "manager", "cron"], forumRequired: true },
|
|
2657
|
-
vault: { scopes: ["dm", "forum", "manager", "cron"], forumRequired: true }
|
|
2657
|
+
vault: { scopes: ["dm", "forum", "manager", "cron"], forumRequired: true },
|
|
2658
|
+
"cua-rs": { scopes: ["dm", "forum", "fork"], forumRequired: false }
|
|
2658
2659
|
};
|
|
2659
2660
|
});
|
|
2660
2661
|
|
|
@@ -2666,6 +2667,9 @@ function browserOwnerCapability(capability, owner) {
|
|
|
2666
2667
|
var init_capability = () => {};
|
|
2667
2668
|
|
|
2668
2669
|
// ../../packages/core/src/platform/mcp-config.ts
|
|
2670
|
+
import { accessSync as accessSync2, constants as fsConstants } from "fs";
|
|
2671
|
+
import { homedir as homedir6 } from "os";
|
|
2672
|
+
import { join as join8 } from "path";
|
|
2669
2673
|
function buildStdioMcpServer(agent, serverFile, serverArgs, env) {
|
|
2670
2674
|
if (agent === "codex") {
|
|
2671
2675
|
return {
|
|
@@ -2781,6 +2785,27 @@ function backgroundBashTransport(agent, port, userId, topic) {
|
|
|
2781
2785
|
}
|
|
2782
2786
|
return { type: "sse", url: `http://127.0.0.1:${port}/sse`, headers };
|
|
2783
2787
|
}
|
|
2788
|
+
function cuaRsArgs() {
|
|
2789
|
+
const raw = envText("NEGOTIUM_CUA_RS_ALLOW_HID")?.trim().toLowerCase();
|
|
2790
|
+
const on = raw === "1" || raw === "true" || raw === "yes";
|
|
2791
|
+
return on ? ["--allow-hid"] : [];
|
|
2792
|
+
}
|
|
2793
|
+
function resolveCuaRsBinary(platform2 = process.platform) {
|
|
2794
|
+
if (platform2 !== "darwin")
|
|
2795
|
+
return null;
|
|
2796
|
+
const candidates = [
|
|
2797
|
+
envText("NEGOTIUM_CUA_RS_BIN"),
|
|
2798
|
+
join8(homedir6(), ".local", "bin", "cua-rs"),
|
|
2799
|
+
"/usr/local/bin/cua-rs"
|
|
2800
|
+
].filter((p) => Boolean(p));
|
|
2801
|
+
for (const candidate of candidates) {
|
|
2802
|
+
try {
|
|
2803
|
+
accessSync2(candidate, fsConstants.X_OK);
|
|
2804
|
+
return candidate;
|
|
2805
|
+
} catch {}
|
|
2806
|
+
}
|
|
2807
|
+
return null;
|
|
2808
|
+
}
|
|
2784
2809
|
function refreshForumCatalogViews() {
|
|
2785
2810
|
const { all, required, optional } = classifyForumMcpServers(MCP_CATALOG);
|
|
2786
2811
|
allForumMcpServerNames.splice(0, allForumMcpServerNames.length, ...all);
|
|
@@ -3240,6 +3265,15 @@ var init_mcp_config = __esm(() => {
|
|
|
3240
3265
|
args.push("--list-only=true");
|
|
3241
3266
|
return buildBuiltinMcpServer("vault", { ...ctx, userId: vaultUserId ?? userId }, () => buildStdioMcpServer(agent, VAULT_SERVER, args));
|
|
3242
3267
|
}
|
|
3268
|
+
},
|
|
3269
|
+
"cua-rs": {
|
|
3270
|
+
...commonRuntimeMcpPolicy("cua-rs"),
|
|
3271
|
+
build() {
|
|
3272
|
+
const bin = resolveCuaRsBinary();
|
|
3273
|
+
if (!bin)
|
|
3274
|
+
return null;
|
|
3275
|
+
return { command: bin, args: cuaRsArgs() };
|
|
3276
|
+
}
|
|
3243
3277
|
}
|
|
3244
3278
|
};
|
|
3245
3279
|
allForumMcpServerNames = [];
|
|
@@ -3311,14 +3345,14 @@ var init_execution_host = __esm(async () => {
|
|
|
3311
3345
|
// ../../packages/core/src/agents/rollout/codex.ts
|
|
3312
3346
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
3313
3347
|
import { existsSync as existsSync6, readFileSync as readFileSync5, realpathSync as realpathSync2, statSync as statSync2, unlinkSync as unlinkSync5 } from "fs";
|
|
3314
|
-
import { basename, dirname as dirname6, join as
|
|
3348
|
+
import { basename, dirname as dirname6, join as join9, resolve as resolve5 } from "path";
|
|
3315
3349
|
function codexSessionsDir() {
|
|
3316
|
-
return
|
|
3350
|
+
return join9(hostedCodexHomePath(), "sessions");
|
|
3317
3351
|
}
|
|
3318
3352
|
function loadCodexShell() {
|
|
3319
3353
|
if (_shellCache)
|
|
3320
3354
|
return _shellCache;
|
|
3321
|
-
const raw = readFileSync5(
|
|
3355
|
+
const raw = readFileSync5(join9(FIXTURES_DIR, "codex-shell.jsonl"), "utf8");
|
|
3322
3356
|
const lines = parseJsonlText(raw);
|
|
3323
3357
|
if (lines.length < 5) {
|
|
3324
3358
|
throw new Error(`loadCodexShell: expected >=5 entries in codex-shell.jsonl, got ${lines.length}`);
|
|
@@ -3385,8 +3419,8 @@ function codexRolloutPath(threadId, fallback) {
|
|
|
3385
3419
|
const hh = String(createdAt.getHours()).padStart(2, "0");
|
|
3386
3420
|
const min = String(createdAt.getMinutes()).padStart(2, "0");
|
|
3387
3421
|
const ss = String(createdAt.getSeconds()).padStart(2, "0");
|
|
3388
|
-
const dir =
|
|
3389
|
-
return
|
|
3422
|
+
const dir = join9(codexSessionsDir(), yyyy, mm, dd);
|
|
3423
|
+
return join9(dir, `rollout-${yyyy}-${mm}-${dd}T${hh}-${min}-${ss}-${threadId}.jsonl`);
|
|
3390
3424
|
}
|
|
3391
3425
|
function canonicalFilePath(path) {
|
|
3392
3426
|
const absolute = resolve5(path);
|
|
@@ -3394,7 +3428,7 @@ function canonicalFilePath(path) {
|
|
|
3394
3428
|
return realpathSync2(absolute);
|
|
3395
3429
|
} catch {
|
|
3396
3430
|
try {
|
|
3397
|
-
return
|
|
3431
|
+
return join9(realpathSync2(dirname6(absolute)), basename(absolute));
|
|
3398
3432
|
} catch {
|
|
3399
3433
|
return absolute;
|
|
3400
3434
|
}
|
|
@@ -3624,19 +3658,19 @@ function latestCodexRolloutPath(threadId) {
|
|
|
3624
3658
|
try {
|
|
3625
3659
|
if (buckets) {
|
|
3626
3660
|
for (const bucket of buckets) {
|
|
3627
|
-
const dir =
|
|
3661
|
+
const dir = join9(sessionsDir, bucket);
|
|
3628
3662
|
if (!existsSync6(dir))
|
|
3629
3663
|
continue;
|
|
3630
3664
|
const glob = new Bun.Glob(`rollout-*-${threadId}.jsonl`);
|
|
3631
3665
|
for (const rel of glob.scanSync({ cwd: dir, onlyFiles: true })) {
|
|
3632
|
-
candidates.push(
|
|
3666
|
+
candidates.push(join9(dir, rel));
|
|
3633
3667
|
}
|
|
3634
3668
|
}
|
|
3635
3669
|
}
|
|
3636
3670
|
if (candidates.length === 0) {
|
|
3637
3671
|
const glob = new Bun.Glob(`**/rollout-*-${threadId}.jsonl`);
|
|
3638
3672
|
for (const rel of glob.scanSync({ cwd: sessionsDir, onlyFiles: true })) {
|
|
3639
|
-
candidates.push(
|
|
3673
|
+
candidates.push(join9(sessionsDir, rel));
|
|
3640
3674
|
}
|
|
3641
3675
|
}
|
|
3642
3676
|
return candidates.sort((a, b) => statSync2(b).mtimeMs - statSync2(a).mtimeMs)[0];
|
|
@@ -3757,13 +3791,13 @@ function sweepPriorRolloutsForThread(threadId) {
|
|
|
3757
3791
|
return;
|
|
3758
3792
|
}
|
|
3759
3793
|
for (const bucket of buckets) {
|
|
3760
|
-
const dir =
|
|
3794
|
+
const dir = join9(sessionsDir, bucket);
|
|
3761
3795
|
if (!existsSync6(dir))
|
|
3762
3796
|
continue;
|
|
3763
3797
|
try {
|
|
3764
3798
|
const glob = new Bun.Glob(`rollout-*-${threadId}.jsonl`);
|
|
3765
3799
|
for (const rel of glob.scanSync({ cwd: dir, onlyFiles: true })) {
|
|
3766
|
-
const fullPath =
|
|
3800
|
+
const fullPath = join9(dir, rel);
|
|
3767
3801
|
try {
|
|
3768
3802
|
unlinkSync5(fullPath);
|
|
3769
3803
|
} catch (e) {
|
|
@@ -3781,7 +3815,7 @@ function sweepPriorRolloutsFullTree(threadId, sessionsDir) {
|
|
|
3781
3815
|
try {
|
|
3782
3816
|
const glob = new Bun.Glob(`**/rollout-*-${threadId}.jsonl`);
|
|
3783
3817
|
for (const rel of glob.scanSync({ cwd: sessionsDir, onlyFiles: true })) {
|
|
3784
|
-
const fullPath =
|
|
3818
|
+
const fullPath = join9(sessionsDir, rel);
|
|
3785
3819
|
try {
|
|
3786
3820
|
unlinkSync5(fullPath);
|
|
3787
3821
|
} catch (e) {
|
|
@@ -3959,7 +3993,7 @@ var init_codex_app_server = __esm(async () => {
|
|
|
3959
3993
|
|
|
3960
3994
|
// ../../packages/core/src/agents/codex-registry.ts
|
|
3961
3995
|
import { existsSync as existsSync7, unlinkSync as unlinkSync6 } from "fs";
|
|
3962
|
-
import { join as
|
|
3996
|
+
import { join as join10 } from "path";
|
|
3963
3997
|
var VALID_EFFORTS2, codexRegistry, codexRegistryOperations;
|
|
3964
3998
|
var init_codex_registry = __esm(async () => {
|
|
3965
3999
|
await init_codex_app_server();
|
|
@@ -4002,7 +4036,7 @@ var init_codex_registry = __esm(async () => {
|
|
|
4002
4036
|
async cleanupRollouts({ sessionIds }) {
|
|
4003
4037
|
if (sessionIds.length === 0)
|
|
4004
4038
|
return;
|
|
4005
|
-
const sessionsDir =
|
|
4039
|
+
const sessionsDir = join10(hostedCodexHomePath(), "sessions");
|
|
4006
4040
|
if (!existsSync7(sessionsDir))
|
|
4007
4041
|
return;
|
|
4008
4042
|
const failures = [];
|
|
@@ -4010,7 +4044,7 @@ var init_codex_registry = __esm(async () => {
|
|
|
4010
4044
|
try {
|
|
4011
4045
|
const glob = new Bun.Glob(`**/rollout-*-${tid}.jsonl`);
|
|
4012
4046
|
for await (const rel of glob.scan({ cwd: sessionsDir, onlyFiles: true })) {
|
|
4013
|
-
const path =
|
|
4047
|
+
const path = join10(sessionsDir, rel);
|
|
4014
4048
|
try {
|
|
4015
4049
|
unlinkSync6(path);
|
|
4016
4050
|
} catch (e) {
|
|
@@ -4035,16 +4069,16 @@ var init_codex_registry = __esm(async () => {
|
|
|
4035
4069
|
// ../../packages/core/src/agents/maestro-registry.ts
|
|
4036
4070
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
4037
4071
|
import { existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
4038
|
-
import { homedir as
|
|
4039
|
-
import { join as
|
|
4072
|
+
import { homedir as homedir7 } from "os";
|
|
4073
|
+
import { join as join11, resolve as resolve6 } from "path";
|
|
4040
4074
|
function maestroSessionsDir() {
|
|
4041
|
-
return
|
|
4075
|
+
return join11(process.env.MAESTRO_DATA_DIR ? resolve6(process.env.MAESTRO_DATA_DIR) : join11(homedir7(), ".maestro"), "sessions");
|
|
4042
4076
|
}
|
|
4043
4077
|
function maestroSessionPath(sessionId) {
|
|
4044
|
-
return
|
|
4078
|
+
return join11(maestroSessionsDir(), `${sessionId}.jsonl`);
|
|
4045
4079
|
}
|
|
4046
4080
|
function maestroActiveSessionPath(sessionId) {
|
|
4047
|
-
return
|
|
4081
|
+
return join11(maestroSessionsDir(), `${sessionId}.active.jsonl`);
|
|
4048
4082
|
}
|
|
4049
4083
|
function existingCreatedAt(path) {
|
|
4050
4084
|
if (!existsSync8(path))
|
|
@@ -4283,7 +4317,7 @@ __export(exports_tasks, {
|
|
|
4283
4317
|
TASK_STATUS_VALUES: () => TASK_STATUS_VALUES
|
|
4284
4318
|
});
|
|
4285
4319
|
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync7, renameSync as renameSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
4286
|
-
import { dirname as dirname7, join as
|
|
4320
|
+
import { dirname as dirname7, join as join12 } from "path";
|
|
4287
4321
|
function safeTaskScopeKey(scopeKey) {
|
|
4288
4322
|
const safe = sanitizeFileName(scopeKey);
|
|
4289
4323
|
if (!safe || safe === "." || safe === "..") {
|
|
@@ -4295,7 +4329,7 @@ function taskScopeKey(opts) {
|
|
|
4295
4329
|
return opts.topicId?.trim() || opts.session || "default";
|
|
4296
4330
|
}
|
|
4297
4331
|
function getTaskFilePath(userId, scopeKey) {
|
|
4298
|
-
return
|
|
4332
|
+
return join12(resolveStorageDataDir(), "tasks", `${safeTaskScopeKey(scopeKey)}.json`);
|
|
4299
4333
|
}
|
|
4300
4334
|
function readTasks(userId, scopeKey) {
|
|
4301
4335
|
const path = getTaskFilePath(userId, scopeKey);
|
|
@@ -4479,16 +4513,16 @@ import {
|
|
|
4479
4513
|
unlinkSync as unlinkSync8,
|
|
4480
4514
|
writeFileSync as writeFileSync7
|
|
4481
4515
|
} from "fs";
|
|
4482
|
-
import { dirname as dirname8, join as
|
|
4516
|
+
import { dirname as dirname8, join as join13 } from "path";
|
|
4483
4517
|
function conversationDir(_userId) {
|
|
4484
|
-
return
|
|
4518
|
+
return join13(resolveStorageDataDir(), "conversations");
|
|
4485
4519
|
}
|
|
4486
4520
|
function topicFilename(topicName) {
|
|
4487
4521
|
const t = sanitizeTopicName(topicName, true);
|
|
4488
4522
|
return `${t}.jsonl`;
|
|
4489
4523
|
}
|
|
4490
4524
|
function getConversationPath(userId, topicName) {
|
|
4491
|
-
return
|
|
4525
|
+
return join13(conversationDir(userId), topicFilename(topicName));
|
|
4492
4526
|
}
|
|
4493
4527
|
function getActiveConversationPath(userId, topicName) {
|
|
4494
4528
|
const rawPath = getConversationPath(userId, topicName);
|
|
@@ -5245,7 +5279,7 @@ import { existsSync as existsSync13 } from "fs";
|
|
|
5245
5279
|
import { chmod, mkdtemp, rm, writeFile } from "fs/promises";
|
|
5246
5280
|
import { createServer } from "net";
|
|
5247
5281
|
import { tmpdir as tmpdir2 } from "os";
|
|
5248
|
-
import { dirname as dirname9, join as
|
|
5282
|
+
import { dirname as dirname9, join as join14, resolve as resolve7 } from "path";
|
|
5249
5283
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5250
5284
|
function evaluateCodexVaultPreToolUse(input, userId, operations) {
|
|
5251
5285
|
if (operations.referencesSensitiveStorage(input.tool_input)) {
|
|
@@ -5298,10 +5332,10 @@ function privateCodexWrapper(codexScript, socketPath, token) {
|
|
|
5298
5332
|
`);
|
|
5299
5333
|
}
|
|
5300
5334
|
async function createCodexVaultHookBridge(userId) {
|
|
5301
|
-
const root = await mkdtemp(
|
|
5335
|
+
const root = await mkdtemp(join14(tmpdir2(), "negotium-codex-vault-"));
|
|
5302
5336
|
await chmod(root, 448);
|
|
5303
|
-
const socketPath =
|
|
5304
|
-
const wrapperPath =
|
|
5337
|
+
const socketPath = join14(root, "hook.sock");
|
|
5338
|
+
const wrapperPath = join14(root, "codex-with-hooks");
|
|
5305
5339
|
const token = randomBytes5(32).toString("hex");
|
|
5306
5340
|
const connections = new Set;
|
|
5307
5341
|
const server = createServer((socket) => {
|
|
@@ -5918,8 +5952,8 @@ __export(exports_codex_provider, {
|
|
|
5918
5952
|
});
|
|
5919
5953
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
5920
5954
|
import { existsSync as existsSync14, readFileSync as readFileSync11, realpathSync as realpathSync3, statSync as statSync5 } from "fs";
|
|
5921
|
-
import { homedir as
|
|
5922
|
-
import { dirname as dirname10, isAbsolute as isAbsolute2, join as
|
|
5955
|
+
import { homedir as homedir8 } from "os";
|
|
5956
|
+
import { dirname as dirname10, isAbsolute as isAbsolute2, join as join15, relative, resolve as resolve9 } from "path";
|
|
5923
5957
|
import { Codex } from "@openai/codex-sdk";
|
|
5924
5958
|
function sameCodexUsage(usage, total) {
|
|
5925
5959
|
return usage.input_tokens === total.inputTokens && usage.output_tokens === total.outputTokens && (usage.cached_input_tokens ?? 0) === total.cachedInputTokens && (usage.cache_write_input_tokens ?? 0) === total.cacheWriteInputTokens;
|
|
@@ -5947,7 +5981,7 @@ function codexMcpServerName(name) {
|
|
|
5947
5981
|
return CODEX_MCP_SERVER_NAME_OVERRIDES[name] ?? name;
|
|
5948
5982
|
}
|
|
5949
5983
|
function globalCodexMcpServerNames(authFilePath) {
|
|
5950
|
-
const configPath =
|
|
5984
|
+
const configPath = join15(dirname10(authFilePath), "config.toml");
|
|
5951
5985
|
if (!existsSync14(configPath))
|
|
5952
5986
|
return [];
|
|
5953
5987
|
try {
|
|
@@ -6305,7 +6339,7 @@ async function* codexProvider(opts) {
|
|
|
6305
6339
|
mcpServerCount: Object.keys(codexMcpServers).length
|
|
6306
6340
|
}, "codexProvider: starting turn");
|
|
6307
6341
|
const hostedCodexHome = hostedCodexHomePath();
|
|
6308
|
-
const inheritedCodexHome = process.env.CODEX_HOME ||
|
|
6342
|
+
const inheritedCodexHome = process.env.CODEX_HOME || join15(homedir8(), ".codex");
|
|
6309
6343
|
const codexEnvironment = scopedBrowserCapability || resolve9(hostedCodexHome) !== resolve9(inheritedCodexHome) ? {
|
|
6310
6344
|
...Object.fromEntries(Object.entries(process.env).filter((entry) => typeof entry[1] === "string")),
|
|
6311
6345
|
CODEX_HOME: hostedCodexHome,
|
|
@@ -6759,8 +6793,8 @@ var init_maestro_provider = __esm(async () => {
|
|
|
6759
6793
|
|
|
6760
6794
|
// ../../packages/core/src/agents/index.ts
|
|
6761
6795
|
import { existsSync as existsSync15 } from "fs";
|
|
6762
|
-
import { homedir as
|
|
6763
|
-
import { join as
|
|
6796
|
+
import { homedir as homedir9 } from "os";
|
|
6797
|
+
import { join as join16 } from "path";
|
|
6764
6798
|
async function* dispatchAgent(opts) {
|
|
6765
6799
|
switch (opts.agent) {
|
|
6766
6800
|
case "claude": {
|
|
@@ -6794,11 +6828,11 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
|
|
|
6794
6828
|
switch (agent) {
|
|
6795
6829
|
case "claude": {
|
|
6796
6830
|
const encodedCwd = encodeClaudeCwd(cwd);
|
|
6797
|
-
const path =
|
|
6831
|
+
const path = join16(homedir9(), ".claude", "projects", encodedCwd, `${sessionId}.jsonl`);
|
|
6798
6832
|
return !existsSync15(path);
|
|
6799
6833
|
}
|
|
6800
6834
|
case "codex": {
|
|
6801
|
-
const sessionsDir =
|
|
6835
|
+
const sessionsDir = join16(hostedCodexHomePath(), "sessions");
|
|
6802
6836
|
const glob = new Bun.Glob(`**/rollout-*-${sessionId}.jsonl`);
|
|
6803
6837
|
for await (const _rel of glob.scan({ cwd: sessionsDir, onlyFiles: true })) {
|
|
6804
6838
|
return false;
|
|
@@ -10127,13 +10161,13 @@ var init_browser_processes = __esm(async () => {
|
|
|
10127
10161
|
});
|
|
10128
10162
|
|
|
10129
10163
|
// ../../packages/core/src/platform/playwright/headed-launch.ts
|
|
10130
|
-
import { accessSync as
|
|
10164
|
+
import { accessSync as accessSync3, constants as constants2 } from "fs";
|
|
10131
10165
|
import { delimiter, isAbsolute as isAbsolute3, resolve as resolve12 } from "path";
|
|
10132
10166
|
function findExecutableOnPath(command, environment = process.env) {
|
|
10133
10167
|
const candidates = isAbsolute3(command) ? [command] : (environment.PATH ?? "").split(delimiter).filter(Boolean).map((directory) => resolve12(directory, command));
|
|
10134
10168
|
for (const candidate of candidates) {
|
|
10135
10169
|
try {
|
|
10136
|
-
|
|
10170
|
+
accessSync3(candidate, constants2.X_OK);
|
|
10137
10171
|
return candidate;
|
|
10138
10172
|
} catch {}
|
|
10139
10173
|
}
|
|
@@ -10255,7 +10289,7 @@ import { randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual2 } from
|
|
|
10255
10289
|
import { chmodSync as chmodSync4 } from "fs";
|
|
10256
10290
|
import { createServer as createServer3 } from "net";
|
|
10257
10291
|
import { tmpdir as tmpdir3 } from "os";
|
|
10258
|
-
import { join as
|
|
10292
|
+
import { join as join17 } from "path";
|
|
10259
10293
|
function deepMapStrings2(value, transform) {
|
|
10260
10294
|
if (typeof value === "string")
|
|
10261
10295
|
return transform(value);
|
|
@@ -10342,7 +10376,7 @@ function authorized(actual, expected) {
|
|
|
10342
10376
|
}
|
|
10343
10377
|
async function createBrowserVaultBroker(userId) {
|
|
10344
10378
|
const token = randomBytes6(32).toString("hex");
|
|
10345
|
-
const socketPath =
|
|
10379
|
+
const socketPath = join17(process.platform === "win32" ? tmpdir3() : "/tmp", `negotium-browser-vault-${process.pid}-${randomBytes6(8).toString("hex")}.sock`);
|
|
10346
10380
|
const retainedForms = new Map;
|
|
10347
10381
|
const leases = new Map;
|
|
10348
10382
|
const sockets = new Set;
|
|
@@ -10608,7 +10642,7 @@ import {
|
|
|
10608
10642
|
unlinkSync as unlinkSync11,
|
|
10609
10643
|
writeFileSync as writeFileSync8
|
|
10610
10644
|
} from "fs";
|
|
10611
|
-
import { dirname as dirname11, join as
|
|
10645
|
+
import { dirname as dirname11, join as join18, resolve as resolve13 } from "path";
|
|
10612
10646
|
function removeDefaultProfileDataDir(userDataDir) {
|
|
10613
10647
|
const root = resolve13(BROWSER_PROFILES_DIR);
|
|
10614
10648
|
const target = resolve13(userDataDir);
|
|
@@ -10698,14 +10732,14 @@ function portFileName(instanceKey) {
|
|
|
10698
10732
|
function writePortFile(instanceKey, port) {
|
|
10699
10733
|
try {
|
|
10700
10734
|
mkdirSync10(managerHost.portsDir, { recursive: true });
|
|
10701
|
-
writeFileSync8(
|
|
10735
|
+
writeFileSync8(join18(managerHost.portsDir, portFileName(instanceKey)), String(port));
|
|
10702
10736
|
} catch (e) {
|
|
10703
10737
|
logger.warn({ err: e, instanceKey, port }, "Failed to save playwright port file");
|
|
10704
10738
|
}
|
|
10705
10739
|
}
|
|
10706
10740
|
function deletePortFile(instanceKey) {
|
|
10707
10741
|
try {
|
|
10708
|
-
unlinkSync11(
|
|
10742
|
+
unlinkSync11(join18(managerHost.portsDir, portFileName(instanceKey)));
|
|
10709
10743
|
} catch (e) {
|
|
10710
10744
|
if (e.code === "ENOENT")
|
|
10711
10745
|
return;
|
|
@@ -12251,32 +12285,32 @@ __export(exports_wiki, {
|
|
|
12251
12285
|
getSharedWikiDir: () => getSharedWikiDir
|
|
12252
12286
|
});
|
|
12253
12287
|
import { existsSync as existsSync17, readdirSync as readdirSync3, statSync as statSync6 } from "fs";
|
|
12254
|
-
import { basename as basename2, dirname as dirname12, join as
|
|
12288
|
+
import { basename as basename2, dirname as dirname12, join as join19 } from "path";
|
|
12255
12289
|
function getWikiDir(_userId, workspaceDir = resolveStorageWorkspaceDir()) {
|
|
12256
|
-
return
|
|
12290
|
+
return join19(workspaceDir, "wiki");
|
|
12257
12291
|
}
|
|
12258
12292
|
function getSharedWikiDir(workspaceDir = resolveStorageWorkspaceDir()) {
|
|
12259
|
-
return workspaceDir === resolveStorageWorkspaceDir() ? resolveStorageSharedWikiDir() :
|
|
12293
|
+
return workspaceDir === resolveStorageWorkspaceDir() ? resolveStorageSharedWikiDir() : join19(workspaceDir, "wiki");
|
|
12260
12294
|
}
|
|
12261
12295
|
function findLatestSummaryFile(wikiDir, safeTopic) {
|
|
12262
|
-
const summariesDir =
|
|
12296
|
+
const summariesDir = join19(wikiDir, "summaries");
|
|
12263
12297
|
if (!existsSync17(summariesDir))
|
|
12264
12298
|
return null;
|
|
12265
12299
|
const files = readdirSync3(summariesDir).filter((f) => f.endsWith(".md") && f.match(new RegExp(`^\\d{4}-\\d{2}-\\d{2}-${safeTopic}(\\.md|~\\d+\\.md)$`)) && !f.endsWith("-sent-files.md")).sort((left, right) => {
|
|
12266
|
-
const mtimeDelta = statSync6(
|
|
12300
|
+
const mtimeDelta = statSync6(join19(summariesDir, right)).mtimeMs - statSync6(join19(summariesDir, left)).mtimeMs;
|
|
12267
12301
|
return mtimeDelta || right.localeCompare(left, undefined, { numeric: true });
|
|
12268
12302
|
});
|
|
12269
|
-
return files.length > 0 ?
|
|
12303
|
+
return files.length > 0 ? join19(summariesDir, files[0]) : null;
|
|
12270
12304
|
}
|
|
12271
12305
|
function getTopicMemoryFilePaths(_userId, topicName, forkOrigin, workspaceDir = resolveStorageWorkspaceDir()) {
|
|
12272
12306
|
const wikiDir = getSharedWikiDir(workspaceDir);
|
|
12273
12307
|
const resolveBrief = (name) => {
|
|
12274
12308
|
const safe = sanitizeTopicName(name, true);
|
|
12275
|
-
const brief =
|
|
12309
|
+
const brief = join19(wikiDir, "topic", `${safe}.md`);
|
|
12276
12310
|
const latestSummary = findLatestSummaryFile(wikiDir, safe);
|
|
12277
12311
|
return { brief, latestSummary };
|
|
12278
12312
|
};
|
|
12279
|
-
const archiveDir =
|
|
12313
|
+
const archiveDir = join19(wikiDir, "archive");
|
|
12280
12314
|
const archiveExistsFor = (name) => {
|
|
12281
12315
|
const safe = sanitizeTopicName(name);
|
|
12282
12316
|
return existsSync17(archiveDir) && readdirSync3(archiveDir).some((f) => f.endsWith(".jsonl") && f.startsWith(`${safe}_`));
|
|
@@ -12293,7 +12327,7 @@ function getTopicMemoryFilePaths(_userId, topicName, forkOrigin, workspaceDir =
|
|
|
12293
12327
|
};
|
|
12294
12328
|
}
|
|
12295
12329
|
return {
|
|
12296
|
-
memoryDir:
|
|
12330
|
+
memoryDir: join19(wikiDir, "topic"),
|
|
12297
12331
|
memoryFiles: [],
|
|
12298
12332
|
...target.latestSummary ? { latestSummaryFile: target.latestSummary } : {},
|
|
12299
12333
|
...hasArchive ? { hasArchive: true } : {}
|
|
@@ -12306,7 +12340,7 @@ var init_wiki = __esm(async () => {
|
|
|
12306
12340
|
// ../../packages/core/src/agents/archiver.ts
|
|
12307
12341
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
12308
12342
|
import { existsSync as existsSync18, readdirSync as readdirSync4, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
|
|
12309
|
-
import { join as
|
|
12343
|
+
import { join as join20 } from "path";
|
|
12310
12344
|
function resolveMemoryLanguage() {
|
|
12311
12345
|
const override = process.env.NEGOTIUM_MEMORY_LANG?.trim();
|
|
12312
12346
|
return override && override.length > 0 ? override : resolveOutputLanguage();
|
|
@@ -12557,10 +12591,10 @@ function distillOneLine(summaryMd) {
|
|
|
12557
12591
|
return "";
|
|
12558
12592
|
}
|
|
12559
12593
|
function findSummaryFile(storage, topicTitle, date, sinceMs, topicId) {
|
|
12560
|
-
const dir =
|
|
12594
|
+
const dir = join20(storage.getWikiDir(), "summaries");
|
|
12561
12595
|
if (!storage.fileExists(dir))
|
|
12562
12596
|
return null;
|
|
12563
|
-
const predicted =
|
|
12597
|
+
const predicted = join20(dir, wikiSummaryFilename(date, topicTitle, topicId));
|
|
12564
12598
|
if (storage.fileExists(predicted) && storage.fileModifiedAt(predicted) >= sinceMs)
|
|
12565
12599
|
return predicted;
|
|
12566
12600
|
let best = null;
|
|
@@ -12568,7 +12602,7 @@ function findSummaryFile(storage, topicTitle, date, sinceMs, topicId) {
|
|
|
12568
12602
|
if (!f.startsWith(`${date}-`) || !isTopicSummaryFile(f, topicId ?? "", topicTitle)) {
|
|
12569
12603
|
continue;
|
|
12570
12604
|
}
|
|
12571
|
-
const p =
|
|
12605
|
+
const p = join20(dir, f);
|
|
12572
12606
|
try {
|
|
12573
12607
|
const m = storage.fileModifiedAt(p);
|
|
12574
12608
|
if (m >= sinceMs && (!best || m > best.mtime))
|
|
@@ -12784,13 +12818,13 @@ __export(exports_topic_archive, {
|
|
|
12784
12818
|
archiveConversationEvents: () => archiveConversationEvents
|
|
12785
12819
|
});
|
|
12786
12820
|
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
12787
|
-
import { join as
|
|
12821
|
+
import { join as join21 } from "path";
|
|
12788
12822
|
function archiveTopicMessages(topicId, topicTitle, options = {}) {
|
|
12789
12823
|
const rows = options.afterRowid !== undefined ? getMessagesForTopicAfterRowid(topicId, options.afterRowid) : getAllMessagesForTopic(topicId);
|
|
12790
12824
|
if (rows.length === 0)
|
|
12791
12825
|
return null;
|
|
12792
12826
|
const safeTopic = sanitizeTopicName(topicTitle, true);
|
|
12793
|
-
const archiveDir =
|
|
12827
|
+
const archiveDir = join21(getSharedWikiDir(), "archive");
|
|
12794
12828
|
mkdirSync11(archiveDir, { recursive: true });
|
|
12795
12829
|
const date = new Date().toISOString().slice(0, 10);
|
|
12796
12830
|
const reasonSuffix = options.reason && options.reason !== "delete" ? `_${options.reason}` : "";
|
|
@@ -12803,7 +12837,7 @@ function archiveTopicMessages(topicId, topicTitle, options = {}) {
|
|
|
12803
12837
|
let path;
|
|
12804
12838
|
while (true) {
|
|
12805
12839
|
filename = `${safeTopic}_${date}${reasonSuffix}${counter === 1 ? "" : `_${counter}`}.jsonl`;
|
|
12806
|
-
path =
|
|
12840
|
+
path = join21(archiveDir, filename);
|
|
12807
12841
|
try {
|
|
12808
12842
|
writeFileSync9(path, body, { flag: "wx" });
|
|
12809
12843
|
break;
|
|
@@ -12848,7 +12882,7 @@ function archiveConversationEvents(topicId, topicTitle, userId, options = {}) {
|
|
|
12848
12882
|
const entries = readRawConversation(userId, topicTitle);
|
|
12849
12883
|
if (entries.length === 0)
|
|
12850
12884
|
return null;
|
|
12851
|
-
const archiveDir =
|
|
12885
|
+
const archiveDir = join21(getSharedWikiDir(), "archive");
|
|
12852
12886
|
mkdirSync11(archiveDir, { recursive: true });
|
|
12853
12887
|
const safeTopic = sanitizeTopicName(topicTitle, true);
|
|
12854
12888
|
const date = new Date().toISOString().slice(0, 10);
|
|
@@ -12876,7 +12910,7 @@ function archiveConversationEvents(topicId, topicTitle, userId, options = {}) {
|
|
|
12876
12910
|
let counter = 1;
|
|
12877
12911
|
while (true) {
|
|
12878
12912
|
const suffix = counter === 1 ? "" : `_${counter}`;
|
|
12879
|
-
const path =
|
|
12913
|
+
const path = join21(archiveDir, `${safeTopic}_${date}${reasonSuffix}_events${suffix}.jsonl`);
|
|
12880
12914
|
try {
|
|
12881
12915
|
writeFileSync9(path, body, { flag: "wx" });
|
|
12882
12916
|
logger.info({ topicId, topicTitle, archive: path, eventCount: entries.length }, "archiveConversationEvents: archived raw conversation events");
|
|
@@ -13887,7 +13921,7 @@ var init_runtime_turn_requests = __esm(async () => {
|
|
|
13887
13921
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
13888
13922
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync4, writeFileSync as writeFileSync11 } from "fs";
|
|
13889
13923
|
import { tmpdir as tmpdir4 } from "os";
|
|
13890
|
-
import { join as
|
|
13924
|
+
import { join as join22 } from "path";
|
|
13891
13925
|
async function waitForMemoryArchive(settled, timeoutMs) {
|
|
13892
13926
|
let timer;
|
|
13893
13927
|
try {
|
|
@@ -14140,7 +14174,7 @@ function formatCompactElapsed(startedAt) {
|
|
|
14140
14174
|
async function summarizeTopicContext(request) {
|
|
14141
14175
|
const startedAt = Date.now();
|
|
14142
14176
|
const sessionIds = [];
|
|
14143
|
-
const compactCwd = mkdtempSync2(
|
|
14177
|
+
const compactCwd = mkdtempSync2(join22(tmpdir4(), "negotium-compact-"));
|
|
14144
14178
|
const abortController = new AbortController;
|
|
14145
14179
|
const relayAbort = () => abortController.abort(request.signal?.reason);
|
|
14146
14180
|
if (request.signal?.aborted)
|
|
@@ -14167,7 +14201,7 @@ async function summarizeTopicContext(request) {
|
|
|
14167
14201
|
let error = "";
|
|
14168
14202
|
let toolViolation = false;
|
|
14169
14203
|
let compactionLogCalls = 0;
|
|
14170
|
-
const compactionLogPath =
|
|
14204
|
+
const compactionLogPath = join22(compactCwd, "conversation.log");
|
|
14171
14205
|
try {
|
|
14172
14206
|
const compactionMcp = useCompactionLog ? {
|
|
14173
14207
|
compact_log: {
|
|
@@ -15488,14 +15522,14 @@ var init_self_config = __esm(async () => {
|
|
|
15488
15522
|
});
|
|
15489
15523
|
|
|
15490
15524
|
// ../../packages/core/src/query/session-inbox-path.ts
|
|
15491
|
-
import { join as
|
|
15525
|
+
import { join as join23 } from "path";
|
|
15492
15526
|
function sessionInboxPath(userId, topicId) {
|
|
15493
15527
|
const key = Buffer.from(topicId, "utf8").toString("base64url");
|
|
15494
|
-
return
|
|
15528
|
+
return join23(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${JSONL_SUFFIX}`);
|
|
15495
15529
|
}
|
|
15496
15530
|
function scheduledSessionInboxPath(userId, topicId) {
|
|
15497
15531
|
const key = Buffer.from(topicId, "utf8").toString("base64url");
|
|
15498
|
-
return
|
|
15532
|
+
return join23(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${SCHEDULE_SUFFIX}`);
|
|
15499
15533
|
}
|
|
15500
15534
|
function decodeTopicIdFileName(fileName, suffix) {
|
|
15501
15535
|
if (!fileName.startsWith(TOPIC_ID_FILE_PREFIX) || !fileName.endsWith(suffix))
|
|
@@ -15523,13 +15557,13 @@ var init_session_inbox_path = __esm(() => {
|
|
|
15523
15557
|
|
|
15524
15558
|
// ../../packages/core/src/query/session-inbox-cleanup.ts
|
|
15525
15559
|
import { unlinkSync as unlinkSync14 } from "fs";
|
|
15526
|
-
import { basename as basename3, join as
|
|
15560
|
+
import { basename as basename3, join as join24 } from "path";
|
|
15527
15561
|
function cleanupSessionInboxFiles(userId, topicId, legacyTopicTitle) {
|
|
15528
15562
|
const live = sessionInboxPath(userId, topicId);
|
|
15529
15563
|
const scheduled = scheduledSessionInboxPath(userId, topicId);
|
|
15530
15564
|
const candidates = new Set([live, `${live}.processing`, scheduled, `${scheduled}.processing`]);
|
|
15531
15565
|
if (legacyTopicTitle && legacyTopicTitle !== "." && legacyTopicTitle !== ".." && basename3(legacyTopicTitle) === legacyTopicTitle) {
|
|
15532
|
-
const legacyBase =
|
|
15566
|
+
const legacyBase = join24(SESSION_INBOX_DIR, userId, legacyTopicTitle);
|
|
15533
15567
|
for (const suffix of [".jsonl", ".jsonl.processing", ".schedule", ".schedule.processing"]) {
|
|
15534
15568
|
candidates.add(`${legacyBase}${suffix}`);
|
|
15535
15569
|
}
|
|
@@ -15555,16 +15589,16 @@ var init_session_inbox_cleanup = __esm(() => {
|
|
|
15555
15589
|
|
|
15556
15590
|
// ../../packages/core/src/query/state.ts
|
|
15557
15591
|
import { mkdirSync as mkdirSync14, renameSync as renameSync7, unlinkSync as unlinkSync15, writeFileSync as writeFileSync12 } from "fs";
|
|
15558
|
-
import { basename as basename4, join as
|
|
15592
|
+
import { basename as basename4, join as join25 } from "path";
|
|
15559
15593
|
function createQueryStateStore(options) {
|
|
15560
15594
|
const sanitize = options.sanitizeTopicId ?? sanitizeId;
|
|
15561
|
-
const queryStateDirPath = (userId) =>
|
|
15562
|
-
const queryStateFile = (userId, topicId) =>
|
|
15595
|
+
const queryStateDirPath = (userId) => join25(options.usersLogDir, String(userId), "active-queries");
|
|
15596
|
+
const queryStateFile = (userId, topicId) => join25(queryStateDirPath(userId), `${sanitize(topicId)}.json`);
|
|
15563
15597
|
const legacyQueryStateFile = (userId, topicName) => {
|
|
15564
15598
|
if (!topicName || topicName === "." || topicName === ".." || basename4(topicName) !== topicName) {
|
|
15565
15599
|
return null;
|
|
15566
15600
|
}
|
|
15567
|
-
return
|
|
15601
|
+
return join25(queryStateDirPath(userId), `${topicName}.json`);
|
|
15568
15602
|
};
|
|
15569
15603
|
return {
|
|
15570
15604
|
write(userId, topicId, topicName, task) {
|
|
@@ -15725,29 +15759,29 @@ import {
|
|
|
15725
15759
|
unlinkSync as unlinkSync16,
|
|
15726
15760
|
writeFileSync as writeFileSync13
|
|
15727
15761
|
} from "fs";
|
|
15728
|
-
import { dirname as dirname14, join as
|
|
15762
|
+
import { dirname as dirname14, join as join26 } from "path";
|
|
15729
15763
|
function pendingAskDir(userId) {
|
|
15730
15764
|
const rawUserId = String(userId);
|
|
15731
15765
|
const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash6("sha256").update(rawUserId).digest("hex")}`;
|
|
15732
|
-
return
|
|
15766
|
+
return join26(resolveStorageSessionAsksDir(), safeUserId);
|
|
15733
15767
|
}
|
|
15734
15768
|
function encodeAskKey(key) {
|
|
15735
15769
|
return JSON.stringify([key.from, key.to]);
|
|
15736
15770
|
}
|
|
15737
15771
|
function pendingAskPath(key) {
|
|
15738
15772
|
const digest = createHash6("sha256").update(encodeAskKey(key)).digest("hex");
|
|
15739
|
-
return
|
|
15773
|
+
return join26(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest}.pending`);
|
|
15740
15774
|
}
|
|
15741
15775
|
function v2PendingAskPath(key) {
|
|
15742
15776
|
const encoded = Buffer.from(encodeAskKey(key), "utf8").toString("base64url");
|
|
15743
|
-
return
|
|
15777
|
+
return join26(pendingAskDir(key.userId), `${V2_ASK_FILENAME_PREFIX}${encoded}.pending`);
|
|
15744
15778
|
}
|
|
15745
15779
|
function legacyPendingAskPath(key) {
|
|
15746
15780
|
if (key.from.includes("/") || key.from.includes("\\") || key.to.includes("/") || key.to.includes("\\") || key.from.includes("\x00") || key.to.includes("\x00")) {
|
|
15747
15781
|
return null;
|
|
15748
15782
|
}
|
|
15749
15783
|
const dir = pendingAskDir(key.userId);
|
|
15750
|
-
const candidate =
|
|
15784
|
+
const candidate = join26(dir, `${key.from}___${key.to}.pending`);
|
|
15751
15785
|
return dirname14(candidate) === dir ? candidate : null;
|
|
15752
15786
|
}
|
|
15753
15787
|
function parsePendingAskFilename(fileName) {
|
|
@@ -15988,7 +16022,7 @@ function listPendingAsksForCaller(args) {
|
|
|
15988
16022
|
const parsed = isV3 ? { from: args.from, to: "" } : parsePendingAskFilename(fileName);
|
|
15989
16023
|
if (!parsed)
|
|
15990
16024
|
continue;
|
|
15991
|
-
const path =
|
|
16025
|
+
const path = join26(dir, fileName);
|
|
15992
16026
|
const record = readPendingAskFile(path, {
|
|
15993
16027
|
userId: args.userId,
|
|
15994
16028
|
from: parsed.from,
|
|
@@ -16030,7 +16064,7 @@ function deletePendingAsksForTopic(args) {
|
|
|
16030
16064
|
}
|
|
16031
16065
|
let deleted = 0;
|
|
16032
16066
|
for (const fileName of files) {
|
|
16033
|
-
const path =
|
|
16067
|
+
const path = join26(dir, fileName);
|
|
16034
16068
|
const parsed = parsePendingAskFilename(fileName);
|
|
16035
16069
|
const record = readPendingAskFile(path, {
|
|
16036
16070
|
userId: args.userId,
|
|
@@ -16448,7 +16482,7 @@ __export(exports_token_stats, {
|
|
|
16448
16482
|
});
|
|
16449
16483
|
import { createHash as createHash7 } from "crypto";
|
|
16450
16484
|
import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync14 } from "fs";
|
|
16451
|
-
import { join as
|
|
16485
|
+
import { join as join27 } from "path";
|
|
16452
16486
|
function emptyBucket() {
|
|
16453
16487
|
return {
|
|
16454
16488
|
inputTokens: 0,
|
|
@@ -16467,7 +16501,7 @@ function queriesPath(userId) {
|
|
|
16467
16501
|
const fileId = tokenStatsFileId(userId);
|
|
16468
16502
|
const logDir = resolveStorageLogDir();
|
|
16469
16503
|
mkdirSync16(logDir, { recursive: true });
|
|
16470
|
-
return
|
|
16504
|
+
return join27(logDir, `token-queries-${fileId}.jsonl`);
|
|
16471
16505
|
}
|
|
16472
16506
|
function loadRecords(userId) {
|
|
16473
16507
|
try {
|
|
@@ -16896,7 +16930,7 @@ var init_lifecycle = __esm(async () => {
|
|
|
16896
16930
|
// ../../packages/core/src/runtime/attachments.ts
|
|
16897
16931
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
16898
16932
|
import { copyFileSync as copyFileSync2, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
16899
|
-
import { basename as basename5, join as
|
|
16933
|
+
import { basename as basename5, join as join28 } from "path";
|
|
16900
16934
|
function workspaceCwdFor(topicId) {
|
|
16901
16935
|
return resolveTopicWorkspaceDir(topicId);
|
|
16902
16936
|
}
|
|
@@ -16909,7 +16943,7 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
|
|
|
16909
16943
|
if (!attachmentIds?.length)
|
|
16910
16944
|
return [];
|
|
16911
16945
|
const out = [];
|
|
16912
|
-
const destDir =
|
|
16946
|
+
const destDir = join28(workspaceCwdFor(topicId), "attachments", queryId);
|
|
16913
16947
|
for (const rawId of attachmentIds) {
|
|
16914
16948
|
if (typeof rawId !== "string")
|
|
16915
16949
|
continue;
|
|
@@ -16926,7 +16960,7 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
|
|
|
16926
16960
|
mkdirSync17(destDir, { recursive: true });
|
|
16927
16961
|
const index = String(out.length + 1).padStart(2, "0");
|
|
16928
16962
|
const safeName = safeAttachmentFilename(attachment.filename, fileId);
|
|
16929
|
-
const destPath =
|
|
16963
|
+
const destPath = join28(destDir, `${index}-${fileId.slice(0, 8)}-${safeName}`);
|
|
16930
16964
|
copyFileSync2(sourcePath, destPath);
|
|
16931
16965
|
out.push({
|
|
16932
16966
|
id: attachment.id,
|
|
@@ -16956,10 +16990,10 @@ function promptWithAttachments(prompt, attachments) {
|
|
|
16956
16990
|
return composeAttachmentPrompt(prompt, attachments.map(({ filename, path }) => attachmentPromptLine(filename, path)));
|
|
16957
16991
|
}
|
|
16958
16992
|
function ingestAttachment(args) {
|
|
16959
|
-
const destDir =
|
|
16993
|
+
const destDir = join28(UPLOADS_DIR, args.topicId);
|
|
16960
16994
|
mkdirSync17(destDir, { recursive: true });
|
|
16961
16995
|
const safeName = safeAttachmentFilename(args.filename, "upload");
|
|
16962
|
-
const destPath =
|
|
16996
|
+
const destPath = join28(destDir, `${Date.now()}-${randomUUID14().slice(0, 8)}-${safeName}`);
|
|
16963
16997
|
if (args.sourcePath !== undefined) {
|
|
16964
16998
|
copyFileSync2(args.sourcePath, destPath);
|
|
16965
16999
|
} else if (args.bytes !== undefined) {
|
|
@@ -18270,9 +18304,9 @@ __export(exports_app_settings, {
|
|
|
18270
18304
|
DEFAULT_AI_NAME: () => DEFAULT_AI_NAME
|
|
18271
18305
|
});
|
|
18272
18306
|
import { existsSync as existsSync19, mkdirSync as mkdirSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync16 } from "fs";
|
|
18273
|
-
import { dirname as dirname15, join as
|
|
18307
|
+
import { dirname as dirname15, join as join29 } from "path";
|
|
18274
18308
|
function settingsFile() {
|
|
18275
|
-
return
|
|
18309
|
+
return join29(resolveStorageDataDir(), "otium-settings.json");
|
|
18276
18310
|
}
|
|
18277
18311
|
function getGlobalAiName() {
|
|
18278
18312
|
const path = settingsFile();
|
|
@@ -18376,7 +18410,7 @@ __export(exports_turn_runner, {
|
|
|
18376
18410
|
});
|
|
18377
18411
|
import { randomUUID as randomUUID16 } from "crypto";
|
|
18378
18412
|
import { existsSync as existsSync20, mkdirSync as mkdirSync19, readdirSync as readdirSync6, statSync as statSync10 } from "fs";
|
|
18379
|
-
import { join as
|
|
18413
|
+
import { join as join30 } from "path";
|
|
18380
18414
|
function withDefaultPlaywright(configuredMcp, isManager) {
|
|
18381
18415
|
if (isManager)
|
|
18382
18416
|
return configuredMcp;
|
|
@@ -18431,7 +18465,7 @@ function appendAskReplyMessage(topicId, text2, agentType) {
|
|
|
18431
18465
|
return message;
|
|
18432
18466
|
}
|
|
18433
18467
|
function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, matchesTitle, preferExact = true) {
|
|
18434
|
-
const preferred =
|
|
18468
|
+
const preferred = join30(directory, preferredFilename);
|
|
18435
18469
|
if (preferExact && existsSync20(preferred))
|
|
18436
18470
|
return preferred;
|
|
18437
18471
|
let newestLegacyId = null;
|
|
@@ -18442,7 +18476,7 @@ function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, ma
|
|
|
18442
18476
|
const legacyIdMatch = !titleMatch && matchesLegacyId(filename);
|
|
18443
18477
|
if (!titleMatch && !legacyIdMatch)
|
|
18444
18478
|
continue;
|
|
18445
|
-
const path =
|
|
18479
|
+
const path = join30(directory, filename);
|
|
18446
18480
|
const mtimeMs = statSync10(path).mtimeMs;
|
|
18447
18481
|
if (titleMatch) {
|
|
18448
18482
|
if (!newestTitle || mtimeMs > newestTitle.mtimeMs) {
|
|
@@ -18456,9 +18490,9 @@ function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, ma
|
|
|
18456
18490
|
return newestTitle?.path ?? newestLegacyId?.path ?? preferred;
|
|
18457
18491
|
}
|
|
18458
18492
|
function resolveWikiMemoryMirror(wikiDir, topicId, topicTitle) {
|
|
18459
|
-
const briefFile = resolveWikiMirrorPath(
|
|
18493
|
+
const briefFile = resolveWikiMirrorPath(join30(wikiDir, "topic"), `${wikiBriefStorageKey(topicTitle, topicId)}.md`, (filename) => isTopicBriefFile(filename, topicId), (filename) => isTopicBriefFile(filename, topicId, topicTitle));
|
|
18460
18494
|
const hasBriefFile = existsSync20(briefFile) && statSync10(briefFile).isFile();
|
|
18461
|
-
const latestSummaryCandidate = resolveWikiMirrorPath(
|
|
18495
|
+
const latestSummaryCandidate = resolveWikiMirrorPath(join30(wikiDir, "summaries"), `__missing__-${wikiSummaryFilename("0000-00-00", topicTitle, topicId)}`, (filename) => isTopicSummaryFile(filename, topicId), (filename) => isTopicSummaryFile(filename, topicId, topicTitle), false);
|
|
18462
18496
|
const latestSummaryFile = existsSync20(latestSummaryCandidate) && statSync10(latestSummaryCandidate).isFile() ? latestSummaryCandidate : null;
|
|
18463
18497
|
return { briefFile, hasBriefFile, latestSummaryFile };
|
|
18464
18498
|
}
|
|
@@ -21208,7 +21242,7 @@ var init_vault_command = __esm(async () => {
|
|
|
21208
21242
|
import { execFile } from "child_process";
|
|
21209
21243
|
import { existsSync as existsSync21, mkdirSync as mkdirSync21, readFileSync as readFileSync17, rmSync as rmSync7 } from "fs";
|
|
21210
21244
|
import { readFile } from "fs/promises";
|
|
21211
|
-
import { extname, join as
|
|
21245
|
+
import { extname, join as join31 } from "path";
|
|
21212
21246
|
import { promisify } from "util";
|
|
21213
21247
|
async function extractText(filePath) {
|
|
21214
21248
|
const ext = extname(filePath).toLowerCase();
|
|
@@ -21325,7 +21359,7 @@ async function extractFromAudio(filePath, opts = {}) {
|
|
|
21325
21359
|
const tmpDir = `${filePath}_whisper_tmp`;
|
|
21326
21360
|
try {
|
|
21327
21361
|
mkdirSync21(tmpDir, { recursive: true });
|
|
21328
|
-
const mp3Path =
|
|
21362
|
+
const mp3Path = join31(tmpDir, "audio.mp3");
|
|
21329
21363
|
await execFileAsync(opts.ffmpegBin ?? FFMPEG_BIN2, [
|
|
21330
21364
|
"-y",
|
|
21331
21365
|
"-i",
|
|
@@ -21352,7 +21386,7 @@ async function extractFromAudio(filePath, opts = {}) {
|
|
|
21352
21386
|
"--output-format",
|
|
21353
21387
|
"txt"
|
|
21354
21388
|
], { timeout: 120000 });
|
|
21355
|
-
const txtPath =
|
|
21389
|
+
const txtPath = join31(tmpDir, "audio.txt");
|
|
21356
21390
|
const text2 = existsSync21(txtPath) ? readFileSync17(txtPath, "utf-8").trim() : null;
|
|
21357
21391
|
if (!text2) {
|
|
21358
21392
|
return { text: null, method: "whisper", error: "Whisper produced no text" };
|
|
@@ -21525,7 +21559,7 @@ var init_lifecycle2 = __esm(() => {
|
|
|
21525
21559
|
|
|
21526
21560
|
// ../../packages/core/src/platform/log-rotation.ts
|
|
21527
21561
|
import { existsSync as existsSync22, renameSync as renameSync8, statSync as statSync11 } from "fs";
|
|
21528
|
-
import { join as
|
|
21562
|
+
import { join as join32 } from "path";
|
|
21529
21563
|
function rotateOversizedLog(logPath, maxBytes = DEFAULT_DAEMON_LOG_ROTATE_BYTES) {
|
|
21530
21564
|
try {
|
|
21531
21565
|
if (!existsSync22(logPath))
|
|
@@ -21534,9 +21568,9 @@ function rotateOversizedLog(logPath, maxBytes = DEFAULT_DAEMON_LOG_ROTATE_BYTES)
|
|
|
21534
21568
|
if (size < maxBytes)
|
|
21535
21569
|
return;
|
|
21536
21570
|
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
21537
|
-
const dir =
|
|
21571
|
+
const dir = join32(logPath, "..");
|
|
21538
21572
|
const base = logPath.slice(dir.length + 1);
|
|
21539
|
-
renameSync8(logPath,
|
|
21573
|
+
renameSync8(logPath, join32(dir, `${base}.${stamp}`));
|
|
21540
21574
|
} catch {}
|
|
21541
21575
|
}
|
|
21542
21576
|
var DEFAULT_DAEMON_LOG_ROTATE_BYTES;
|
|
@@ -21729,7 +21763,7 @@ import {
|
|
|
21729
21763
|
rmSync as rmSync8,
|
|
21730
21764
|
statSync as statSync12
|
|
21731
21765
|
} from "fs";
|
|
21732
|
-
import { join as
|
|
21766
|
+
import { join as join33 } from "path";
|
|
21733
21767
|
function setBashrsCompletionSink(sink) {
|
|
21734
21768
|
completionSink = sink ?? defaultSink;
|
|
21735
21769
|
}
|
|
@@ -21756,15 +21790,15 @@ function readTail(filePath) {
|
|
|
21756
21790
|
}
|
|
21757
21791
|
}
|
|
21758
21792
|
function buildMessage(dir, result) {
|
|
21759
|
-
const stdout = readTail(
|
|
21760
|
-
const stderr = readTail(
|
|
21793
|
+
const stdout = readTail(join33(dir, "stdout.log"));
|
|
21794
|
+
const stderr = readTail(join33(dir, "stderr.log"));
|
|
21761
21795
|
const parts = [];
|
|
21762
21796
|
if (stdout.text.trim() || stdout.truncated) {
|
|
21763
|
-
parts.push(`stdout${stdout.truncated ? ` (truncated, full output: ${
|
|
21797
|
+
parts.push(`stdout${stdout.truncated ? ` (truncated, full output: ${join33(dir, "stdout.log")})` : ""}:
|
|
21764
21798
|
${stdout.text.trim()}`);
|
|
21765
21799
|
}
|
|
21766
21800
|
if (stderr.text.trim() || stderr.truncated) {
|
|
21767
|
-
parts.push(`stderr${stderr.truncated ? ` (truncated, full output: ${
|
|
21801
|
+
parts.push(`stderr${stderr.truncated ? ` (truncated, full output: ${join33(dir, "stderr.log")})` : ""}:
|
|
21768
21802
|
${stderr.text.trim()}`);
|
|
21769
21803
|
}
|
|
21770
21804
|
const header = watchHeader(result) ?? `[background_bash ${result.bash_id} finished]`;
|
|
@@ -21798,7 +21832,7 @@ function parseOwner(owner) {
|
|
|
21798
21832
|
return { userId, topicId };
|
|
21799
21833
|
}
|
|
21800
21834
|
function injectedMarker(dir) {
|
|
21801
|
-
return
|
|
21835
|
+
return join33(dir, "result.json.injected");
|
|
21802
21836
|
}
|
|
21803
21837
|
async function flushBashrsCompletions() {
|
|
21804
21838
|
let entries;
|
|
@@ -21809,8 +21843,8 @@ async function flushBashrsCompletions() {
|
|
|
21809
21843
|
}
|
|
21810
21844
|
const now = Date.now();
|
|
21811
21845
|
for (const bashId of entries) {
|
|
21812
|
-
const dir =
|
|
21813
|
-
const resultPath =
|
|
21846
|
+
const dir = join33(BASHRS_SPILL_ROOT, bashId);
|
|
21847
|
+
const resultPath = join33(dir, "result.json");
|
|
21814
21848
|
const marker = injectedMarker(dir);
|
|
21815
21849
|
try {
|
|
21816
21850
|
const markerStat = statSync12(marker);
|
|
@@ -22108,7 +22142,7 @@ var init_file_ops = __esm(() => {
|
|
|
22108
22142
|
// ../../packages/core/src/runtime/inbox.ts
|
|
22109
22143
|
import { createHash as createHash9, randomUUID as randomUUID20 } from "crypto";
|
|
22110
22144
|
import { readdirSync as readdirSync8, statSync as statSync13, writeFileSync as writeFileSync17 } from "fs";
|
|
22111
|
-
import { join as
|
|
22145
|
+
import { join as join34 } from "path";
|
|
22112
22146
|
async function createAskForkPlan(options) {
|
|
22113
22147
|
const snapshot = structuredClone(options.entries);
|
|
22114
22148
|
const prepareSession = async () => options.synthesize(structuredClone(snapshot));
|
|
@@ -22248,7 +22282,7 @@ async function flushSessionInbox() {
|
|
|
22248
22282
|
return;
|
|
22249
22283
|
}
|
|
22250
22284
|
for (const uid of userDirs) {
|
|
22251
|
-
const userInboxDir =
|
|
22285
|
+
const userInboxDir = join34(SESSION_INBOX_DIR, uid);
|
|
22252
22286
|
let entries;
|
|
22253
22287
|
try {
|
|
22254
22288
|
entries = readdirSync8(userInboxDir);
|
|
@@ -22256,7 +22290,7 @@ async function flushSessionInbox() {
|
|
|
22256
22290
|
continue;
|
|
22257
22291
|
}
|
|
22258
22292
|
for (const entry of entries) {
|
|
22259
|
-
const entryPath =
|
|
22293
|
+
const entryPath = join34(userInboxDir, entry);
|
|
22260
22294
|
let isDir = false;
|
|
22261
22295
|
try {
|
|
22262
22296
|
isDir = statSync13(entryPath).isDirectory();
|
|
@@ -22346,7 +22380,7 @@ function sweepScheduledSessionInbox(nowMs = Date.now()) {
|
|
|
22346
22380
|
return;
|
|
22347
22381
|
}
|
|
22348
22382
|
for (const userId of userDirs) {
|
|
22349
|
-
const userInboxDir =
|
|
22383
|
+
const userInboxDir = join34(SESSION_INBOX_DIR, userId);
|
|
22350
22384
|
let files;
|
|
22351
22385
|
try {
|
|
22352
22386
|
files = readdirSync8(userInboxDir);
|
|
@@ -22358,7 +22392,7 @@ function sweepScheduledSessionInbox(nowMs = Date.now()) {
|
|
|
22358
22392
|
const topicId = topicIdFromScheduledSessionInboxFileName(file);
|
|
22359
22393
|
if (!topicId)
|
|
22360
22394
|
continue;
|
|
22361
|
-
const schedulePath =
|
|
22395
|
+
const schedulePath = join34(userInboxDir, file);
|
|
22362
22396
|
const hasProcessingClaim = files.includes(`${file}.processing`);
|
|
22363
22397
|
if (!hasProcessingClaim && !scheduledFileNeedsClaim(schedulePath, nowMs))
|
|
22364
22398
|
continue;
|
|
@@ -23195,7 +23229,7 @@ var init_src = __esm(async () => {
|
|
|
23195
23229
|
|
|
23196
23230
|
// ../../packages/core/src/storage/conversation-migration.ts
|
|
23197
23231
|
import { copyFileSync as copyFileSync3, existsSync as existsSync24, mkdirSync as mkdirSync23, readFileSync as readFileSync20 } from "fs";
|
|
23198
|
-
import { dirname as dirname16, join as
|
|
23232
|
+
import { dirname as dirname16, join as join35 } from "path";
|
|
23199
23233
|
function readEntries(path) {
|
|
23200
23234
|
const entries = [];
|
|
23201
23235
|
for (const [index, line] of readFileSync20(path, "utf8").split(`
|
|
@@ -23262,7 +23296,7 @@ function migrateLegacyCompactedConversations() {
|
|
|
23262
23296
|
result.skipped++;
|
|
23263
23297
|
continue;
|
|
23264
23298
|
}
|
|
23265
|
-
const backupPath =
|
|
23299
|
+
const backupPath = join35(resolveStorageDataDir(), "conversation-migration-backups", MIGRATION_NAME, userId, `${sanitizeTopicName(topic.title, true)}.jsonl`);
|
|
23266
23300
|
const sourcePath = existsSync24(backupPath) ? backupPath : rawPath;
|
|
23267
23301
|
const legacyEntries = readEntries(sourcePath);
|
|
23268
23302
|
const compactIndex = compactionEntryIndex(legacyEntries);
|
|
@@ -23322,7 +23356,7 @@ __export(exports_decisions, {
|
|
|
23322
23356
|
DECISION_STATUS_VALUES: () => DECISION_STATUS_VALUES
|
|
23323
23357
|
});
|
|
23324
23358
|
import { existsSync as existsSync25, mkdirSync as mkdirSync24, readFileSync as readFileSync21, renameSync as renameSync11, writeFileSync as writeFileSync18 } from "fs";
|
|
23325
|
-
import { dirname as dirname17, join as
|
|
23359
|
+
import { dirname as dirname17, join as join36 } from "path";
|
|
23326
23360
|
function safeDecisionScopeKey(scopeKey) {
|
|
23327
23361
|
const safe = sanitizeFileName(scopeKey);
|
|
23328
23362
|
if (!safe || safe === "." || safe === "..") {
|
|
@@ -23334,10 +23368,10 @@ function decisionScopeKey(opts) {
|
|
|
23334
23368
|
return opts.topicId?.trim() || opts.session || "default";
|
|
23335
23369
|
}
|
|
23336
23370
|
function getDecisionFilePath(userId, scopeKey) {
|
|
23337
|
-
return
|
|
23371
|
+
return join36(resolveStorageDataDir(), "decisions", `${safeDecisionScopeKey(scopeKey)}.json`);
|
|
23338
23372
|
}
|
|
23339
23373
|
function getDecisionGraphSvgPath(userId, scopeKey) {
|
|
23340
|
-
return
|
|
23374
|
+
return join36(resolveStorageDataDir(), "decision-renders", safeDecisionScopeKey(scopeKey), "latest.svg");
|
|
23341
23375
|
}
|
|
23342
23376
|
function writeDecisionGraphSvg(userId, scopeKey, svg) {
|
|
23343
23377
|
const path = getDecisionGraphSvgPath(userId, scopeKey);
|
|
@@ -24597,7 +24631,7 @@ __export(exports_agent_health, {
|
|
|
24597
24631
|
});
|
|
24598
24632
|
import { spawn as spawn6 } from "child_process";
|
|
24599
24633
|
import { existsSync as existsSync27, readdirSync as readdirSync9 } from "fs";
|
|
24600
|
-
import { join as
|
|
24634
|
+
import { join as join37 } from "path";
|
|
24601
24635
|
import { McpServer as McpServer5 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
24602
24636
|
import { z as z10 } from "zod";
|
|
24603
24637
|
function signalProcessTree2(child, signal) {
|
|
@@ -24841,7 +24875,7 @@ ${results.every((result) => result.ok) ? "All agents healthy" : "Some agents fai
|
|
|
24841
24875
|
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 () => {
|
|
24842
24876
|
if (!context.userId)
|
|
24843
24877
|
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC870\uD68C \uBD88\uAC00 (user context \uC5C6\uC74C)");
|
|
24844
|
-
const stateDir =
|
|
24878
|
+
const stateDir = join37(USERS_LOG_DIR, context.userId, "active-queries");
|
|
24845
24879
|
if (!existsSync27(stateDir))
|
|
24846
24880
|
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC5C6\uC74C");
|
|
24847
24881
|
let files;
|
|
@@ -24854,7 +24888,7 @@ ${results.every((result) => result.ok) ? "All agents healthy" : "Some agents fai
|
|
|
24854
24888
|
const entries = files.flatMap((file) => {
|
|
24855
24889
|
if (!file.endsWith(".json"))
|
|
24856
24890
|
return [];
|
|
24857
|
-
const state = readJsonFile(
|
|
24891
|
+
const state = readJsonFile(join37(stateDir, file));
|
|
24858
24892
|
if (!state)
|
|
24859
24893
|
return [];
|
|
24860
24894
|
const sinceMs = new Date(state.since).getTime();
|
|
@@ -25087,7 +25121,7 @@ var exports_default_host = {};
|
|
|
25087
25121
|
__export(exports_default_host, {
|
|
25088
25122
|
createDefaultSessionCommMcpHost: () => createDefaultSessionCommMcpHost
|
|
25089
25123
|
});
|
|
25090
|
-
import { basename as basename6, join as
|
|
25124
|
+
import { basename as basename6, join as join38 } from "path";
|
|
25091
25125
|
function ok2(text2) {
|
|
25092
25126
|
return { content: [{ type: "text", text: text2 }] };
|
|
25093
25127
|
}
|
|
@@ -25134,10 +25168,10 @@ function remoteTarget(context, to) {
|
|
|
25134
25168
|
return { node: to.slice(0, slash), topic: to.slice(slash + 1) };
|
|
25135
25169
|
}
|
|
25136
25170
|
function activeQuery(context, topicId, title) {
|
|
25137
|
-
const dir =
|
|
25138
|
-
const candidates = [
|
|
25171
|
+
const dir = join38(USERS_LOG_DIR, context.userId, "active-queries");
|
|
25172
|
+
const candidates = [join38(dir, `${sanitizeId(topicId)}.json`)];
|
|
25139
25173
|
if (title && basename6(title) === title && title !== "." && title !== "..") {
|
|
25140
|
-
candidates.push(
|
|
25174
|
+
candidates.push(join38(dir, `${title}.json`));
|
|
25141
25175
|
}
|
|
25142
25176
|
for (const path of candidates) {
|
|
25143
25177
|
const state = readJsonFile(path);
|
|
@@ -25686,7 +25720,7 @@ import {
|
|
|
25686
25720
|
unlinkSync as unlinkSync19,
|
|
25687
25721
|
writeFileSync as writeFileSync19
|
|
25688
25722
|
} from "fs";
|
|
25689
|
-
import { basename as basename7, dirname as dirname18, join as
|
|
25723
|
+
import { basename as basename7, dirname as dirname18, join as join39, relative as relative2, resolve as resolve18 } from "path";
|
|
25690
25724
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
25691
25725
|
import { StdioServerTransport as StdioServerTransport2 } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
25692
25726
|
import {
|
|
@@ -26136,13 +26170,13 @@ function wikiQuery(args) {
|
|
|
26136
26170
|
try {
|
|
26137
26171
|
for (const entry of readdirSync10(dir, { withFileTypes: true })) {
|
|
26138
26172
|
if (entry.isDirectory()) {
|
|
26139
|
-
const sub =
|
|
26173
|
+
const sub = join39(dir, entry.name);
|
|
26140
26174
|
if (label === "articles" || label === "skills") {
|
|
26141
26175
|
try {
|
|
26142
26176
|
for (const f of readdirSync10(sub, { withFileTypes: true })) {
|
|
26143
26177
|
if (!f.isFile() || !f.name.endsWith(".md"))
|
|
26144
26178
|
continue;
|
|
26145
|
-
const fp =
|
|
26179
|
+
const fp = join39(sub, f.name);
|
|
26146
26180
|
try {
|
|
26147
26181
|
const text2 = readFileSync24(fp, "utf-8");
|
|
26148
26182
|
const key = `${entry.name}/${f.name.replace(/\.md$/i, "")}`;
|
|
@@ -26163,7 +26197,7 @@ function wikiQuery(args) {
|
|
|
26163
26197
|
if (label === "topic" && canReadTopicMemory && !canReadTopicMemory(entry.name.replace(/\.md$/i, ""), runtime().userId)) {
|
|
26164
26198
|
continue;
|
|
26165
26199
|
}
|
|
26166
|
-
const fp =
|
|
26200
|
+
const fp = join39(dir, entry.name);
|
|
26167
26201
|
try {
|
|
26168
26202
|
const text2 = readFileSync24(fp, "utf-8");
|
|
26169
26203
|
const key = entry.name.replace(/\.md$/i, "");
|
|
@@ -26884,21 +26918,21 @@ function collectIndexableDocuments() {
|
|
|
26884
26918
|
}
|
|
26885
26919
|
for (const entry of entries) {
|
|
26886
26920
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
26887
|
-
add(kind, entry.name.replace(/\.md$/i, ""),
|
|
26921
|
+
add(kind, entry.name.replace(/\.md$/i, ""), join39(root, entry.name));
|
|
26888
26922
|
continue;
|
|
26889
26923
|
}
|
|
26890
26924
|
if (!entry.isDirectory() || !allowSubdirectories)
|
|
26891
26925
|
continue;
|
|
26892
26926
|
let nested;
|
|
26893
26927
|
try {
|
|
26894
|
-
nested = readdirSync10(
|
|
26928
|
+
nested = readdirSync10(join39(root, entry.name), { withFileTypes: true });
|
|
26895
26929
|
} catch {
|
|
26896
26930
|
continue;
|
|
26897
26931
|
}
|
|
26898
26932
|
for (const file of nested) {
|
|
26899
26933
|
if (!file.isFile() || !file.name.endsWith(".md"))
|
|
26900
26934
|
continue;
|
|
26901
|
-
add(kind, `${entry.name}/${file.name.replace(/\.md$/i, "")}`,
|
|
26935
|
+
add(kind, `${entry.name}/${file.name.replace(/\.md$/i, "")}`, join39(root, entry.name, file.name));
|
|
26902
26936
|
}
|
|
26903
26937
|
}
|
|
26904
26938
|
}
|
|
@@ -27407,7 +27441,7 @@ import {
|
|
|
27407
27441
|
unlinkSync as unlinkSync20,
|
|
27408
27442
|
writeFileSync as writeFileSync20
|
|
27409
27443
|
} from "fs";
|
|
27410
|
-
import { basename as basename8, join as
|
|
27444
|
+
import { basename as basename8, join as join40 } from "path";
|
|
27411
27445
|
function startLogRotation() {
|
|
27412
27446
|
if (rotationTimer)
|
|
27413
27447
|
return;
|
|
@@ -27421,7 +27455,7 @@ function writeLog(entry) {
|
|
|
27421
27455
|
mkdirSync26(logDir, { recursive: true });
|
|
27422
27456
|
const safeSession = sanitizeTopicName(entry.session);
|
|
27423
27457
|
const sidShort = entry.sessionId ? entry.sessionId.slice(0, 8) : "new";
|
|
27424
|
-
const file =
|
|
27458
|
+
const file = join40(logDir, `${entry.userId}_${safeSession}_${sidShort}.jsonl`);
|
|
27425
27459
|
try {
|
|
27426
27460
|
const stat = statSync16(file);
|
|
27427
27461
|
if (stat.size >= MAX_FILE_SIZE) {
|
|
@@ -27441,7 +27475,7 @@ function rotateOldLogs() {
|
|
|
27441
27475
|
try {
|
|
27442
27476
|
const files = readdirSync11(logDir).filter((f) => f.endsWith(".jsonl")).map((f) => {
|
|
27443
27477
|
try {
|
|
27444
|
-
const stat = statSync16(
|
|
27478
|
+
const stat = statSync16(join40(logDir, f));
|
|
27445
27479
|
return { name: f, size: stat.size, mtimeMs: stat.mtimeMs };
|
|
27446
27480
|
} catch {
|
|
27447
27481
|
return null;
|
|
@@ -27457,7 +27491,7 @@ function rotateOldLogs() {
|
|
|
27457
27491
|
if (freed >= toFree)
|
|
27458
27492
|
break;
|
|
27459
27493
|
try {
|
|
27460
|
-
unlinkSync20(
|
|
27494
|
+
unlinkSync20(join40(logDir, file.name));
|
|
27461
27495
|
freed += file.size;
|
|
27462
27496
|
logger.info({ file: file.name, sizeKB: (file.size / 1024).toFixed(0) }, "Rotated out old log");
|
|
27463
27497
|
} catch (e) {
|
|
@@ -27469,9 +27503,9 @@ function rotateOldLogs() {
|
|
|
27469
27503
|
}
|
|
27470
27504
|
}
|
|
27471
27505
|
function writeSentFileLog(entry) {
|
|
27472
|
-
const dir =
|
|
27506
|
+
const dir = join40(resolveStorageUsersLogDir(), String(entry.userId));
|
|
27473
27507
|
mkdirSync26(dir, { recursive: true });
|
|
27474
|
-
const file =
|
|
27508
|
+
const file = join40(dir, "sent-files.jsonl");
|
|
27475
27509
|
try {
|
|
27476
27510
|
appendJsonlEntry(file, { ...entry, fileName: basename8(entry.filePath) });
|
|
27477
27511
|
} catch (e) {
|
|
@@ -27482,7 +27516,7 @@ function entryMatchesTopic(e, topicName) {
|
|
|
27482
27516
|
return e.topicName === topicName;
|
|
27483
27517
|
}
|
|
27484
27518
|
function readSentFilesForTopic(userId, topicName) {
|
|
27485
|
-
const file =
|
|
27519
|
+
const file = join40(resolveStorageUsersLogDir(), String(userId), "sent-files.jsonl");
|
|
27486
27520
|
if (!existsSync30(file))
|
|
27487
27521
|
return [];
|
|
27488
27522
|
try {
|
|
@@ -27493,7 +27527,7 @@ function readSentFilesForTopic(userId, topicName) {
|
|
|
27493
27527
|
}
|
|
27494
27528
|
}
|
|
27495
27529
|
function removeSentFilesForTopic(userId, topicName) {
|
|
27496
|
-
const file =
|
|
27530
|
+
const file = join40(resolveStorageUsersLogDir(), String(userId), "sent-files.jsonl");
|
|
27497
27531
|
if (!existsSync30(file))
|
|
27498
27532
|
return;
|
|
27499
27533
|
try {
|
|
@@ -28980,11 +29014,11 @@ var init_src2 = __esm(async () => {
|
|
|
28980
29014
|
});
|
|
28981
29015
|
|
|
28982
29016
|
// ../../packages/mcp-host/src/paths.ts
|
|
28983
|
-
import { homedir as
|
|
29017
|
+
import { homedir as homedir10 } from "os";
|
|
28984
29018
|
import { resolve as resolve21 } from "path";
|
|
28985
29019
|
function stateDir() {
|
|
28986
29020
|
const env = process.env.NEGOTIUM_STATE_DIR?.trim();
|
|
28987
|
-
return env ? resolve21(env) : resolve21(
|
|
29021
|
+
return env ? resolve21(env) : resolve21(homedir10(), ".negotium");
|
|
28988
29022
|
}
|
|
28989
29023
|
function defaultPortsDir() {
|
|
28990
29024
|
return resolve21(stateDir(), "run", "mcp-ports");
|
|
@@ -29137,7 +29171,7 @@ import {
|
|
|
29137
29171
|
writeFileSync as writeFileSync22
|
|
29138
29172
|
} from "fs";
|
|
29139
29173
|
import { connect, createServer as createServer4 } from "net";
|
|
29140
|
-
import { join as
|
|
29174
|
+
import { join as join41 } from "path";
|
|
29141
29175
|
function regKey(key, instanceKey) {
|
|
29142
29176
|
return `${key}\x00${instanceKey}`;
|
|
29143
29177
|
}
|
|
@@ -29439,7 +29473,7 @@ class McpHost {
|
|
|
29439
29473
|
if (file.includes(".tmp-"))
|
|
29440
29474
|
continue;
|
|
29441
29475
|
try {
|
|
29442
|
-
const port = Number.parseInt(readFileSync26(
|
|
29476
|
+
const port = Number.parseInt(readFileSync26(join41(this.portsDir, file), "utf8").trim(), 10);
|
|
29443
29477
|
if (!Number.isNaN(port))
|
|
29444
29478
|
claims.set(file, port);
|
|
29445
29479
|
} catch {}
|
|
@@ -29449,7 +29483,7 @@ class McpHost {
|
|
|
29449
29483
|
writePortFile(fileName, port) {
|
|
29450
29484
|
try {
|
|
29451
29485
|
mkdirSync28(this.portsDir, { recursive: true });
|
|
29452
|
-
const file =
|
|
29486
|
+
const file = join41(this.portsDir, fileName);
|
|
29453
29487
|
const tmp = `${file}.tmp-${process.pid}`;
|
|
29454
29488
|
writeFileSync22(tmp, String(port));
|
|
29455
29489
|
renameSync15(tmp, file);
|
|
@@ -29459,7 +29493,7 @@ class McpHost {
|
|
|
29459
29493
|
}
|
|
29460
29494
|
deletePortFile(fileName) {
|
|
29461
29495
|
try {
|
|
29462
|
-
unlinkSync21(
|
|
29496
|
+
unlinkSync21(join41(this.portsDir, fileName));
|
|
29463
29497
|
} catch {}
|
|
29464
29498
|
}
|
|
29465
29499
|
cleanupRunning(rkey, inst) {
|
|
@@ -29571,7 +29605,7 @@ import {
|
|
|
29571
29605
|
statSync as statSync18,
|
|
29572
29606
|
writeFileSync as writeFileSync23
|
|
29573
29607
|
} from "fs";
|
|
29574
|
-
import { basename as basename10, extname as extname4, join as
|
|
29608
|
+
import { basename as basename10, extname as extname4, join as join42 } from "path";
|
|
29575
29609
|
function safeExtension(filename) {
|
|
29576
29610
|
const extension = extname4(basename10(filename));
|
|
29577
29611
|
return /^\.[A-Za-z0-9]{1,16}$/.test(extension) ? extension.toLowerCase() : "";
|
|
@@ -29589,14 +29623,14 @@ function contentDisposition(filename) {
|
|
|
29589
29623
|
|
|
29590
29624
|
class NodeFileStore {
|
|
29591
29625
|
uploadDir;
|
|
29592
|
-
constructor(uploadDir =
|
|
29626
|
+
constructor(uploadDir = join42(DATA_DIR, "uploads")) {
|
|
29593
29627
|
this.uploadDir = uploadDir;
|
|
29594
29628
|
}
|
|
29595
29629
|
#ensureDir() {
|
|
29596
29630
|
mkdirSync29(this.uploadDir, { recursive: true });
|
|
29597
29631
|
}
|
|
29598
29632
|
#metadataPath(fileId) {
|
|
29599
|
-
return
|
|
29633
|
+
return join42(this.uploadDir, `${fileId}.meta.json`);
|
|
29600
29634
|
}
|
|
29601
29635
|
#metadata(fileId) {
|
|
29602
29636
|
if (!FILE_ID_RE.test(fileId))
|
|
@@ -29625,7 +29659,7 @@ class NodeFileStore {
|
|
|
29625
29659
|
hooks = {
|
|
29626
29660
|
resolveAttachmentByFileId: (fileId) => {
|
|
29627
29661
|
const metadata = this.#metadata(fileId);
|
|
29628
|
-
if (!metadata || !existsSync32(
|
|
29662
|
+
if (!metadata || !existsSync32(join42(this.uploadDir, metadata.savedName)))
|
|
29629
29663
|
return null;
|
|
29630
29664
|
return this.#attachment(fileId, metadata);
|
|
29631
29665
|
},
|
|
@@ -29633,7 +29667,7 @@ class NodeFileStore {
|
|
|
29633
29667
|
const metadata = this.#metadata(fileId);
|
|
29634
29668
|
if (!metadata)
|
|
29635
29669
|
return null;
|
|
29636
|
-
const path =
|
|
29670
|
+
const path = join42(this.uploadDir, metadata.savedName);
|
|
29637
29671
|
return existsSync32(path) ? path : null;
|
|
29638
29672
|
},
|
|
29639
29673
|
storeLocalFileAsUpload: (absPath, access = {}) => this.store(absPath, access),
|
|
@@ -29648,11 +29682,11 @@ class NodeFileStore {
|
|
|
29648
29682
|
const mimeType = file.type || MIME_BY_EXT2[extension] || "application/octet-stream";
|
|
29649
29683
|
const existing = this.#metadata(fileId);
|
|
29650
29684
|
if (existing) {
|
|
29651
|
-
const matches = existing.filename === filename && existing.mimeType === mimeType && existing.sizeBytes === file.size && existing.ownerUserId === access.ownerUserId && existing.topicId === access.topicId && existsSync32(
|
|
29685
|
+
const matches = existing.filename === filename && existing.mimeType === mimeType && existing.sizeBytes === file.size && existing.ownerUserId === access.ownerUserId && existing.topicId === access.topicId && existsSync32(join42(this.uploadDir, existing.savedName));
|
|
29652
29686
|
return matches ? this.#attachment(fileId, existing) : null;
|
|
29653
29687
|
}
|
|
29654
29688
|
const savedName = `${fileId}${extension}`;
|
|
29655
|
-
const savedPath =
|
|
29689
|
+
const savedPath = join42(this.uploadDir, savedName);
|
|
29656
29690
|
try {
|
|
29657
29691
|
const sizeBytes = await Bun.write(savedPath, file);
|
|
29658
29692
|
if (sizeBytes !== file.size)
|
|
@@ -29677,14 +29711,14 @@ class NodeFileStore {
|
|
|
29677
29711
|
}
|
|
29678
29712
|
allows(fileId, access) {
|
|
29679
29713
|
const metadata = this.#metadata(fileId);
|
|
29680
|
-
return Boolean(metadata && metadata.ownerUserId === access.ownerUserId && metadata.topicId === access.topicId && existsSync32(
|
|
29714
|
+
return Boolean(metadata && metadata.ownerUserId === access.ownerUserId && metadata.topicId === access.topicId && existsSync32(join42(this.uploadDir, metadata.savedName)));
|
|
29681
29715
|
}
|
|
29682
29716
|
store(absPath, access = {}) {
|
|
29683
29717
|
this.#ensureDir();
|
|
29684
29718
|
const fileId = randomUUID24();
|
|
29685
29719
|
const extension = safeExtension(absPath);
|
|
29686
29720
|
const savedName = `${fileId}${extension}`;
|
|
29687
|
-
const savedPath =
|
|
29721
|
+
const savedPath = join42(this.uploadDir, savedName);
|
|
29688
29722
|
try {
|
|
29689
29723
|
const stats = statSync18(absPath);
|
|
29690
29724
|
if (!stats.isFile() || stats.size > MAX_NODE_UPLOAD_BYTES)
|
|
@@ -29716,7 +29750,7 @@ class NodeFileStore {
|
|
|
29716
29750
|
const allowed = metadata.visibility === "workspace" || metadata.ownerUserId === userId || Boolean(topic && isParticipant(topic, userId));
|
|
29717
29751
|
if (!allowed)
|
|
29718
29752
|
return null;
|
|
29719
|
-
const path =
|
|
29753
|
+
const path = join42(this.uploadDir, metadata.savedName);
|
|
29720
29754
|
if (!existsSync32(path))
|
|
29721
29755
|
return null;
|
|
29722
29756
|
return new Response(Bun.file(path), {
|
|
@@ -29735,7 +29769,7 @@ class NodeFileStore {
|
|
|
29735
29769
|
const metadata = this.#metadata(fileId);
|
|
29736
29770
|
if (metadata?.topicId !== topicId)
|
|
29737
29771
|
continue;
|
|
29738
|
-
rmSync9(
|
|
29772
|
+
rmSync9(join42(this.uploadDir, metadata.savedName), { force: true });
|
|
29739
29773
|
rmSync9(this.#metadataPath(fileId), { force: true });
|
|
29740
29774
|
}
|
|
29741
29775
|
}
|
|
@@ -33858,8 +33892,8 @@ var init_context_usage = __esm(async () => {
|
|
|
33858
33892
|
// ../../adapters/terminal/src/path-suggest.ts
|
|
33859
33893
|
import { execFile as execFile3 } from "child_process";
|
|
33860
33894
|
import { existsSync as existsSync36, readdirSync as readdirSync14, statSync as statSync19 } from "fs";
|
|
33861
|
-
import { homedir as
|
|
33862
|
-
import { basename as basename11, dirname as dirname21, join as
|
|
33895
|
+
import { homedir as homedir11 } from "os";
|
|
33896
|
+
import { basename as basename11, dirname as dirname21, join as join43, sep as sep3 } from "path";
|
|
33863
33897
|
import { promisify as promisify3 } from "util";
|
|
33864
33898
|
function indexRecursivePaths(files) {
|
|
33865
33899
|
const paths = [];
|
|
@@ -33953,25 +33987,25 @@ function activeAtToken(lineText, col) {
|
|
|
33953
33987
|
return { start: col - frag.length - 1, frag };
|
|
33954
33988
|
}
|
|
33955
33989
|
function resolveFragment(frag) {
|
|
33956
|
-
const home =
|
|
33990
|
+
const home = homedir11();
|
|
33957
33991
|
let path;
|
|
33958
33992
|
if (frag === "" || frag === "~")
|
|
33959
33993
|
path = home;
|
|
33960
33994
|
else if (frag === "~/")
|
|
33961
33995
|
path = home;
|
|
33962
33996
|
else if (frag.startsWith("~/"))
|
|
33963
|
-
path =
|
|
33997
|
+
path = join43(home, frag.slice(2));
|
|
33964
33998
|
else if (frag.startsWith("/"))
|
|
33965
33999
|
path = frag;
|
|
33966
34000
|
else
|
|
33967
|
-
path =
|
|
34001
|
+
path = join43(home, frag);
|
|
33968
34002
|
if (frag.endsWith("/") || frag === "" || frag === "~") {
|
|
33969
34003
|
return { dir: path, prefix: "" };
|
|
33970
34004
|
}
|
|
33971
34005
|
return { dir: dirname21(path), prefix: basename11(path) };
|
|
33972
34006
|
}
|
|
33973
34007
|
function toToken(fullPath, isDir) {
|
|
33974
|
-
const home =
|
|
34008
|
+
const home = homedir11();
|
|
33975
34009
|
let shown = fullPath;
|
|
33976
34010
|
if (fullPath === home)
|
|
33977
34011
|
shown = "~";
|
|
@@ -33993,7 +34027,7 @@ function rankAndSlice(dir, candidates) {
|
|
|
33993
34027
|
});
|
|
33994
34028
|
return candidates.slice(0, MAX_SUGGESTIONS).map(({ relPath, isDir }) => ({
|
|
33995
34029
|
label: `${relPath}${isDir ? "/" : ""}`,
|
|
33996
|
-
value: toToken(
|
|
34030
|
+
value: toToken(join43(dir, relPath), isDir),
|
|
33997
34031
|
isDir
|
|
33998
34032
|
}));
|
|
33999
34033
|
}
|
|
@@ -34072,7 +34106,7 @@ function pathSuggestions(lineText, col) {
|
|
|
34072
34106
|
let isDir = entry.isDirectory();
|
|
34073
34107
|
if (!isDir && entry.isSymbolicLink()) {
|
|
34074
34108
|
try {
|
|
34075
|
-
isDir = statSync19(
|
|
34109
|
+
isDir = statSync19(join43(dir, entry.name)).isDirectory();
|
|
34076
34110
|
} catch {}
|
|
34077
34111
|
}
|
|
34078
34112
|
return {
|
|
@@ -34095,14 +34129,14 @@ function pathSuggestions(lineText, col) {
|
|
|
34095
34129
|
};
|
|
34096
34130
|
}
|
|
34097
34131
|
function fragmentToAbsolutePath(frag) {
|
|
34098
|
-
const home =
|
|
34132
|
+
const home = homedir11();
|
|
34099
34133
|
if (frag === "~" || frag === "~/")
|
|
34100
34134
|
return home;
|
|
34101
34135
|
if (frag.startsWith("~/"))
|
|
34102
|
-
return
|
|
34136
|
+
return join43(home, frag.slice(2));
|
|
34103
34137
|
if (frag.startsWith("/"))
|
|
34104
34138
|
return frag;
|
|
34105
|
-
return
|
|
34139
|
+
return join43(home, frag);
|
|
34106
34140
|
}
|
|
34107
34141
|
function fragmentResolves(frag) {
|
|
34108
34142
|
try {
|
|
@@ -40608,7 +40642,7 @@ var init_commands2 = __esm(async () => {
|
|
|
40608
40642
|
// ../../adapters/telegram/src/mapping-store.ts
|
|
40609
40643
|
import { Database as Database2 } from "bun:sqlite";
|
|
40610
40644
|
import { mkdirSync as mkdirSync32 } from "fs";
|
|
40611
|
-
import { dirname as dirname22, join as
|
|
40645
|
+
import { dirname as dirname22, join as join44 } from "path";
|
|
40612
40646
|
function outboxRowToEntry(row) {
|
|
40613
40647
|
return {
|
|
40614
40648
|
id: row.id,
|
|
@@ -40674,7 +40708,7 @@ function migrateOutboxSchema(db4) {
|
|
|
40674
40708
|
db4.run("CREATE INDEX IF NOT EXISTS idx_telegram_outbox_runtime_message ON outbox(runtime_message_id)");
|
|
40675
40709
|
}
|
|
40676
40710
|
function openMappingStore(path) {
|
|
40677
|
-
const dbPath = path ??
|
|
40711
|
+
const dbPath = path ?? join44(DATA_DIR, "adapter-telegram.db");
|
|
40678
40712
|
if (dbPath !== ":memory:")
|
|
40679
40713
|
mkdirSync32(dirname22(dbPath), { recursive: true });
|
|
40680
40714
|
const db4 = new Database2(dbPath);
|
|
@@ -42574,9 +42608,9 @@ function firstCell() {
|
|
|
42574
42608
|
return cell;
|
|
42575
42609
|
return null;
|
|
42576
42610
|
}
|
|
42577
|
-
function attachOtiumCentralCell(
|
|
42578
|
-
cells.set(
|
|
42579
|
-
join:
|
|
42611
|
+
function attachOtiumCentralCell(join45) {
|
|
42612
|
+
cells.set(join45.cellId, {
|
|
42613
|
+
join: join45,
|
|
42580
42614
|
nodesCache: null,
|
|
42581
42615
|
verifyCache: new Map,
|
|
42582
42616
|
tokenCache: new Map
|
|
@@ -42588,10 +42622,10 @@ function detachOtiumCentralCell(cellId) {
|
|
|
42588
42622
|
function attachedOtiumCells() {
|
|
42589
42623
|
return [...cells.values()].map((cell) => cell.join);
|
|
42590
42624
|
}
|
|
42591
|
-
function configureOtiumCentral(
|
|
42625
|
+
function configureOtiumCentral(join45) {
|
|
42592
42626
|
cells.clear();
|
|
42593
|
-
if (
|
|
42594
|
-
attachOtiumCentralCell(
|
|
42627
|
+
if (join45)
|
|
42628
|
+
attachOtiumCentralCell(join45);
|
|
42595
42629
|
}
|
|
42596
42630
|
function isOtiumCentralConfigured() {
|
|
42597
42631
|
return cells.size > 0;
|
|
@@ -43155,17 +43189,17 @@ function withJoinCredentialLock(operation) {
|
|
|
43155
43189
|
function joinsEqual(left, right) {
|
|
43156
43190
|
return left.central === right.central && left.relay === right.relay && left.cellId === right.cellId && left.secret === right.secret;
|
|
43157
43191
|
}
|
|
43158
|
-
function normalizedJoin(
|
|
43192
|
+
function normalizedJoin(join45) {
|
|
43159
43193
|
return normalizeJoin({
|
|
43160
|
-
v:
|
|
43161
|
-
central:
|
|
43162
|
-
relay:
|
|
43163
|
-
cellId:
|
|
43164
|
-
secret:
|
|
43194
|
+
v: join45.v,
|
|
43195
|
+
central: join45.central,
|
|
43196
|
+
relay: join45.relay,
|
|
43197
|
+
cellId: join45.cellId,
|
|
43198
|
+
secret: join45.secret
|
|
43165
43199
|
});
|
|
43166
43200
|
}
|
|
43167
|
-
function joinCredentialDigest(
|
|
43168
|
-
return createHash11("sha256").update(JSON.stringify(normalizedJoin(
|
|
43201
|
+
function joinCredentialDigest(join45) {
|
|
43202
|
+
return createHash11("sha256").update(JSON.stringify(normalizedJoin(join45))).digest("base64url");
|
|
43169
43203
|
}
|
|
43170
43204
|
function readPersistedJoins(path = joinFilePath()) {
|
|
43171
43205
|
if (!existsSync39(path))
|
|
@@ -43184,9 +43218,9 @@ function readPersistedJoins(path = joinFilePath()) {
|
|
|
43184
43218
|
return normalizeJoin(entry);
|
|
43185
43219
|
});
|
|
43186
43220
|
}
|
|
43187
|
-
function isJoinPersisted(
|
|
43221
|
+
function isJoinPersisted(join45) {
|
|
43188
43222
|
try {
|
|
43189
|
-
const normalized = normalizedJoin(
|
|
43223
|
+
const normalized = normalizedJoin(join45);
|
|
43190
43224
|
return readPersistedJoins().some((persisted) => joinsEqual(persisted, normalized));
|
|
43191
43225
|
} catch {
|
|
43192
43226
|
return false;
|
|
@@ -43230,10 +43264,10 @@ function writeJoins(joins, allowOverwrite) {
|
|
|
43230
43264
|
}
|
|
43231
43265
|
return path;
|
|
43232
43266
|
}
|
|
43233
|
-
function saveJoinWhileLocked(
|
|
43267
|
+
function saveJoinWhileLocked(join45, options = {}) {
|
|
43234
43268
|
const path = joinFilePath();
|
|
43235
43269
|
const directory = dirname23(path);
|
|
43236
|
-
const normalized = normalizedJoin(
|
|
43270
|
+
const normalized = normalizedJoin(join45);
|
|
43237
43271
|
mkdirSync33(directory, { recursive: true });
|
|
43238
43272
|
if (!existsSync39(path))
|
|
43239
43273
|
return writeJoins([normalized], false);
|
|
@@ -43263,8 +43297,8 @@ function saveJoinWhileLocked(join44, options = {}) {
|
|
|
43263
43297
|
const next = conflict ? existing.map((persisted) => persisted.cellId === normalized.cellId ? normalized : persisted) : [...existing, normalized];
|
|
43264
43298
|
return writeJoins(next, true);
|
|
43265
43299
|
}
|
|
43266
|
-
function saveJoin(
|
|
43267
|
-
return withJoinCredentialLock(() => saveJoinWhileLocked(
|
|
43300
|
+
function saveJoin(join45, options = {}) {
|
|
43301
|
+
return withJoinCredentialLock(() => saveJoinWhileLocked(join45, options));
|
|
43268
43302
|
}
|
|
43269
43303
|
function removeJoin(cellId) {
|
|
43270
43304
|
return withJoinCredentialLock(() => {
|
|
@@ -43277,7 +43311,7 @@ function removeJoin(cellId) {
|
|
|
43277
43311
|
if (cellId) {
|
|
43278
43312
|
let remaining;
|
|
43279
43313
|
try {
|
|
43280
|
-
remaining = readPersistedJoins(path).filter((
|
|
43314
|
+
remaining = readPersistedJoins(path).filter((join45) => join45.cellId !== cellId);
|
|
43281
43315
|
} catch {
|
|
43282
43316
|
return false;
|
|
43283
43317
|
}
|
|
@@ -43330,7 +43364,7 @@ var init_join = __esm(async () => {
|
|
|
43330
43364
|
// ../../adapters/otium/src/peer-files.ts
|
|
43331
43365
|
import { randomUUID as randomUUID29 } from "crypto";
|
|
43332
43366
|
import { copyFileSync as copyFileSync5, mkdirSync as mkdirSync34, rmSync as rmSync11, statSync as statSync21 } from "fs";
|
|
43333
|
-
import { basename as basename13, extname as extname6, join as
|
|
43367
|
+
import { basename as basename13, extname as extname6, join as join45 } from "path";
|
|
43334
43368
|
function fileType(mimeType) {
|
|
43335
43369
|
if (mimeType.startsWith("image/"))
|
|
43336
43370
|
return "image";
|
|
@@ -43396,7 +43430,7 @@ function recordFile(args) {
|
|
|
43396
43430
|
function insertLocalFile(args) {
|
|
43397
43431
|
const id = randomUUID29();
|
|
43398
43432
|
mkdirSync34(PEER_FILES_DIR, { recursive: true });
|
|
43399
|
-
const path =
|
|
43433
|
+
const path = join45(PEER_FILES_DIR, `${id}-${safeFilename(args.filename)}`);
|
|
43400
43434
|
copyFileSync5(args.sourcePath, path);
|
|
43401
43435
|
return recordFile({ id, path, sizeBytes: statSync21(path).size, ...args });
|
|
43402
43436
|
}
|
|
@@ -43442,7 +43476,7 @@ function installPeerFileHooks() {
|
|
|
43442
43476
|
var PEER_FILES_DIR;
|
|
43443
43477
|
var init_peer_files = __esm(async () => {
|
|
43444
43478
|
await init_src();
|
|
43445
|
-
PEER_FILES_DIR =
|
|
43479
|
+
PEER_FILES_DIR = join45(DATA_DIR, "otium-peer-files");
|
|
43446
43480
|
db.exec(`
|
|
43447
43481
|
CREATE TABLE IF NOT EXISTS otium_peer_files (
|
|
43448
43482
|
id TEXT PRIMARY KEY,
|
|
@@ -43854,19 +43888,19 @@ function readCache() {
|
|
|
43854
43888
|
return {};
|
|
43855
43889
|
}
|
|
43856
43890
|
}
|
|
43857
|
-
function cachedSurfaceScope(
|
|
43858
|
-
const record = readCache()[
|
|
43859
|
-
if (!record || record.central !==
|
|
43891
|
+
function cachedSurfaceScope(join46) {
|
|
43892
|
+
const record = readCache()[join46.cellId];
|
|
43893
|
+
if (!record || record.central !== join46.central || !record.workspaceId)
|
|
43860
43894
|
return null;
|
|
43861
43895
|
return surfaceScopeFor(record.central, record.workspaceId);
|
|
43862
43896
|
}
|
|
43863
|
-
function cacheSurfaceScope(
|
|
43864
|
-
const scope = surfaceScopeFor(
|
|
43897
|
+
function cacheSurfaceScope(join46, workspaceId) {
|
|
43898
|
+
const scope = surfaceScopeFor(join46.central, workspaceId);
|
|
43865
43899
|
const path = scopeCachePath();
|
|
43866
43900
|
try {
|
|
43867
43901
|
mkdirSync35(dirname24(path), { recursive: true });
|
|
43868
43902
|
const cache = readCache();
|
|
43869
|
-
cache[
|
|
43903
|
+
cache[join46.cellId] = { central: join46.central, workspaceId, scope };
|
|
43870
43904
|
writeFileSync26(path, `${JSON.stringify(cache, null, 2)}
|
|
43871
43905
|
`, { mode: 384 });
|
|
43872
43906
|
} catch (err2) {
|
|
@@ -43874,23 +43908,23 @@ function cacheSurfaceScope(join45, workspaceId) {
|
|
|
43874
43908
|
}
|
|
43875
43909
|
return scope;
|
|
43876
43910
|
}
|
|
43877
|
-
async function resolveSurfaceScope(
|
|
43878
|
-
const cached = cachedSurfaceScope(
|
|
43911
|
+
async function resolveSurfaceScope(join46) {
|
|
43912
|
+
const cached = cachedSurfaceScope(join46);
|
|
43879
43913
|
if (cached)
|
|
43880
43914
|
return cached;
|
|
43881
43915
|
try {
|
|
43882
|
-
const workspaceId = await peerWorkspaceIdForCell(
|
|
43916
|
+
const workspaceId = await peerWorkspaceIdForCell(join46.cellId);
|
|
43883
43917
|
if (!workspaceId)
|
|
43884
43918
|
return null;
|
|
43885
|
-
return cacheSurfaceScope(
|
|
43919
|
+
return cacheSurfaceScope(join46, workspaceId);
|
|
43886
43920
|
} catch (err2) {
|
|
43887
43921
|
logger.warn({ err: err2 }, "otium: workspace scope unresolved (will retry on the next contact)");
|
|
43888
43922
|
return null;
|
|
43889
43923
|
}
|
|
43890
43924
|
}
|
|
43891
43925
|
function surfaceScopeForCell(cellId) {
|
|
43892
|
-
const
|
|
43893
|
-
return
|
|
43926
|
+
const join46 = attachedOtiumCells().find((candidate) => candidate.cellId === cellId);
|
|
43927
|
+
return join46 ? cachedSurfaceScope(join46) : null;
|
|
43894
43928
|
}
|
|
43895
43929
|
function unscopedRoomsAddressable() {
|
|
43896
43930
|
return attachedOtiumCells().length < 2;
|
|
@@ -45023,13 +45057,13 @@ function replacePendingEnrollment(pending2) {
|
|
|
45023
45057
|
throw error2;
|
|
45024
45058
|
}
|
|
45025
45059
|
}
|
|
45026
|
-
function recordClaimedCredential(pending2,
|
|
45060
|
+
function recordClaimedCredential(pending2, join46) {
|
|
45027
45061
|
withJoinCredentialLock(() => {
|
|
45028
45062
|
const current3 = JSON.parse(readFileSync31(pendingEnrollmentPath(), "utf8"));
|
|
45029
45063
|
if (current3.central !== pending2.central || current3.token !== pending2.token || current3.idempotencyKey !== pending2.idempotencyKey || current3.publicKey !== pending2.publicKey) {
|
|
45030
45064
|
throw new Error("pending Otium enrollment changed while its claim was in flight");
|
|
45031
45065
|
}
|
|
45032
|
-
const claimed = { digest: joinCredentialDigest(
|
|
45066
|
+
const claimed = { digest: joinCredentialDigest(join46), cellId: join46.cellId };
|
|
45033
45067
|
if (current3.claimed && (current3.claimed.digest !== claimed.digest || current3.claimed.cellId !== claimed.cellId)) {
|
|
45034
45068
|
throw new Error("central returned different credentials for an idempotent enrollment claim");
|
|
45035
45069
|
}
|
|
@@ -45087,30 +45121,30 @@ async function claimEnrollment(invite, nodeName) {
|
|
|
45087
45121
|
const secret = openCredential(credential, pending2.privateKey);
|
|
45088
45122
|
if (!secret.startsWith("rcs_"))
|
|
45089
45123
|
throw new Error("central returned an invalid runtime credential");
|
|
45090
|
-
const
|
|
45124
|
+
const join46 = {
|
|
45091
45125
|
v: 2,
|
|
45092
45126
|
central: invite.central,
|
|
45093
45127
|
relay: String(response.relayUrl),
|
|
45094
45128
|
cellId: String(response.cell?.id),
|
|
45095
45129
|
secret
|
|
45096
45130
|
};
|
|
45097
|
-
if (!
|
|
45131
|
+
if (!join46.relay || !join46.cellId || join46.cellId === "undefined") {
|
|
45098
45132
|
throw new Error("central returned an incomplete enrollment response");
|
|
45099
45133
|
}
|
|
45100
|
-
assertSecureRelayUrl(
|
|
45101
|
-
recordClaimedCredential(pending2,
|
|
45102
|
-
return
|
|
45134
|
+
assertSecureRelayUrl(join46.relay);
|
|
45135
|
+
recordClaimedCredential(pending2, join46);
|
|
45136
|
+
return join46;
|
|
45103
45137
|
}
|
|
45104
|
-
function commitEnrollment(
|
|
45138
|
+
function commitEnrollment(join46, options = {}) {
|
|
45105
45139
|
return withJoinCredentialLock(() => {
|
|
45106
45140
|
const pendingPath = pendingEnrollmentPath();
|
|
45107
45141
|
const pending2 = existsSync40(pendingPath) ? JSON.parse(readFileSync31(pendingPath, "utf8")) : null;
|
|
45108
|
-
const digest = joinCredentialDigest(
|
|
45109
|
-
if (pending2 && (!pending2.claimed || pending2.claimed.digest !== digest || pending2.claimed.cellId !==
|
|
45142
|
+
const digest = joinCredentialDigest(join46);
|
|
45143
|
+
if (pending2 && (!pending2.claimed || pending2.claimed.digest !== digest || pending2.claimed.cellId !== join46.cellId)) {
|
|
45110
45144
|
throw new Error(`pending Otium enrollment at ${pendingPath} does not match these credentials`);
|
|
45111
45145
|
}
|
|
45112
|
-
const path = saveJoinWhileLocked(
|
|
45113
|
-
if (!isJoinPersisted(
|
|
45146
|
+
const path = saveJoinWhileLocked(join46, options);
|
|
45147
|
+
if (!isJoinPersisted(join46)) {
|
|
45114
45148
|
throw new Error("Otium join credentials were not durably persisted");
|
|
45115
45149
|
}
|
|
45116
45150
|
if (!pending2)
|
|
@@ -45704,24 +45738,24 @@ function refreshDefaultSurfaceScope() {
|
|
|
45704
45738
|
setSurfaceScopeRequired(scopes.length > 1);
|
|
45705
45739
|
}
|
|
45706
45740
|
function startOtiumNodeRuntime(options) {
|
|
45707
|
-
const { join:
|
|
45708
|
-
attachOtiumCentralCell(
|
|
45741
|
+
const { join: join46 } = options;
|
|
45742
|
+
attachOtiumCentralCell(join46);
|
|
45709
45743
|
const releaseGlobals = acquireGlobalOtiumServices();
|
|
45710
45744
|
let stopped = false;
|
|
45711
|
-
logger.info({ central:
|
|
45712
|
-
mountedScopes.set(
|
|
45745
|
+
logger.info({ central: join46.central, cellId: join46.cellId }, "otium: worker mode enabled");
|
|
45746
|
+
mountedScopes.set(join46.cellId, cachedSurfaceScope(join46));
|
|
45713
45747
|
refreshDefaultSurfaceScope();
|
|
45714
|
-
selfPeerNodeForCell(
|
|
45748
|
+
selfPeerNodeForCell(join46.cellId).then((self) => {
|
|
45715
45749
|
if (self) {
|
|
45716
45750
|
logger.info({ nodeName: self.nodeName, baseUrl: self.baseUrl }, "otium: attached to workspace");
|
|
45717
45751
|
}
|
|
45718
45752
|
}).catch((err2) => {
|
|
45719
45753
|
logger.warn({ err: err2 }, "otium: self check against central failed (will retry per request)");
|
|
45720
45754
|
});
|
|
45721
|
-
resolveSurfaceScope(
|
|
45755
|
+
resolveSurfaceScope(join46).then((scope) => {
|
|
45722
45756
|
if (!scope || stopped)
|
|
45723
45757
|
return;
|
|
45724
|
-
mountedScopes.set(
|
|
45758
|
+
mountedScopes.set(join46.cellId, scope);
|
|
45725
45759
|
refreshDefaultSurfaceScope();
|
|
45726
45760
|
if (mountedScopes.size === 1)
|
|
45727
45761
|
stampUnscopedOtiumTopics(scope);
|
|
@@ -45730,14 +45764,14 @@ function startOtiumNodeRuntime(options) {
|
|
|
45730
45764
|
});
|
|
45731
45765
|
return {
|
|
45732
45766
|
name: "otium",
|
|
45733
|
-
join:
|
|
45767
|
+
join: join46,
|
|
45734
45768
|
stop: () => {
|
|
45735
45769
|
if (stopped)
|
|
45736
45770
|
return;
|
|
45737
45771
|
stopped = true;
|
|
45738
|
-
mountedScopes.delete(
|
|
45772
|
+
mountedScopes.delete(join46.cellId);
|
|
45739
45773
|
refreshDefaultSurfaceScope();
|
|
45740
|
-
detachOtiumCentralCell(
|
|
45774
|
+
detachOtiumCentralCell(join46.cellId);
|
|
45741
45775
|
releaseGlobals();
|
|
45742
45776
|
}
|
|
45743
45777
|
};
|
|
@@ -45832,14 +45866,14 @@ __export(exports_node_runtime, {
|
|
|
45832
45866
|
function sameCredentials(left, right) {
|
|
45833
45867
|
return left.central === right.central && left.relay === right.relay && left.secret === right.secret;
|
|
45834
45868
|
}
|
|
45835
|
-
function attachOtiumWorkspace(
|
|
45836
|
-
const current3 = mounted.get(
|
|
45869
|
+
function attachOtiumWorkspace(join46) {
|
|
45870
|
+
const current3 = mounted.get(join46.cellId);
|
|
45837
45871
|
if (current3) {
|
|
45838
|
-
if (sameCredentials(current3.join,
|
|
45872
|
+
if (sameCredentials(current3.join, join46))
|
|
45839
45873
|
return false;
|
|
45840
|
-
detachOtiumWorkspace(
|
|
45874
|
+
detachOtiumWorkspace(join46.cellId);
|
|
45841
45875
|
}
|
|
45842
|
-
mounted.set(
|
|
45876
|
+
mounted.set(join46.cellId, startOtiumNodeRuntime({ join: join46 }));
|
|
45843
45877
|
return true;
|
|
45844
45878
|
}
|
|
45845
45879
|
function detachOtiumWorkspace(cellId) {
|
|
@@ -45854,7 +45888,7 @@ function mountedOtiumWorkspaces() {
|
|
|
45854
45888
|
return [...mounted.values()].map((runtime2) => runtime2.join);
|
|
45855
45889
|
}
|
|
45856
45890
|
function reconcileOtiumWorkspaces(joins = loadJoins()) {
|
|
45857
|
-
const wanted = new Map(joins.map((
|
|
45891
|
+
const wanted = new Map(joins.map((join46) => [join46.cellId, join46]));
|
|
45858
45892
|
const detached = [];
|
|
45859
45893
|
for (const cellId of [...mounted.keys()]) {
|
|
45860
45894
|
if (wanted.has(cellId))
|
|
@@ -45863,8 +45897,8 @@ function reconcileOtiumWorkspaces(joins = loadJoins()) {
|
|
|
45863
45897
|
detached.push(cellId);
|
|
45864
45898
|
}
|
|
45865
45899
|
const attached = [];
|
|
45866
|
-
for (const [cellId,
|
|
45867
|
-
if (attachOtiumWorkspace(
|
|
45900
|
+
for (const [cellId, join46] of wanted) {
|
|
45901
|
+
if (attachOtiumWorkspace(join46))
|
|
45868
45902
|
attached.push(cellId);
|
|
45869
45903
|
}
|
|
45870
45904
|
if (attached.length > 0 || detached.length > 0) {
|
|
@@ -45887,9 +45921,9 @@ async function handleOtiumAdapterControlRequest(req) {
|
|
|
45887
45921
|
if (req.method === "GET") {
|
|
45888
45922
|
return Response.json({
|
|
45889
45923
|
ok: true,
|
|
45890
|
-
workspaces: mountedOtiumWorkspaces().map((
|
|
45891
|
-
cellId:
|
|
45892
|
-
central:
|
|
45924
|
+
workspaces: mountedOtiumWorkspaces().map((join46) => ({
|
|
45925
|
+
cellId: join46.cellId,
|
|
45926
|
+
central: join46.central
|
|
45893
45927
|
}))
|
|
45894
45928
|
});
|
|
45895
45929
|
}
|
|
@@ -45910,8 +45944,8 @@ function mountConfiguredOtiumNodeRuntime() {
|
|
|
45910
45944
|
const joins = loadJoins();
|
|
45911
45945
|
if (joins.length === 0)
|
|
45912
45946
|
return null;
|
|
45913
|
-
for (const
|
|
45914
|
-
attachOtiumWorkspace(
|
|
45947
|
+
for (const join46 of joins)
|
|
45948
|
+
attachOtiumWorkspace(join46);
|
|
45915
45949
|
registerNodeRequestHandler("otium-adapter-control", handleOtiumAdapterControlRequest);
|
|
45916
45950
|
let stopped = false;
|
|
45917
45951
|
return {
|
|
@@ -46023,11 +46057,11 @@ async function joinCommand(args) {
|
|
|
46023
46057
|
process.exitCode = 1;
|
|
46024
46058
|
return;
|
|
46025
46059
|
}
|
|
46026
|
-
let
|
|
46060
|
+
let join46;
|
|
46027
46061
|
let productionEnrollment = false;
|
|
46028
46062
|
if (args.includes("--legacy")) {
|
|
46029
46063
|
try {
|
|
46030
|
-
|
|
46064
|
+
join46 = parseInviteCode(code);
|
|
46031
46065
|
} catch (err2) {
|
|
46032
46066
|
console.error(`invalid legacy invite code: ${err2 instanceof Error ? err2.message : err2}`);
|
|
46033
46067
|
process.exitCode = 1;
|
|
@@ -46053,7 +46087,7 @@ async function joinCommand(args) {
|
|
|
46053
46087
|
return;
|
|
46054
46088
|
}
|
|
46055
46089
|
}
|
|
46056
|
-
|
|
46090
|
+
join46 = await claimEnrollment(invite, nodeName);
|
|
46057
46091
|
productionEnrollment = true;
|
|
46058
46092
|
} catch (err2) {
|
|
46059
46093
|
console.error(`enrollment failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
@@ -46064,16 +46098,16 @@ async function joinCommand(args) {
|
|
|
46064
46098
|
let path;
|
|
46065
46099
|
try {
|
|
46066
46100
|
const saveOptions = { replaceExisting: args.includes("--replace") };
|
|
46067
|
-
path = productionEnrollment ? commitEnrollment(
|
|
46101
|
+
path = productionEnrollment ? commitEnrollment(join46, saveOptions) : saveJoin(join46, saveOptions);
|
|
46068
46102
|
} catch (err2) {
|
|
46069
46103
|
console.error(`could not save join credentials: ${err2 instanceof Error ? err2.message : err2}`);
|
|
46070
46104
|
process.exitCode = 1;
|
|
46071
46105
|
return;
|
|
46072
46106
|
}
|
|
46073
46107
|
console.log(`otium join credentials saved to ${path}`);
|
|
46074
|
-
console.log(` central: ${
|
|
46075
|
-
console.log(` cellId: ${
|
|
46076
|
-
configureOtiumCentral(
|
|
46108
|
+
console.log(` central: ${join46.central}`);
|
|
46109
|
+
console.log(` cellId: ${join46.cellId}`);
|
|
46110
|
+
configureOtiumCentral(join46);
|
|
46077
46111
|
try {
|
|
46078
46112
|
const self = await selfPeerNode();
|
|
46079
46113
|
if (self) {
|
|
@@ -46115,19 +46149,19 @@ async function statusCommand() {
|
|
|
46115
46149
|
return;
|
|
46116
46150
|
}
|
|
46117
46151
|
configureOtiumCentral(joins[0] ?? null);
|
|
46118
|
-
for (const
|
|
46119
|
-
attachOtiumCentralCell(
|
|
46120
|
-
for (const [index,
|
|
46152
|
+
for (const join46 of joins.slice(1))
|
|
46153
|
+
attachOtiumCentralCell(join46);
|
|
46154
|
+
for (const [index, join46] of joins.entries()) {
|
|
46121
46155
|
if (index > 0)
|
|
46122
46156
|
console.log("");
|
|
46123
|
-
console.log(`cellId: ${
|
|
46124
|
-
console.log(`central: ${
|
|
46125
|
-
if (
|
|
46126
|
-
console.log(`relay: ${
|
|
46157
|
+
console.log(`cellId: ${join46.cellId}`);
|
|
46158
|
+
console.log(`central: ${join46.central}`);
|
|
46159
|
+
if (join46.relay)
|
|
46160
|
+
console.log(`relay: ${join46.relay}`);
|
|
46127
46161
|
try {
|
|
46128
|
-
const self = await selfPeerNodeForCell(
|
|
46162
|
+
const self = await selfPeerNodeForCell(join46.cellId);
|
|
46129
46163
|
if (self) {
|
|
46130
|
-
console.log(`node: ${self.nodeName ??
|
|
46164
|
+
console.log(`node: ${self.nodeName ?? join46.cellId}${self.isPrimary ? " (primary)" : ""}`);
|
|
46131
46165
|
console.log(`baseUrl: ${self.baseUrl}`);
|
|
46132
46166
|
} else {
|
|
46133
46167
|
console.warn(" warning: central answered but this cell has no visible assignment yet \u2014 check the workspace assignment");
|
|
@@ -46163,13 +46197,13 @@ function resolveTunnelTargets(joins, relayOverride) {
|
|
|
46163
46197
|
const targets = [];
|
|
46164
46198
|
const skippedNoRelay = [];
|
|
46165
46199
|
const envRelay = process.env.OTIUM_RELAY_URL?.trim();
|
|
46166
|
-
for (const
|
|
46167
|
-
const relayUrl = relayOverride?.trim() ||
|
|
46200
|
+
for (const join46 of joins) {
|
|
46201
|
+
const relayUrl = relayOverride?.trim() || join46.relay || envRelay;
|
|
46168
46202
|
if (!relayUrl) {
|
|
46169
|
-
skippedNoRelay.push(
|
|
46203
|
+
skippedNoRelay.push(join46.cellId);
|
|
46170
46204
|
continue;
|
|
46171
46205
|
}
|
|
46172
|
-
targets.push({ cellId:
|
|
46206
|
+
targets.push({ cellId: join46.cellId, relayUrl, secret: join46.secret });
|
|
46173
46207
|
}
|
|
46174
46208
|
return { targets, skippedNoRelay };
|
|
46175
46209
|
}
|
|
@@ -46406,9 +46440,9 @@ async function runOtiumCli(args = process.argv.slice(2)) {
|
|
|
46406
46440
|
if (joins.length === 0)
|
|
46407
46441
|
throw new Error("not joined to an Otium workspace");
|
|
46408
46442
|
if (!targetCellId && joins.length > 1) {
|
|
46409
|
-
throw new Error(`this node is joined to ${joins.length} workspaces; name one to leave: ${joins.map((
|
|
46443
|
+
throw new Error(`this node is joined to ${joins.length} workspaces; name one to leave: ${joins.map((join46) => join46.cellId).join(", ")}`);
|
|
46410
46444
|
}
|
|
46411
|
-
if (targetCellId && !joins.some((
|
|
46445
|
+
if (targetCellId && !joins.some((join46) => join46.cellId === targetCellId)) {
|
|
46412
46446
|
throw new Error(`not joined as ${targetCellId}`);
|
|
46413
46447
|
}
|
|
46414
46448
|
removeJoin2(targetCellId);
|
|
@@ -47195,4 +47229,4 @@ switch (command) {
|
|
|
47195
47229
|
}
|
|
47196
47230
|
}
|
|
47197
47231
|
|
|
47198
|
-
//# debugId=
|
|
47232
|
+
//# debugId=805E32726887103964756E2164756E21
|