@wrongstack/core 0.260.0 → 0.265.1
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-bridge-BbskZ7HH.d.ts → agent-bridge-DrkBxszZ.d.ts} +1 -1
- package/dist/{agent-subagent-runner-BNIGZx18.d.ts → agent-subagent-runner-DM2pP-B6.d.ts} +116 -12
- package/dist/{brain-C2yDd7Lw.d.ts → brain-BXd_61kQ.d.ts} +32 -3
- package/dist/{compactor-t0R_AIt_.d.ts → compactor-B8pOf45Y.d.ts} +1 -1
- package/dist/{config-FG6As4H5.d.ts → config-BMCj_XDs.d.ts} +86 -12
- package/dist/{context-JFOVvu6z.d.ts → context-MRk5PhNv.d.ts} +26 -1
- package/dist/coordination/index.d.ts +1737 -15
- package/dist/coordination/index.js +3152 -494
- package/dist/coordination/index.js.map +1 -1
- package/dist/{default-config-CXsDvOmP.d.ts → default-config-B0cj-Hry.d.ts} +11 -1
- package/dist/defaults/index.d.ts +28 -28
- package/dist/defaults/index.js +1804 -1363
- package/dist/defaults/index.js.map +1 -1
- package/dist/dispatcher-types.d-BBeXBQgS.d.ts +66 -0
- package/dist/execution/index.d.ts +16 -16
- package/dist/execution/index.js +933 -672
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +1 -1
- package/dist/execution/prompt-enhancer.js +7 -1
- package/dist/execution/prompt-enhancer.js.map +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/extension/index.js.map +1 -1
- package/dist/{goal-preamble-B1IXJtLX.d.ts → goal-preamble-DvHDSKSe.d.ts} +26 -10
- package/dist/{goal-store-CPXz6Mml.d.ts → goal-store-DtLMySNb.d.ts} +1 -1
- package/dist/{index-CebbJB94.d.ts → index-B-ch8K9C.d.ts} +8 -8
- package/dist/{index-BPcg4N3M.d.ts → index-CEDeNodM.d.ts} +5 -5
- package/dist/index.d.ts +189 -104
- package/dist/index.js +24693 -21162
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/infrastructure/index.js +12 -8
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +9 -9
- package/dist/kernel/index.js +7 -2
- package/dist/kernel/index.js.map +1 -1
- package/dist/{llm-selector-DXxI2tlu.d.ts → llm-selector-C0tfTCUe.d.ts} +14 -2
- package/dist/{mcp-servers-OwNHo43-.d.ts → mcp-servers-2x4w6Jn9.d.ts} +3 -3
- package/dist/models/index.d.ts +5 -5
- package/dist/models/index.js +80 -31
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-Djlmq4uB.d.ts → models-registry-DmJlKuNp.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-CEmrSCMJ.d.ts → multi-agent-coordinator-DyCkCZnU.d.ts} +2 -2
- package/dist/{null-fleet-bus-DT92xqgJ.d.ts → null-fleet-bus-CG9QY2aP.d.ts} +6 -6
- package/dist/observability/index.d.ts +2 -2
- package/dist/observability/index.js +8 -3
- package/dist/observability/index.js.map +1 -1
- package/dist/{parallel-eternal-engine-0SItuq5r.d.ts → parallel-eternal-engine-Jw9uhEoT.d.ts} +9 -9
- package/dist/{path-resolver-DKBh6Jlo.d.ts → path-resolver-Dy2ej-gE.d.ts} +3 -3
- package/dist/{permission-BJ7eO9Vl.d.ts → permission-B9SB45lp.d.ts} +1 -1
- package/dist/{permission-policy-DEXOfnpm.d.ts → permission-policy-CkjSXabK.d.ts} +2 -2
- package/dist/{pipeline-zflkI2dp.d.ts → pipeline-DPDxH_7m.d.ts} +59 -4
- package/dist/{plan-templates-BFXyRkEK.d.ts → plan-templates-CzD9GnAU.d.ts} +32 -8
- package/dist/{provider-runner-BC-uywtT.d.ts → provider-runner-DMa70ODu.d.ts} +3 -3
- package/dist/{retry-policy-Cavrzmtk.d.ts → retry-policy-CN0khdlj.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -8
- package/dist/sdd/index.js +313 -122
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-CDvDYXWX.d.ts → secret-vault-B2yw84VT.d.ts} +43 -4
- package/dist/secret-vault-BAKpgFw_.d.ts +57 -0
- package/dist/security/index.d.ts +5 -5
- package/dist/security/index.js +411 -225
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-B7AivHsu.d.ts → selector-CzHh_igB.d.ts} +1 -1
- package/dist/{session-event-bridge-BmIDxdJd.d.ts → session-event-bridge-BUI6Jf-4.d.ts} +8 -2
- package/dist/{session-reader-DtofsB-2.d.ts → session-reader-CMgdMSRP.d.ts} +1 -1
- package/dist/skills/index.js +67 -64
- package/dist/skills/index.js.map +1 -1
- package/dist/storage/index.d.ts +132 -16
- package/dist/storage/index.js +851 -432
- package/dist/storage/index.js.map +1 -1
- package/dist/tools/index.d.ts +57 -0
- package/dist/tools/index.js +411 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types/index.d.ts +21 -21
- package/dist/types/index.js +928 -711
- package/dist/types/index.js.map +1 -1
- package/dist/utils/error.d.ts +7 -0
- package/dist/utils/error.js +8 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/index.d.ts +8 -68
- package/dist/utils/index.js +20 -10
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-CJjEwPXn.d.ts → wstack-paths-hOpNLmvf.d.ts} +2 -0
- package/package.json +5 -1
- package/skills/api-design/SKILL.md +1 -1
- package/skills/audit-log/SKILL.md +6 -6
- package/skills/bug-hunter/SKILL.md +5 -5
- package/skills/chimera/SKILL.md +4 -4
- package/skills/docker-deploy/SKILL.md +1 -1
- package/skills/git-flow/SKILL.md +3 -3
- package/skills/multi-agent/SKILL.md +3 -3
- package/skills/node-modern/SKILL.md +1 -0
- package/skills/observability/SKILL.md +2 -2
- package/skills/output-standards/SKILL.md +51 -28
- package/skills/refactor-planner/SKILL.md +3 -3
- package/skills/security-scanner/SKILL.md +4 -3
- package/skills/tech-stack/SKILL.md +1 -2
- package/dist/package-outdated-watcher-C70ag2G9.d.ts +0 -581
- package/dist/secret-vault-BJDY28ev.d.ts +0 -25
package/dist/security/index.js
CHANGED
|
@@ -44,6 +44,27 @@ var PATTERNS = [
|
|
|
44
44
|
{ type: "postgres_uri", regex: /postgres(?:ql)?:\/\/[^\s"'`]+/g },
|
|
45
45
|
{ type: "mysql_uri", regex: /mysql:\/\/[^\s"'`]+/g },
|
|
46
46
|
{ type: "redis_uri", regex: /redis:\/\/[^\s"'`]+/g },
|
|
47
|
+
// AI/ML provider keys — modern LLM services with well-known prefixes
|
|
48
|
+
{
|
|
49
|
+
type: "huggingface_token",
|
|
50
|
+
// HuggingFace tokens: hf_ followed by 34 alphanumeric chars
|
|
51
|
+
regex: /(?<![A-Za-z0-9])hf_[A-Za-z0-9]{34}(?![A-Za-z0-9])/g
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
type: "replicate_token",
|
|
55
|
+
// Replicate tokens: r8_ followed by 40+ alphanumeric chars
|
|
56
|
+
regex: /(?<![A-Za-z0-9])r8_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: "perplexity_key",
|
|
60
|
+
// Perplexity API keys: pplx- followed by 40+ alphanumeric chars
|
|
61
|
+
regex: /(?<![A-Za-z0-9])pplx-[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: "groq_key",
|
|
65
|
+
// Groq API keys: gsk_ followed by 40+ alphanumeric chars
|
|
66
|
+
regex: /(?<![A-Za-z0-9])gsk_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g
|
|
67
|
+
},
|
|
47
68
|
{
|
|
48
69
|
type: "bearer_token",
|
|
49
70
|
// Anchored with alternation instead of negative lookahead — avoids V8
|
|
@@ -77,6 +98,10 @@ function hasCredentialAnchors(text) {
|
|
|
77
98
|
text.includes("xox") || // Slack token (xoxa/xoxb/xoxp/xoxo/xoxs)
|
|
78
99
|
text.includes("Bearer ") || // Bearer token (space suffix reduces false positives)
|
|
79
100
|
text.includes("/bot") || // Telegram bot token (URL path pattern)
|
|
101
|
+
text.includes("hf_") || // HuggingFace token
|
|
102
|
+
text.includes("r8_") || // Replicate token
|
|
103
|
+
text.includes("pplx-") || // Perplexity API key
|
|
104
|
+
text.includes("gsk_") || // Groq API key
|
|
80
105
|
text.includes("_KEY=") || // High-entropy env vars: API_KEY=, SECRET_KEY=, ...
|
|
81
106
|
text.includes("_TOKEN=") || // ACCESS_TOKEN=, AUTH_TOKEN=, ...
|
|
82
107
|
text.includes("_SECRET=") || // API_SECRET=, CLIENT_SECRET=, ...
|
|
@@ -143,108 +168,6 @@ var DefaultSecretScrubber = class {
|
|
|
143
168
|
return visit(obj);
|
|
144
169
|
}
|
|
145
170
|
};
|
|
146
|
-
|
|
147
|
-
// src/types/errors.ts
|
|
148
|
-
var ERROR_CODES = {
|
|
149
|
-
// Provider
|
|
150
|
-
PROVIDER_RATE_LIMITED: "PROVIDER_RATE_LIMITED",
|
|
151
|
-
PROVIDER_AUTH_FAILED: "PROVIDER_AUTH_FAILED",
|
|
152
|
-
PROVIDER_OVERLOADED: "PROVIDER_OVERLOADED",
|
|
153
|
-
PROVIDER_INVALID_REQUEST: "PROVIDER_INVALID_REQUEST",
|
|
154
|
-
PROVIDER_SERVER_ERROR: "PROVIDER_SERVER_ERROR",
|
|
155
|
-
PROVIDER_NETWORK_ERROR: "PROVIDER_NETWORK_ERROR",
|
|
156
|
-
PROVIDER_CONTEXT_OVERFLOW: "PROVIDER_CONTEXT_OVERFLOW",
|
|
157
|
-
// Tool
|
|
158
|
-
TOOL_NOT_FOUND: "TOOL_NOT_FOUND",
|
|
159
|
-
TOOL_PERMISSION_DENIED: "TOOL_PERMISSION_DENIED",
|
|
160
|
-
TOOL_EXECUTION_FAILED: "TOOL_EXECUTION_FAILED",
|
|
161
|
-
TOOL_TIMEOUT: "TOOL_TIMEOUT",
|
|
162
|
-
TOOL_INPUT_INVALID: "TOOL_INPUT_INVALID",
|
|
163
|
-
// Config
|
|
164
|
-
CONFIG_INVALID: "CONFIG_INVALID",
|
|
165
|
-
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
166
|
-
CONFIG_PARSE_FAILED: "CONFIG_PARSE_FAILED",
|
|
167
|
-
CONFIG_MIGRATION_NEEDED: "CONFIG_MIGRATION_NEEDED",
|
|
168
|
-
// Plugin
|
|
169
|
-
PLUGIN_LOAD_FAILED: "PLUGIN_LOAD_FAILED",
|
|
170
|
-
PLUGIN_API_MISMATCH: "PLUGIN_API_MISMATCH",
|
|
171
|
-
PLUGIN_MISSING_DEPENDENCY: "PLUGIN_MISSING_DEPENDENCY",
|
|
172
|
-
// Agent
|
|
173
|
-
AGENT_ITERATION_LIMIT: "AGENT_ITERATION_LIMIT",
|
|
174
|
-
AGENT_CONTEXT_OVERFLOW: "AGENT_CONTEXT_OVERFLOW",
|
|
175
|
-
AGENT_ABORTED: "AGENT_ABORTED",
|
|
176
|
-
AGENT_RUN_FAILED: "AGENT_RUN_FAILED",
|
|
177
|
-
// Session
|
|
178
|
-
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
179
|
-
SESSION_CORRUPTED: "SESSION_CORRUPTED",
|
|
180
|
-
SESSION_WRITE_FAILED: "SESSION_WRITE_FAILED",
|
|
181
|
-
// Container / Registry
|
|
182
|
-
CONTAINER_TOKEN_ALREADY_BOUND: "CONTAINER_TOKEN_ALREADY_BOUND",
|
|
183
|
-
CONTAINER_TOKEN_NOT_BOUND: "CONTAINER_TOKEN_NOT_BOUND",
|
|
184
|
-
CONTAINER_CIRCULAR_DEPENDENCY: "CONTAINER_CIRCULAR_DEPENDENCY",
|
|
185
|
-
REGISTRY_DUPLICATE: "REGISTRY_DUPLICATE",
|
|
186
|
-
REGISTRY_NOT_FOUND: "REGISTRY_NOT_FOUND",
|
|
187
|
-
REGISTRY_INVALID: "REGISTRY_INVALID",
|
|
188
|
-
// File system
|
|
189
|
-
FS_READ_FAILED: "FS_READ_FAILED",
|
|
190
|
-
FS_WRITE_FAILED: "FS_WRITE_FAILED",
|
|
191
|
-
FS_MKDIR_FAILED: "FS_MKDIR_FAILED",
|
|
192
|
-
FS_DELETE_FAILED: "FS_DELETE_FAILED",
|
|
193
|
-
FS_ATOMIC_WRITE_FAILED: "FS_ATOMIC_WRITE_FAILED",
|
|
194
|
-
// SDD (Spec-Driven Development)
|
|
195
|
-
SDD_VALIDATION_FAILED: "SDD_VALIDATION_FAILED",
|
|
196
|
-
SDD_PARSE_FAILED: "SDD_PARSE_FAILED",
|
|
197
|
-
SDD_INVALID_STATE: "SDD_INVALID_STATE",
|
|
198
|
-
SDD_NOT_READY: "SDD_NOT_READY",
|
|
199
|
-
// General
|
|
200
|
-
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
201
|
-
UNKNOWN: "UNKNOWN"
|
|
202
|
-
};
|
|
203
|
-
var WrongStackError = class extends Error {
|
|
204
|
-
code;
|
|
205
|
-
subsystem;
|
|
206
|
-
severity;
|
|
207
|
-
recoverable;
|
|
208
|
-
context;
|
|
209
|
-
constructor(opts) {
|
|
210
|
-
super(opts.message, { cause: opts.cause });
|
|
211
|
-
this.name = "WrongStackError";
|
|
212
|
-
this.code = opts.code;
|
|
213
|
-
this.subsystem = opts.subsystem;
|
|
214
|
-
this.severity = opts.severity ?? "error";
|
|
215
|
-
this.recoverable = opts.recoverable ?? false;
|
|
216
|
-
this.context = opts.context;
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Render a one-line user-facing description.
|
|
220
|
-
* Subclasses should override for domain-specific formatting.
|
|
221
|
-
*/
|
|
222
|
-
describe() {
|
|
223
|
-
const ctx = this.context ? ` ${formatContext(this.context)}` : "";
|
|
224
|
-
return `${this.code}: ${this.message}${ctx}`;
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
function formatContext(ctx) {
|
|
228
|
-
const parts = Object.entries(ctx).filter(([, v]) => v !== void 0).slice(0, 3).map(([k, v]) => `${k}=${String(v)}`);
|
|
229
|
-
return parts.length > 0 ? `[${parts.join(" ")}]` : "";
|
|
230
|
-
}
|
|
231
|
-
var ConfigError = class extends WrongStackError {
|
|
232
|
-
constructor(opts) {
|
|
233
|
-
super({
|
|
234
|
-
message: opts.message,
|
|
235
|
-
code: opts.code,
|
|
236
|
-
subsystem: "config",
|
|
237
|
-
severity: "fatal",
|
|
238
|
-
recoverable: false,
|
|
239
|
-
context: opts.context,
|
|
240
|
-
cause: opts.cause
|
|
241
|
-
});
|
|
242
|
-
this.name = "ConfigError";
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
// src/types/secret-vault.ts
|
|
247
|
-
var ENCRYPTED_PREFIX = "enc:v1:";
|
|
248
171
|
async function atomicWrite(targetPath, content, opts = {}) {
|
|
249
172
|
const dir = path3.dirname(targetPath);
|
|
250
173
|
await fs.mkdir(dir, { recursive: true });
|
|
@@ -307,6 +230,112 @@ async function renameWithRetry(from, to) {
|
|
|
307
230
|
throw lastErr;
|
|
308
231
|
}
|
|
309
232
|
|
|
233
|
+
// src/utils/error.ts
|
|
234
|
+
function toErrorMessage(err) {
|
|
235
|
+
return err instanceof Error ? err.message : String(err);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/utils/safe-json.ts
|
|
239
|
+
function safeParse(input, maxBytes = 5e6) {
|
|
240
|
+
if (input.length > maxBytes) {
|
|
241
|
+
return { ok: false, error: `Input exceeds limit (${maxBytes} bytes)` };
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
return { ok: true, value: JSON.parse(input) };
|
|
245
|
+
} catch (err) {
|
|
246
|
+
return {
|
|
247
|
+
ok: false,
|
|
248
|
+
error: toErrorMessage(err)
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/utils/expect-defined.ts
|
|
254
|
+
function expectDefined(value, label) {
|
|
255
|
+
if (value === null || value === void 0) {
|
|
256
|
+
const err = new Error("Expected value to be defined");
|
|
257
|
+
err.name = "ExpectDefinedError";
|
|
258
|
+
throw err;
|
|
259
|
+
}
|
|
260
|
+
return value;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// src/utils/glob-match.ts
|
|
264
|
+
function escapeRegex(s) {
|
|
265
|
+
return s.replace(/[.+^${}()|\\]/g, "\\$&");
|
|
266
|
+
}
|
|
267
|
+
var COMPILED_GLOB_CACHE = /* @__PURE__ */ new Map();
|
|
268
|
+
var CACHE_MAX_SIZE = 2e3;
|
|
269
|
+
function getCachedGlob(pattern) {
|
|
270
|
+
const cached = COMPILED_GLOB_CACHE.get(pattern);
|
|
271
|
+
if (cached) return cached;
|
|
272
|
+
if (COMPILED_GLOB_CACHE.size >= CACHE_MAX_SIZE) {
|
|
273
|
+
const keys = [...COMPILED_GLOB_CACHE.keys()];
|
|
274
|
+
for (let i = 0; i < Math.floor(CACHE_MAX_SIZE / 4); i++) {
|
|
275
|
+
COMPILED_GLOB_CACHE.delete(expectDefined(keys[i]));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const re = compileGlob(pattern);
|
|
279
|
+
COMPILED_GLOB_CACHE.set(pattern, re);
|
|
280
|
+
return re;
|
|
281
|
+
}
|
|
282
|
+
var MAX_GLOB_PATTERN_LEN = 1024;
|
|
283
|
+
function compileGlob(pattern) {
|
|
284
|
+
if (pattern.length > MAX_GLOB_PATTERN_LEN) {
|
|
285
|
+
throw new Error(`Glob pattern exceeds ${MAX_GLOB_PATTERN_LEN} characters`);
|
|
286
|
+
}
|
|
287
|
+
let i = 0;
|
|
288
|
+
let re = "^";
|
|
289
|
+
while (i < pattern.length) {
|
|
290
|
+
const c = pattern[i];
|
|
291
|
+
if (c === "*") {
|
|
292
|
+
if (pattern[i + 1] === "*") {
|
|
293
|
+
re += ".*";
|
|
294
|
+
i += 2;
|
|
295
|
+
if (pattern[i] === "/") i++;
|
|
296
|
+
} else {
|
|
297
|
+
re += "[^/]*";
|
|
298
|
+
i++;
|
|
299
|
+
}
|
|
300
|
+
} else if (c === "?") {
|
|
301
|
+
re += "[^/]";
|
|
302
|
+
i++;
|
|
303
|
+
} else if (c === "[") {
|
|
304
|
+
let cls = "[";
|
|
305
|
+
i++;
|
|
306
|
+
if (pattern[i] === "!" || pattern[i] === "^") {
|
|
307
|
+
cls += "^";
|
|
308
|
+
i++;
|
|
309
|
+
}
|
|
310
|
+
while (i < pattern.length && pattern[i] !== "]") {
|
|
311
|
+
const ch = pattern[i] ?? "";
|
|
312
|
+
if (ch === "\\") {
|
|
313
|
+
cls += "\\\\";
|
|
314
|
+
} else if (ch === "]" || ch === "^") {
|
|
315
|
+
cls += `\\${ch}`;
|
|
316
|
+
} else {
|
|
317
|
+
cls += ch;
|
|
318
|
+
}
|
|
319
|
+
i++;
|
|
320
|
+
}
|
|
321
|
+
cls += "]";
|
|
322
|
+
re += cls;
|
|
323
|
+
i++;
|
|
324
|
+
} else {
|
|
325
|
+
re += escapeRegex(c ?? "");
|
|
326
|
+
i++;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
re += "$";
|
|
330
|
+
return new RegExp(re);
|
|
331
|
+
}
|
|
332
|
+
function matchGlob(pattern, input) {
|
|
333
|
+
return getCachedGlob(pattern).test(input);
|
|
334
|
+
}
|
|
335
|
+
function matchAny(patterns, input) {
|
|
336
|
+
return patterns.some((p) => matchGlob(p, input));
|
|
337
|
+
}
|
|
338
|
+
|
|
310
339
|
// src/utils/deep-merge.ts
|
|
311
340
|
var FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set([
|
|
312
341
|
"__proto__",
|
|
@@ -366,12 +395,119 @@ function deepMerge(base, patch, options = {}) {
|
|
|
366
395
|
return out;
|
|
367
396
|
}
|
|
368
397
|
|
|
398
|
+
// src/types/errors.ts
|
|
399
|
+
var ERROR_CODES = {
|
|
400
|
+
// Provider
|
|
401
|
+
PROVIDER_RATE_LIMITED: "PROVIDER_RATE_LIMITED",
|
|
402
|
+
PROVIDER_AUTH_FAILED: "PROVIDER_AUTH_FAILED",
|
|
403
|
+
PROVIDER_OVERLOADED: "PROVIDER_OVERLOADED",
|
|
404
|
+
PROVIDER_INVALID_REQUEST: "PROVIDER_INVALID_REQUEST",
|
|
405
|
+
PROVIDER_SERVER_ERROR: "PROVIDER_SERVER_ERROR",
|
|
406
|
+
PROVIDER_NETWORK_ERROR: "PROVIDER_NETWORK_ERROR",
|
|
407
|
+
PROVIDER_CONTEXT_OVERFLOW: "PROVIDER_CONTEXT_OVERFLOW",
|
|
408
|
+
// Tool
|
|
409
|
+
TOOL_NOT_FOUND: "TOOL_NOT_FOUND",
|
|
410
|
+
TOOL_PERMISSION_DENIED: "TOOL_PERMISSION_DENIED",
|
|
411
|
+
TOOL_EXECUTION_FAILED: "TOOL_EXECUTION_FAILED",
|
|
412
|
+
TOOL_TIMEOUT: "TOOL_TIMEOUT",
|
|
413
|
+
TOOL_INPUT_INVALID: "TOOL_INPUT_INVALID",
|
|
414
|
+
// Config
|
|
415
|
+
CONFIG_INVALID: "CONFIG_INVALID",
|
|
416
|
+
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
417
|
+
CONFIG_PARSE_FAILED: "CONFIG_PARSE_FAILED",
|
|
418
|
+
CONFIG_MIGRATION_NEEDED: "CONFIG_MIGRATION_NEEDED",
|
|
419
|
+
// Plugin
|
|
420
|
+
PLUGIN_LOAD_FAILED: "PLUGIN_LOAD_FAILED",
|
|
421
|
+
PLUGIN_API_MISMATCH: "PLUGIN_API_MISMATCH",
|
|
422
|
+
PLUGIN_MISSING_DEPENDENCY: "PLUGIN_MISSING_DEPENDENCY",
|
|
423
|
+
// Agent
|
|
424
|
+
AGENT_ITERATION_LIMIT: "AGENT_ITERATION_LIMIT",
|
|
425
|
+
AGENT_CONTEXT_OVERFLOW: "AGENT_CONTEXT_OVERFLOW",
|
|
426
|
+
AGENT_ABORTED: "AGENT_ABORTED",
|
|
427
|
+
AGENT_RUN_FAILED: "AGENT_RUN_FAILED",
|
|
428
|
+
// Session
|
|
429
|
+
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
430
|
+
SESSION_CORRUPTED: "SESSION_CORRUPTED",
|
|
431
|
+
SESSION_WRITE_FAILED: "SESSION_WRITE_FAILED",
|
|
432
|
+
// Container / Registry
|
|
433
|
+
CONTAINER_TOKEN_ALREADY_BOUND: "CONTAINER_TOKEN_ALREADY_BOUND",
|
|
434
|
+
CONTAINER_TOKEN_NOT_BOUND: "CONTAINER_TOKEN_NOT_BOUND",
|
|
435
|
+
CONTAINER_CIRCULAR_DEPENDENCY: "CONTAINER_CIRCULAR_DEPENDENCY",
|
|
436
|
+
REGISTRY_DUPLICATE: "REGISTRY_DUPLICATE",
|
|
437
|
+
REGISTRY_NOT_FOUND: "REGISTRY_NOT_FOUND",
|
|
438
|
+
REGISTRY_INVALID: "REGISTRY_INVALID",
|
|
439
|
+
// File system
|
|
440
|
+
FS_READ_FAILED: "FS_READ_FAILED",
|
|
441
|
+
FS_WRITE_FAILED: "FS_WRITE_FAILED",
|
|
442
|
+
FS_MKDIR_FAILED: "FS_MKDIR_FAILED",
|
|
443
|
+
FS_DELETE_FAILED: "FS_DELETE_FAILED",
|
|
444
|
+
FS_ATOMIC_WRITE_FAILED: "FS_ATOMIC_WRITE_FAILED",
|
|
445
|
+
// SDD (Spec-Driven Development)
|
|
446
|
+
SDD_VALIDATION_FAILED: "SDD_VALIDATION_FAILED",
|
|
447
|
+
SDD_PARSE_FAILED: "SDD_PARSE_FAILED",
|
|
448
|
+
SDD_INVALID_STATE: "SDD_INVALID_STATE",
|
|
449
|
+
SDD_NOT_READY: "SDD_NOT_READY",
|
|
450
|
+
// General
|
|
451
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
452
|
+
UNKNOWN: "UNKNOWN"
|
|
453
|
+
};
|
|
454
|
+
var WrongStackError = class extends Error {
|
|
455
|
+
code;
|
|
456
|
+
subsystem;
|
|
457
|
+
severity;
|
|
458
|
+
recoverable;
|
|
459
|
+
context;
|
|
460
|
+
constructor(opts) {
|
|
461
|
+
super(opts.message, { cause: opts.cause });
|
|
462
|
+
this.name = "WrongStackError";
|
|
463
|
+
this.code = opts.code;
|
|
464
|
+
this.subsystem = opts.subsystem;
|
|
465
|
+
this.severity = opts.severity ?? "error";
|
|
466
|
+
this.recoverable = opts.recoverable ?? false;
|
|
467
|
+
this.context = opts.context;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Render a one-line user-facing description.
|
|
471
|
+
* Subclasses should override for domain-specific formatting.
|
|
472
|
+
*/
|
|
473
|
+
describe() {
|
|
474
|
+
const ctx = this.context ? ` ${formatContext(this.context)}` : "";
|
|
475
|
+
return `${this.code}: ${this.message}${ctx}`;
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
function formatContext(ctx) {
|
|
479
|
+
const parts = Object.entries(ctx).filter(([, v]) => v !== void 0).slice(0, 3).map(([k, v]) => `${k}=${String(v)}`);
|
|
480
|
+
return parts.length > 0 ? `[${parts.join(" ")}]` : "";
|
|
481
|
+
}
|
|
482
|
+
var ConfigError = class extends WrongStackError {
|
|
483
|
+
constructor(opts) {
|
|
484
|
+
super({
|
|
485
|
+
message: opts.message,
|
|
486
|
+
code: opts.code,
|
|
487
|
+
subsystem: "config",
|
|
488
|
+
severity: "fatal",
|
|
489
|
+
recoverable: false,
|
|
490
|
+
context: opts.context,
|
|
491
|
+
cause: opts.cause
|
|
492
|
+
});
|
|
493
|
+
this.name = "ConfigError";
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
// src/types/secret-vault.ts
|
|
498
|
+
var ENCRYPTED_PREFIX_PATTERN = /^enc:v(\d+):/;
|
|
499
|
+
function encryptedPrefixForVersion(version) {
|
|
500
|
+
return `enc:v${version}:`;
|
|
501
|
+
}
|
|
502
|
+
|
|
369
503
|
// src/security/secret-vault.ts
|
|
370
504
|
var KEY_BYTES = 32;
|
|
371
505
|
var IV_BYTES = 12;
|
|
372
506
|
var TAG_BYTES = 16;
|
|
373
507
|
var ALGO = "aes-256-gcm";
|
|
374
508
|
var KEY_FILE_MODE = 384;
|
|
509
|
+
var KEY_FILE_MAGIC = Buffer.from("WSKV", "ascii");
|
|
510
|
+
var VERSIONED_KEY_FILE_SIZE = KEY_FILE_MAGIC.length + 1 + KEY_BYTES;
|
|
375
511
|
function checkKeyFilePermissions(keyFile) {
|
|
376
512
|
if (process.platform === "win32") return;
|
|
377
513
|
try {
|
|
@@ -394,11 +530,17 @@ function checkKeyFilePermissions(keyFile) {
|
|
|
394
530
|
var DefaultSecretVault = class {
|
|
395
531
|
keyFile;
|
|
396
532
|
key;
|
|
533
|
+
_keyVersion = 1;
|
|
397
534
|
constructor(opts) {
|
|
398
535
|
this.keyFile = opts.keyFile;
|
|
399
536
|
}
|
|
537
|
+
/** Current key version. Starts at 1; incremented by rotateKey(). */
|
|
538
|
+
get keyVersion() {
|
|
539
|
+
if (!this.key) this.loadOrCreateKey();
|
|
540
|
+
return this._keyVersion;
|
|
541
|
+
}
|
|
400
542
|
isEncrypted(value) {
|
|
401
|
-
return typeof value === "string" &&
|
|
543
|
+
return typeof value === "string" && ENCRYPTED_PREFIX_PATTERN.test(value);
|
|
402
544
|
}
|
|
403
545
|
encrypt(plaintext) {
|
|
404
546
|
if (this.isEncrypted(plaintext)) return plaintext;
|
|
@@ -407,11 +549,20 @@ var DefaultSecretVault = class {
|
|
|
407
549
|
const cipher = createCipheriv(ALGO, key, iv);
|
|
408
550
|
const ct = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
409
551
|
const tag = cipher.getAuthTag();
|
|
410
|
-
|
|
552
|
+
const prefix = encryptedPrefixForVersion(this._keyVersion);
|
|
553
|
+
return `${prefix}${iv.toString("base64")}:${tag.toString("base64")}:${ct.toString("base64")}`;
|
|
411
554
|
}
|
|
412
555
|
decrypt(value) {
|
|
413
556
|
if (!this.isEncrypted(value)) return value;
|
|
414
|
-
const
|
|
557
|
+
const prefixMatch = value.match(ENCRYPTED_PREFIX_PATTERN);
|
|
558
|
+
if (!prefixMatch) {
|
|
559
|
+
throw new ConfigError({
|
|
560
|
+
message: "SecretVault: malformed encrypted value",
|
|
561
|
+
code: ERROR_CODES.CONFIG_PARSE_FAILED,
|
|
562
|
+
context: { field: "encrypted_value" }
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
const rest = value.slice(prefixMatch[0].length);
|
|
415
566
|
const parts = rest.split(":");
|
|
416
567
|
if (parts.length !== 3) {
|
|
417
568
|
throw new ConfigError({
|
|
@@ -440,20 +591,64 @@ var DefaultSecretVault = class {
|
|
|
440
591
|
const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
|
|
441
592
|
return pt.toString("utf8");
|
|
442
593
|
}
|
|
594
|
+
/**
|
|
595
|
+
* Generate a new encryption key, write it to disk, and increment the key version.
|
|
596
|
+
* After rotation, encrypt() emits the new version prefix (e.g. enc:v2:).
|
|
597
|
+
* The caller must re-encrypt existing config values (see rotateConfigKeys()).
|
|
598
|
+
*/
|
|
599
|
+
rotateKey() {
|
|
600
|
+
const oldVersion = this._keyVersion;
|
|
601
|
+
const newKey = randomBytes(KEY_BYTES);
|
|
602
|
+
const newVersion = oldVersion + 1;
|
|
603
|
+
const keyFileBuf = Buffer.alloc(VERSIONED_KEY_FILE_SIZE);
|
|
604
|
+
KEY_FILE_MAGIC.copy(keyFileBuf, 0);
|
|
605
|
+
keyFileBuf[KEY_FILE_MAGIC.length] = newVersion;
|
|
606
|
+
newKey.copy(keyFileBuf, KEY_FILE_MAGIC.length + 1);
|
|
607
|
+
fs2.mkdirSync(path3.dirname(this.keyFile), { recursive: true });
|
|
608
|
+
fs2.writeFileSync(this.keyFile, keyFileBuf, { mode: 384 });
|
|
609
|
+
checkKeyFilePermissions(this.keyFile);
|
|
610
|
+
this.key = newKey;
|
|
611
|
+
this._keyVersion = newVersion;
|
|
612
|
+
return { oldVersion, newVersion };
|
|
613
|
+
}
|
|
443
614
|
loadOrCreateKey() {
|
|
444
615
|
if (this.key) return this.key;
|
|
445
616
|
try {
|
|
446
617
|
const buf = fs2.readFileSync(this.keyFile);
|
|
447
|
-
if (buf.length
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
});
|
|
618
|
+
if (buf.length === KEY_BYTES) {
|
|
619
|
+
this.key = buf;
|
|
620
|
+
this._keyVersion = 1;
|
|
621
|
+
checkKeyFilePermissions(this.keyFile);
|
|
622
|
+
return this.key;
|
|
453
623
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
624
|
+
if (buf.length === VERSIONED_KEY_FILE_SIZE) {
|
|
625
|
+
const magic = buf.subarray(0, KEY_FILE_MAGIC.length);
|
|
626
|
+
if (!magic.equals(KEY_FILE_MAGIC)) {
|
|
627
|
+
throw new ConfigError({
|
|
628
|
+
message: `SecretVault: key file ${this.keyFile} has invalid magic header`,
|
|
629
|
+
code: ERROR_CODES.CONFIG_INVALID,
|
|
630
|
+
context: { keyFile: this.keyFile }
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
const version = buf[KEY_FILE_MAGIC.length];
|
|
634
|
+
const key2 = buf.subarray(KEY_FILE_MAGIC.length + 1);
|
|
635
|
+
if (key2.length !== KEY_BYTES) {
|
|
636
|
+
throw new ConfigError({
|
|
637
|
+
message: `SecretVault: key file ${this.keyFile} has wrong key size (${key2.length} bytes, expected ${KEY_BYTES})`,
|
|
638
|
+
code: ERROR_CODES.CONFIG_INVALID,
|
|
639
|
+
context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: key2.length }
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
this.key = Buffer.from(key2);
|
|
643
|
+
this._keyVersion = version;
|
|
644
|
+
checkKeyFilePermissions(this.keyFile);
|
|
645
|
+
return this.key;
|
|
646
|
+
}
|
|
647
|
+
throw new ConfigError({
|
|
648
|
+
message: `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES} for v1 or ${VERSIONED_KEY_FILE_SIZE} for v2+). Remove it manually to generate a new key.`,
|
|
649
|
+
code: ERROR_CODES.CONFIG_INVALID,
|
|
650
|
+
context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length }
|
|
651
|
+
});
|
|
457
652
|
} catch (err) {
|
|
458
653
|
if (err.code !== "ENOENT") throw err;
|
|
459
654
|
}
|
|
@@ -464,18 +659,36 @@ var DefaultSecretVault = class {
|
|
|
464
659
|
} catch (err) {
|
|
465
660
|
if (err.code !== "EEXIST") throw err;
|
|
466
661
|
const buf = fs2.readFileSync(this.keyFile);
|
|
467
|
-
if (buf.length
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
662
|
+
if (buf.length === KEY_BYTES) {
|
|
663
|
+
this.key = buf;
|
|
664
|
+
this._keyVersion = 1;
|
|
665
|
+
checkKeyFilePermissions(this.keyFile);
|
|
666
|
+
return this.key;
|
|
667
|
+
}
|
|
668
|
+
if (buf.length === VERSIONED_KEY_FILE_SIZE) {
|
|
669
|
+
const magic = buf.subarray(0, KEY_FILE_MAGIC.length);
|
|
670
|
+
if (!magic.equals(KEY_FILE_MAGIC)) {
|
|
671
|
+
throw new ConfigError({
|
|
672
|
+
message: `SecretVault: key file ${this.keyFile} has invalid magic header`,
|
|
673
|
+
code: ERROR_CODES.CONFIG_INVALID,
|
|
674
|
+
context: { keyFile: this.keyFile }
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
const version = buf[KEY_FILE_MAGIC.length];
|
|
678
|
+
const winnerKey = buf.subarray(KEY_FILE_MAGIC.length + 1);
|
|
679
|
+
this.key = Buffer.from(winnerKey);
|
|
680
|
+
this._keyVersion = version;
|
|
681
|
+
checkKeyFilePermissions(this.keyFile);
|
|
682
|
+
return this.key;
|
|
473
683
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
684
|
+
throw new ConfigError({
|
|
685
|
+
message: `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES} for v1 or ${VERSIONED_KEY_FILE_SIZE} for v2+). Remove it manually to generate a new key.`,
|
|
686
|
+
code: ERROR_CODES.CONFIG_INVALID,
|
|
687
|
+
context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length }
|
|
688
|
+
});
|
|
477
689
|
}
|
|
478
690
|
this.key = key;
|
|
691
|
+
this._keyVersion = 1;
|
|
479
692
|
return key;
|
|
480
693
|
}
|
|
481
694
|
};
|
|
@@ -556,6 +769,80 @@ async function migratePlaintextSecrets(configPath, vault, logger) {
|
|
|
556
769
|
);
|
|
557
770
|
return { migrated: counter.n, file: configPath };
|
|
558
771
|
}
|
|
772
|
+
async function rotateConfigKeys(configPath, vault, logger) {
|
|
773
|
+
const log = logger?.info ?? (() => {
|
|
774
|
+
});
|
|
775
|
+
const warn = logger?.warn ?? ((msg) => console.warn(msg));
|
|
776
|
+
let raw;
|
|
777
|
+
try {
|
|
778
|
+
raw = await fs.readFile(configPath, "utf8");
|
|
779
|
+
} catch {
|
|
780
|
+
const { oldVersion: oldVersion2, newVersion: newVersion2 } = vault.rotateKey();
|
|
781
|
+
log(`[secret-vault] Key rotated (v${oldVersion2} \u2192 v${newVersion2}) \u2014 no config file to re-encrypt`);
|
|
782
|
+
return { rotated: 0, oldVersion: oldVersion2, newVersion: newVersion2, file: configPath };
|
|
783
|
+
}
|
|
784
|
+
let parsed;
|
|
785
|
+
try {
|
|
786
|
+
parsed = JSON.parse(raw);
|
|
787
|
+
} catch {
|
|
788
|
+
warn(`[secret-vault] Config file ${configPath} is not valid JSON \u2014 skipping rotation`);
|
|
789
|
+
return { rotated: 0, oldVersion: vault.keyVersion, newVersion: vault.keyVersion, file: configPath };
|
|
790
|
+
}
|
|
791
|
+
const counter = { n: 0 };
|
|
792
|
+
const decrypted = walkDecryptCount(parsed, vault, counter);
|
|
793
|
+
if (counter.n === 0) {
|
|
794
|
+
const { oldVersion: oldVersion2, newVersion: newVersion2 } = vault.rotateKey();
|
|
795
|
+
log(`[secret-vault] Key rotated (v${oldVersion2} \u2192 v${newVersion2}) \u2014 no encrypted fields to re-encrypt`);
|
|
796
|
+
return { rotated: 0, oldVersion: oldVersion2, newVersion: newVersion2, file: configPath };
|
|
797
|
+
}
|
|
798
|
+
const { oldVersion, newVersion } = vault.rotateKey();
|
|
799
|
+
const reencrypted = walkReencrypt(decrypted, vault);
|
|
800
|
+
await atomicWrite(configPath, JSON.stringify(reencrypted, null, 2), { mode: 384 });
|
|
801
|
+
await restrictFilePermissions(configPath, { warn });
|
|
802
|
+
log(`[secret-vault] Key rotated (v${oldVersion} \u2192 v${newVersion}) \u2014 re-encrypted ${counter.n} field(s)`);
|
|
803
|
+
return { rotated: counter.n, oldVersion, newVersion, file: configPath };
|
|
804
|
+
}
|
|
805
|
+
function walkDecryptCount(node, vault, counter) {
|
|
806
|
+
if (node === null || node === void 0) return node;
|
|
807
|
+
if (typeof node !== "object") return node;
|
|
808
|
+
if (Array.isArray(node)) {
|
|
809
|
+
return node.map((item) => walkDecryptCount(item, vault, counter));
|
|
810
|
+
}
|
|
811
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
812
|
+
for (const [k, v] of Object.entries(node)) {
|
|
813
|
+
if (typeof v === "string" && vault.isEncrypted(v)) {
|
|
814
|
+
try {
|
|
815
|
+
out[k] = vault.decrypt(v);
|
|
816
|
+
counter.n++;
|
|
817
|
+
} catch {
|
|
818
|
+
out[k] = v;
|
|
819
|
+
}
|
|
820
|
+
} else if (typeof v === "object" && v !== null) {
|
|
821
|
+
out[k] = walkDecryptCount(v, vault, counter);
|
|
822
|
+
} else {
|
|
823
|
+
out[k] = v;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return out;
|
|
827
|
+
}
|
|
828
|
+
function walkReencrypt(node, vault) {
|
|
829
|
+
if (node === null || node === void 0) return node;
|
|
830
|
+
if (typeof node !== "object") return node;
|
|
831
|
+
if (Array.isArray(node)) {
|
|
832
|
+
return node.map((item) => walkReencrypt(item, vault));
|
|
833
|
+
}
|
|
834
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
835
|
+
for (const [k, v] of Object.entries(node)) {
|
|
836
|
+
if (typeof v === "string" && isSecretField(k) && v.length > 0 && !vault.isEncrypted(v)) {
|
|
837
|
+
out[k] = vault.encrypt(v);
|
|
838
|
+
} else if (typeof v === "object" && v !== null) {
|
|
839
|
+
out[k] = walkReencrypt(v, vault);
|
|
840
|
+
} else {
|
|
841
|
+
out[k] = v;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
return out;
|
|
845
|
+
}
|
|
559
846
|
async function restrictFilePermissions(filePath, opts) {
|
|
560
847
|
const warn = opts?.warn ?? ((msg) => console.warn(msg));
|
|
561
848
|
if (process.platform === "win32") {
|
|
@@ -664,107 +951,6 @@ function getDangerousCapabilities(toolOrCaps) {
|
|
|
664
951
|
(c) => DANGEROUS_FOR_SUBAGENTS.includes(c)
|
|
665
952
|
);
|
|
666
953
|
}
|
|
667
|
-
|
|
668
|
-
// src/utils/expect-defined.ts
|
|
669
|
-
function expectDefined(value, label) {
|
|
670
|
-
if (value === null || value === void 0) {
|
|
671
|
-
const err = new Error("Expected value to be defined");
|
|
672
|
-
err.name = "ExpectDefinedError";
|
|
673
|
-
throw err;
|
|
674
|
-
}
|
|
675
|
-
return value;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
// src/utils/glob-match.ts
|
|
679
|
-
function escapeRegex(s) {
|
|
680
|
-
return s.replace(/[.+^${}()|\\]/g, "\\$&");
|
|
681
|
-
}
|
|
682
|
-
var COMPILED_GLOB_CACHE = /* @__PURE__ */ new Map();
|
|
683
|
-
var CACHE_MAX_SIZE = 2e3;
|
|
684
|
-
function getCachedGlob(pattern) {
|
|
685
|
-
const cached = COMPILED_GLOB_CACHE.get(pattern);
|
|
686
|
-
if (cached) return cached;
|
|
687
|
-
if (COMPILED_GLOB_CACHE.size >= CACHE_MAX_SIZE) {
|
|
688
|
-
const keys = [...COMPILED_GLOB_CACHE.keys()];
|
|
689
|
-
for (let i = 0; i < Math.floor(CACHE_MAX_SIZE / 4); i++) {
|
|
690
|
-
COMPILED_GLOB_CACHE.delete(expectDefined(keys[i]));
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
const re = compileGlob(pattern);
|
|
694
|
-
COMPILED_GLOB_CACHE.set(pattern, re);
|
|
695
|
-
return re;
|
|
696
|
-
}
|
|
697
|
-
var MAX_GLOB_PATTERN_LEN = 1024;
|
|
698
|
-
function compileGlob(pattern) {
|
|
699
|
-
if (pattern.length > MAX_GLOB_PATTERN_LEN) {
|
|
700
|
-
throw new Error(`Glob pattern exceeds ${MAX_GLOB_PATTERN_LEN} characters`);
|
|
701
|
-
}
|
|
702
|
-
let i = 0;
|
|
703
|
-
let re = "^";
|
|
704
|
-
while (i < pattern.length) {
|
|
705
|
-
const c = pattern[i];
|
|
706
|
-
if (c === "*") {
|
|
707
|
-
if (pattern[i + 1] === "*") {
|
|
708
|
-
re += ".*";
|
|
709
|
-
i += 2;
|
|
710
|
-
if (pattern[i] === "/") i++;
|
|
711
|
-
} else {
|
|
712
|
-
re += "[^/]*";
|
|
713
|
-
i++;
|
|
714
|
-
}
|
|
715
|
-
} else if (c === "?") {
|
|
716
|
-
re += "[^/]";
|
|
717
|
-
i++;
|
|
718
|
-
} else if (c === "[") {
|
|
719
|
-
let cls = "[";
|
|
720
|
-
i++;
|
|
721
|
-
if (pattern[i] === "!" || pattern[i] === "^") {
|
|
722
|
-
cls += "^";
|
|
723
|
-
i++;
|
|
724
|
-
}
|
|
725
|
-
while (i < pattern.length && pattern[i] !== "]") {
|
|
726
|
-
const ch = pattern[i] ?? "";
|
|
727
|
-
if (ch === "\\") {
|
|
728
|
-
cls += "\\\\";
|
|
729
|
-
} else if (ch === "]" || ch === "^") {
|
|
730
|
-
cls += `\\${ch}`;
|
|
731
|
-
} else {
|
|
732
|
-
cls += ch;
|
|
733
|
-
}
|
|
734
|
-
i++;
|
|
735
|
-
}
|
|
736
|
-
cls += "]";
|
|
737
|
-
re += cls;
|
|
738
|
-
i++;
|
|
739
|
-
} else {
|
|
740
|
-
re += escapeRegex(c ?? "");
|
|
741
|
-
i++;
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
re += "$";
|
|
745
|
-
return new RegExp(re);
|
|
746
|
-
}
|
|
747
|
-
function matchGlob(pattern, input) {
|
|
748
|
-
return getCachedGlob(pattern).test(input);
|
|
749
|
-
}
|
|
750
|
-
function matchAny(patterns, input) {
|
|
751
|
-
return patterns.some((p) => matchGlob(p, input));
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
// src/utils/safe-json.ts
|
|
755
|
-
function safeParse(input, maxBytes = 5e6) {
|
|
756
|
-
if (input.length > maxBytes) {
|
|
757
|
-
return { ok: false, error: `Input exceeds limit (${maxBytes} bytes)` };
|
|
758
|
-
}
|
|
759
|
-
try {
|
|
760
|
-
return { ok: true, value: JSON.parse(input) };
|
|
761
|
-
} catch (err) {
|
|
762
|
-
return {
|
|
763
|
-
ok: false,
|
|
764
|
-
error: err instanceof Error ? err.message : String(err)
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
954
|
var DESTRUCTIVE_BASH_PATTERNS = [
|
|
769
955
|
/\bgit\s+(?:clean\s+-[^\s]*[xdf]|reset\s+--hard)\b/i,
|
|
770
956
|
/\b(?:drop|truncate)\s+(?:table|database|schema)\b/i,
|
|
@@ -1217,6 +1403,6 @@ var AutoApprovePermissionPolicy = class _AutoApprovePermissionPolicy {
|
|
|
1217
1403
|
}
|
|
1218
1404
|
};
|
|
1219
1405
|
|
|
1220
|
-
export { AutoApprovePermissionPolicy, DANGEROUS_FOR_SUBAGENTS, DefaultPermissionPolicy, DefaultSecretScrubber, DefaultSecretVault, ToolCapabilities, decryptConfigSecrets, encryptConfigSecrets, getDangerousCapabilities, hasCapability, hasDangerousCapabilityForSubagents, isSecretField, migratePlaintextSecrets, rewriteConfigEncrypted };
|
|
1406
|
+
export { AutoApprovePermissionPolicy, DANGEROUS_FOR_SUBAGENTS, DefaultPermissionPolicy, DefaultSecretScrubber, DefaultSecretVault, ToolCapabilities, decryptConfigSecrets, encryptConfigSecrets, getDangerousCapabilities, hasCapability, hasDangerousCapabilityForSubagents, isSecretField, migratePlaintextSecrets, rewriteConfigEncrypted, rotateConfigKeys };
|
|
1221
1407
|
//# sourceMappingURL=index.js.map
|
|
1222
1408
|
//# sourceMappingURL=index.js.map
|