@runcore-sh/runcore 0.1.8 → 0.1.9
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/access/manifest.d.ts +59 -0
- package/dist/access/manifest.d.ts.map +1 -0
- package/dist/access/manifest.js +251 -0
- package/dist/access/manifest.js.map +1 -0
- package/dist/activity/log.d.ts +1 -1
- package/dist/activity/log.d.ts.map +1 -1
- package/dist/agents/autonomous.d.ts.map +1 -1
- package/dist/agents/autonomous.js +38 -0
- package/dist/agents/autonomous.js.map +1 -1
- package/dist/agents/governance.d.ts +70 -0
- package/dist/agents/governance.d.ts.map +1 -0
- package/dist/agents/governance.js +220 -0
- package/dist/agents/governance.js.map +1 -0
- package/dist/agents/governed-spawn.d.ts +83 -0
- package/dist/agents/governed-spawn.d.ts.map +1 -0
- package/dist/agents/governed-spawn.js +186 -0
- package/dist/agents/governed-spawn.js.map +1 -0
- package/dist/agents/heartbeat.d.ts +91 -0
- package/dist/agents/heartbeat.d.ts.map +1 -0
- package/dist/agents/heartbeat.js +323 -0
- package/dist/agents/heartbeat.js.map +1 -0
- package/dist/agents/index.d.ts +4 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +6 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/spawn-policy.d.ts +45 -0
- package/dist/agents/spawn-policy.d.ts.map +1 -0
- package/dist/agents/spawn-policy.js +202 -0
- package/dist/agents/spawn-policy.js.map +1 -0
- package/dist/alert.d.ts +16 -0
- package/dist/alert.d.ts.map +1 -0
- package/dist/alert.js +70 -0
- package/dist/alert.js.map +1 -0
- package/dist/cli.js +35 -27
- package/dist/cli.js.map +1 -1
- package/dist/credentials/store.d.ts +1 -1
- package/dist/credentials/store.d.ts.map +1 -1
- package/dist/credentials/store.js +14 -3
- package/dist/credentials/store.js.map +1 -1
- package/dist/crystallizer.d.ts +56 -0
- package/dist/crystallizer.d.ts.map +1 -0
- package/dist/crystallizer.js +159 -0
- package/dist/crystallizer.js.map +1 -0
- package/dist/distiller.d.ts +48 -0
- package/dist/distiller.d.ts.map +1 -0
- package/dist/distiller.js +140 -0
- package/dist/distiller.js.map +1 -0
- package/dist/google/auth.d.ts +2 -0
- package/dist/google/auth.d.ts.map +1 -1
- package/dist/google/auth.js +2 -0
- package/dist/google/auth.js.map +1 -1
- package/dist/integrations/gate.d.ts +40 -0
- package/dist/integrations/gate.d.ts.map +1 -0
- package/dist/integrations/gate.js +100 -0
- package/dist/integrations/gate.js.map +1 -0
- package/dist/lib/audit.d.ts +43 -0
- package/dist/lib/audit.d.ts.map +1 -0
- package/dist/lib/audit.js +120 -0
- package/dist/lib/audit.js.map +1 -0
- package/dist/lib/brain-io.d.ts.map +1 -1
- package/dist/lib/brain-io.js +52 -0
- package/dist/lib/brain-io.js.map +1 -1
- package/dist/lib/dpapi.d.ts +14 -0
- package/dist/lib/dpapi.d.ts.map +1 -0
- package/dist/lib/dpapi.js +104 -0
- package/dist/lib/dpapi.js.map +1 -0
- package/dist/lib/glob-match.d.ts +22 -0
- package/dist/lib/glob-match.d.ts.map +1 -0
- package/dist/lib/glob-match.js +64 -0
- package/dist/lib/glob-match.js.map +1 -0
- package/dist/lib/locked.d.ts +40 -0
- package/dist/lib/locked.d.ts.map +1 -0
- package/dist/lib/locked.js +130 -0
- package/dist/lib/locked.js.map +1 -0
- package/dist/llm/complete.d.ts.map +1 -1
- package/dist/llm/complete.js +5 -2
- package/dist/llm/complete.js.map +1 -1
- package/dist/llm/fetch-guard.d.ts +16 -0
- package/dist/llm/fetch-guard.d.ts.map +1 -0
- package/dist/llm/fetch-guard.js +61 -0
- package/dist/llm/fetch-guard.js.map +1 -0
- package/dist/llm/guard.d.ts +40 -0
- package/dist/llm/guard.d.ts.map +1 -0
- package/dist/llm/guard.js +88 -0
- package/dist/llm/guard.js.map +1 -0
- package/dist/llm/membrane.d.ts +46 -0
- package/dist/llm/membrane.d.ts.map +1 -0
- package/dist/llm/membrane.js +123 -0
- package/dist/llm/membrane.js.map +1 -0
- package/dist/llm/providers/index.d.ts +5 -1
- package/dist/llm/providers/index.d.ts.map +1 -1
- package/dist/llm/providers/index.js +8 -1
- package/dist/llm/providers/index.js.map +1 -1
- package/dist/llm/redact.d.ts +39 -0
- package/dist/llm/redact.d.ts.map +1 -0
- package/dist/llm/redact.js +155 -0
- package/dist/llm/redact.js.map +1 -0
- package/dist/llm/sensitive-registry.d.ts +33 -0
- package/dist/llm/sensitive-registry.d.ts.map +1 -0
- package/dist/llm/sensitive-registry.js +106 -0
- package/dist/llm/sensitive-registry.js.map +1 -0
- package/dist/mcp-server.d.ts +11 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +520 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mdns.d.ts +17 -0
- package/dist/mdns.d.ts.map +1 -0
- package/dist/mdns.js +110 -0
- package/dist/mdns.js.map +1 -0
- package/dist/nerve/push.d.ts +26 -0
- package/dist/nerve/push.d.ts.map +1 -0
- package/dist/nerve/push.js +170 -0
- package/dist/nerve/push.js.map +1 -0
- package/dist/nerve/state.d.ts +35 -0
- package/dist/nerve/state.d.ts.map +1 -0
- package/dist/nerve/state.js +257 -0
- package/dist/nerve/state.js.map +1 -0
- package/dist/resend/inbox.d.ts +23 -0
- package/dist/resend/inbox.d.ts.map +1 -0
- package/dist/resend/inbox.js +198 -0
- package/dist/resend/inbox.js.map +1 -0
- package/dist/resend/webhooks.d.ts +30 -0
- package/dist/resend/webhooks.d.ts.map +1 -0
- package/dist/resend/webhooks.js +244 -0
- package/dist/resend/webhooks.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +585 -16
- package/dist/server.js.map +1 -1
- package/dist/settings.d.ts +14 -1
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +32 -1
- package/dist/settings.js.map +1 -1
- package/dist/updater.d.ts +32 -0
- package/dist/updater.d.ts.map +1 -0
- package/dist/updater.js +145 -0
- package/dist/updater.js.map +1 -0
- package/dist/vault/policy.d.ts +42 -0
- package/dist/vault/policy.d.ts.map +1 -0
- package/dist/vault/policy.js +159 -0
- package/dist/vault/policy.js.map +1 -0
- package/dist/vault/store.d.ts +6 -0
- package/dist/vault/store.d.ts.map +1 -1
- package/dist/vault/store.js +15 -5
- package/dist/vault/store.js.map +1 -1
- package/dist/vault/transfer.d.ts +33 -0
- package/dist/vault/transfer.d.ts.map +1 -0
- package/dist/vault/transfer.js +187 -0
- package/dist/vault/transfer.js.map +1 -0
- package/dist/voucher.d.ts +39 -0
- package/dist/voucher.d.ts.map +1 -0
- package/dist/voucher.js +105 -0
- package/dist/voucher.js.map +1 -0
- package/dist/webhooks/handlers.d.ts +10 -0
- package/dist/webhooks/handlers.d.ts.map +1 -1
- package/dist/webhooks/handlers.js +53 -0
- package/dist/webhooks/handlers.js.map +1 -1
- package/dist/webhooks/index.d.ts +2 -2
- package/dist/webhooks/index.d.ts.map +1 -1
- package/dist/webhooks/index.js +2 -2
- package/dist/webhooks/index.js.map +1 -1
- package/dist/webhooks/verify.d.ts +8 -0
- package/dist/webhooks/verify.d.ts.map +1 -1
- package/dist/webhooks/verify.js +56 -0
- package/dist/webhooks/verify.js.map +1 -1
- package/package.json +8 -2
- package/public/board.html +8 -3
- package/public/browser.html +8 -3
- package/public/library.html +8 -3
- package/public/observatory.html +8 -3
- package/public/ops.html +8 -3
- package/public/registry.html +627 -0
- package/public/roadmap.html +975 -0
package/dist/lib/brain-io.js
CHANGED
|
@@ -16,6 +16,10 @@ import { readFileSync, appendFileSync, mkdirSync, existsSync, } from "node:fs";
|
|
|
16
16
|
import { dirname } from "node:path";
|
|
17
17
|
import { createLogger } from "../utils/logger.js";
|
|
18
18
|
import { getEncryptionKey, getWriteEncryptionKey } from "./key-store.js";
|
|
19
|
+
import { logAccess, logAccessSync } from "./audit.js";
|
|
20
|
+
import { assertNotLocked, toBrainRelativePath } from "./locked.js";
|
|
21
|
+
import { getAuditContext } from "./audit.js";
|
|
22
|
+
import { getManifest, canRead, canWrite } from "../access/manifest.js";
|
|
19
23
|
const log = createLogger("brain-io");
|
|
20
24
|
import { shouldEncryptFile } from "./encryption-config.js";
|
|
21
25
|
import { encryptLine, decryptLine, isEncryptedLine, encryptFile, decryptFile, isEncryptedFile, } from "./encryption.js";
|
|
@@ -32,6 +36,37 @@ function writeKey(filePath) {
|
|
|
32
36
|
return null;
|
|
33
37
|
return getWriteEncryptionKey();
|
|
34
38
|
}
|
|
39
|
+
// ── Access enforcement ───────────────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Assert that the current instance (from AuditContext) has access to the path.
|
|
42
|
+
* No-op when instanceName is undefined (backward compatible).
|
|
43
|
+
* Checks the instance's access manifest; logs denied access to audit.
|
|
44
|
+
*
|
|
45
|
+
* @param absolutePath - Absolute file path
|
|
46
|
+
* @param operation - "read" or "write"
|
|
47
|
+
*/
|
|
48
|
+
function assertAccess(absolutePath, operation) {
|
|
49
|
+
const ctx = getAuditContext();
|
|
50
|
+
if (!ctx?.instanceName)
|
|
51
|
+
return; // No instance context — skip check
|
|
52
|
+
const relPath = toBrainRelativePath(absolutePath);
|
|
53
|
+
if (relPath === null)
|
|
54
|
+
return; // Not a brain path
|
|
55
|
+
const manifest = getManifest(ctx.instanceName);
|
|
56
|
+
if (!manifest)
|
|
57
|
+
return; // No manifest loaded — skip (permissive for unknown instances)
|
|
58
|
+
const allowed = operation === "read"
|
|
59
|
+
? canRead(manifest, relPath)
|
|
60
|
+
: canWrite(manifest, relPath);
|
|
61
|
+
if (!allowed) {
|
|
62
|
+
log.warn("Access denied by manifest", {
|
|
63
|
+
instance: ctx.instanceName,
|
|
64
|
+
path: relPath,
|
|
65
|
+
operation,
|
|
66
|
+
});
|
|
67
|
+
throw new Error(`Access denied: ${ctx.instanceName} cannot ${operation} ${relPath}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
35
70
|
// ── Async JSONL (per-line) I/O ───────────────────────────────────────────────
|
|
36
71
|
/**
|
|
37
72
|
* Read a JSONL file, decrypting each line if needed.
|
|
@@ -39,6 +74,9 @@ function writeKey(filePath) {
|
|
|
39
74
|
* Empty/whitespace lines are filtered out.
|
|
40
75
|
*/
|
|
41
76
|
export async function readBrainLines(filePath) {
|
|
77
|
+
assertNotLocked(filePath);
|
|
78
|
+
assertAccess(filePath, "read");
|
|
79
|
+
logAccess(filePath, "readBrainLines");
|
|
42
80
|
let raw;
|
|
43
81
|
try {
|
|
44
82
|
raw = await readFile(filePath, "utf-8");
|
|
@@ -68,6 +106,8 @@ export async function readBrainLines(filePath) {
|
|
|
68
106
|
* The line should be a JSON string (not newline-terminated).
|
|
69
107
|
*/
|
|
70
108
|
export async function appendBrainLine(filePath, jsonLine) {
|
|
109
|
+
assertNotLocked(filePath);
|
|
110
|
+
assertAccess(filePath, "write");
|
|
71
111
|
const key = writeKey(filePath);
|
|
72
112
|
const line = key ? encryptLine(jsonLine, key) : jsonLine;
|
|
73
113
|
await appendFile(filePath, line + "\n", "utf-8");
|
|
@@ -77,6 +117,8 @@ export async function appendBrainLine(filePath, jsonLine) {
|
|
|
77
117
|
* Used for compaction/rotation where the whole file is rewritten.
|
|
78
118
|
*/
|
|
79
119
|
export async function writeBrainLines(filePath, jsonLines) {
|
|
120
|
+
assertNotLocked(filePath);
|
|
121
|
+
assertAccess(filePath, "write");
|
|
80
122
|
const key = writeKey(filePath);
|
|
81
123
|
const output = jsonLines
|
|
82
124
|
.map((l) => (key ? encryptLine(l, key) : l))
|
|
@@ -89,6 +131,9 @@ export async function writeBrainLines(filePath, jsonLines) {
|
|
|
89
131
|
* Returns the plaintext content. Falls back to raw content if not encrypted.
|
|
90
132
|
*/
|
|
91
133
|
export async function readBrainFile(filePath) {
|
|
134
|
+
assertNotLocked(filePath);
|
|
135
|
+
assertAccess(filePath, "read");
|
|
136
|
+
logAccess(filePath, "readBrainFile");
|
|
92
137
|
const raw = await readFile(filePath, "utf-8");
|
|
93
138
|
const key = readKey(filePath);
|
|
94
139
|
if (key && isEncryptedFile(raw)) {
|
|
@@ -101,6 +146,8 @@ export async function readBrainFile(filePath) {
|
|
|
101
146
|
* Creates parent directories if needed.
|
|
102
147
|
*/
|
|
103
148
|
export async function writeBrainFile(filePath, content) {
|
|
149
|
+
assertNotLocked(filePath);
|
|
150
|
+
assertAccess(filePath, "write");
|
|
104
151
|
await mkdir(dirname(filePath), { recursive: true });
|
|
105
152
|
const key = writeKey(filePath);
|
|
106
153
|
const output = key ? encryptFile(content, key) : content;
|
|
@@ -111,6 +158,9 @@ export async function writeBrainFile(filePath, content) {
|
|
|
111
158
|
* Synchronously read a JSONL file, decrypting each line if needed.
|
|
112
159
|
*/
|
|
113
160
|
export function readBrainLinesSync(filePath) {
|
|
161
|
+
assertNotLocked(filePath);
|
|
162
|
+
assertAccess(filePath, "read");
|
|
163
|
+
logAccessSync(filePath, "readBrainLinesSync");
|
|
114
164
|
let raw;
|
|
115
165
|
try {
|
|
116
166
|
raw = readFileSync(filePath, "utf-8");
|
|
@@ -139,6 +189,8 @@ export function readBrainLinesSync(filePath) {
|
|
|
139
189
|
* Synchronously append a single line to a JSONL file, encrypting if enabled.
|
|
140
190
|
*/
|
|
141
191
|
export function appendBrainLineSync(filePath, jsonLine) {
|
|
192
|
+
assertNotLocked(filePath);
|
|
193
|
+
assertAccess(filePath, "write");
|
|
142
194
|
const key = writeKey(filePath);
|
|
143
195
|
const line = key ? encryptLine(jsonLine, key) : jsonLine;
|
|
144
196
|
appendFileSync(filePath, line + "\n", "utf-8");
|
package/dist/lib/brain-io.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brain-io.js","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EACL,YAAY,EAEZ,cAAc,EACd,SAAS,EACT,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"brain-io.js","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DPAPI wrapper — encrypts/decrypts data using Windows Data Protection API.
|
|
3
|
+
* Keys are tied to the current Windows user account.
|
|
4
|
+
* Falls back to plaintext on non-Windows or if DPAPI is unavailable.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Read a session key file. Tries DPAPI-protected format first (.dpapi),
|
|
8
|
+
* falls back to plaintext hex. If plaintext found, migrates to DPAPI.
|
|
9
|
+
* Returns the raw key as a Buffer, or null if not found.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readSessionKey(keyPath: string): Promise<Buffer | null>;
|
|
12
|
+
/** Check if DPAPI is available on this system. */
|
|
13
|
+
export declare function isDpapiAvailable(): boolean;
|
|
14
|
+
//# sourceMappingURL=dpapi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpapi.d.ts","sourceRoot":"","sources":["../../src/lib/dpapi.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkDH;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuC5E;AAED,kDAAkD;AAClD,wBAAgB,gBAAgB,IAAI,OAAO,CAQ1C"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DPAPI wrapper — encrypts/decrypts data using Windows Data Protection API.
|
|
3
|
+
* Keys are tied to the current Windows user account.
|
|
4
|
+
* Falls back to plaintext on non-Windows or if DPAPI is unavailable.
|
|
5
|
+
*/
|
|
6
|
+
import { execSync } from "node:child_process";
|
|
7
|
+
import { readFile, writeFile, realpath } from "node:fs/promises";
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
const IS_WINDOWS = process.platform === "win32";
|
|
10
|
+
/** Encode a PowerShell script as base64 UTF-16LE for -EncodedCommand. */
|
|
11
|
+
function encodePS(script) {
|
|
12
|
+
return Buffer.from(script, "utf16le").toString("base64");
|
|
13
|
+
}
|
|
14
|
+
/** Run a PowerShell script reliably via -EncodedCommand. */
|
|
15
|
+
function runPS(script) {
|
|
16
|
+
const encoded = encodePS(script);
|
|
17
|
+
return execSync(`powershell -NoProfile -EncodedCommand ${encoded}`, { encoding: "utf-8", windowsHide: true }).trim();
|
|
18
|
+
}
|
|
19
|
+
/** DPAPI-protect a Buffer, returns base64-encoded ciphertext. */
|
|
20
|
+
function dpapiProtect(data) {
|
|
21
|
+
const b64Input = data.toString("base64");
|
|
22
|
+
return runPS(`
|
|
23
|
+
Add-Type -AssemblyName System.Security
|
|
24
|
+
$bytes = [Convert]::FromBase64String("${b64Input}")
|
|
25
|
+
$enc = [System.Security.Cryptography.ProtectedData]::Protect(
|
|
26
|
+
$bytes, [byte[]]@(),
|
|
27
|
+
[System.Security.Cryptography.DataProtectionScope]::CurrentUser
|
|
28
|
+
)
|
|
29
|
+
[Convert]::ToBase64String($enc)
|
|
30
|
+
`);
|
|
31
|
+
}
|
|
32
|
+
/** DPAPI-unprotect a base64-encoded ciphertext, returns Buffer. */
|
|
33
|
+
function dpapiUnprotect(b64Ciphertext) {
|
|
34
|
+
const result = runPS(`
|
|
35
|
+
Add-Type -AssemblyName System.Security
|
|
36
|
+
$enc = [Convert]::FromBase64String("${b64Ciphertext}")
|
|
37
|
+
$dec = [System.Security.Cryptography.ProtectedData]::Unprotect(
|
|
38
|
+
$enc, [byte[]]@(),
|
|
39
|
+
[System.Security.Cryptography.DataProtectionScope]::CurrentUser
|
|
40
|
+
)
|
|
41
|
+
[Convert]::ToBase64String($dec)
|
|
42
|
+
`);
|
|
43
|
+
return Buffer.from(result, "base64");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Read a session key file. Tries DPAPI-protected format first (.dpapi),
|
|
47
|
+
* falls back to plaintext hex. If plaintext found, migrates to DPAPI.
|
|
48
|
+
* Returns the raw key as a Buffer, or null if not found.
|
|
49
|
+
*/
|
|
50
|
+
export async function readSessionKey(keyPath) {
|
|
51
|
+
// Resolve symlinks so .dpapi file lands next to the real key
|
|
52
|
+
let resolvedPath = keyPath;
|
|
53
|
+
try {
|
|
54
|
+
resolvedPath = await realpath(keyPath);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// realpath fails if file doesn't exist — use original
|
|
58
|
+
}
|
|
59
|
+
const dpapiPath = resolvedPath + ".dpapi";
|
|
60
|
+
// Try DPAPI-protected version first
|
|
61
|
+
if (IS_WINDOWS && existsSync(dpapiPath)) {
|
|
62
|
+
try {
|
|
63
|
+
const b64 = (await readFile(dpapiPath, "utf-8")).trim();
|
|
64
|
+
if (b64.length > 0)
|
|
65
|
+
return dpapiUnprotect(b64);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// DPAPI decrypt failed — fall through to plaintext
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Try plaintext hex file
|
|
72
|
+
if (!existsSync(resolvedPath))
|
|
73
|
+
return null;
|
|
74
|
+
const hex = (await readFile(resolvedPath, "utf-8")).trim();
|
|
75
|
+
if (!/^[0-9a-f]{64}$/i.test(hex))
|
|
76
|
+
return null;
|
|
77
|
+
const key = Buffer.from(hex, "hex");
|
|
78
|
+
// Migrate: protect with DPAPI and save
|
|
79
|
+
if (IS_WINDOWS) {
|
|
80
|
+
try {
|
|
81
|
+
const protected64 = dpapiProtect(key);
|
|
82
|
+
await writeFile(dpapiPath, protected64, "utf-8");
|
|
83
|
+
// Don't delete the plaintext yet — Dash may still need it
|
|
84
|
+
// until Dash also uses this reader
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// DPAPI not available — keep using plaintext
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return key;
|
|
91
|
+
}
|
|
92
|
+
/** Check if DPAPI is available on this system. */
|
|
93
|
+
export function isDpapiAvailable() {
|
|
94
|
+
if (!IS_WINDOWS)
|
|
95
|
+
return false;
|
|
96
|
+
try {
|
|
97
|
+
dpapiProtect(Buffer.from("test"));
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=dpapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpapi.js","sourceRoot":"","sources":["../../src/lib/dpapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal glob matcher for brain-relative paths.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - `**` — match any number of path segments (including zero)
|
|
6
|
+
* - `*` — match a single path segment (no slashes)
|
|
7
|
+
* - exact — literal string match
|
|
8
|
+
*
|
|
9
|
+
* No external dependencies. Used by vault policy + access manifests.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Test whether a brain-relative path matches a glob pattern.
|
|
13
|
+
*
|
|
14
|
+
* @param pattern - Glob pattern (e.g. "memory/**", "identity/*.md", "ops/audit.jsonl")
|
|
15
|
+
* @param path - Brain-relative path with forward slashes (e.g. "memory/semantic.jsonl")
|
|
16
|
+
*/
|
|
17
|
+
export declare function matchGlob(pattern: string, path: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Test whether a path matches ANY of the given glob patterns.
|
|
20
|
+
*/
|
|
21
|
+
export declare function matchAnyGlob(patterns: string[], path: string): boolean;
|
|
22
|
+
//# sourceMappingURL=glob-match.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-match.d.ts","sourceRoot":"","sources":["../../src/lib/glob-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAqCH;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAIhE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal glob matcher for brain-relative paths.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - `**` — match any number of path segments (including zero)
|
|
6
|
+
* - `*` — match a single path segment (no slashes)
|
|
7
|
+
* - exact — literal string match
|
|
8
|
+
*
|
|
9
|
+
* No external dependencies. Used by vault policy + access manifests.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Convert a glob pattern to a RegExp.
|
|
13
|
+
* Patterns are matched against forward-slash-normalized brain-relative paths.
|
|
14
|
+
*/
|
|
15
|
+
function globToRegex(pattern) {
|
|
16
|
+
// Normalize
|
|
17
|
+
const p = pattern.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
18
|
+
let regex = "^";
|
|
19
|
+
let i = 0;
|
|
20
|
+
while (i < p.length) {
|
|
21
|
+
if (p[i] === "*" && p[i + 1] === "*") {
|
|
22
|
+
// ** — match any depth (including zero segments)
|
|
23
|
+
// Consume trailing slash if present
|
|
24
|
+
i += 2;
|
|
25
|
+
if (p[i] === "/")
|
|
26
|
+
i++;
|
|
27
|
+
regex += "(?:.+/)?";
|
|
28
|
+
}
|
|
29
|
+
else if (p[i] === "*") {
|
|
30
|
+
// * — match single segment (no slashes)
|
|
31
|
+
regex += "[^/]+";
|
|
32
|
+
i++;
|
|
33
|
+
}
|
|
34
|
+
else if (".+?^${}()|[]\\".includes(p[i])) {
|
|
35
|
+
// Escape regex special chars
|
|
36
|
+
regex += "\\" + p[i];
|
|
37
|
+
i++;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
regex += p[i];
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
regex += "$";
|
|
45
|
+
return new RegExp(regex);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Test whether a brain-relative path matches a glob pattern.
|
|
49
|
+
*
|
|
50
|
+
* @param pattern - Glob pattern (e.g. "memory/**", "identity/*.md", "ops/audit.jsonl")
|
|
51
|
+
* @param path - Brain-relative path with forward slashes (e.g. "memory/semantic.jsonl")
|
|
52
|
+
*/
|
|
53
|
+
export function matchGlob(pattern, path) {
|
|
54
|
+
const normalized = path.replace(/\\/g, "/");
|
|
55
|
+
const re = globToRegex(pattern);
|
|
56
|
+
return re.test(normalized);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Test whether a path matches ANY of the given glob patterns.
|
|
60
|
+
*/
|
|
61
|
+
export function matchAnyGlob(patterns, path) {
|
|
62
|
+
return patterns.some((p) => matchGlob(p, path));
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=glob-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-match.js","sourceRoot":"","sources":["../../src/lib/glob-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;GAGG;AACH,SAAS,WAAW,CAAC,OAAe;IAClC,YAAY;IACZ,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE1D,IAAI,KAAK,GAAG,GAAG,CAAC;IAChB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACrC,iDAAiD;YACjD,oCAAoC;YACpC,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,CAAC,EAAE,CAAC;YACtB,KAAK,IAAI,UAAU,CAAC;QACtB,CAAC;aAAM,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACxB,wCAAwC;YACxC,KAAK,IAAI,OAAO,CAAC;YACjB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,6BAA6B;YAC7B,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACrB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,CAAC;YACN,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACd,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IACD,KAAK,IAAI,GAAG,CAAC;IAEb,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,IAAY;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB,EAAE,IAAY;IAC3D,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized .locked file enforcement for brain paths.
|
|
3
|
+
*
|
|
4
|
+
* Shared by both MCP server (stdio) and direct file access (brain-io).
|
|
5
|
+
* Ensures locked paths are consistently protected regardless of access channel.
|
|
6
|
+
*
|
|
7
|
+
* Lock rules:
|
|
8
|
+
* - Exact path match (e.g. "identity/human.json")
|
|
9
|
+
* - Filename-only match (e.g. ".session-key" matches "identity/.session-key")
|
|
10
|
+
* - Directory prefix match (e.g. "identity/" matches "identity/foo.md")
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Read brain/.locked and merge with hardcoded minimums. Caches result.
|
|
14
|
+
* Safe to call multiple times — returns cached paths after first load.
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadLockedPaths(): Promise<string[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Synchronous variant — reads .locked file on first call, caches after.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadLockedPathsSync(): string[];
|
|
21
|
+
/** Force reload of locked paths (e.g. when listing current locks). */
|
|
22
|
+
export declare function reloadLockedPaths(): Promise<string[]>;
|
|
23
|
+
/** Get the currently cached locked paths. Loads synchronously if not yet cached. */
|
|
24
|
+
export declare function getLockedPaths(): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Check if a brain-relative path (forward slashes) is locked.
|
|
27
|
+
* Matches exact paths, filename-only, and directory prefixes.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isLocked(relPath: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Convert an absolute file path to a brain-relative path.
|
|
32
|
+
* Returns null if the path is not under brain/.
|
|
33
|
+
*/
|
|
34
|
+
export declare function toBrainRelativePath(absolutePath: string): string | null;
|
|
35
|
+
/**
|
|
36
|
+
* Assert that an absolute path is not locked. Throws if locked.
|
|
37
|
+
* No-op for paths outside brain/.
|
|
38
|
+
*/
|
|
39
|
+
export declare function assertNotLocked(absolutePath: string): void;
|
|
40
|
+
//# sourceMappingURL=locked.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locked.d.ts","sourceRoot":"","sources":["../../src/lib/locked.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgBH;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAezD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAkB9C;AAED,sEAAsE;AACtE,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAG3D;AAED,oFAAoF;AACpF,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAGzC;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAajD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASvE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAM1D"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized .locked file enforcement for brain paths.
|
|
3
|
+
*
|
|
4
|
+
* Shared by both MCP server (stdio) and direct file access (brain-io).
|
|
5
|
+
* Ensures locked paths are consistently protected regardless of access channel.
|
|
6
|
+
*
|
|
7
|
+
* Lock rules:
|
|
8
|
+
* - Exact path match (e.g. "identity/human.json")
|
|
9
|
+
* - Filename-only match (e.g. ".session-key" matches "identity/.session-key")
|
|
10
|
+
* - Directory prefix match (e.g. "identity/" matches "identity/foo.md")
|
|
11
|
+
*/
|
|
12
|
+
import { readFile } from "node:fs/promises";
|
|
13
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
14
|
+
import { join, relative, resolve } from "node:path";
|
|
15
|
+
const BRAIN_DIR = resolve(process.cwd(), "brain");
|
|
16
|
+
const LOCKED_FILE = join(BRAIN_DIR, ".locked");
|
|
17
|
+
/** Hardcoded minimum locked paths (always locked even without .locked file). */
|
|
18
|
+
const HARDCODED_LOCKED = [".session-key", "human.json"];
|
|
19
|
+
/** Cached locked paths (relative to brain/, forward slashes). */
|
|
20
|
+
let lockedPaths = [];
|
|
21
|
+
let loaded = false;
|
|
22
|
+
/**
|
|
23
|
+
* Read brain/.locked and merge with hardcoded minimums. Caches result.
|
|
24
|
+
* Safe to call multiple times — returns cached paths after first load.
|
|
25
|
+
*/
|
|
26
|
+
export async function loadLockedPaths() {
|
|
27
|
+
const paths = new Set(HARDCODED_LOCKED);
|
|
28
|
+
try {
|
|
29
|
+
const raw = await readFile(LOCKED_FILE, "utf-8");
|
|
30
|
+
for (const line of raw.split("\n")) {
|
|
31
|
+
const trimmed = line.trim();
|
|
32
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
33
|
+
continue;
|
|
34
|
+
paths.add(trimmed.replace(/\\/g, "/"));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// .locked file doesn't exist — use hardcoded only
|
|
39
|
+
}
|
|
40
|
+
lockedPaths = Array.from(paths);
|
|
41
|
+
loaded = true;
|
|
42
|
+
return lockedPaths;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Synchronous variant — reads .locked file on first call, caches after.
|
|
46
|
+
*/
|
|
47
|
+
export function loadLockedPathsSync() {
|
|
48
|
+
if (loaded)
|
|
49
|
+
return lockedPaths;
|
|
50
|
+
const paths = new Set(HARDCODED_LOCKED);
|
|
51
|
+
try {
|
|
52
|
+
if (existsSync(LOCKED_FILE)) {
|
|
53
|
+
const raw = readFileSync(LOCKED_FILE, "utf-8");
|
|
54
|
+
for (const line of raw.split("\n")) {
|
|
55
|
+
const trimmed = line.trim();
|
|
56
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
57
|
+
continue;
|
|
58
|
+
paths.add(trimmed.replace(/\\/g, "/"));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// .locked file doesn't exist — use hardcoded only
|
|
64
|
+
}
|
|
65
|
+
lockedPaths = Array.from(paths);
|
|
66
|
+
loaded = true;
|
|
67
|
+
return lockedPaths;
|
|
68
|
+
}
|
|
69
|
+
/** Force reload of locked paths (e.g. when listing current locks). */
|
|
70
|
+
export async function reloadLockedPaths() {
|
|
71
|
+
loaded = false;
|
|
72
|
+
return loadLockedPaths();
|
|
73
|
+
}
|
|
74
|
+
/** Get the currently cached locked paths. Loads synchronously if not yet cached. */
|
|
75
|
+
export function getLockedPaths() {
|
|
76
|
+
if (!loaded)
|
|
77
|
+
loadLockedPathsSync();
|
|
78
|
+
return lockedPaths;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Check if a brain-relative path (forward slashes) is locked.
|
|
82
|
+
* Matches exact paths, filename-only, and directory prefixes.
|
|
83
|
+
*/
|
|
84
|
+
export function isLocked(relPath) {
|
|
85
|
+
if (!loaded)
|
|
86
|
+
loadLockedPathsSync();
|
|
87
|
+
const normalized = relPath.replace(/\\/g, "/");
|
|
88
|
+
for (const locked of lockedPaths) {
|
|
89
|
+
// Exact match
|
|
90
|
+
if (normalized === locked)
|
|
91
|
+
return true;
|
|
92
|
+
// Filename-only match (e.g. ".session-key" matches "identity/.session-key")
|
|
93
|
+
const filename = normalized.split("/").pop() ?? "";
|
|
94
|
+
if (filename === locked)
|
|
95
|
+
return true;
|
|
96
|
+
// Directory prefix match (e.g. locked="identity/" matches "identity/foo.md")
|
|
97
|
+
if (locked.endsWith("/") && normalized.startsWith(locked))
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Convert an absolute file path to a brain-relative path.
|
|
104
|
+
* Returns null if the path is not under brain/.
|
|
105
|
+
*/
|
|
106
|
+
export function toBrainRelativePath(absolutePath) {
|
|
107
|
+
try {
|
|
108
|
+
const rel = relative(BRAIN_DIR, absolutePath);
|
|
109
|
+
// Escapes brain/ — not a brain path
|
|
110
|
+
if (rel.startsWith("..") || rel.startsWith("/"))
|
|
111
|
+
return null;
|
|
112
|
+
return rel.replace(/\\/g, "/");
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Assert that an absolute path is not locked. Throws if locked.
|
|
120
|
+
* No-op for paths outside brain/.
|
|
121
|
+
*/
|
|
122
|
+
export function assertNotLocked(absolutePath) {
|
|
123
|
+
const rel = toBrainRelativePath(absolutePath);
|
|
124
|
+
if (rel === null)
|
|
125
|
+
return; // Not a brain path — no lock applies
|
|
126
|
+
if (isLocked(rel)) {
|
|
127
|
+
throw new Error(`🔒 Locked: ${rel} — access denied`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=locked.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locked.js","sourceRoot":"","sources":["../../src/lib/locked.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../src/llm/complete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../src/llm/complete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAUzD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,mCAAmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF"}
|
package/dist/llm/complete.js
CHANGED
|
@@ -8,6 +8,7 @@ import { getProvider } from "./providers/index.js";
|
|
|
8
8
|
import { completeChatCached } from "./cache.js";
|
|
9
9
|
import { LLMError } from "./errors.js";
|
|
10
10
|
import { withRetry } from "./retry.js";
|
|
11
|
+
import { rehydrateResponse } from "./redact.js";
|
|
11
12
|
import { createLogger } from "../utils/logger.js";
|
|
12
13
|
const log = createLogger("llm");
|
|
13
14
|
/**
|
|
@@ -29,10 +30,11 @@ async function completeChatUncached(options) {
|
|
|
29
30
|
messageCount: options.messages.length,
|
|
30
31
|
});
|
|
31
32
|
try {
|
|
32
|
-
|
|
33
|
+
const raw = await withRetry(() => {
|
|
33
34
|
const timeout = AbortSignal.timeout(60_000);
|
|
34
35
|
return provider.completeChat(options.messages, options.model, timeout);
|
|
35
36
|
}, { maxRetries: 3, baseDelayMs: 1_000, maxDelayMs: 30_000 });
|
|
37
|
+
return rehydrateResponse(raw);
|
|
36
38
|
}
|
|
37
39
|
catch (err) {
|
|
38
40
|
// On credit/billing errors from cloud providers, try Ollama as a fallback
|
|
@@ -44,10 +46,11 @@ async function completeChatUncached(options) {
|
|
|
44
46
|
provider: options.provider,
|
|
45
47
|
status: err.statusCode,
|
|
46
48
|
});
|
|
47
|
-
|
|
49
|
+
const fallbackRaw = await withRetry(() => {
|
|
48
50
|
const fallbackTimeout = AbortSignal.timeout(120_000);
|
|
49
51
|
return ollama.completeChat(options.messages, undefined, fallbackTimeout);
|
|
50
52
|
}, { maxRetries: 3, baseDelayMs: 1_000, maxDelayMs: 30_000 });
|
|
53
|
+
return rehydrateResponse(fallbackRaw);
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
throw err;
|
package/dist/llm/complete.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"complete.js","sourceRoot":"","sources":["../../src/llm/complete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;AAYhC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC1D,OAAO,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/E,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,oBAAoB,CAAC,OAA4B;IAC9D,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE/C,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE;QAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;QACjC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;KACtC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,
|
|
1
|
+
{"version":3,"file":"complete.js","sourceRoot":"","sources":["../../src/llm/complete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;AAYhC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC1D,OAAO,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/E,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,oBAAoB,CAAC,OAA4B;IAC9D,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE/C,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE;QAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;QACjC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;KACtC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,CACzB,GAAG,EAAE;YACH,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC5C,OAAO,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACzE,CAAC,EACD,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAC1D,CAAC;QACF,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,0EAA0E;QAC1E,IAAI,GAAG,YAAY,QAAQ,IAAI,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACnF,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;YACnD,IAAI,eAAe,EAAE,CAAC;gBACpB,GAAG,CAAC,IAAI,CAAC,0DAA0D,EAAE;oBACnE,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,MAAM,EAAE,GAAG,CAAC,UAAU;iBACvB,CAAC,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,SAAS,CACjC,GAAG,EAAE;oBACH,MAAM,eAAe,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;oBACrD,OAAO,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;gBAC3E,CAAC,EACD,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAC1D,CAAC;gBACF,OAAO,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global fetch interceptor — defense-in-depth for privateMode + sensitive data redaction.
|
|
3
|
+
*
|
|
4
|
+
* Two layers:
|
|
5
|
+
* 1. privateMode enforcement — blocks outbound requests to known cloud LLM API hosts.
|
|
6
|
+
* 2. Sensitive data redaction — strips secrets/PII from LLM request bodies before network egress.
|
|
7
|
+
*
|
|
8
|
+
* The function-level guard in guard.ts → assertProviderAllowed() remains the
|
|
9
|
+
* primary enforcement. This is the safety net.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Monkey-patch globalThis.fetch to block cloud LLM hosts in privateMode.
|
|
13
|
+
* Safe to call multiple times — only installs once.
|
|
14
|
+
*/
|
|
15
|
+
export declare function installFetchGuard(): void;
|
|
16
|
+
//# sourceMappingURL=fetch-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-guard.d.ts","sourceRoot":"","sources":["../../src/llm/fetch-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAuBH;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAiCxC"}
|