negotium 0.1.21 → 0.1.23
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 +199 -203
- package/dist/agent-helpers.js.map +10 -10
- package/dist/cron.js +249 -223
- package/dist/cron.js.map +12 -12
- package/dist/hosted-agent.js +249 -253
- package/dist/hosted-agent.js.map +11 -11
- package/dist/main.js +409 -398
- package/dist/main.js.map +14 -14
- package/dist/runtime/scripts/browser-webauthn-policy.mjs +37 -0
- package/dist/runtime/scripts/mcp-patchright-http.mjs +8 -3
- package/dist/runtime/src/agents/claude-provider.ts +11 -5
- package/dist/runtime/src/agents/maestro-provider.ts +4 -1
- package/dist/runtime/src/agents/vault-tool-policy.ts +28 -4
- package/dist/runtime/src/platform/mcp-config.ts +2 -1
- package/dist/runtime/src/platform/playwright/manager.ts +18 -0
- package/dist/runtime/src/prompts/sessions/channel-system.md +1 -1
- package/dist/runtime/src/prompts/sessions/topic-system.md +1 -1
- package/dist/runtime/src/version.ts +1 -1
- package/dist/types/packages/core/src/agents/claude-provider.d.ts +1 -1
- package/dist/types/packages/core/src/agents/vault-tool-policy.d.ts +2 -1
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/agent-helpers.js
CHANGED
|
@@ -1787,197 +1787,6 @@ function isSensitivePath(filePath) {
|
|
|
1787
1787
|
return false;
|
|
1788
1788
|
}
|
|
1789
1789
|
|
|
1790
|
-
// ../../packages/core/src/storage/vault.ts
|
|
1791
|
-
import { chmodSync as chmodSync2, mkdirSync as mkdirSync7 } from "fs";
|
|
1792
|
-
import { join as join10 } from "path";
|
|
1793
|
-
|
|
1794
|
-
// ../../packages/core/src/storage/vault-crypto.ts
|
|
1795
|
-
import { createCipheriv, createDecipheriv, createHash, randomBytes as randomBytes3 } from "crypto";
|
|
1796
|
-
var ENVELOPE_PREFIX = "otium-vault:v1:";
|
|
1797
|
-
var IV_BYTES = 12;
|
|
1798
|
-
var KEY_BYTES = 32;
|
|
1799
|
-
function encryptionKey(masterKey = VAULT_MASTER_KEY) {
|
|
1800
|
-
return createHash("sha256").update("otium-vault-value-v1\x00", "utf8").update(masterKey, "utf8").digest().subarray(0, KEY_BYTES);
|
|
1801
|
-
}
|
|
1802
|
-
function aad(userId, key) {
|
|
1803
|
-
return Buffer.from(`${userId}\x00${key.toUpperCase()}`, "utf8");
|
|
1804
|
-
}
|
|
1805
|
-
function isEncryptedVaultValue(value) {
|
|
1806
|
-
return value.startsWith(ENVELOPE_PREFIX);
|
|
1807
|
-
}
|
|
1808
|
-
function encryptVaultValue(userId, key, value, masterKey = VAULT_MASTER_KEY) {
|
|
1809
|
-
const iv = randomBytes3(IV_BYTES);
|
|
1810
|
-
const cipher = createCipheriv("aes-256-gcm", encryptionKey(masterKey), iv);
|
|
1811
|
-
cipher.setAAD(aad(userId, key));
|
|
1812
|
-
const ciphertext = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
|
|
1813
|
-
const tag = cipher.getAuthTag();
|
|
1814
|
-
return `${ENVELOPE_PREFIX}${iv.toString("base64url")}.${ciphertext.toString("base64url")}.${tag.toString("base64url")}`;
|
|
1815
|
-
}
|
|
1816
|
-
function decryptVaultValue(userId, key, storedValue, masterKey = VAULT_MASTER_KEY) {
|
|
1817
|
-
if (!isEncryptedVaultValue(storedValue)) {
|
|
1818
|
-
return { value: storedValue, legacyPlaintext: true };
|
|
1819
|
-
}
|
|
1820
|
-
const encoded = storedValue.slice(ENVELOPE_PREFIX.length);
|
|
1821
|
-
const [ivPart, ciphertextPart, tagPart, ...extra] = encoded.split(".");
|
|
1822
|
-
if (!ivPart || ciphertextPart === undefined || !tagPart || extra.length > 0) {
|
|
1823
|
-
throw new Error("Invalid encrypted vault value");
|
|
1824
|
-
}
|
|
1825
|
-
const iv = Buffer.from(ivPart, "base64url");
|
|
1826
|
-
const ciphertext = Buffer.from(ciphertextPart, "base64url");
|
|
1827
|
-
const tag = Buffer.from(tagPart, "base64url");
|
|
1828
|
-
if (iv.length !== IV_BYTES || tag.length !== 16) {
|
|
1829
|
-
throw new Error("Invalid encrypted vault value");
|
|
1830
|
-
}
|
|
1831
|
-
const decipher = createDecipheriv("aes-256-gcm", encryptionKey(masterKey), iv);
|
|
1832
|
-
decipher.setAAD(aad(userId, key));
|
|
1833
|
-
decipher.setAuthTag(tag);
|
|
1834
|
-
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
1835
|
-
return { value: plaintext.toString("utf8"), legacyPlaintext: false };
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
// ../../packages/core/src/storage/vault.ts
|
|
1839
|
-
var vaultDb;
|
|
1840
|
-
var vaultMasterKey = VAULT_MASTER_KEY;
|
|
1841
|
-
function initializeVaultDatabase(database) {
|
|
1842
|
-
database.exec("PRAGMA journal_mode = WAL");
|
|
1843
|
-
database.exec("PRAGMA busy_timeout = 5000");
|
|
1844
|
-
database.exec(`
|
|
1845
|
-
CREATE TABLE IF NOT EXISTS vault (
|
|
1846
|
-
user_id TEXT NOT NULL,
|
|
1847
|
-
key TEXT NOT NULL,
|
|
1848
|
-
value TEXT NOT NULL,
|
|
1849
|
-
description TEXT NOT NULL DEFAULT '',
|
|
1850
|
-
PRIMARY KEY (user_id, key)
|
|
1851
|
-
)
|
|
1852
|
-
`);
|
|
1853
|
-
{
|
|
1854
|
-
const cols = database.prepare("PRAGMA table_info(vault)").all();
|
|
1855
|
-
const uid = cols.find((c) => c.name === "user_id");
|
|
1856
|
-
if (uid && uid.type.toUpperCase() === "INTEGER") {
|
|
1857
|
-
database.exec("BEGIN");
|
|
1858
|
-
database.exec(`
|
|
1859
|
-
CREATE TABLE vault_migrated (
|
|
1860
|
-
user_id TEXT NOT NULL,
|
|
1861
|
-
key TEXT NOT NULL,
|
|
1862
|
-
value TEXT NOT NULL,
|
|
1863
|
-
description TEXT NOT NULL DEFAULT '',
|
|
1864
|
-
PRIMARY KEY (user_id, key)
|
|
1865
|
-
)
|
|
1866
|
-
`);
|
|
1867
|
-
database.exec("INSERT INTO vault_migrated SELECT CAST(user_id AS TEXT), key, value, description FROM vault");
|
|
1868
|
-
database.exec("DROP TABLE vault");
|
|
1869
|
-
database.exec("ALTER TABLE vault_migrated RENAME TO vault");
|
|
1870
|
-
database.exec("COMMIT");
|
|
1871
|
-
}
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
function openVaultDatabase(dataDir) {
|
|
1875
|
-
const path = join10(dataDir, "vault.db");
|
|
1876
|
-
mkdirSync7(dataDir, { recursive: true });
|
|
1877
|
-
const database = new Database(path, { create: true });
|
|
1878
|
-
chmodSync2(path, 384);
|
|
1879
|
-
initializeVaultDatabase(database);
|
|
1880
|
-
return database;
|
|
1881
|
-
}
|
|
1882
|
-
function activeVaultDatabase() {
|
|
1883
|
-
if (!vaultDb)
|
|
1884
|
-
vaultDb = openVaultDatabase(DATA_DIR);
|
|
1885
|
-
return vaultDb;
|
|
1886
|
-
}
|
|
1887
|
-
var VAULT_VALUE_MAX_BYTES = 64 * 1024;
|
|
1888
|
-
function normalizeVaultKey(key) {
|
|
1889
|
-
return key.trim().toUpperCase();
|
|
1890
|
-
}
|
|
1891
|
-
function decryptRow(userId, key, storedValue) {
|
|
1892
|
-
const database = activeVaultDatabase();
|
|
1893
|
-
const decoded = decryptVaultValue(userId, key, storedValue, vaultMasterKey);
|
|
1894
|
-
if (decoded.legacyPlaintext) {
|
|
1895
|
-
database.prepare("UPDATE vault SET value = ? WHERE user_id = ? AND key = ? AND value = ?").run(encryptVaultValue(userId, key, decoded.value, vaultMasterKey), userId, key, storedValue);
|
|
1896
|
-
}
|
|
1897
|
-
return decoded.value;
|
|
1898
|
-
}
|
|
1899
|
-
function vaultListWithValues(userId) {
|
|
1900
|
-
const rows = activeVaultDatabase().prepare("SELECT key, description, value FROM vault WHERE user_id = ? ORDER BY key").all(userId);
|
|
1901
|
-
return rows.map((row) => ({
|
|
1902
|
-
key: row.key,
|
|
1903
|
-
description: row.description,
|
|
1904
|
-
value: decryptRow(userId, row.key, row.value)
|
|
1905
|
-
}));
|
|
1906
|
-
}
|
|
1907
|
-
function vaultList(userId) {
|
|
1908
|
-
return activeVaultDatabase().prepare("SELECT key, description FROM vault WHERE user_id = ? ORDER BY key").all(userId);
|
|
1909
|
-
}
|
|
1910
|
-
function vaultSubstituteDetailed(userId, text) {
|
|
1911
|
-
const entries = new Map(vaultListWithValues(userId).map((entry) => [entry.key, entry.value]));
|
|
1912
|
-
const usedKeys = new Set;
|
|
1913
|
-
const substituted = text.replace(/\{\{([^}]+)\}\}/g, (match, rawKey) => {
|
|
1914
|
-
const key = normalizeVaultKey(rawKey);
|
|
1915
|
-
const value = entries.get(key);
|
|
1916
|
-
if (value === undefined)
|
|
1917
|
-
return match;
|
|
1918
|
-
usedKeys.add(key);
|
|
1919
|
-
return value;
|
|
1920
|
-
});
|
|
1921
|
-
return { text: substituted, usedKeys: [...usedKeys] };
|
|
1922
|
-
}
|
|
1923
|
-
function valueReferencesVaultKey(userId, value) {
|
|
1924
|
-
const keys = new Set(vaultList(userId).map((entry) => entry.key));
|
|
1925
|
-
const visit = (candidate) => {
|
|
1926
|
-
if (typeof candidate === "string") {
|
|
1927
|
-
for (const match of candidate.matchAll(/\{\{([^}]+)\}\}/g)) {
|
|
1928
|
-
if (keys.has(normalizeVaultKey(match[1] ?? "")))
|
|
1929
|
-
return true;
|
|
1930
|
-
}
|
|
1931
|
-
return false;
|
|
1932
|
-
}
|
|
1933
|
-
if (Array.isArray(candidate))
|
|
1934
|
-
return candidate.some(visit);
|
|
1935
|
-
if (candidate && typeof candidate === "object") {
|
|
1936
|
-
return Object.values(candidate).some(visit);
|
|
1937
|
-
}
|
|
1938
|
-
return false;
|
|
1939
|
-
};
|
|
1940
|
-
return visit(value);
|
|
1941
|
-
}
|
|
1942
|
-
function encodedSecretForms(value) {
|
|
1943
|
-
const forms = new Set([
|
|
1944
|
-
value,
|
|
1945
|
-
encodeURIComponent(value),
|
|
1946
|
-
Buffer.from(value, "utf8").toString("base64"),
|
|
1947
|
-
Buffer.from(value, "utf8").toString("base64url"),
|
|
1948
|
-
Buffer.from(value, "utf8").toString("hex")
|
|
1949
|
-
]);
|
|
1950
|
-
forms.delete("");
|
|
1951
|
-
return [...forms].sort((a, b) => b.length - a.length);
|
|
1952
|
-
}
|
|
1953
|
-
function redactVaultSecrets(userId, text) {
|
|
1954
|
-
const candidates = vaultListWithValues(userId).flatMap((entry) => encodedSecretForms(entry.value).map((form) => ({ form, key: entry.key }))).sort((a, b) => b.form.length - a.form.length || a.key.localeCompare(b.key));
|
|
1955
|
-
if (candidates.length === 0)
|
|
1956
|
-
return text;
|
|
1957
|
-
const candidatesByFirstCharacter = new Map;
|
|
1958
|
-
for (const candidate of candidates) {
|
|
1959
|
-
const first = candidate.form[0];
|
|
1960
|
-
if (!first)
|
|
1961
|
-
continue;
|
|
1962
|
-
const bucket = candidatesByFirstCharacter.get(first) ?? [];
|
|
1963
|
-
bucket.push(candidate);
|
|
1964
|
-
candidatesByFirstCharacter.set(first, bucket);
|
|
1965
|
-
}
|
|
1966
|
-
let redacted = "";
|
|
1967
|
-
let offset = 0;
|
|
1968
|
-
while (offset < text.length) {
|
|
1969
|
-
const match = candidatesByFirstCharacter.get(text[offset] ?? "")?.find((candidate) => text.startsWith(candidate.form, offset));
|
|
1970
|
-
if (!match) {
|
|
1971
|
-
redacted += text[offset];
|
|
1972
|
-
offset += 1;
|
|
1973
|
-
continue;
|
|
1974
|
-
}
|
|
1975
|
-
redacted += `[REDACTED:${match.key}]`;
|
|
1976
|
-
offset += match.form.length;
|
|
1977
|
-
}
|
|
1978
|
-
return redacted;
|
|
1979
|
-
}
|
|
1980
|
-
|
|
1981
1790
|
// ../../packages/core/src/agents/vault-tool-policy.ts
|
|
1982
1791
|
var SENSITIVE_RUNTIME_NAMES = [
|
|
1983
1792
|
"vault.db",
|
|
@@ -1985,7 +1794,16 @@ var SENSITIVE_RUNTIME_NAMES = [
|
|
|
1985
1794
|
"runtime-mcp-secret",
|
|
1986
1795
|
"sessions.db"
|
|
1987
1796
|
];
|
|
1988
|
-
var
|
|
1797
|
+
var DIRECT_VAULT_EXECUTION_TOOLS = new Set(["Bash", "WebFetch"]);
|
|
1798
|
+
function leafToolName(toolName) {
|
|
1799
|
+
const parts = toolName.split("__");
|
|
1800
|
+
return parts.at(-1) ?? toolName;
|
|
1801
|
+
}
|
|
1802
|
+
function shouldSubstituteVaultToolInput(toolName) {
|
|
1803
|
+
const leaf = leafToolName(toolName);
|
|
1804
|
+
return leaf.startsWith("browser_") || DIRECT_VAULT_EXECUTION_TOOLS.has(leaf);
|
|
1805
|
+
}
|
|
1806
|
+
var VAULT_BROKER_REDIRECT_ERROR = "Vault broker redirection is disabled; use {{KEY}} directly in normal tool inputs.";
|
|
1989
1807
|
function createVaultToolPolicy(host) {
|
|
1990
1808
|
function isVaultBrokerTool(toolName) {
|
|
1991
1809
|
return toolName.includes("vault_run") || toolName.includes("vault_http_request");
|
|
@@ -2005,11 +1823,14 @@ function createVaultToolPolicy(host) {
|
|
|
2005
1823
|
return false;
|
|
2006
1824
|
}
|
|
2007
1825
|
function shouldRedirectVaultTool(userId, toolName, input) {
|
|
2008
|
-
return
|
|
1826
|
+
return false;
|
|
2009
1827
|
}
|
|
2010
1828
|
return { isVaultBrokerTool, referencesRuntimeSecretStorage, shouldRedirectVaultTool };
|
|
2011
1829
|
}
|
|
2012
|
-
var defaultVaultToolPolicy = createVaultToolPolicy({
|
|
1830
|
+
var defaultVaultToolPolicy = createVaultToolPolicy({
|
|
1831
|
+
isSensitivePath,
|
|
1832
|
+
valueReferencesVaultKey: () => false
|
|
1833
|
+
});
|
|
2013
1834
|
var isVaultBrokerTool = defaultVaultToolPolicy.isVaultBrokerTool;
|
|
2014
1835
|
var referencesRuntimeSecretStorage = defaultVaultToolPolicy.referencesRuntimeSecretStorage;
|
|
2015
1836
|
var shouldRedirectVaultTool = defaultVaultToolPolicy.shouldRedirectVaultTool;
|
|
@@ -2089,7 +1910,7 @@ function peerSessionBridgeIpcEnv() {
|
|
|
2089
1910
|
|
|
2090
1911
|
// ../../packages/core/src/platform/background-bash/manager.ts
|
|
2091
1912
|
import { execFileSync as execFileSync3, spawn } from "child_process";
|
|
2092
|
-
import { randomBytes as
|
|
1913
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
2093
1914
|
|
|
2094
1915
|
// ../../packages/core/src/platform/delay.ts
|
|
2095
1916
|
var delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -2117,8 +1938,8 @@ function createBackgroundBashManager(options = {}) {
|
|
|
2117
1938
|
const usedPorts = new Set;
|
|
2118
1939
|
const spawning = new Map;
|
|
2119
1940
|
const knownContexts = new Map;
|
|
2120
|
-
const runtimeCapability = options.capability ??
|
|
2121
|
-
const runtimeServerId = options.serverId ??
|
|
1941
|
+
const runtimeCapability = options.capability ?? randomBytes3(32).toString("hex");
|
|
1942
|
+
const runtimeServerId = options.serverId ?? randomBytes3(16).toString("hex");
|
|
2122
1943
|
const serverFile = options.serverFile ?? BACKGROUND_BASH_SERVER;
|
|
2123
1944
|
const basePort = options.basePort ?? BG_BASH_BASE_PORT;
|
|
2124
1945
|
const maxPort = options.maxPort ?? BG_BASH_MAX_PORT;
|
|
@@ -2546,7 +2367,9 @@ var MCP_CATALOG = {
|
|
|
2546
2367
|
vault: {
|
|
2547
2368
|
...commonRuntimeMcpPolicy("vault"),
|
|
2548
2369
|
build({ userId, agent }) {
|
|
2549
|
-
const args = [`--user-id=${userId}
|
|
2370
|
+
const args = [`--user-id=${userId}`];
|
|
2371
|
+
if (agent !== "codex")
|
|
2372
|
+
args.push("--list-only=true");
|
|
2550
2373
|
return buildStdioMcpServer(agent, VAULT_SERVER, args);
|
|
2551
2374
|
}
|
|
2552
2375
|
}
|
|
@@ -2764,6 +2587,175 @@ function getMcpServersForQuery(opts) {
|
|
|
2764
2587
|
});
|
|
2765
2588
|
}
|
|
2766
2589
|
|
|
2590
|
+
// ../../packages/core/src/storage/vault.ts
|
|
2591
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync7 } from "fs";
|
|
2592
|
+
import { join as join10 } from "path";
|
|
2593
|
+
|
|
2594
|
+
// ../../packages/core/src/storage/vault-crypto.ts
|
|
2595
|
+
import { createCipheriv, createDecipheriv, createHash, randomBytes as randomBytes4 } from "crypto";
|
|
2596
|
+
var ENVELOPE_PREFIX = "otium-vault:v1:";
|
|
2597
|
+
var IV_BYTES = 12;
|
|
2598
|
+
var KEY_BYTES = 32;
|
|
2599
|
+
function encryptionKey(masterKey = VAULT_MASTER_KEY) {
|
|
2600
|
+
return createHash("sha256").update("otium-vault-value-v1\x00", "utf8").update(masterKey, "utf8").digest().subarray(0, KEY_BYTES);
|
|
2601
|
+
}
|
|
2602
|
+
function aad(userId, key) {
|
|
2603
|
+
return Buffer.from(`${userId}\x00${key.toUpperCase()}`, "utf8");
|
|
2604
|
+
}
|
|
2605
|
+
function isEncryptedVaultValue(value) {
|
|
2606
|
+
return value.startsWith(ENVELOPE_PREFIX);
|
|
2607
|
+
}
|
|
2608
|
+
function encryptVaultValue(userId, key, value, masterKey = VAULT_MASTER_KEY) {
|
|
2609
|
+
const iv = randomBytes4(IV_BYTES);
|
|
2610
|
+
const cipher = createCipheriv("aes-256-gcm", encryptionKey(masterKey), iv);
|
|
2611
|
+
cipher.setAAD(aad(userId, key));
|
|
2612
|
+
const ciphertext = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
|
|
2613
|
+
const tag = cipher.getAuthTag();
|
|
2614
|
+
return `${ENVELOPE_PREFIX}${iv.toString("base64url")}.${ciphertext.toString("base64url")}.${tag.toString("base64url")}`;
|
|
2615
|
+
}
|
|
2616
|
+
function decryptVaultValue(userId, key, storedValue, masterKey = VAULT_MASTER_KEY) {
|
|
2617
|
+
if (!isEncryptedVaultValue(storedValue)) {
|
|
2618
|
+
return { value: storedValue, legacyPlaintext: true };
|
|
2619
|
+
}
|
|
2620
|
+
const encoded = storedValue.slice(ENVELOPE_PREFIX.length);
|
|
2621
|
+
const [ivPart, ciphertextPart, tagPart, ...extra] = encoded.split(".");
|
|
2622
|
+
if (!ivPart || ciphertextPart === undefined || !tagPart || extra.length > 0) {
|
|
2623
|
+
throw new Error("Invalid encrypted vault value");
|
|
2624
|
+
}
|
|
2625
|
+
const iv = Buffer.from(ivPart, "base64url");
|
|
2626
|
+
const ciphertext = Buffer.from(ciphertextPart, "base64url");
|
|
2627
|
+
const tag = Buffer.from(tagPart, "base64url");
|
|
2628
|
+
if (iv.length !== IV_BYTES || tag.length !== 16) {
|
|
2629
|
+
throw new Error("Invalid encrypted vault value");
|
|
2630
|
+
}
|
|
2631
|
+
const decipher = createDecipheriv("aes-256-gcm", encryptionKey(masterKey), iv);
|
|
2632
|
+
decipher.setAAD(aad(userId, key));
|
|
2633
|
+
decipher.setAuthTag(tag);
|
|
2634
|
+
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
2635
|
+
return { value: plaintext.toString("utf8"), legacyPlaintext: false };
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
// ../../packages/core/src/storage/vault.ts
|
|
2639
|
+
var vaultDb;
|
|
2640
|
+
var vaultMasterKey = VAULT_MASTER_KEY;
|
|
2641
|
+
function initializeVaultDatabase(database) {
|
|
2642
|
+
database.exec("PRAGMA journal_mode = WAL");
|
|
2643
|
+
database.exec("PRAGMA busy_timeout = 5000");
|
|
2644
|
+
database.exec(`
|
|
2645
|
+
CREATE TABLE IF NOT EXISTS vault (
|
|
2646
|
+
user_id TEXT NOT NULL,
|
|
2647
|
+
key TEXT NOT NULL,
|
|
2648
|
+
value TEXT NOT NULL,
|
|
2649
|
+
description TEXT NOT NULL DEFAULT '',
|
|
2650
|
+
PRIMARY KEY (user_id, key)
|
|
2651
|
+
)
|
|
2652
|
+
`);
|
|
2653
|
+
{
|
|
2654
|
+
const cols = database.prepare("PRAGMA table_info(vault)").all();
|
|
2655
|
+
const uid = cols.find((c) => c.name === "user_id");
|
|
2656
|
+
if (uid && uid.type.toUpperCase() === "INTEGER") {
|
|
2657
|
+
database.exec("BEGIN");
|
|
2658
|
+
database.exec(`
|
|
2659
|
+
CREATE TABLE vault_migrated (
|
|
2660
|
+
user_id TEXT NOT NULL,
|
|
2661
|
+
key TEXT NOT NULL,
|
|
2662
|
+
value TEXT NOT NULL,
|
|
2663
|
+
description TEXT NOT NULL DEFAULT '',
|
|
2664
|
+
PRIMARY KEY (user_id, key)
|
|
2665
|
+
)
|
|
2666
|
+
`);
|
|
2667
|
+
database.exec("INSERT INTO vault_migrated SELECT CAST(user_id AS TEXT), key, value, description FROM vault");
|
|
2668
|
+
database.exec("DROP TABLE vault");
|
|
2669
|
+
database.exec("ALTER TABLE vault_migrated RENAME TO vault");
|
|
2670
|
+
database.exec("COMMIT");
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
function openVaultDatabase(dataDir) {
|
|
2675
|
+
const path = join10(dataDir, "vault.db");
|
|
2676
|
+
mkdirSync7(dataDir, { recursive: true });
|
|
2677
|
+
const database = new Database(path, { create: true });
|
|
2678
|
+
chmodSync2(path, 384);
|
|
2679
|
+
initializeVaultDatabase(database);
|
|
2680
|
+
return database;
|
|
2681
|
+
}
|
|
2682
|
+
function activeVaultDatabase() {
|
|
2683
|
+
if (!vaultDb)
|
|
2684
|
+
vaultDb = openVaultDatabase(DATA_DIR);
|
|
2685
|
+
return vaultDb;
|
|
2686
|
+
}
|
|
2687
|
+
var VAULT_VALUE_MAX_BYTES = 64 * 1024;
|
|
2688
|
+
function normalizeVaultKey(key) {
|
|
2689
|
+
return key.trim().toUpperCase();
|
|
2690
|
+
}
|
|
2691
|
+
function decryptRow(userId, key, storedValue) {
|
|
2692
|
+
const database = activeVaultDatabase();
|
|
2693
|
+
const decoded = decryptVaultValue(userId, key, storedValue, vaultMasterKey);
|
|
2694
|
+
if (decoded.legacyPlaintext) {
|
|
2695
|
+
database.prepare("UPDATE vault SET value = ? WHERE user_id = ? AND key = ? AND value = ?").run(encryptVaultValue(userId, key, decoded.value, vaultMasterKey), userId, key, storedValue);
|
|
2696
|
+
}
|
|
2697
|
+
return decoded.value;
|
|
2698
|
+
}
|
|
2699
|
+
function vaultListWithValues(userId) {
|
|
2700
|
+
const rows = activeVaultDatabase().prepare("SELECT key, description, value FROM vault WHERE user_id = ? ORDER BY key").all(userId);
|
|
2701
|
+
return rows.map((row) => ({
|
|
2702
|
+
key: row.key,
|
|
2703
|
+
description: row.description,
|
|
2704
|
+
value: decryptRow(userId, row.key, row.value)
|
|
2705
|
+
}));
|
|
2706
|
+
}
|
|
2707
|
+
function vaultSubstituteDetailed(userId, text) {
|
|
2708
|
+
const entries = new Map(vaultListWithValues(userId).map((entry) => [entry.key, entry.value]));
|
|
2709
|
+
const usedKeys = new Set;
|
|
2710
|
+
const substituted = text.replace(/\{\{([^}]+)\}\}/g, (match, rawKey) => {
|
|
2711
|
+
const key = normalizeVaultKey(rawKey);
|
|
2712
|
+
const value = entries.get(key);
|
|
2713
|
+
if (value === undefined)
|
|
2714
|
+
return match;
|
|
2715
|
+
usedKeys.add(key);
|
|
2716
|
+
return value;
|
|
2717
|
+
});
|
|
2718
|
+
return { text: substituted, usedKeys: [...usedKeys] };
|
|
2719
|
+
}
|
|
2720
|
+
function encodedSecretForms(value) {
|
|
2721
|
+
const forms = new Set([
|
|
2722
|
+
value,
|
|
2723
|
+
encodeURIComponent(value),
|
|
2724
|
+
Buffer.from(value, "utf8").toString("base64"),
|
|
2725
|
+
Buffer.from(value, "utf8").toString("base64url"),
|
|
2726
|
+
Buffer.from(value, "utf8").toString("hex")
|
|
2727
|
+
]);
|
|
2728
|
+
forms.delete("");
|
|
2729
|
+
return [...forms].sort((a, b) => b.length - a.length);
|
|
2730
|
+
}
|
|
2731
|
+
function redactVaultSecrets(userId, text) {
|
|
2732
|
+
const candidates = vaultListWithValues(userId).flatMap((entry) => encodedSecretForms(entry.value).map((form) => ({ form, key: entry.key }))).sort((a, b) => b.form.length - a.form.length || a.key.localeCompare(b.key));
|
|
2733
|
+
if (candidates.length === 0)
|
|
2734
|
+
return text;
|
|
2735
|
+
const candidatesByFirstCharacter = new Map;
|
|
2736
|
+
for (const candidate of candidates) {
|
|
2737
|
+
const first = candidate.form[0];
|
|
2738
|
+
if (!first)
|
|
2739
|
+
continue;
|
|
2740
|
+
const bucket = candidatesByFirstCharacter.get(first) ?? [];
|
|
2741
|
+
bucket.push(candidate);
|
|
2742
|
+
candidatesByFirstCharacter.set(first, bucket);
|
|
2743
|
+
}
|
|
2744
|
+
let redacted = "";
|
|
2745
|
+
let offset = 0;
|
|
2746
|
+
while (offset < text.length) {
|
|
2747
|
+
const match = candidatesByFirstCharacter.get(text[offset] ?? "")?.find((candidate) => text.startsWith(candidate.form, offset));
|
|
2748
|
+
if (!match) {
|
|
2749
|
+
redacted += text[offset];
|
|
2750
|
+
offset += 1;
|
|
2751
|
+
continue;
|
|
2752
|
+
}
|
|
2753
|
+
redacted += `[REDACTED:${match.key}]`;
|
|
2754
|
+
offset += match.form.length;
|
|
2755
|
+
}
|
|
2756
|
+
return redacted;
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2767
2759
|
// ../../packages/core/src/agents/execution-host.ts
|
|
2768
2760
|
var defaultHost = {
|
|
2769
2761
|
getMcpServersForQuery,
|
|
@@ -2848,7 +2840,9 @@ var CLAUDE_DEFAULT_DISALLOWED_TOOLS = [
|
|
|
2848
2840
|
"TaskGet"
|
|
2849
2841
|
];
|
|
2850
2842
|
var CLAUDE_NATIVE_AGENT_TOOLS = ["Task", "Agent", "TaskOutput", "TaskStop"];
|
|
2851
|
-
function substituteClaudeToolInput(userId, input) {
|
|
2843
|
+
function substituteClaudeToolInput(userId, toolName, input) {
|
|
2844
|
+
if (!shouldSubstituteVaultToolInput(toolName))
|
|
2845
|
+
return input;
|
|
2852
2846
|
return deepMapStrings(input, (value) => substituteHostedSecrets(userId, value));
|
|
2853
2847
|
}
|
|
2854
2848
|
function buildClaudeDisallowedTools(extra = undefined) {
|
|
@@ -3089,7 +3083,7 @@ async function* claudeProvider(opts) {
|
|
|
3089
3083
|
};
|
|
3090
3084
|
}
|
|
3091
3085
|
const userId = opts.userId ?? "";
|
|
3092
|
-
const withVault = substituteClaudeToolInput(userId, tool_input);
|
|
3086
|
+
const withVault = substituteClaudeToolInput(userId, tool_name, tool_input);
|
|
3093
3087
|
if (JSON.stringify(withVault) === JSON.stringify(tool_input)) {
|
|
3094
3088
|
return { continue: true };
|
|
3095
3089
|
}
|
|
@@ -3321,7 +3315,7 @@ import { createRequire } from "module";
|
|
|
3321
3315
|
import { dirname as dirname6, join as join11 } from "path";
|
|
3322
3316
|
|
|
3323
3317
|
// ../../packages/core/src/version.ts
|
|
3324
|
-
var NEGOTIUM_VERSION = "0.1.
|
|
3318
|
+
var NEGOTIUM_VERSION = "0.1.23";
|
|
3325
3319
|
|
|
3326
3320
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
3327
3321
|
var NEGOTIUM_MODEL_CATALOG = "negotium-model-catalog.json";
|
|
@@ -3956,10 +3950,12 @@ function buildMaestroDisallowedTools(callerDisallowedTools = []) {
|
|
|
3956
3950
|
function buildVaultHook(userId) {
|
|
3957
3951
|
return {
|
|
3958
3952
|
name: "vault-guard",
|
|
3959
|
-
pre({ input }) {
|
|
3953
|
+
pre({ toolName, input }) {
|
|
3960
3954
|
if (referencesHostedSecretStorage(input)) {
|
|
3961
3955
|
return { decision: "block", error: "Runtime secret storage access is not permitted" };
|
|
3962
3956
|
}
|
|
3957
|
+
if (!shouldSubstituteVaultToolInput(toolName))
|
|
3958
|
+
return { decision: "allow" };
|
|
3963
3959
|
const substituted = deepMapStrings(input, (value) => substituteHostedSecrets(userId, value));
|
|
3964
3960
|
return JSON.stringify(substituted) === JSON.stringify(input) ? { decision: "allow" } : { decision: "modify", input: substituted };
|
|
3965
3961
|
},
|
|
@@ -6365,4 +6361,4 @@ export {
|
|
|
6365
6361
|
VAULT_BROKER_REDIRECT_ERROR
|
|
6366
6362
|
};
|
|
6367
6363
|
|
|
6368
|
-
//# debugId=
|
|
6364
|
+
//# debugId=26F98623C1C9180664756E2164756E21
|