negotium 0.1.49 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agent-helpers.js +58 -74
- package/dist/agent-helpers.js.map +15 -15
- package/dist/background-bash.js +22 -10
- package/dist/background-bash.js.map +3 -3
- package/dist/browser-runtime.js +35 -68
- package/dist/browser-runtime.js.map +7 -7
- package/dist/{chunk-5rpw9d1f.js → chunk-kc5kmr95.js} +28 -11
- package/dist/{chunk-5rpw9d1f.js.map → chunk-kc5kmr95.js.map} +4 -4
- package/dist/hosted-agent.js +36 -18
- package/dist/hosted-agent.js.map +7 -7
- package/dist/main.js +562 -98
- package/dist/main.js.map +21 -19
- package/dist/mcp-factories.js +62 -78
- package/dist/mcp-factories.js.map +16 -16
- package/dist/prompts.js +22 -10
- package/dist/prompts.js.map +3 -3
- package/dist/query-runtime.js +22 -10
- package/dist/query-runtime.js.map +4 -4
- package/dist/registry.js +5 -12
- package/dist/registry.js.map +5 -5
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/agents/maestro-registry.ts +1 -1
- package/dist/runtime/src/agents/rollout/shared.ts +12 -4
- package/dist/runtime/src/mcp/mcp-helpers.ts +1 -1
- package/dist/runtime/src/mcp/wiki-server.ts +1 -1
- package/dist/runtime/src/migration/single-user.ts +621 -0
- package/dist/runtime/src/platform/config.ts +24 -11
- package/dist/runtime/src/platform/mcp-config.ts +4 -4
- package/dist/runtime/src/platform/playwright/manager.ts +10 -28
- package/dist/runtime/src/runtime/attachments.ts +3 -3
- package/dist/runtime/src/storage/browser-profiles.ts +11 -9
- package/dist/runtime/src/storage/conversations.ts +5 -18
- package/dist/runtime/src/storage/storage-host.ts +1 -1
- package/dist/runtime/src/storage/tasks.ts +2 -14
- package/dist/runtime/src/storage/vault.ts +3 -2
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +22 -10
- package/dist/runtime-helpers.js.map +5 -5
- package/dist/storage.js +5 -19
- package/dist/storage.js.map +5 -5
- package/dist/types/packages/core/src/mcp/mcp-helpers.d.ts +1 -1
- package/dist/types/packages/core/src/platform/config.d.ts +9 -1
- package/dist/types/packages/core/src/runtime/attachments.d.ts +1 -1
- package/dist/types/packages/core/src/storage/conversations.d.ts +2 -2
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +25 -12
- package/dist/vault.js.map +4 -4
- package/install-browser-rs.mjs +1 -1
- package/package.json +2 -2
package/dist/main.js
CHANGED
|
@@ -168,7 +168,7 @@ function resolveBrowserRsBin(envValue) {
|
|
|
168
168
|
if (!override && !versionAtLeast(BROWSER_RS_VERSION.replace(/^v/, ""), BROWSER_RS_MIN_SECURE_VERSION)) {
|
|
169
169
|
return;
|
|
170
170
|
}
|
|
171
|
-
const candidate = override ? resolve(override) : resolve(
|
|
171
|
+
const candidate = override ? resolve(override) : resolve(BINARIES_DIR, "browser-rs", BROWSER_RS_VERSION, "browser-rs");
|
|
172
172
|
try {
|
|
173
173
|
accessSync(candidate, constants.X_OK);
|
|
174
174
|
return browserRsMeetsMinimumVersion(candidate) ? candidate : undefined;
|
|
@@ -180,7 +180,7 @@ function resolveBrowserMcpBin(envValue) {
|
|
|
180
180
|
const override = envValue?.trim();
|
|
181
181
|
if (override)
|
|
182
182
|
return resolve(override);
|
|
183
|
-
return BROWSER_RS_BIN ?? resolve(
|
|
183
|
+
return BROWSER_RS_BIN ?? resolve(BINARIES_DIR, "browser-rs", BROWSER_RS_VERSION, "browser-rs");
|
|
184
184
|
}
|
|
185
185
|
function resolveBrowserProxy() {
|
|
186
186
|
const raw = envText("BROWSER_PROXY_URL");
|
|
@@ -212,7 +212,7 @@ function resolveTopicWorkspaceDir(topicId) {
|
|
|
212
212
|
}
|
|
213
213
|
function loadOrCreateLocalSecret(envKey, filename, options = {}) {
|
|
214
214
|
const envValue = envText(envKey);
|
|
215
|
-
const secretFile = resolve(
|
|
215
|
+
const secretFile = resolve(SECRETS_DIR, filename);
|
|
216
216
|
mkdirSync(dirname(secretFile), { recursive: true });
|
|
217
217
|
if (envValue) {
|
|
218
218
|
if (options.persistEnvValue) {
|
|
@@ -253,7 +253,7 @@ function resolveDefaultModel(agent, registryDefaultModel) {
|
|
|
253
253
|
function codexAuthFilePath() {
|
|
254
254
|
return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(homedir(), ".codex", "auth.json");
|
|
255
255
|
}
|
|
256
|
-
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR,
|
|
256
|
+
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, CONTEXTS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.16", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", BROWSER_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, BACKGROUND_BASH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
|
|
257
257
|
var init_config = __esm(() => {
|
|
258
258
|
init_config_helpers();
|
|
259
259
|
init_logger();
|
|
@@ -265,10 +265,14 @@ var init_config = __esm(() => {
|
|
|
265
265
|
WORKSPACE_DIR = resolveLocalStateDir("NEGOTIUM_WORKSPACE_DIR", "workspace");
|
|
266
266
|
TOPIC_WORKSPACE_DIR = resolve(WORKSPACE_DIR, "topics");
|
|
267
267
|
SHARED_WIKI_DIR = resolve(WORKSPACE_DIR, "wiki");
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
268
|
+
CRON_WORKSPACE_DIR = resolve(WORKSPACE_DIR, "cron");
|
|
269
|
+
BROWSER_DIR = resolveLocalStateDir("NEGOTIUM_BROWSER_DIR", "browser");
|
|
270
|
+
BROWSER_PROFILES_DIR = resolve(BROWSER_DIR, "profiles");
|
|
271
|
+
BINARIES_DIR = resolve(STATE_DIR, "binaries");
|
|
272
|
+
SECRETS_DIR = resolve(STATE_DIR, "secrets");
|
|
273
|
+
CONTEXTS_DIR = resolve(STATE_DIR, "data", "contexts");
|
|
274
|
+
DM_WORKSPACE_DIR = resolve(STATE_DIR, "data", "dm");
|
|
275
|
+
SESSION_WORKSPACE_DIR = resolve(STATE_DIR, "data", "sessions");
|
|
272
276
|
CLAUDE_EXECUTABLE_ENV = envText("NEGOTIUM_CLAUDE_EXECUTABLE");
|
|
273
277
|
CLAUDE_EXECUTABLE = CLAUDE_EXECUTABLE_ENV ? resolve(CLAUDE_EXECUTABLE_ENV) : undefined;
|
|
274
278
|
BROWSER_RS_BIN = resolveBrowserRsBin(envText("NEGOTIUM_BROWSER_RS_BIN"));
|
|
@@ -297,10 +301,12 @@ var init_config = __esm(() => {
|
|
|
297
301
|
hostname = process.env.HOSTNAME || "127.0.0.1";
|
|
298
302
|
DATA_DIR = resolveLocalStateDir("NEGOTIUM_DATA_DIR", "data");
|
|
299
303
|
LOG_DIR = resolveLocalStateDir("NEGOTIUM_LOG_DIR", "logs");
|
|
304
|
+
UPLOADS_DIR = resolve(DATA_DIR, "uploads");
|
|
305
|
+
VAULT_DIR = resolve(DATA_DIR, "vault");
|
|
300
306
|
SESSIONS_DB = process.env.SESSIONS_DB_PATH ? resolve(process.env.SESSIONS_DB_PATH) : resolve(DATA_DIR, "sessions.db");
|
|
301
307
|
DEBUG_FILE = resolve(DATA_DIR, "debug-users.json");
|
|
302
308
|
USERS_LOG_DIR = resolve(DATA_DIR, "users");
|
|
303
|
-
RUN_DIR = resolveLocalStateDir("NEGOTIUM_RUN_DIR", "
|
|
309
|
+
RUN_DIR = resolveLocalStateDir("NEGOTIUM_RUN_DIR", "runtime");
|
|
304
310
|
PROGRESS_DIR = resolve(RUN_DIR, "progress");
|
|
305
311
|
DM_CMD_DIR = resolve(RUN_DIR, "dm-commands");
|
|
306
312
|
DM_RESP_DIR = resolve(RUN_DIR, "dm-responses");
|
|
@@ -311,6 +317,8 @@ var init_config = __esm(() => {
|
|
|
311
317
|
PLAYWRIGHT_PORTS_DIR = resolve(RUN_DIR, "playwright-ports");
|
|
312
318
|
mkdirSync(STATE_DIR, { recursive: true });
|
|
313
319
|
mkdirSync(DATA_DIR, { recursive: true });
|
|
320
|
+
mkdirSync(UPLOADS_DIR, { recursive: true });
|
|
321
|
+
mkdirSync(VAULT_DIR, { recursive: true, mode: 448 });
|
|
314
322
|
mkdirSync(LOG_DIR, { recursive: true });
|
|
315
323
|
mkdirSync(PROGRESS_DIR, { recursive: true });
|
|
316
324
|
mkdirSync(DM_CMD_DIR, { recursive: true });
|
|
@@ -321,10 +329,14 @@ var init_config = __esm(() => {
|
|
|
321
329
|
mkdirSync(WORKSPACE_DIR, { recursive: true });
|
|
322
330
|
mkdirSync(TOPIC_WORKSPACE_DIR, { recursive: true });
|
|
323
331
|
mkdirSync(SHARED_WIKI_DIR, { recursive: true });
|
|
332
|
+
mkdirSync(CRON_WORKSPACE_DIR, { recursive: true });
|
|
324
333
|
mkdirSync(CONTEXTS_DIR, { recursive: true });
|
|
325
|
-
mkdirSync(BROWSER_PROFILES_DIR, { recursive: true });
|
|
326
334
|
mkdirSync(DM_WORKSPACE_DIR, { recursive: true });
|
|
327
335
|
mkdirSync(SESSION_WORKSPACE_DIR, { recursive: true });
|
|
336
|
+
mkdirSync(BROWSER_DIR, { recursive: true });
|
|
337
|
+
mkdirSync(BROWSER_PROFILES_DIR, { recursive: true });
|
|
338
|
+
mkdirSync(BINARIES_DIR, { recursive: true });
|
|
339
|
+
mkdirSync(SECRETS_DIR, { recursive: true, mode: 448 });
|
|
328
340
|
ACTIVE_QUERY_STALE_MS = 10 * 60 * 1000;
|
|
329
341
|
AGENTS_PROMPTS_DIR = resolve(PROJECT_ROOT, "src/prompts/agents");
|
|
330
342
|
RESOURCES_DIR = resolve(PROJECT_ROOT, "src/resources");
|
|
@@ -481,8 +493,9 @@ function initializeVaultDatabase(database) {
|
|
|
481
493
|
}
|
|
482
494
|
}
|
|
483
495
|
function openVaultDatabase(dataDir) {
|
|
484
|
-
const
|
|
485
|
-
|
|
496
|
+
const vaultDir = join2(dataDir, "vault");
|
|
497
|
+
const path = join2(vaultDir, "vault.db");
|
|
498
|
+
mkdirSync2(vaultDir, { recursive: true, mode: 448 });
|
|
486
499
|
const database = new Database(path, { create: true });
|
|
487
500
|
chmodSync2(path, 384);
|
|
488
501
|
initializeVaultDatabase(database);
|
|
@@ -1119,7 +1132,12 @@ var init_shared = __esm(() => {
|
|
|
1119
1132
|
init_config();
|
|
1120
1133
|
init_logger();
|
|
1121
1134
|
__dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
1122
|
-
trustedWorkspaceRoots = [
|
|
1135
|
+
trustedWorkspaceRoots = [
|
|
1136
|
+
WORKSPACE_DIR,
|
|
1137
|
+
DM_WORKSPACE_DIR,
|
|
1138
|
+
SESSION_WORKSPACE_DIR,
|
|
1139
|
+
TOPIC_WORKSPACE_DIR
|
|
1140
|
+
].map((root) => resolve2(root));
|
|
1123
1141
|
FIXTURES_DIR = join4(__dirname2, "..", "fixtures");
|
|
1124
1142
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1125
1143
|
});
|
|
@@ -2029,7 +2047,7 @@ function defaultWorkspaceDir() {
|
|
|
2029
2047
|
return envPath("NEGOTIUM_WORKSPACE_DIR", join8(defaultStateDir(), "workspace"));
|
|
2030
2048
|
}
|
|
2031
2049
|
function defaultSessionAsksDir() {
|
|
2032
|
-
const runDir = envPath("NEGOTIUM_RUN_DIR", join8(defaultStateDir(), "
|
|
2050
|
+
const runDir = envPath("NEGOTIUM_RUN_DIR", join8(defaultStateDir(), "runtime"));
|
|
2033
2051
|
return join8(runDir, "session-asks");
|
|
2034
2052
|
}
|
|
2035
2053
|
function defaultSessionsDatabasePath() {
|
|
@@ -2210,15 +2228,8 @@ import {
|
|
|
2210
2228
|
writeFileSync as writeFileSync4
|
|
2211
2229
|
} from "fs";
|
|
2212
2230
|
import { dirname as dirname6, join as join9 } from "path";
|
|
2213
|
-
function
|
|
2214
|
-
|
|
2215
|
-
if (!str || /[/\\]|\.\./.test(str)) {
|
|
2216
|
-
throw new Error(`conversations: refusing unsafe userId path component: ${str}`);
|
|
2217
|
-
}
|
|
2218
|
-
return str;
|
|
2219
|
-
}
|
|
2220
|
-
function conversationDir(userId) {
|
|
2221
|
-
return join9(resolveStorageDataDir(), "conversations", safeUserIdComponent(userId));
|
|
2231
|
+
function conversationDir(_userId) {
|
|
2232
|
+
return join9(resolveStorageDataDir(), "conversations");
|
|
2222
2233
|
}
|
|
2223
2234
|
function topicFilename(topicName) {
|
|
2224
2235
|
const t = sanitizeTopicName(topicName, true);
|
|
@@ -2500,7 +2511,7 @@ function writeRollout(options) {
|
|
|
2500
2511
|
version: 1,
|
|
2501
2512
|
cwd: options.cwd,
|
|
2502
2513
|
createdAt: existingCreatedAt(path) ?? new Date().toISOString(),
|
|
2503
|
-
sdkVersion: "0.1.
|
|
2514
|
+
sdkVersion: "0.1.54"
|
|
2504
2515
|
}
|
|
2505
2516
|
},
|
|
2506
2517
|
...messages
|
|
@@ -2677,13 +2688,6 @@ __export(exports_tasks, {
|
|
|
2677
2688
|
});
|
|
2678
2689
|
import { existsSync as existsSync10, mkdirSync as mkdirSync9, readFileSync as readFileSync7, renameSync as renameSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
2679
2690
|
import { dirname as dirname7, join as join12 } from "path";
|
|
2680
|
-
function safeUserIdComponent2(userId) {
|
|
2681
|
-
const str = String(userId);
|
|
2682
|
-
if (!str || /[/\\]|\.\./.test(str)) {
|
|
2683
|
-
throw new Error(`tasks: refusing unsafe userId path component: ${str}`);
|
|
2684
|
-
}
|
|
2685
|
-
return str;
|
|
2686
|
-
}
|
|
2687
2691
|
function safeTaskScopeKey(scopeKey) {
|
|
2688
2692
|
const safe = sanitizeFileName(scopeKey);
|
|
2689
2693
|
if (!safe || safe === "." || safe === "..") {
|
|
@@ -2695,7 +2699,7 @@ function taskScopeKey(opts) {
|
|
|
2695
2699
|
return opts.topicId?.trim() || opts.session || "default";
|
|
2696
2700
|
}
|
|
2697
2701
|
function getTaskFilePath(userId, scopeKey) {
|
|
2698
|
-
return join12(resolveStorageDataDir(), "tasks",
|
|
2702
|
+
return join12(resolveStorageDataDir(), "tasks", `${safeTaskScopeKey(scopeKey)}.json`);
|
|
2699
2703
|
}
|
|
2700
2704
|
function readTasks(userId, scopeKey) {
|
|
2701
2705
|
const path = getTaskFilePath(userId, scopeKey);
|
|
@@ -3680,7 +3684,7 @@ function getMcpServersForQuery(opts) {
|
|
|
3680
3684
|
if (!opts.topicId)
|
|
3681
3685
|
throw new Error("getMcpServersForQuery: cron sessionType requires topicId");
|
|
3682
3686
|
return getCronMcpServers({
|
|
3683
|
-
userId: opts.userId || "
|
|
3687
|
+
userId: opts.userId || "local",
|
|
3684
3688
|
session: opts.session || "cron",
|
|
3685
3689
|
topicId: opts.topicId,
|
|
3686
3690
|
queryId: opts.queryId,
|
|
@@ -3697,7 +3701,7 @@ function getMcpServersForQuery(opts) {
|
|
|
3697
3701
|
}
|
|
3698
3702
|
if (opts.sessionType === "dm" || opts.sessionType === "ephemeral") {
|
|
3699
3703
|
return getDmMcpServers({
|
|
3700
|
-
userId: opts.userId || "
|
|
3704
|
+
userId: opts.userId || "local",
|
|
3701
3705
|
agent: opts.agent,
|
|
3702
3706
|
playwrightPort: opts.playwrightPort,
|
|
3703
3707
|
playwrightCapability: opts.playwrightCapability
|
|
@@ -3705,7 +3709,7 @@ function getMcpServersForQuery(opts) {
|
|
|
3705
3709
|
}
|
|
3706
3710
|
if (opts.sessionType === "manager") {
|
|
3707
3711
|
return getManagerMcpServers({
|
|
3708
|
-
userId: opts.userId || "
|
|
3712
|
+
userId: opts.userId || "local",
|
|
3709
3713
|
session: opts.session,
|
|
3710
3714
|
topicId: opts.topicId,
|
|
3711
3715
|
queryId: opts.queryId,
|
|
@@ -3722,7 +3726,7 @@ function getMcpServersForQuery(opts) {
|
|
|
3722
3726
|
});
|
|
3723
3727
|
}
|
|
3724
3728
|
return getForumMcpServers({
|
|
3725
|
-
userId: opts.userId || "
|
|
3729
|
+
userId: opts.userId || "local",
|
|
3726
3730
|
session: opts.session || "default",
|
|
3727
3731
|
topicId: opts.topicId,
|
|
3728
3732
|
subagentParentTopicId: opts.subagentParentTopicId,
|
|
@@ -4580,7 +4584,7 @@ var exports_version = {};
|
|
|
4580
4584
|
__export(exports_version, {
|
|
4581
4585
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
4582
4586
|
});
|
|
4583
|
-
var NEGOTIUM_VERSION = "0.
|
|
4587
|
+
var NEGOTIUM_VERSION = "0.2.0";
|
|
4584
4588
|
|
|
4585
4589
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
4586
4590
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -9730,7 +9734,7 @@ function createBrowserProfile(ownerId, rawName) {
|
|
|
9730
9734
|
const name = normalizeBrowserProfileName(rawName);
|
|
9731
9735
|
if (name === DEFAULT_BROWSER_PROFILE)
|
|
9732
9736
|
return name;
|
|
9733
|
-
db.query("INSERT OR IGNORE INTO browser_profiles (owner_id, name, created_at) VALUES (?, ?, ?)").run(
|
|
9737
|
+
db.query("INSERT OR IGNORE INTO browser_profiles (owner_id, name, created_at) VALUES (?, ?, ?)").run("local", name, new Date().toISOString());
|
|
9734
9738
|
return name;
|
|
9735
9739
|
}
|
|
9736
9740
|
function assignTopicBrowserProfile(opts) {
|
|
@@ -9750,10 +9754,9 @@ function assignTopicBrowserProfile(opts) {
|
|
|
9750
9754
|
return { previous, profile };
|
|
9751
9755
|
}
|
|
9752
9756
|
function listBrowserProfiles(ownerId) {
|
|
9753
|
-
const records = db.query("SELECT name, created_at FROM browser_profiles WHERE owner_id = ? ORDER BY name").all(
|
|
9757
|
+
const records = db.query("SELECT name, created_at FROM browser_profiles WHERE owner_id = ? ORDER BY name").all("local");
|
|
9754
9758
|
const topics = db.query(`SELECT t.id, t.title, t.browser_profile FROM api_topics t
|
|
9755
|
-
|
|
9756
|
-
ORDER BY t.title`).all(ownerId);
|
|
9759
|
+
ORDER BY t.title`).all();
|
|
9757
9760
|
const byName = new Map;
|
|
9758
9761
|
byName.set(DEFAULT_BROWSER_PROFILE, {
|
|
9759
9762
|
name: DEFAULT_BROWSER_PROFILE,
|
|
@@ -9798,7 +9801,6 @@ import {
|
|
|
9798
9801
|
existsSync as existsSync15,
|
|
9799
9802
|
mkdirSync as mkdirSync10,
|
|
9800
9803
|
readFileSync as readFileSync12,
|
|
9801
|
-
renameSync as renameSync6,
|
|
9802
9804
|
rmSync as rmSync2,
|
|
9803
9805
|
unlinkSync as unlinkSync11,
|
|
9804
9806
|
writeFileSync as writeFileSync8
|
|
@@ -9814,7 +9816,7 @@ function defaultTopicBinding(userId, topic) {
|
|
|
9814
9816
|
if (!topic)
|
|
9815
9817
|
return managerHost.resolveNamedBinding(userId, "default");
|
|
9816
9818
|
const ownerId = getBrowserProfileOwner(topic, userId);
|
|
9817
|
-
const profile =
|
|
9819
|
+
const profile = getTopicBrowserProfile(topic);
|
|
9818
9820
|
return managerHost.resolveNamedBinding(ownerId, profile);
|
|
9819
9821
|
}
|
|
9820
9822
|
function resolvePlaywrightProfileBinding(ownerId, rawProfile) {
|
|
@@ -9826,34 +9828,15 @@ function validateProfileBinding(binding) {
|
|
|
9826
9828
|
}
|
|
9827
9829
|
return Object.freeze({ ...binding });
|
|
9828
9830
|
}
|
|
9829
|
-
function defaultNamedBinding(
|
|
9831
|
+
function defaultNamedBinding(_ownerId, rawProfile) {
|
|
9830
9832
|
const profile = normalizeBrowserProfileName(rawProfile);
|
|
9831
|
-
const instanceKey = `profile:${
|
|
9833
|
+
const instanceKey = `profile:${profile}`;
|
|
9832
9834
|
return {
|
|
9833
9835
|
instanceKey,
|
|
9834
|
-
ownerId,
|
|
9836
|
+
ownerId: "local",
|
|
9835
9837
|
profile
|
|
9836
9838
|
};
|
|
9837
9839
|
}
|
|
9838
|
-
function legacyBrowserProfileName(topic) {
|
|
9839
|
-
return `legacy_${createHash3("sha256").update(topic).digest("hex").slice(0, 12)}`;
|
|
9840
|
-
}
|
|
9841
|
-
function migrateLegacyTopicProfile(ownerId, topic) {
|
|
9842
|
-
const current2 = getTopicBrowserProfile(topic);
|
|
9843
|
-
if (current2 !== "default" || !hasBrowserProfileTopic(topic))
|
|
9844
|
-
return current2;
|
|
9845
|
-
const legacyDir = resolve12(BROWSER_PROFILES_DIR, sanitizeTopicName(topic));
|
|
9846
|
-
if (!existsSync15(legacyDir))
|
|
9847
|
-
return current2;
|
|
9848
|
-
const profile = legacyBrowserProfileName(topic);
|
|
9849
|
-
const profileDir = defaultProfileDir(ownerId, profile);
|
|
9850
|
-
mkdirSync10(dirname10(profileDir), { recursive: true });
|
|
9851
|
-
if (!existsSync15(profileDir))
|
|
9852
|
-
renameSync6(legacyDir, profileDir);
|
|
9853
|
-
assignTopicBrowserProfile({ topicId: topic, actorUserId: ownerId, profile });
|
|
9854
|
-
logger.info({ ownerId, topic, profile }, "Adopted legacy topic browser profile");
|
|
9855
|
-
return profile;
|
|
9856
|
-
}
|
|
9857
9840
|
function defaultChildEnvironment(context) {
|
|
9858
9841
|
const childEnvironment = {};
|
|
9859
9842
|
for (const key of [
|
|
@@ -9884,6 +9867,10 @@ function defaultChildEnvironment(context) {
|
|
|
9884
9867
|
return childEnvironment;
|
|
9885
9868
|
}
|
|
9886
9869
|
function parseInstanceKey(instanceKey) {
|
|
9870
|
+
const shared = /^profile:(.+)$/.exec(instanceKey);
|
|
9871
|
+
if (shared && !shared[1].includes(":")) {
|
|
9872
|
+
return { ownerId: "local", profile: normalizeBrowserProfileName(shared[1]) };
|
|
9873
|
+
}
|
|
9887
9874
|
const match = /^profile:([^:]+):(.+)$/.exec(instanceKey);
|
|
9888
9875
|
if (!match)
|
|
9889
9876
|
return { ownerId: "legacy", profile: sanitizeTopicName(instanceKey) };
|
|
@@ -10026,12 +10013,8 @@ async function allocatePort() {
|
|
|
10026
10013
|
function releasePort(port) {
|
|
10027
10014
|
usedPorts.delete(port);
|
|
10028
10015
|
}
|
|
10029
|
-
function
|
|
10030
|
-
|
|
10031
|
-
return `${sanitizeTopicName(ownerId).slice(0, 24)}_${digest}`;
|
|
10032
|
-
}
|
|
10033
|
-
function defaultProfileDir(ownerId, profile) {
|
|
10034
|
-
return resolve12(BROWSER_PROFILES_DIR, "profiles", ownerDirectory(ownerId), profile);
|
|
10016
|
+
function defaultProfileDir(_ownerId, profile) {
|
|
10017
|
+
return resolve12(BROWSER_PROFILES_DIR, profile);
|
|
10035
10018
|
}
|
|
10036
10019
|
function resolveUserDataDir(instanceKey) {
|
|
10037
10020
|
return managerHost.resolveInstanceDataDir(instanceKey);
|
|
@@ -12440,7 +12423,7 @@ var init_idle_archiver = __esm(async () => {
|
|
|
12440
12423
|
});
|
|
12441
12424
|
|
|
12442
12425
|
// ../../packages/core/src/agents/topic-cleanup.ts
|
|
12443
|
-
import { mkdirSync as mkdirSync12, renameSync as
|
|
12426
|
+
import { mkdirSync as mkdirSync12, renameSync as renameSync6, unlinkSync as unlinkSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
12444
12427
|
import { dirname as dirname12 } from "path";
|
|
12445
12428
|
function collectSessionIdsByAgent(entries, extraSessions = []) {
|
|
12446
12429
|
const out = new Map;
|
|
@@ -12511,7 +12494,7 @@ function createTopicLogMaintenance(host) {
|
|
|
12511
12494
|
writeFileSync10(tempPath, retained.length > 0 ? `${retained.map((entry) => JSON.stringify(entry)).join(`
|
|
12512
12495
|
`)}
|
|
12513
12496
|
` : "", { flag: "wx" });
|
|
12514
|
-
|
|
12497
|
+
renameSync6(tempPath, path);
|
|
12515
12498
|
} catch (e) {
|
|
12516
12499
|
try {
|
|
12517
12500
|
unlinkSync12(tempPath);
|
|
@@ -14767,7 +14750,7 @@ var init_session_inbox_cleanup = __esm(() => {
|
|
|
14767
14750
|
});
|
|
14768
14751
|
|
|
14769
14752
|
// ../../packages/core/src/query/state.ts
|
|
14770
|
-
import { mkdirSync as mkdirSync14, renameSync as
|
|
14753
|
+
import { mkdirSync as mkdirSync14, renameSync as renameSync7, unlinkSync as unlinkSync15, writeFileSync as writeFileSync12 } from "fs";
|
|
14771
14754
|
import { basename as basename4, join as join24 } from "path";
|
|
14772
14755
|
function createQueryStateStore(options) {
|
|
14773
14756
|
const sanitize = options.sanitizeTopicId ?? sanitizeId;
|
|
@@ -14789,7 +14772,7 @@ function createQueryStateStore(options) {
|
|
|
14789
14772
|
const target = queryStateFile(userId, topicId);
|
|
14790
14773
|
const tmp = `${target}.${process.pid}.${Date.now()}.tmp`;
|
|
14791
14774
|
writeFileSync12(tmp, JSON.stringify(state));
|
|
14792
|
-
|
|
14775
|
+
renameSync7(tmp, target);
|
|
14793
14776
|
},
|
|
14794
14777
|
clear(userId, topicId, legacyTopicName) {
|
|
14795
14778
|
const paths = [
|
|
@@ -15943,7 +15926,7 @@ function promptWithAttachments(prompt, attachments) {
|
|
|
15943
15926
|
return composeAttachmentPrompt(prompt, attachments.map(({ filename, path }) => attachmentPromptLine(filename, path)));
|
|
15944
15927
|
}
|
|
15945
15928
|
function ingestAttachment(args) {
|
|
15946
|
-
const destDir = join26(
|
|
15929
|
+
const destDir = join26(UPLOADS_DIR, args.topicId);
|
|
15947
15930
|
mkdirSync16(destDir, { recursive: true });
|
|
15948
15931
|
const safeName = safeAttachmentFilename(args.filename, "upload");
|
|
15949
15932
|
const destPath = join26(destDir, `${Date.now()}-${randomUUID15().slice(0, 8)}-${safeName}`);
|
|
@@ -20616,7 +20599,7 @@ function renderTurnFooter(msg) {
|
|
|
20616
20599
|
|
|
20617
20600
|
// ../../packages/core/src/outbox/file-ops.ts
|
|
20618
20601
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
20619
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync21, readFileSync as readFileSync18, renameSync as
|
|
20602
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync21, readFileSync as readFileSync18, renameSync as renameSync8, unlinkSync as unlinkSync17 } from "fs";
|
|
20620
20603
|
function host() {
|
|
20621
20604
|
return hostContext.getStore() ?? defaultHost2;
|
|
20622
20605
|
}
|
|
@@ -20657,7 +20640,7 @@ function drainOutboxFile(filePath, label) {
|
|
|
20657
20640
|
if (!existsSync21(filePath))
|
|
20658
20641
|
return null;
|
|
20659
20642
|
try {
|
|
20660
|
-
|
|
20643
|
+
renameSync8(filePath, processingPath);
|
|
20661
20644
|
} catch (e) {
|
|
20662
20645
|
host().logger.warn({ err: e, filePath }, `${label}: failed to rename for processing`);
|
|
20663
20646
|
return null;
|
|
@@ -23678,7 +23661,7 @@ import {
|
|
|
23678
23661
|
openSync as openSync3,
|
|
23679
23662
|
readdirSync as readdirSync9,
|
|
23680
23663
|
readFileSync as readFileSync20,
|
|
23681
|
-
renameSync as
|
|
23664
|
+
renameSync as renameSync9,
|
|
23682
23665
|
statSync as statSync12,
|
|
23683
23666
|
unlinkSync as unlinkSync18,
|
|
23684
23667
|
writeFileSync as writeFileSync17
|
|
@@ -23798,7 +23781,7 @@ function atomicWriteFile(path, content) {
|
|
|
23798
23781
|
const temporaryPath = `${path}.tmp.${process.pid}.${Date.now()}`;
|
|
23799
23782
|
writeFileSync17(temporaryPath, content, "utf-8");
|
|
23800
23783
|
try {
|
|
23801
|
-
|
|
23784
|
+
renameSync9(temporaryPath, path);
|
|
23802
23785
|
} catch (error2) {
|
|
23803
23786
|
try {
|
|
23804
23787
|
unlinkSync18(temporaryPath);
|
|
@@ -24531,7 +24514,7 @@ import {
|
|
|
24531
24514
|
existsSync as existsSync25,
|
|
24532
24515
|
mkdirSync as mkdirSync25,
|
|
24533
24516
|
readdirSync as readdirSync10,
|
|
24534
|
-
renameSync as
|
|
24517
|
+
renameSync as renameSync10,
|
|
24535
24518
|
statSync as statSync13,
|
|
24536
24519
|
unlinkSync as unlinkSync19,
|
|
24537
24520
|
writeFileSync as writeFileSync18
|
|
@@ -24555,7 +24538,7 @@ function writeLog(entry) {
|
|
|
24555
24538
|
const stat = statSync13(file);
|
|
24556
24539
|
if (stat.size >= MAX_FILE_SIZE) {
|
|
24557
24540
|
const rotated = file.replace(/\.jsonl$/, `.${Date.now()}.jsonl`);
|
|
24558
|
-
|
|
24541
|
+
renameSync10(file, rotated);
|
|
24559
24542
|
}
|
|
24560
24543
|
} catch {}
|
|
24561
24544
|
try {
|
|
@@ -26143,7 +26126,7 @@ var init_spec = __esm(() => {
|
|
|
26143
26126
|
});
|
|
26144
26127
|
|
|
26145
26128
|
// ../../packages/mcp-host/src/manifest.ts
|
|
26146
|
-
import { existsSync as existsSync26, mkdirSync as mkdirSync26, readFileSync as readFileSync21, renameSync as
|
|
26129
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync26, readFileSync as readFileSync21, renameSync as renameSync11, writeFileSync as writeFileSync19 } from "fs";
|
|
26147
26130
|
import { dirname as dirname17 } from "path";
|
|
26148
26131
|
import { z as z13 } from "zod";
|
|
26149
26132
|
|
|
@@ -26212,7 +26195,7 @@ class McpManifest {
|
|
|
26212
26195
|
const tmp = `${this.file}.tmp-${process.pid}`;
|
|
26213
26196
|
writeFileSync19(tmp, `${JSON.stringify(payload, null, 2)}
|
|
26214
26197
|
`);
|
|
26215
|
-
|
|
26198
|
+
renameSync11(tmp, this.file);
|
|
26216
26199
|
}
|
|
26217
26200
|
}
|
|
26218
26201
|
var manifestEntrySchema, manifestFileSchema;
|
|
@@ -26243,7 +26226,7 @@ import {
|
|
|
26243
26226
|
mkdirSync as mkdirSync27,
|
|
26244
26227
|
readdirSync as readdirSync11,
|
|
26245
26228
|
readFileSync as readFileSync22,
|
|
26246
|
-
renameSync as
|
|
26229
|
+
renameSync as renameSync12,
|
|
26247
26230
|
unlinkSync as unlinkSync20,
|
|
26248
26231
|
writeFileSync as writeFileSync20
|
|
26249
26232
|
} from "fs";
|
|
@@ -26563,7 +26546,7 @@ class McpHost {
|
|
|
26563
26546
|
const file = join37(this.portsDir, fileName);
|
|
26564
26547
|
const tmp = `${file}.tmp-${process.pid}`;
|
|
26565
26548
|
writeFileSync20(tmp, String(port));
|
|
26566
|
-
|
|
26549
|
+
renameSync12(tmp, file);
|
|
26567
26550
|
} catch (e) {
|
|
26568
26551
|
this.log("warn", "Failed to write MCP port file", { fileName, port, err: String(e) });
|
|
26569
26552
|
}
|
|
@@ -26961,7 +26944,7 @@ import {
|
|
|
26961
26944
|
existsSync as existsSync28,
|
|
26962
26945
|
mkdirSync as mkdirSync29,
|
|
26963
26946
|
readFileSync as readFileSync24,
|
|
26964
|
-
renameSync as
|
|
26947
|
+
renameSync as renameSync13,
|
|
26965
26948
|
unlinkSync as unlinkSync21,
|
|
26966
26949
|
writeFileSync as writeFileSync22
|
|
26967
26950
|
} from "fs";
|
|
@@ -27456,7 +27439,7 @@ function writeNodeDaemonInfo(port, startedAt) {
|
|
|
27456
27439
|
writeFileSync22(temporary, `${JSON.stringify(info, null, 2)}
|
|
27457
27440
|
`, { mode: 384 });
|
|
27458
27441
|
chmodSync5(temporary, 384);
|
|
27459
|
-
|
|
27442
|
+
renameSync13(temporary, NODE_DAEMON_INFO_PATH);
|
|
27460
27443
|
chmodSync5(NODE_DAEMON_INFO_PATH, 384);
|
|
27461
27444
|
return info;
|
|
27462
27445
|
}
|
|
@@ -38926,7 +38909,7 @@ import {
|
|
|
38926
38909
|
mkdirSync as mkdirSync32,
|
|
38927
38910
|
openSync as openSync4,
|
|
38928
38911
|
readFileSync as readFileSync25,
|
|
38929
|
-
renameSync as
|
|
38912
|
+
renameSync as renameSync14,
|
|
38930
38913
|
rmSync as rmSync9,
|
|
38931
38914
|
statSync as statSync17,
|
|
38932
38915
|
unlinkSync as unlinkSync22,
|
|
@@ -39047,7 +39030,7 @@ function withJoinCredentialLock(operation) {
|
|
|
39047
39030
|
}
|
|
39048
39031
|
const stalePath = `${lockPath}.stale.${process.pid}.${randomUUID28()}`;
|
|
39049
39032
|
try {
|
|
39050
|
-
|
|
39033
|
+
renameSync14(lockPath, stalePath);
|
|
39051
39034
|
rmSync9(stalePath, { recursive: true, force: true });
|
|
39052
39035
|
} catch (staleError) {
|
|
39053
39036
|
if (staleError.code !== "ENOENT")
|
|
@@ -39145,7 +39128,7 @@ function saveJoinWhileLocked(join41, options = {}) {
|
|
|
39145
39128
|
closeSync4(fd);
|
|
39146
39129
|
fd = undefined;
|
|
39147
39130
|
if (options.replaceExisting) {
|
|
39148
|
-
|
|
39131
|
+
renameSync14(temporaryPath, path);
|
|
39149
39132
|
} else {
|
|
39150
39133
|
linkSync(temporaryPath, path);
|
|
39151
39134
|
unlinkSync22(temporaryPath);
|
|
@@ -41931,7 +41914,7 @@ import {
|
|
|
41931
41914
|
mkdirSync as mkdirSync34,
|
|
41932
41915
|
openSync as openSync5,
|
|
41933
41916
|
readFileSync as readFileSync26,
|
|
41934
|
-
renameSync as
|
|
41917
|
+
renameSync as renameSync15,
|
|
41935
41918
|
unlinkSync as unlinkSync23,
|
|
41936
41919
|
writeFileSync as writeFileSync24
|
|
41937
41920
|
} from "fs";
|
|
@@ -42030,7 +42013,7 @@ function replacePendingEnrollment(pending2) {
|
|
|
42030
42013
|
fsyncSync3(fd);
|
|
42031
42014
|
closeSync5(fd);
|
|
42032
42015
|
fd = undefined;
|
|
42033
|
-
|
|
42016
|
+
renameSync15(temporaryPath, path);
|
|
42034
42017
|
const directoryFd = openSync5(directory, "r");
|
|
42035
42018
|
try {
|
|
42036
42019
|
fsyncSync3(directoryFd);
|
|
@@ -43657,6 +43640,476 @@ var init_init = __esm(async () => {
|
|
|
43657
43640
|
await init_src();
|
|
43658
43641
|
});
|
|
43659
43642
|
|
|
43643
|
+
// ../../packages/core/src/migration/single-user.ts
|
|
43644
|
+
import { createHash as createHash11, randomUUID as randomUUID34 } from "crypto";
|
|
43645
|
+
import {
|
|
43646
|
+
chmodSync as chmodSync8,
|
|
43647
|
+
copyFileSync as copyFileSync6,
|
|
43648
|
+
existsSync as existsSync36,
|
|
43649
|
+
mkdirSync as mkdirSync35,
|
|
43650
|
+
readdirSync as readdirSync14,
|
|
43651
|
+
readFileSync as readFileSync27,
|
|
43652
|
+
renameSync as renameSync16,
|
|
43653
|
+
rmSync as rmSync11,
|
|
43654
|
+
statSync as statSync19,
|
|
43655
|
+
writeFileSync as writeFileSync25
|
|
43656
|
+
} from "fs";
|
|
43657
|
+
import { homedir as homedir12 } from "os";
|
|
43658
|
+
import { basename as basename14, dirname as dirname23, join as join42, resolve as resolve25 } from "path";
|
|
43659
|
+
function entries(path) {
|
|
43660
|
+
return existsSync36(path) && statSync19(path).isDirectory() ? readdirSync14(path) : [];
|
|
43661
|
+
}
|
|
43662
|
+
function processIsAlive2(pid) {
|
|
43663
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
43664
|
+
return false;
|
|
43665
|
+
try {
|
|
43666
|
+
process.kill(pid, 0);
|
|
43667
|
+
return true;
|
|
43668
|
+
} catch (error2) {
|
|
43669
|
+
return error2.code === "EPERM";
|
|
43670
|
+
}
|
|
43671
|
+
}
|
|
43672
|
+
function assertNoActiveNode(stateDir2) {
|
|
43673
|
+
for (const runtimeName of ["run", "runtime"]) {
|
|
43674
|
+
const infoPath = join42(stateDir2, runtimeName, "node-daemon.json");
|
|
43675
|
+
if (!existsSync36(infoPath))
|
|
43676
|
+
continue;
|
|
43677
|
+
try {
|
|
43678
|
+
const value = JSON.parse(readFileSync27(infoPath, "utf8"));
|
|
43679
|
+
if (typeof value.pid === "number" && processIsAlive2(value.pid)) {
|
|
43680
|
+
throw new Error(`Refusing migration while Negotium pid ${value.pid} is active.`);
|
|
43681
|
+
}
|
|
43682
|
+
} catch (error2) {
|
|
43683
|
+
if (error2 instanceof SyntaxError) {
|
|
43684
|
+
throw new Error(`Refusing migration: unreadable process metadata at ${infoPath}.`);
|
|
43685
|
+
}
|
|
43686
|
+
throw error2;
|
|
43687
|
+
}
|
|
43688
|
+
}
|
|
43689
|
+
const dbPath = join42(stateDir2, "data", "sessions.db");
|
|
43690
|
+
if (!existsSync36(dbPath))
|
|
43691
|
+
return;
|
|
43692
|
+
const database = new Database(dbPath, { readonly: true });
|
|
43693
|
+
try {
|
|
43694
|
+
const hasLeases = database.query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='runtime_process_leases'").get();
|
|
43695
|
+
if (!hasLeases)
|
|
43696
|
+
return;
|
|
43697
|
+
const leases = database.query("SELECT role, pid FROM runtime_process_leases").all();
|
|
43698
|
+
const active2 = leases.find((lease) => processIsAlive2(lease.pid));
|
|
43699
|
+
if (active2)
|
|
43700
|
+
throw new Error(`Refusing migration while ${active2.role} pid ${active2.pid} is active.`);
|
|
43701
|
+
} finally {
|
|
43702
|
+
database.close();
|
|
43703
|
+
}
|
|
43704
|
+
}
|
|
43705
|
+
function oldOwnerDirectory(ownerId) {
|
|
43706
|
+
const digest = createHash11("sha256").update(ownerId).digest("hex").slice(0, 16);
|
|
43707
|
+
return `${sanitizeTopicName(ownerId).slice(0, 24)}_${digest}`;
|
|
43708
|
+
}
|
|
43709
|
+
function addDirectoryContents(operations, sourceDir, destinationDir, stagingDir) {
|
|
43710
|
+
for (const name of entries(sourceDir)) {
|
|
43711
|
+
operations.push({
|
|
43712
|
+
source: join42(sourceDir, name),
|
|
43713
|
+
staged: join42(stagingDir, randomUUID34()),
|
|
43714
|
+
...destinationDir ? { destination: join42(destinationDir, name) } : {},
|
|
43715
|
+
state: "pending"
|
|
43716
|
+
});
|
|
43717
|
+
}
|
|
43718
|
+
}
|
|
43719
|
+
function assertNoCollisions(operations) {
|
|
43720
|
+
const destinations = new Set;
|
|
43721
|
+
for (const operation of operations) {
|
|
43722
|
+
if (!operation.destination)
|
|
43723
|
+
continue;
|
|
43724
|
+
if (existsSync36(operation.destination)) {
|
|
43725
|
+
throw new Error(`Migration collision at ${operation.destination}.`);
|
|
43726
|
+
}
|
|
43727
|
+
if (destinations.has(operation.destination)) {
|
|
43728
|
+
throw new Error(`Multiple legacy paths target ${operation.destination}.`);
|
|
43729
|
+
}
|
|
43730
|
+
destinations.add(operation.destination);
|
|
43731
|
+
}
|
|
43732
|
+
}
|
|
43733
|
+
function writeJournal(path, journal) {
|
|
43734
|
+
writeFileSync25(path, `${JSON.stringify(journal, null, 2)}
|
|
43735
|
+
`, { mode: 384 });
|
|
43736
|
+
}
|
|
43737
|
+
function rollbackFilesystem(journal, journalPath) {
|
|
43738
|
+
for (const operation of [...journal.operations].reverse()) {
|
|
43739
|
+
const current3 = operation.state === "placed" ? operation.destination : operation.staged;
|
|
43740
|
+
if (!current3 || !existsSync36(current3) || existsSync36(operation.source))
|
|
43741
|
+
continue;
|
|
43742
|
+
mkdirSync35(dirname23(operation.source), { recursive: true });
|
|
43743
|
+
renameSync16(current3, operation.source);
|
|
43744
|
+
operation.state = "pending";
|
|
43745
|
+
}
|
|
43746
|
+
journal.phase = "filesystem";
|
|
43747
|
+
writeJournal(journalPath, journal);
|
|
43748
|
+
}
|
|
43749
|
+
function tablesWithColumn(database, columnName) {
|
|
43750
|
+
const tables = database.query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").all();
|
|
43751
|
+
return tables.map((row) => row.name).filter((table) => database.query(`PRAGMA table_info("${table.replaceAll('"', '""')}")`).all().some((column) => column.name === columnName));
|
|
43752
|
+
}
|
|
43753
|
+
function selectedTopicIds(dbPath, source) {
|
|
43754
|
+
if (!existsSync36(dbPath))
|
|
43755
|
+
return null;
|
|
43756
|
+
const database = new Database(dbPath, { readonly: true });
|
|
43757
|
+
try {
|
|
43758
|
+
const hasMemberships = database.query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='topic_members'").get();
|
|
43759
|
+
if (!hasMemberships)
|
|
43760
|
+
return null;
|
|
43761
|
+
return new Set(database.query("SELECT topic_id FROM topic_members WHERE user_id = ?").all(source).map((row) => row.topic_id));
|
|
43762
|
+
} finally {
|
|
43763
|
+
database.close();
|
|
43764
|
+
}
|
|
43765
|
+
}
|
|
43766
|
+
function migrateDatabase(dbPath, source, masterKey, legacyTopicProfiles = []) {
|
|
43767
|
+
if (!existsSync36(dbPath))
|
|
43768
|
+
return [];
|
|
43769
|
+
const database = new Database(dbPath);
|
|
43770
|
+
const userTables = tablesWithColumn(database, "user_id");
|
|
43771
|
+
const ownerUserTables = tablesWithColumn(database, "owner_user_id");
|
|
43772
|
+
const migratedTables = [...new Set([...userTables, ...ownerUserTables])];
|
|
43773
|
+
const retainedTopicIds = selectedTopicIds(dbPath, source);
|
|
43774
|
+
const quote = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
43775
|
+
try {
|
|
43776
|
+
if (source !== CANONICAL_LOCAL_USER_ID) {
|
|
43777
|
+
for (const [column, tables] of [
|
|
43778
|
+
["user_id", userTables],
|
|
43779
|
+
["owner_user_id", ownerUserTables]
|
|
43780
|
+
]) {
|
|
43781
|
+
for (const table of tables) {
|
|
43782
|
+
const collision = database.query(`SELECT COUNT(*) AS count FROM ${quote(table)} WHERE ${column} = ?`).get(CANONICAL_LOCAL_USER_ID)?.count;
|
|
43783
|
+
if (collision)
|
|
43784
|
+
throw new Error(`Database collision: ${table}.${column} already contains local rows.`);
|
|
43785
|
+
}
|
|
43786
|
+
}
|
|
43787
|
+
const hasUsers = database.query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='users'").get();
|
|
43788
|
+
if (hasUsers) {
|
|
43789
|
+
const localUser = database.query("SELECT 1 FROM users WHERE id = ?").get(CANONICAL_LOCAL_USER_ID);
|
|
43790
|
+
if (localUser)
|
|
43791
|
+
throw new Error("Database collision: users already contains canonical local.");
|
|
43792
|
+
}
|
|
43793
|
+
}
|
|
43794
|
+
database.exec("PRAGMA foreign_keys = OFF");
|
|
43795
|
+
database.exec("BEGIN IMMEDIATE");
|
|
43796
|
+
for (const table of userTables) {
|
|
43797
|
+
database.query(`DELETE FROM ${quote(table)} WHERE user_id <> ?`).run(source);
|
|
43798
|
+
if (table === "vault" && source !== CANONICAL_LOCAL_USER_ID) {
|
|
43799
|
+
if (!masterKey)
|
|
43800
|
+
throw new Error("Cannot migrate encrypted vault rows without vault-master-key.");
|
|
43801
|
+
const rows = database.query("SELECT key, value FROM vault WHERE user_id = ?").all(source);
|
|
43802
|
+
for (const row of rows) {
|
|
43803
|
+
const plaintext = decryptVaultValue(source, row.key, row.value, masterKey).value;
|
|
43804
|
+
database.query("UPDATE vault SET value = ? WHERE user_id = ? AND key = ?").run(encryptVaultValue(CANONICAL_LOCAL_USER_ID, row.key, plaintext, masterKey), source, row.key);
|
|
43805
|
+
}
|
|
43806
|
+
}
|
|
43807
|
+
database.query(`UPDATE ${quote(table)} SET user_id = ? WHERE user_id = ?`).run(CANONICAL_LOCAL_USER_ID, source);
|
|
43808
|
+
}
|
|
43809
|
+
for (const table of ownerUserTables) {
|
|
43810
|
+
database.query(`DELETE FROM ${quote(table)} WHERE owner_user_id <> ?`).run(source);
|
|
43811
|
+
database.query(`UPDATE ${quote(table)} SET owner_user_id = ? WHERE owner_user_id = ?`).run(CANONICAL_LOCAL_USER_ID, source);
|
|
43812
|
+
}
|
|
43813
|
+
if (retainedTopicIds) {
|
|
43814
|
+
database.exec("CREATE TEMP TABLE migration_selected_topics (id TEXT PRIMARY KEY)");
|
|
43815
|
+
for (const topicId of retainedTopicIds) {
|
|
43816
|
+
database.query("INSERT INTO migration_selected_topics (id) VALUES (?)").run(topicId);
|
|
43817
|
+
}
|
|
43818
|
+
const topicTables = database.query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").all().map((row) => row.name).filter((table) => database.query(`PRAGMA table_info(${quote(table)})`).all().some((column) => column.name === "topic_id"));
|
|
43819
|
+
for (const table of topicTables) {
|
|
43820
|
+
database.query(`DELETE FROM ${quote(table)} WHERE topic_id NOT IN (SELECT id FROM migration_selected_topics)`).run();
|
|
43821
|
+
}
|
|
43822
|
+
if (database.query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='api_topics'").get()) {
|
|
43823
|
+
database.query("DELETE FROM api_topics WHERE id NOT IN (SELECT id FROM migration_selected_topics)").run();
|
|
43824
|
+
}
|
|
43825
|
+
}
|
|
43826
|
+
if (database.query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='browser_profiles'").get()) {
|
|
43827
|
+
database.query("DELETE FROM browser_profiles WHERE owner_id <> ?").run(source);
|
|
43828
|
+
database.query("UPDATE browser_profiles SET owner_id = ? WHERE owner_id = ?").run(CANONICAL_LOCAL_USER_ID, source);
|
|
43829
|
+
}
|
|
43830
|
+
if (database.query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='api_topics'").get() && database.query("PRAGMA table_info(api_topics)").all().some((column) => column.name === "browser_profile_owner")) {
|
|
43831
|
+
database.query("UPDATE api_topics SET browser_profile_owner = ? WHERE browser_profile_owner = ?").run(CANONICAL_LOCAL_USER_ID, source);
|
|
43832
|
+
if (retainedTopicIds) {
|
|
43833
|
+
database.query("UPDATE api_topics SET browser_profile_owner = ? WHERE browser_profile_owner IS NOT NULL").run(CANONICAL_LOCAL_USER_ID);
|
|
43834
|
+
} else {
|
|
43835
|
+
database.query("DELETE FROM api_topics WHERE browser_profile_owner IS NOT NULL AND browser_profile_owner <> ?").run(CANONICAL_LOCAL_USER_ID);
|
|
43836
|
+
}
|
|
43837
|
+
for (const binding of legacyTopicProfiles) {
|
|
43838
|
+
database.query("UPDATE api_topics SET browser_profile = ?, browser_profile_owner = ? WHERE id = ?").run(binding.profile, CANONICAL_LOCAL_USER_ID, binding.topicId);
|
|
43839
|
+
}
|
|
43840
|
+
}
|
|
43841
|
+
if (database.query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='users'").get()) {
|
|
43842
|
+
database.query("DELETE FROM users WHERE id <> ?").run(source);
|
|
43843
|
+
database.query("UPDATE users SET id = ? WHERE id = ?").run(CANONICAL_LOCAL_USER_ID, source);
|
|
43844
|
+
}
|
|
43845
|
+
database.exec("COMMIT");
|
|
43846
|
+
database.exec("PRAGMA foreign_keys = ON");
|
|
43847
|
+
const fkErrors = database.query("PRAGMA foreign_key_check").all();
|
|
43848
|
+
if (fkErrors.length > 0)
|
|
43849
|
+
throw new Error("Database migration left foreign-key violations.");
|
|
43850
|
+
return migratedTables;
|
|
43851
|
+
} catch (error2) {
|
|
43852
|
+
try {
|
|
43853
|
+
database.exec("ROLLBACK");
|
|
43854
|
+
} catch {}
|
|
43855
|
+
throw error2;
|
|
43856
|
+
} finally {
|
|
43857
|
+
database.close();
|
|
43858
|
+
}
|
|
43859
|
+
}
|
|
43860
|
+
function migrateSingleUserState(options) {
|
|
43861
|
+
const stateDir2 = resolve25(options.stateDir ?? process.env.NEGOTIUM_STATE_DIR ?? join42(homedir12(), ".negotium"));
|
|
43862
|
+
const source = options.sourcePrincipal?.trim() || CANONICAL_LOCAL_USER_ID;
|
|
43863
|
+
if (!source || /[/\\]|\.\./.test(source))
|
|
43864
|
+
throw new Error("Invalid source principal.");
|
|
43865
|
+
if (!options.deleteOtherUsers || !options.confirmed) {
|
|
43866
|
+
throw new Error("Migration requires --delete-other-users and --yes; other principals are permanently deleted.");
|
|
43867
|
+
}
|
|
43868
|
+
const markerPath = join42(stateDir2, ".migration-0.2.0-single-user.json");
|
|
43869
|
+
if (existsSync36(markerPath)) {
|
|
43870
|
+
const marker = JSON.parse(readFileSync27(markerPath, "utf8"));
|
|
43871
|
+
if (marker.id !== SINGLE_USER_MIGRATION_ID)
|
|
43872
|
+
throw new Error(`Unexpected migration marker at ${markerPath}.`);
|
|
43873
|
+
return {
|
|
43874
|
+
status: "already-completed",
|
|
43875
|
+
markerPath,
|
|
43876
|
+
sourcePrincipal: marker.sourcePrincipal ?? source,
|
|
43877
|
+
movedPaths: marker.movedPaths ?? 0,
|
|
43878
|
+
deletedPaths: marker.deletedPaths ?? 0,
|
|
43879
|
+
migratedTables: marker.migratedTables ?? []
|
|
43880
|
+
};
|
|
43881
|
+
}
|
|
43882
|
+
assertNoActiveNode(stateDir2);
|
|
43883
|
+
mkdirSync35(stateDir2, { recursive: true });
|
|
43884
|
+
const stagingRoot = join42(stateDir2, ".migration-0.2.0-staging");
|
|
43885
|
+
const journalPath = join42(stagingRoot, "journal.json");
|
|
43886
|
+
mkdirSync35(stagingRoot, { recursive: true, mode: 448 });
|
|
43887
|
+
let journal;
|
|
43888
|
+
if (existsSync36(journalPath)) {
|
|
43889
|
+
journal = JSON.parse(readFileSync27(journalPath, "utf8"));
|
|
43890
|
+
if (journal.sourcePrincipal !== source)
|
|
43891
|
+
throw new Error("Interrupted migration used a different source principal.");
|
|
43892
|
+
} else {
|
|
43893
|
+
const operations = [];
|
|
43894
|
+
const retainedTopicIds = selectedTopicIds(join42(stateDir2, "data", "sessions.db"), source);
|
|
43895
|
+
addDirectoryContents(operations, join42(stateDir2, "run"), join42(stateDir2, "runtime"), stagingRoot);
|
|
43896
|
+
addDirectoryContents(operations, join42(stateDir2, "bin"), join42(stateDir2, "binaries"), stagingRoot);
|
|
43897
|
+
for (const secret of ["node-control-token", "runtime-mcp-secret", "vault-master-key"]) {
|
|
43898
|
+
const sourcePath = join42(stateDir2, secret);
|
|
43899
|
+
if (existsSync36(sourcePath))
|
|
43900
|
+
operations.push({
|
|
43901
|
+
source: sourcePath,
|
|
43902
|
+
staged: join42(stagingRoot, randomUUID34()),
|
|
43903
|
+
destination: join42(stateDir2, "secrets", secret),
|
|
43904
|
+
state: "pending"
|
|
43905
|
+
});
|
|
43906
|
+
}
|
|
43907
|
+
const legacyVaultDb = join42(stateDir2, "data", "vault.db");
|
|
43908
|
+
if (existsSync36(legacyVaultDb)) {
|
|
43909
|
+
operations.push({
|
|
43910
|
+
source: legacyVaultDb,
|
|
43911
|
+
staged: join42(stagingRoot, randomUUID34()),
|
|
43912
|
+
destination: join42(stateDir2, "data", "vault", "vault.db"),
|
|
43913
|
+
state: "pending"
|
|
43914
|
+
});
|
|
43915
|
+
}
|
|
43916
|
+
for (const store of ["conversations", "tasks", "users"]) {
|
|
43917
|
+
const root = join42(stateDir2, "data", store);
|
|
43918
|
+
addDirectoryContents(operations, join42(root, source), root, stagingRoot);
|
|
43919
|
+
for (const owner of entries(root)) {
|
|
43920
|
+
const ownerPath = join42(root, owner);
|
|
43921
|
+
if (owner !== source && statSync19(ownerPath).isDirectory()) {
|
|
43922
|
+
operations.push({
|
|
43923
|
+
source: ownerPath,
|
|
43924
|
+
staged: join42(stagingRoot, randomUUID34()),
|
|
43925
|
+
state: "pending"
|
|
43926
|
+
});
|
|
43927
|
+
}
|
|
43928
|
+
}
|
|
43929
|
+
}
|
|
43930
|
+
for (const legacyWorkspaceDir of ["contexts", "dm", "sessions"]) {
|
|
43931
|
+
addDirectoryContents(operations, join42(stateDir2, "workspace", legacyWorkspaceDir), join42(stateDir2, "data", legacyWorkspaceDir), stagingRoot);
|
|
43932
|
+
}
|
|
43933
|
+
for (const topicId of entries(join42(stateDir2, "workspace", "topics"))) {
|
|
43934
|
+
const topicPath = join42(stateDir2, "workspace", "topics", topicId);
|
|
43935
|
+
if (retainedTopicIds && !retainedTopicIds.has(topicId)) {
|
|
43936
|
+
operations.push({
|
|
43937
|
+
source: topicPath,
|
|
43938
|
+
staged: join42(stagingRoot, randomUUID34()),
|
|
43939
|
+
state: "pending"
|
|
43940
|
+
});
|
|
43941
|
+
} else {
|
|
43942
|
+
addDirectoryContents(operations, join42(topicPath, "uploads"), join42(stateDir2, "data", "uploads", topicId), stagingRoot);
|
|
43943
|
+
}
|
|
43944
|
+
}
|
|
43945
|
+
if (retainedTopicIds) {
|
|
43946
|
+
for (const topicId of entries(join42(stateDir2, "workspace", "wiki"))) {
|
|
43947
|
+
if (retainedTopicIds.has(topicId))
|
|
43948
|
+
continue;
|
|
43949
|
+
operations.push({
|
|
43950
|
+
source: join42(stateDir2, "workspace", "wiki", topicId),
|
|
43951
|
+
staged: join42(stagingRoot, randomUUID34()),
|
|
43952
|
+
state: "pending"
|
|
43953
|
+
});
|
|
43954
|
+
}
|
|
43955
|
+
}
|
|
43956
|
+
const legacyBrowserRoot = join42(stateDir2, "workspace", "browser-profiles");
|
|
43957
|
+
const selectedProfiles = join42(legacyBrowserRoot, "profiles", oldOwnerDirectory(source));
|
|
43958
|
+
addDirectoryContents(operations, selectedProfiles, join42(stateDir2, "browser", "profiles"), stagingRoot);
|
|
43959
|
+
for (const owner of entries(join42(legacyBrowserRoot, "profiles"))) {
|
|
43960
|
+
const ownerPath = join42(legacyBrowserRoot, "profiles", owner);
|
|
43961
|
+
if (ownerPath !== selectedProfiles) {
|
|
43962
|
+
operations.push({
|
|
43963
|
+
source: ownerPath,
|
|
43964
|
+
staged: join42(stagingRoot, randomUUID34()),
|
|
43965
|
+
state: "pending"
|
|
43966
|
+
});
|
|
43967
|
+
}
|
|
43968
|
+
}
|
|
43969
|
+
for (const topicId of entries(legacyBrowserRoot).filter((name) => name !== "profiles")) {
|
|
43970
|
+
if (retainedTopicIds && !retainedTopicIds.has(topicId)) {
|
|
43971
|
+
operations.push({
|
|
43972
|
+
source: join42(legacyBrowserRoot, topicId),
|
|
43973
|
+
staged: join42(stagingRoot, randomUUID34()),
|
|
43974
|
+
state: "pending"
|
|
43975
|
+
});
|
|
43976
|
+
continue;
|
|
43977
|
+
}
|
|
43978
|
+
const profile = `legacy_${createHash11("sha256").update(topicId).digest("hex").slice(0, 12)}`;
|
|
43979
|
+
operations.push({
|
|
43980
|
+
source: join42(legacyBrowserRoot, topicId),
|
|
43981
|
+
staged: join42(stagingRoot, randomUUID34()),
|
|
43982
|
+
destination: join42(stateDir2, "browser", "profiles", profile),
|
|
43983
|
+
state: "pending"
|
|
43984
|
+
});
|
|
43985
|
+
}
|
|
43986
|
+
assertNoCollisions(operations);
|
|
43987
|
+
journal = {
|
|
43988
|
+
id: SINGLE_USER_MIGRATION_ID,
|
|
43989
|
+
sourcePrincipal: source,
|
|
43990
|
+
createdAt: new Date().toISOString(),
|
|
43991
|
+
phase: "filesystem",
|
|
43992
|
+
operations
|
|
43993
|
+
};
|
|
43994
|
+
writeJournal(journalPath, journal);
|
|
43995
|
+
}
|
|
43996
|
+
const dbPath = join42(stateDir2, "data", "sessions.db");
|
|
43997
|
+
const dbBackup = join42(stagingRoot, "sessions.db.rollback");
|
|
43998
|
+
const vaultDbPath = join42(stateDir2, "data", "vault", "vault.db");
|
|
43999
|
+
const vaultDbBackup = join42(stagingRoot, "vault.db.rollback");
|
|
44000
|
+
try {
|
|
44001
|
+
for (const operation of journal.operations) {
|
|
44002
|
+
if (operation.state === "pending" && !existsSync36(operation.source) && existsSync36(operation.staged)) {
|
|
44003
|
+
operation.state = "staged";
|
|
44004
|
+
}
|
|
44005
|
+
if (operation.state === "staged" && operation.destination && !existsSync36(operation.staged) && existsSync36(operation.destination)) {
|
|
44006
|
+
operation.state = "placed";
|
|
44007
|
+
}
|
|
44008
|
+
if (operation.state === "pending") {
|
|
44009
|
+
mkdirSync35(dirname23(operation.staged), { recursive: true });
|
|
44010
|
+
renameSync16(operation.source, operation.staged);
|
|
44011
|
+
operation.state = "staged";
|
|
44012
|
+
writeJournal(journalPath, journal);
|
|
44013
|
+
}
|
|
44014
|
+
if (operation.state === "staged" && operation.destination) {
|
|
44015
|
+
mkdirSync35(dirname23(operation.destination), { recursive: true });
|
|
44016
|
+
renameSync16(operation.staged, operation.destination);
|
|
44017
|
+
operation.state = "placed";
|
|
44018
|
+
writeJournal(journalPath, journal);
|
|
44019
|
+
}
|
|
44020
|
+
}
|
|
44021
|
+
journal.phase = "database";
|
|
44022
|
+
writeJournal(journalPath, journal);
|
|
44023
|
+
if (existsSync36(dbPath) && !existsSync36(dbBackup))
|
|
44024
|
+
copyFileSync6(dbPath, dbBackup);
|
|
44025
|
+
if (existsSync36(vaultDbPath) && !existsSync36(vaultDbBackup))
|
|
44026
|
+
copyFileSync6(vaultDbPath, vaultDbBackup);
|
|
44027
|
+
const masterKeyPath = join42(stateDir2, "secrets", "vault-master-key");
|
|
44028
|
+
const masterKey = existsSync36(masterKeyPath) ? readFileSync27(masterKeyPath, "utf8").trim() : undefined;
|
|
44029
|
+
const legacyBrowserRoot = join42(stateDir2, "workspace", "browser-profiles");
|
|
44030
|
+
const legacyTopicProfiles = journal.operations.filter((operation) => dirname23(operation.source) === legacyBrowserRoot && operation.destination).map((operation) => ({
|
|
44031
|
+
topicId: basename14(operation.source),
|
|
44032
|
+
profile: basename14(operation.destination)
|
|
44033
|
+
}));
|
|
44034
|
+
const migratedTables = migrateDatabase(dbPath, source, masterKey, legacyTopicProfiles);
|
|
44035
|
+
const migratedVaultTables = migrateDatabase(vaultDbPath, source, masterKey);
|
|
44036
|
+
for (const table of migratedVaultTables)
|
|
44037
|
+
if (!migratedTables.includes(table))
|
|
44038
|
+
migratedTables.push(table);
|
|
44039
|
+
mkdirSync35(join42(stateDir2, "secrets"), { recursive: true, mode: 448 });
|
|
44040
|
+
chmodSync8(join42(stateDir2, "secrets"), 448);
|
|
44041
|
+
for (const secret of ["node-control-token", "runtime-mcp-secret", "vault-master-key"]) {
|
|
44042
|
+
const path = join42(stateDir2, "secrets", secret);
|
|
44043
|
+
if (existsSync36(path))
|
|
44044
|
+
chmodSync8(path, 384);
|
|
44045
|
+
}
|
|
44046
|
+
const deletedPaths = journal.operations.filter((operation) => !operation.destination).length;
|
|
44047
|
+
const movedPaths = journal.operations.length - deletedPaths;
|
|
44048
|
+
const marker = {
|
|
44049
|
+
id: SINGLE_USER_MIGRATION_ID,
|
|
44050
|
+
version: "0.2.0",
|
|
44051
|
+
completedAt: new Date().toISOString(),
|
|
44052
|
+
sourcePrincipal: source,
|
|
44053
|
+
canonicalPrincipal: CANONICAL_LOCAL_USER_ID,
|
|
44054
|
+
movedPaths,
|
|
44055
|
+
deletedPaths,
|
|
44056
|
+
migratedTables
|
|
44057
|
+
};
|
|
44058
|
+
for (const store of ["conversations", "tasks", "users"]) {
|
|
44059
|
+
rmSync11(join42(stateDir2, "data", store, source), { recursive: true, force: true });
|
|
44060
|
+
}
|
|
44061
|
+
rmSync11(join42(stateDir2, "workspace", "browser-profiles"), { recursive: true, force: true });
|
|
44062
|
+
writeFileSync25(markerPath, `${JSON.stringify(marker, null, 2)}
|
|
44063
|
+
`, { mode: 384, flag: "wx" });
|
|
44064
|
+
journal.phase = "complete";
|
|
44065
|
+
rmSync11(stagingRoot, { recursive: true, force: true });
|
|
44066
|
+
return {
|
|
44067
|
+
status: "completed",
|
|
44068
|
+
markerPath,
|
|
44069
|
+
sourcePrincipal: source,
|
|
44070
|
+
movedPaths,
|
|
44071
|
+
deletedPaths,
|
|
44072
|
+
migratedTables
|
|
44073
|
+
};
|
|
44074
|
+
} catch (error2) {
|
|
44075
|
+
if (existsSync36(dbBackup))
|
|
44076
|
+
copyFileSync6(dbBackup, dbPath);
|
|
44077
|
+
if (existsSync36(vaultDbBackup))
|
|
44078
|
+
copyFileSync6(vaultDbBackup, vaultDbPath);
|
|
44079
|
+
rollbackFilesystem(journal, journalPath);
|
|
44080
|
+
throw error2;
|
|
44081
|
+
}
|
|
44082
|
+
}
|
|
44083
|
+
var CANONICAL_LOCAL_USER_ID = "local", SINGLE_USER_MIGRATION_ID = "negotium-0.2.0-single-user";
|
|
44084
|
+
var init_single_user = __esm(async () => {
|
|
44085
|
+
init_vault_crypto();
|
|
44086
|
+
await init_sqlite();
|
|
44087
|
+
});
|
|
44088
|
+
|
|
44089
|
+
// ../cli/src/commands/migrate.ts
|
|
44090
|
+
var exports_migrate = {};
|
|
44091
|
+
__export(exports_migrate, {
|
|
44092
|
+
migrateCommand: () => migrateCommand
|
|
44093
|
+
});
|
|
44094
|
+
function option3(args, name) {
|
|
44095
|
+
const prefix = `--${name}=`;
|
|
44096
|
+
return args.find((arg) => arg.startsWith(prefix))?.slice(prefix.length);
|
|
44097
|
+
}
|
|
44098
|
+
function migrateCommand(args) {
|
|
44099
|
+
if (args[0] !== "single-user") {
|
|
44100
|
+
throw new Error("usage: negotium migrate single-user [--source=local] --delete-other-users --yes");
|
|
44101
|
+
}
|
|
44102
|
+
const result = migrateSingleUserState({
|
|
44103
|
+
sourcePrincipal: option3(args, "source"),
|
|
44104
|
+
deleteOtherUsers: args.includes("--delete-other-users"),
|
|
44105
|
+
confirmed: args.includes("--yes")
|
|
44106
|
+
});
|
|
44107
|
+
console.log(`${result.status}: ${result.markerPath}`);
|
|
44108
|
+
}
|
|
44109
|
+
var init_migrate = __esm(async () => {
|
|
44110
|
+
await init_single_user();
|
|
44111
|
+
});
|
|
44112
|
+
|
|
43660
44113
|
// ../cli/src/commands/topics.ts
|
|
43661
44114
|
var exports_topics = {};
|
|
43662
44115
|
__export(exports_topics, {
|
|
@@ -43758,12 +44211,12 @@ function vaultCommand(args) {
|
|
|
43758
44211
|
switch (sub) {
|
|
43759
44212
|
case undefined:
|
|
43760
44213
|
case "list": {
|
|
43761
|
-
const
|
|
43762
|
-
if (
|
|
44214
|
+
const entries2 = vaultListWithValues(DEFAULT_USER);
|
|
44215
|
+
if (entries2.length === 0) {
|
|
43763
44216
|
console.log("vault is empty \u2014 `negotium vault set MY_KEY <value> [description]`");
|
|
43764
44217
|
return;
|
|
43765
44218
|
}
|
|
43766
|
-
for (const entry of
|
|
44219
|
+
for (const entry of entries2) {
|
|
43767
44220
|
console.log(`${entry.key} ${entry.description || ""}`.trimEnd());
|
|
43768
44221
|
}
|
|
43769
44222
|
return;
|
|
@@ -44087,6 +44540,12 @@ var CLI_COMMANDS = [
|
|
|
44087
44540
|
description: "bootstrap ~/.negotium and check agent auth",
|
|
44088
44541
|
group: "Setup"
|
|
44089
44542
|
},
|
|
44543
|
+
{
|
|
44544
|
+
name: "migrate",
|
|
44545
|
+
usage: "migrate single-user [--source=local] --delete-other-users --yes",
|
|
44546
|
+
description: "explicitly migrate a 0.1 state tree to the 0.2 single-user layout",
|
|
44547
|
+
group: "Setup"
|
|
44548
|
+
},
|
|
44090
44549
|
{
|
|
44091
44550
|
name: "serve",
|
|
44092
44551
|
usage: "serve [otium]",
|
|
@@ -44193,7 +44652,7 @@ async function runCanonicalNode(port) {
|
|
|
44193
44652
|
});
|
|
44194
44653
|
console.log(`negotium node listening on 127.0.0.1:${node.port} (ctrl-c to stop)`);
|
|
44195
44654
|
await node.completed;
|
|
44196
|
-
await new Promise((
|
|
44655
|
+
await new Promise((resolve26) => setImmediate(resolve26));
|
|
44197
44656
|
process.exit(0);
|
|
44198
44657
|
}
|
|
44199
44658
|
async function stopAdapter(name) {
|
|
@@ -44216,6 +44675,11 @@ switch (command) {
|
|
|
44216
44675
|
initCommand2();
|
|
44217
44676
|
break;
|
|
44218
44677
|
}
|
|
44678
|
+
case "migrate": {
|
|
44679
|
+
const { migrateCommand: migrateCommand2 } = await init_migrate().then(() => exports_migrate);
|
|
44680
|
+
migrateCommand2(args);
|
|
44681
|
+
break;
|
|
44682
|
+
}
|
|
44219
44683
|
case "-v":
|
|
44220
44684
|
case "--version": {
|
|
44221
44685
|
const { NEGOTIUM_VERSION: NEGOTIUM_VERSION2 } = await Promise.resolve().then(() => exports_version);
|
|
@@ -44324,4 +44788,4 @@ switch (command) {
|
|
|
44324
44788
|
}
|
|
44325
44789
|
}
|
|
44326
44790
|
|
|
44327
|
-
//# debugId=
|
|
44791
|
+
//# debugId=0E990AB8BEC23DD564756E2164756E21
|