negotium 0.2.0 → 0.2.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 +16 -6
- package/dist/agent-helpers.js.map +6 -5
- package/dist/browser-runtime.js +13 -5
- package/dist/browser-runtime.js.map +5 -4
- package/dist/hosted-agent.js +14 -6
- package/dist/hosted-agent.js.map +6 -5
- package/dist/main.js +185 -31
- package/dist/main.js.map +7 -6
- package/dist/mcp-factories.js +16 -6
- package/dist/mcp-factories.js.map +6 -5
- package/dist/runtime/cron/mcp-server.ts +1 -1
- package/dist/runtime/src/migration/single-user.ts +213 -29
- package/dist/runtime/src/storage/vault-crypto-core.ts +65 -0
- package/dist/runtime/src/storage/vault-crypto.ts +8 -48
- package/dist/runtime/src/version.ts +1 -1
- package/dist/types/packages/core/src/storage/vault-crypto-core.d.ts +6 -0
- package/dist/types/packages/core/src/storage/vault-crypto.d.ts +2 -1
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +13 -5
- package/dist/vault.js.map +5 -4
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -411,9 +411,9 @@ var init_sqlite = __esm(async () => {
|
|
|
411
411
|
}
|
|
412
412
|
});
|
|
413
413
|
|
|
414
|
-
// ../../packages/core/src/storage/vault-crypto.ts
|
|
414
|
+
// ../../packages/core/src/storage/vault-crypto-core.ts
|
|
415
415
|
import { createCipheriv, createDecipheriv, createHash, randomBytes as randomBytes2 } from "crypto";
|
|
416
|
-
function encryptionKey(masterKey
|
|
416
|
+
function encryptionKey(masterKey) {
|
|
417
417
|
return createHash("sha256").update("otium-vault-value-v1\x00", "utf8").update(masterKey, "utf8").digest().subarray(0, KEY_BYTES);
|
|
418
418
|
}
|
|
419
419
|
function aad(userId, key) {
|
|
@@ -422,7 +422,7 @@ function aad(userId, key) {
|
|
|
422
422
|
function isEncryptedVaultValue(value) {
|
|
423
423
|
return value.startsWith(ENVELOPE_PREFIX);
|
|
424
424
|
}
|
|
425
|
-
function
|
|
425
|
+
function encryptVaultValueWithKey(userId, key, value, masterKey) {
|
|
426
426
|
const iv = randomBytes2(IV_BYTES);
|
|
427
427
|
const cipher = createCipheriv("aes-256-gcm", encryptionKey(masterKey), iv);
|
|
428
428
|
cipher.setAAD(aad(userId, key));
|
|
@@ -430,7 +430,7 @@ function encryptVaultValue(userId, key, value, masterKey = VAULT_MASTER_KEY) {
|
|
|
430
430
|
const tag = cipher.getAuthTag();
|
|
431
431
|
return `${ENVELOPE_PREFIX}${iv.toString("base64url")}.${ciphertext.toString("base64url")}.${tag.toString("base64url")}`;
|
|
432
432
|
}
|
|
433
|
-
function
|
|
433
|
+
function decryptVaultValueWithKey(userId, key, storedValue, masterKey) {
|
|
434
434
|
if (!isEncryptedVaultValue(storedValue)) {
|
|
435
435
|
return { value: storedValue, legacyPlaintext: true };
|
|
436
436
|
}
|
|
@@ -452,8 +452,18 @@ function decryptVaultValue(userId, key, storedValue, masterKey = VAULT_MASTER_KE
|
|
|
452
452
|
return { value: plaintext.toString("utf8"), legacyPlaintext: false };
|
|
453
453
|
}
|
|
454
454
|
var ENVELOPE_PREFIX = "otium-vault:v1:", IV_BYTES = 12, KEY_BYTES = 32;
|
|
455
|
+
var init_vault_crypto_core = () => {};
|
|
456
|
+
|
|
457
|
+
// ../../packages/core/src/storage/vault-crypto.ts
|
|
458
|
+
function encryptVaultValue(userId, key, value, masterKey = VAULT_MASTER_KEY) {
|
|
459
|
+
return encryptVaultValueWithKey(userId, key, value, masterKey);
|
|
460
|
+
}
|
|
461
|
+
function decryptVaultValue(userId, key, storedValue, masterKey = VAULT_MASTER_KEY) {
|
|
462
|
+
return decryptVaultValueWithKey(userId, key, storedValue, masterKey);
|
|
463
|
+
}
|
|
455
464
|
var init_vault_crypto = __esm(() => {
|
|
456
465
|
init_config();
|
|
466
|
+
init_vault_crypto_core();
|
|
457
467
|
});
|
|
458
468
|
|
|
459
469
|
// ../../packages/core/src/storage/vault.ts
|
|
@@ -4584,7 +4594,7 @@ var exports_version = {};
|
|
|
4584
4594
|
__export(exports_version, {
|
|
4585
4595
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
4586
4596
|
});
|
|
4587
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
4597
|
+
var NEGOTIUM_VERSION = "0.2.2";
|
|
4588
4598
|
|
|
4589
4599
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
4590
4600
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -43716,18 +43726,49 @@ function addDirectoryContents(operations, sourceDir, destinationDir, stagingDir)
|
|
|
43716
43726
|
});
|
|
43717
43727
|
}
|
|
43718
43728
|
}
|
|
43719
|
-
function
|
|
43729
|
+
function pathWithin(path, root) {
|
|
43730
|
+
return path === root || path.startsWith(`${root}/`);
|
|
43731
|
+
}
|
|
43732
|
+
function collisionPolicy(operation, stateDir2) {
|
|
43733
|
+
const destination = operation.destination;
|
|
43734
|
+
if (!destination || !existsSync36(destination))
|
|
43735
|
+
return;
|
|
43736
|
+
if (pathWithin(destination, join42(stateDir2, "runtime")))
|
|
43737
|
+
return "keep-destination";
|
|
43738
|
+
if (pathWithin(destination, join42(stateDir2, "binaries")))
|
|
43739
|
+
return "keep-destination";
|
|
43740
|
+
if (pathWithin(destination, join42(stateDir2, "secrets")))
|
|
43741
|
+
return "replace-destination";
|
|
43742
|
+
if (destination === join42(stateDir2, "data", "vault", "vault.db")) {
|
|
43743
|
+
return "replace-destination";
|
|
43744
|
+
}
|
|
43745
|
+
if (pathWithin(destination, join42(stateDir2, "browser", "profiles"))) {
|
|
43746
|
+
return "replace-destination";
|
|
43747
|
+
}
|
|
43748
|
+
if (pathWithin(destination, join42(stateDir2, "data", "conversations")) && destination.endsWith(".jsonl")) {
|
|
43749
|
+
return "merge-jsonl";
|
|
43750
|
+
}
|
|
43751
|
+
if (pathWithin(destination, join42(stateDir2, "data", "tasks")) && destination.endsWith(".json")) {
|
|
43752
|
+
return "merge-tasks";
|
|
43753
|
+
}
|
|
43754
|
+
if (statSync19(operation.source).isFile() && statSync19(destination).isFile() && readFileSync27(operation.source).equals(readFileSync27(destination))) {
|
|
43755
|
+
return "keep-destination";
|
|
43756
|
+
}
|
|
43757
|
+
throw new Error(`Migration collision at ${destination}.`);
|
|
43758
|
+
}
|
|
43759
|
+
function configureCollisions(operations, stateDir2, stagingRoot) {
|
|
43720
43760
|
const destinations = new Set;
|
|
43721
43761
|
for (const operation of operations) {
|
|
43722
43762
|
if (!operation.destination)
|
|
43723
43763
|
continue;
|
|
43724
|
-
if (existsSync36(operation.destination)) {
|
|
43725
|
-
throw new Error(`Migration collision at ${operation.destination}.`);
|
|
43726
|
-
}
|
|
43727
43764
|
if (destinations.has(operation.destination)) {
|
|
43728
43765
|
throw new Error(`Multiple legacy paths target ${operation.destination}.`);
|
|
43729
43766
|
}
|
|
43730
43767
|
destinations.add(operation.destination);
|
|
43768
|
+
operation.collision = collisionPolicy(operation, stateDir2);
|
|
43769
|
+
if (operation.collision && operation.collision !== "keep-destination") {
|
|
43770
|
+
operation.destinationStaged = join42(stagingRoot, randomUUID34());
|
|
43771
|
+
}
|
|
43731
43772
|
}
|
|
43732
43773
|
}
|
|
43733
43774
|
function writeJournal(path, journal) {
|
|
@@ -43736,16 +43777,96 @@ function writeJournal(path, journal) {
|
|
|
43736
43777
|
}
|
|
43737
43778
|
function rollbackFilesystem(journal, journalPath) {
|
|
43738
43779
|
for (const operation of [...journal.operations].reverse()) {
|
|
43739
|
-
|
|
43740
|
-
|
|
43741
|
-
|
|
43742
|
-
|
|
43743
|
-
|
|
43780
|
+
if (operation.state === "placed") {
|
|
43781
|
+
if (operation.collision === "keep-destination" || !operation.destination) {
|
|
43782
|
+
if (existsSync36(operation.staged) && !existsSync36(operation.source)) {
|
|
43783
|
+
mkdirSync35(dirname23(operation.source), { recursive: true });
|
|
43784
|
+
renameSync16(operation.staged, operation.source);
|
|
43785
|
+
}
|
|
43786
|
+
} else if (operation.destination && existsSync36(operation.destination)) {
|
|
43787
|
+
if (operation.collision === "merge-jsonl" || operation.collision === "merge-tasks") {
|
|
43788
|
+
rmSync11(operation.destination, { recursive: true, force: true });
|
|
43789
|
+
if (existsSync36(operation.staged) && !existsSync36(operation.source)) {
|
|
43790
|
+
mkdirSync35(dirname23(operation.source), { recursive: true });
|
|
43791
|
+
renameSync16(operation.staged, operation.source);
|
|
43792
|
+
}
|
|
43793
|
+
} else if (!existsSync36(operation.source)) {
|
|
43794
|
+
mkdirSync35(dirname23(operation.source), { recursive: true });
|
|
43795
|
+
renameSync16(operation.destination, operation.source);
|
|
43796
|
+
}
|
|
43797
|
+
}
|
|
43798
|
+
} else if (existsSync36(operation.staged) && !existsSync36(operation.source)) {
|
|
43799
|
+
mkdirSync35(dirname23(operation.source), { recursive: true });
|
|
43800
|
+
renameSync16(operation.staged, operation.source);
|
|
43801
|
+
}
|
|
43802
|
+
if (operation.destination && operation.destinationStaged && existsSync36(operation.destinationStaged) && !existsSync36(operation.destination)) {
|
|
43803
|
+
mkdirSync35(dirname23(operation.destination), { recursive: true });
|
|
43804
|
+
renameSync16(operation.destinationStaged, operation.destination);
|
|
43805
|
+
}
|
|
43744
43806
|
operation.state = "pending";
|
|
43745
43807
|
}
|
|
43746
43808
|
journal.phase = "filesystem";
|
|
43747
43809
|
writeJournal(journalPath, journal);
|
|
43748
43810
|
}
|
|
43811
|
+
function mergedJsonl(source, destination) {
|
|
43812
|
+
const lines = new Set;
|
|
43813
|
+
for (const path of [source, destination]) {
|
|
43814
|
+
for (const line2 of readFileSync27(path, "utf8").split(/\r?\n/)) {
|
|
43815
|
+
if (line2)
|
|
43816
|
+
lines.add(line2);
|
|
43817
|
+
}
|
|
43818
|
+
}
|
|
43819
|
+
return lines.size > 0 ? `${[...lines].join(`
|
|
43820
|
+
`)}
|
|
43821
|
+
` : "";
|
|
43822
|
+
}
|
|
43823
|
+
function readTaskFile(path) {
|
|
43824
|
+
const parsed = JSON.parse(readFileSync27(path, "utf8"));
|
|
43825
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.tasks)) {
|
|
43826
|
+
throw new Error(`Invalid task file during migration: ${path}`);
|
|
43827
|
+
}
|
|
43828
|
+
return parsed;
|
|
43829
|
+
}
|
|
43830
|
+
function mergedTasks(source, destination) {
|
|
43831
|
+
const legacy = readTaskFile(source).tasks;
|
|
43832
|
+
const current3 = readTaskFile(destination).tasks;
|
|
43833
|
+
const merged = legacy.map((task) => ({ ...task }));
|
|
43834
|
+
const usedIds = new Set(merged.map((task) => String(task.id)));
|
|
43835
|
+
let nextId = Math.max(0, ...[...usedIds].map(Number).filter(Number.isInteger)) + 1;
|
|
43836
|
+
const remapped = new Map;
|
|
43837
|
+
for (const task of current3) {
|
|
43838
|
+
const originalId = String(task.id);
|
|
43839
|
+
const exact = merged.find((candidate) => candidate.id === originalId && JSON.stringify(candidate) === JSON.stringify(task));
|
|
43840
|
+
if (exact) {
|
|
43841
|
+
remapped.set(originalId, originalId);
|
|
43842
|
+
continue;
|
|
43843
|
+
}
|
|
43844
|
+
const id = usedIds.has(originalId) ? String(nextId++) : originalId;
|
|
43845
|
+
usedIds.add(id);
|
|
43846
|
+
remapped.set(originalId, id);
|
|
43847
|
+
merged.push({ ...task, id });
|
|
43848
|
+
}
|
|
43849
|
+
for (const task of merged.slice(legacy.length)) {
|
|
43850
|
+
if (task.blockedBy)
|
|
43851
|
+
task.blockedBy = task.blockedBy.map((id) => remapped.get(id) ?? id);
|
|
43852
|
+
}
|
|
43853
|
+
return `${JSON.stringify({ version: 1, tasks: merged }, null, 2)}
|
|
43854
|
+
`;
|
|
43855
|
+
}
|
|
43856
|
+
function placeOperation(operation) {
|
|
43857
|
+
if (!operation.destination || operation.collision === "keep-destination")
|
|
43858
|
+
return;
|
|
43859
|
+
mkdirSync35(dirname23(operation.destination), { recursive: true });
|
|
43860
|
+
if (operation.collision === "merge-jsonl") {
|
|
43861
|
+
writeFileSync25(operation.destination, mergedJsonl(operation.staged, operation.destinationStaged));
|
|
43862
|
+
return;
|
|
43863
|
+
}
|
|
43864
|
+
if (operation.collision === "merge-tasks") {
|
|
43865
|
+
writeFileSync25(operation.destination, mergedTasks(operation.staged, operation.destinationStaged));
|
|
43866
|
+
return;
|
|
43867
|
+
}
|
|
43868
|
+
renameSync16(operation.staged, operation.destination);
|
|
43869
|
+
}
|
|
43749
43870
|
function tablesWithColumn(database, columnName) {
|
|
43750
43871
|
const tables = database.query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").all();
|
|
43751
43872
|
return tables.map((row) => row.name).filter((table) => database.query(`PRAGMA table_info("${table.replaceAll('"', '""')}")`).all().some((column) => column.name === columnName));
|
|
@@ -43800,8 +43921,8 @@ function migrateDatabase(dbPath, source, masterKey, legacyTopicProfiles = []) {
|
|
|
43800
43921
|
throw new Error("Cannot migrate encrypted vault rows without vault-master-key.");
|
|
43801
43922
|
const rows = database.query("SELECT key, value FROM vault WHERE user_id = ?").all(source);
|
|
43802
43923
|
for (const row of rows) {
|
|
43803
|
-
const plaintext =
|
|
43804
|
-
database.query("UPDATE vault SET value = ? WHERE user_id = ? AND key = ?").run(
|
|
43924
|
+
const plaintext = decryptVaultValueWithKey(source, row.key, row.value, masterKey).value;
|
|
43925
|
+
database.query("UPDATE vault SET value = ? WHERE user_id = ? AND key = ?").run(encryptVaultValueWithKey(CANONICAL_LOCAL_USER_ID, row.key, plaintext, masterKey), source, row.key);
|
|
43805
43926
|
}
|
|
43806
43927
|
}
|
|
43807
43928
|
database.query(`UPDATE ${quote(table)} SET user_id = ? WHERE user_id = ?`).run(CANONICAL_LOCAL_USER_ID, source);
|
|
@@ -43983,7 +44104,7 @@ function migrateSingleUserState(options) {
|
|
|
43983
44104
|
state: "pending"
|
|
43984
44105
|
});
|
|
43985
44106
|
}
|
|
43986
|
-
|
|
44107
|
+
configureCollisions(operations, stateDir2, stagingRoot);
|
|
43987
44108
|
journal = {
|
|
43988
44109
|
id: SINGLE_USER_MIGRATION_ID,
|
|
43989
44110
|
sourcePrincipal: source,
|
|
@@ -43999,21 +44120,43 @@ function migrateSingleUserState(options) {
|
|
|
43999
44120
|
const vaultDbBackup = join42(stagingRoot, "vault.db.rollback");
|
|
44000
44121
|
try {
|
|
44001
44122
|
for (const operation of journal.operations) {
|
|
44002
|
-
if (operation.state === "
|
|
44003
|
-
operation.state = "staged";
|
|
44004
|
-
|
|
44005
|
-
|
|
44006
|
-
|
|
44123
|
+
if (operation.state === "staged")
|
|
44124
|
+
operation.state = "source-staged";
|
|
44125
|
+
if (operation.state === "pending" && !existsSync36(operation.source)) {
|
|
44126
|
+
if (existsSync36(operation.staged))
|
|
44127
|
+
operation.state = "source-staged";
|
|
44128
|
+
else if (operation.destination && existsSync36(operation.destination)) {
|
|
44129
|
+
operation.state = "placed";
|
|
44130
|
+
}
|
|
44007
44131
|
}
|
|
44008
44132
|
if (operation.state === "pending") {
|
|
44009
44133
|
mkdirSync35(dirname23(operation.staged), { recursive: true });
|
|
44010
44134
|
renameSync16(operation.source, operation.staged);
|
|
44011
|
-
operation.state = "staged";
|
|
44135
|
+
operation.state = "source-staged";
|
|
44012
44136
|
writeJournal(journalPath, journal);
|
|
44013
44137
|
}
|
|
44014
|
-
if (operation.state === "staged" && operation.destination) {
|
|
44015
|
-
|
|
44016
|
-
|
|
44138
|
+
if (operation.state === "source-staged" && operation.collision === "replace-destination" && operation.destination && operation.destinationStaged && !existsSync36(operation.staged) && existsSync36(operation.destination) && existsSync36(operation.destinationStaged)) {
|
|
44139
|
+
operation.state = "placed";
|
|
44140
|
+
writeJournal(journalPath, journal);
|
|
44141
|
+
}
|
|
44142
|
+
if (operation.state === "destination-staged" && operation.collision !== "merge-jsonl" && operation.collision !== "merge-tasks" && operation.collision !== "keep-destination" && operation.destination && !existsSync36(operation.staged) && existsSync36(operation.destination)) {
|
|
44143
|
+
operation.state = "placed";
|
|
44144
|
+
writeJournal(journalPath, journal);
|
|
44145
|
+
}
|
|
44146
|
+
if (operation.state === "source-staged") {
|
|
44147
|
+
if (operation.destination && operation.destinationStaged) {
|
|
44148
|
+
if (existsSync36(operation.destination) && !existsSync36(operation.destinationStaged)) {
|
|
44149
|
+
renameSync16(operation.destination, operation.destinationStaged);
|
|
44150
|
+
}
|
|
44151
|
+
if (!existsSync36(operation.destinationStaged)) {
|
|
44152
|
+
throw new Error(`Missing collision backup for ${operation.destination}.`);
|
|
44153
|
+
}
|
|
44154
|
+
}
|
|
44155
|
+
operation.state = "destination-staged";
|
|
44156
|
+
writeJournal(journalPath, journal);
|
|
44157
|
+
}
|
|
44158
|
+
if (operation.state === "destination-staged") {
|
|
44159
|
+
placeOperation(operation);
|
|
44017
44160
|
operation.state = "placed";
|
|
44018
44161
|
writeJournal(journalPath, journal);
|
|
44019
44162
|
}
|
|
@@ -44056,11 +44199,22 @@ function migrateSingleUserState(options) {
|
|
|
44056
44199
|
migratedTables
|
|
44057
44200
|
};
|
|
44058
44201
|
for (const store of ["conversations", "tasks", "users"]) {
|
|
44059
|
-
rmSync11(join42(stateDir2, "data", store, source), {
|
|
44202
|
+
rmSync11(join42(stateDir2, "data", store, source), {
|
|
44203
|
+
recursive: true,
|
|
44204
|
+
force: true
|
|
44205
|
+
});
|
|
44060
44206
|
}
|
|
44061
|
-
rmSync11(join42(stateDir2, "
|
|
44207
|
+
rmSync11(join42(stateDir2, "run"), { recursive: true, force: true });
|
|
44208
|
+
rmSync11(join42(stateDir2, "bin"), { recursive: true, force: true });
|
|
44209
|
+
rmSync11(join42(stateDir2, "workspace", "browser-profiles"), {
|
|
44210
|
+
recursive: true,
|
|
44211
|
+
force: true
|
|
44212
|
+
});
|
|
44062
44213
|
writeFileSync25(markerPath, `${JSON.stringify(marker, null, 2)}
|
|
44063
|
-
`, {
|
|
44214
|
+
`, {
|
|
44215
|
+
mode: 384,
|
|
44216
|
+
flag: "wx"
|
|
44217
|
+
});
|
|
44064
44218
|
journal.phase = "complete";
|
|
44065
44219
|
rmSync11(stagingRoot, { recursive: true, force: true });
|
|
44066
44220
|
return {
|
|
@@ -44082,7 +44236,7 @@ function migrateSingleUserState(options) {
|
|
|
44082
44236
|
}
|
|
44083
44237
|
var CANONICAL_LOCAL_USER_ID = "local", SINGLE_USER_MIGRATION_ID = "negotium-0.2.0-single-user";
|
|
44084
44238
|
var init_single_user = __esm(async () => {
|
|
44085
|
-
|
|
44239
|
+
init_vault_crypto_core();
|
|
44086
44240
|
await init_sqlite();
|
|
44087
44241
|
});
|
|
44088
44242
|
|
|
@@ -44788,4 +44942,4 @@ switch (command) {
|
|
|
44788
44942
|
}
|
|
44789
44943
|
}
|
|
44790
44944
|
|
|
44791
|
-
//# debugId=
|
|
44945
|
+
//# debugId=29CE1495263F2C6864756E2164756E21
|