@wrongstack/core 0.3.3 → 0.3.7
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-C3DUGjSb.d.ts → agent-bridge-DaOnnHNW.d.ts} +1 -1
- package/dist/{compactor-DpJBI1YH.d.ts → compactor-CFky6JKM.d.ts} +1 -1
- package/dist/{config-D2qvAxVd.d.ts → config-RlhKLjme.d.ts} +2 -1
- package/dist/{context-IovtuTf8.d.ts → context-B1kBj1lY.d.ts} +4 -3
- package/dist/coordination/index.d.ts +12 -10
- package/dist/coordination/index.js +50 -9
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +16 -16
- package/dist/defaults/index.js +213 -17
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-BHIQs4o1.d.ts → events-BBaKeMfb.d.ts} +11 -1
- package/dist/execution/index.d.ts +11 -11
- package/dist/execution/index.js +54 -1
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/{index-hWNybrNZ.d.ts → index-meJRuQtc.d.ts} +26 -5
- package/dist/index.d.ts +26 -26
- package/dist/index.js +306 -39
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/kernel/index.d.ts +9 -9
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-C2OopXOn.d.ts → mcp-servers-Cf4-bJnd.d.ts} +3 -3
- package/dist/models/index.d.ts +2 -2
- package/dist/models/index.js +1 -0
- package/dist/models/index.js.map +1 -1
- package/dist/{multi-agent-B9a6sflH.d.ts → multi-agent-D5m66hzB.d.ts} +1 -1
- package/dist/observability/index.d.ts +2 -2
- package/dist/{path-resolver--59rCou3.d.ts → path-resolver-Bg4OP5fi.d.ts} +2 -2
- package/dist/{provider-runner-B39miKRw.d.ts → provider-runner-CU9gnU2E.d.ts} +3 -3
- package/dist/sdd/index.d.ts +3 -3
- package/dist/secret-scrubber-DyUAWS09.d.ts +54 -0
- package/dist/{secret-scrubber-Cuy5afaQ.d.ts → secret-scrubber-Dyh5LVYL.d.ts} +1 -1
- package/dist/security/index.d.ts +58 -5
- package/dist/security/index.js +95 -6
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-wT2fv9Fg.d.ts → selector-DBEiwXBk.d.ts} +1 -1
- package/dist/{session-reader-CcPi4BQ8.d.ts → session-reader-D-z0AgHs.d.ts} +1 -1
- package/dist/{skill-C_7znCIC.d.ts → skill-DayhFUBb.d.ts} +1 -1
- package/dist/storage/index.d.ts +5 -5
- package/dist/storage/index.js +53 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/{system-prompt-Dk1qm8ey.d.ts → system-prompt-DNetCecu.d.ts} +1 -1
- package/dist/{tool-executor-HsBLGRaA.d.ts → tool-executor-B5bgmEgE.d.ts} +12 -5
- package/dist/types/index.d.ts +15 -15
- package/dist/types/index.js +59 -2
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +23 -2
- package/dist/utils/index.js +41 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/secret-scrubber-CgG2tV2B.d.ts +0 -31
package/dist/defaults/index.d.ts
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
export { D as DefaultLogger, a as DefaultLoggerOptions } from '../logger-BH6AE0W9.js';
|
|
2
2
|
export { AbandonedSession, AttachmentStoreOptions, ConfigLoaderOptions, ConfigMigration, ConfigMigrationError, ConfigSource, DEFAULT_CONFIG_MIGRATIONS, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultMemoryStore, DefaultSessionStore, DirectorStateCheckpoint, DirectorStateSnapshot, DirectorSubagentState, DirectorTaskState, MemoryStoreOptions, MigrationContext, MigrationResult, PersistedQueueItem, PlanFile, PlanItem, QueueStore, RecoveryLock, RecoveryLockOptions, SessionAnalyzer, SessionStoreOptions, TodosCheckpointFile, addPlanItem, attachPlanCheckpoint, attachTodosCheckpoint, clearPlan, emptyPlan, formatPlan, loadDirectorState, loadPlan, loadTodosCheckpoint, removePlanItem, runConfigMigrations, savePlan, saveTodosCheckpoint, setPlanItemStatus } from '../storage/index.js';
|
|
3
|
-
export { D as DefaultSessionReader } from '../session-reader-
|
|
4
|
-
export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-scrubber-
|
|
3
|
+
export { D as DefaultSessionReader } from '../session-reader-D-z0AgHs.js';
|
|
4
|
+
export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-scrubber-Dyh5LVYL.js';
|
|
5
5
|
export { AutoApprovePermissionPolicy, DefaultPermissionPolicy, PermissionPolicyOptions } from '../security/index.js';
|
|
6
|
-
export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-
|
|
6
|
+
export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-B5bgmEgE.js';
|
|
7
7
|
export { AutoCompactionMiddleware, AutonomousRunner, AutonomousRunnerOptions, DefaultSkillLoader, DoneCheckResult, DoneConditionChecker, IntelligentCompactor, IntelligentCompactorOptions, SelectiveCompactor, SelectiveCompactorOptions, SkillLoaderOptions } from '../execution/index.js';
|
|
8
|
-
import { P as ProviderRunner, R as RunProviderOptions } from '../provider-runner-
|
|
9
|
-
import { j as Response } from '../context-
|
|
8
|
+
import { P as ProviderRunner, R as RunProviderOptions } from '../provider-runner-CU9gnU2E.js';
|
|
9
|
+
import { j as Response } from '../context-B1kBj1lY.js';
|
|
10
10
|
export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AgentFactory, AgentFactoryResult, AgentRunnerOptions, BUG_HUNTER_AGENT, CreateDelegateToolOptions, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultMultiAgentCoordinator, DelegateHost, Director, DirectorBudgetError, DirectorPromptParts, DirectorSessionFactory, DirectorSessionFactoryOptions, FLEET_ROSTER, FleetBus, FleetEvent, FleetHandler, FleetUsage, FleetUsageAggregator, MultiAgentCoordinatorOptions, REFACTOR_PLANNER_AGENT, SECURITY_SCANNER_AGENT, SubagentPromptParts, SubagentUsageSnapshot, composeDirectorPrompt, composeSubagentPrompt, createDelegateTool, makeAgentSubagentRunner, makeDirectorSessionFactory, rosterSummaryFromConfigs } from '../coordination/index.js';
|
|
11
|
-
export { n as BudgetExceededError, o as BudgetKind, p as BudgetLimits, q as BudgetUsage, r as SubagentBudget } from '../multi-agent-
|
|
12
|
-
export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-
|
|
11
|
+
export { n as BudgetExceededError, o as BudgetKind, p as BudgetLimits, q as BudgetUsage, r as SubagentBudget } from '../multi-agent-D5m66hzB.js';
|
|
12
|
+
export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-DaOnnHNW.js';
|
|
13
13
|
export { D as DefaultModelsRegistry, a as DefaultModelsRegistryOptions, c as classifyFamily } from '../models-registry-DqzwpBQy.js';
|
|
14
14
|
export { DefaultModeStore, LLMSelector, LLMSelectorOptions, ModeLoaderOptions, loadProjectModes, loadUserModes } from '../models/index.js';
|
|
15
15
|
export { DefaultTaskStore, GeneratedTask, SpecDrivenDev, SpecDrivenDevOptions, SpecParser, TaskFlow, TaskFlowEventMap, TaskFlowEventName, TaskFlowExecutionContext, TaskFlowOptions, TaskFlowPhase, TaskGenerator, TaskGeneratorOptions, TaskStore, TaskTracker, TaskTrackerOptions, TaskTransition } from '../sdd/index.js';
|
|
16
16
|
export { DefaultHealthRegistry, InMemoryMetricsSink, MetricsServerHandle, MetricsServerOptions, NoopMetricsSink, NoopTracer, OTelTracer, OtlpMetricsExporterHandle, OtlpMetricsExporterOptions, OtlpTraceExporterHandle, OtlpTraceExporterOptions, PROMETHEUS_CONTENT_TYPE, buildOtlpMetricsRequest, buildOtlpTracesRequest, renderPrometheus, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, wireMetricsToEvents } from '../observability/index.js';
|
|
17
|
-
export { C as ContextManagerAction, a as ContextManagerInput, b as ContextManagerResult, c as ContextManagerToolOptions, d as allServers, e as awsServer, f as blockServer, g as braveSearchServer, h as context7Server, i as contextManagerTool, j as createContextManagerTool, k as everArtServer, l as filesystemServer, m as githubServer, n as googleMapsServer, o as miniMaxVisionServer, s as sentinelServer, p as slackServer, z as zaiVisionServer } from '../mcp-servers-
|
|
17
|
+
export { C as ContextManagerAction, a as ContextManagerInput, b as ContextManagerResult, c as ContextManagerToolOptions, d as allServers, e as awsServer, f as blockServer, g as braveSearchServer, h as context7Server, i as contextManagerTool, j as createContextManagerTool, k as everArtServer, l as filesystemServer, m as githubServer, n as googleMapsServer, o as miniMaxVisionServer, s as sentinelServer, p as slackServer, z as zaiVisionServer } from '../mcp-servers-Cf4-bJnd.js';
|
|
18
18
|
import '../logger-BMQgxvdy.js';
|
|
19
|
-
import '../events-
|
|
19
|
+
import '../events-BBaKeMfb.js';
|
|
20
20
|
import '../memory-CEXuo7sz.js';
|
|
21
21
|
import '../wstack-paths-BGu2INTm.js';
|
|
22
|
-
import '../config-
|
|
22
|
+
import '../config-RlhKLjme.js';
|
|
23
23
|
import '../models-registry-Y2xbog0E.js';
|
|
24
24
|
import '../secret-vault-DoISxaKO.js';
|
|
25
|
-
import '../secret-scrubber-
|
|
25
|
+
import '../secret-scrubber-DyUAWS09.js';
|
|
26
26
|
import '../input-reader-E-ffP2ee.js';
|
|
27
|
-
import '../compactor-
|
|
28
|
-
import '../skill-
|
|
29
|
-
import '../index-
|
|
30
|
-
import '../system-prompt-
|
|
27
|
+
import '../compactor-CFky6JKM.js';
|
|
28
|
+
import '../skill-DayhFUBb.js';
|
|
29
|
+
import '../index-meJRuQtc.js';
|
|
30
|
+
import '../system-prompt-DNetCecu.js';
|
|
31
31
|
import '../observability-BhnVLBLS.js';
|
|
32
|
-
import '../selector-
|
|
32
|
+
import '../selector-DBEiwXBk.js';
|
|
33
33
|
import 'node:events';
|
|
34
34
|
import '../mode-CV077NjV.js';
|
|
35
35
|
import '../task-graph-BITvWt4t.js';
|
package/dist/defaults/index.js
CHANGED
|
@@ -638,6 +638,7 @@ var QueueStore = class {
|
|
|
638
638
|
} catch (err) {
|
|
639
639
|
const code = err.code;
|
|
640
640
|
if (code === "ENOENT") return [];
|
|
641
|
+
console.warn(`[QueueStore] failed to read queue file "${this.file}":`, err instanceof Error ? err.message : String(err));
|
|
641
642
|
return [];
|
|
642
643
|
}
|
|
643
644
|
let parsed;
|
|
@@ -737,6 +738,13 @@ var DefaultAttachmentStore = class {
|
|
|
737
738
|
return mergeAdjacentText(blocks);
|
|
738
739
|
}
|
|
739
740
|
async clear() {
|
|
741
|
+
if (this.spoolDir) {
|
|
742
|
+
const toDelete = [];
|
|
743
|
+
for (const att of this.items.values()) {
|
|
744
|
+
if (att.path) toDelete.push(att.path);
|
|
745
|
+
}
|
|
746
|
+
await Promise.all(toDelete.map((p) => fsp.unlink(p).catch(() => void 0)));
|
|
747
|
+
}
|
|
740
748
|
this.items.clear();
|
|
741
749
|
this.refs.length = 0;
|
|
742
750
|
this.nextSeq = { text: 0, image: 0, file: 0 };
|
|
@@ -1480,6 +1488,42 @@ function defaultIsPidAlive(pid) {
|
|
|
1480
1488
|
}
|
|
1481
1489
|
}
|
|
1482
1490
|
|
|
1491
|
+
// src/utils/regex-guard.ts
|
|
1492
|
+
var MAX_PATTERN_LEN = 512;
|
|
1493
|
+
var DANGEROUS_PATTERNS = [
|
|
1494
|
+
/(\([^)]*[+*][^)]*\))[+*]/,
|
|
1495
|
+
// (a+)+, (.*)+, etc
|
|
1496
|
+
/(\(\?:[^)]*[+*][^)]*\))[+*]/
|
|
1497
|
+
// same, with non-capturing group
|
|
1498
|
+
];
|
|
1499
|
+
function compileUserRegex(pattern, flags) {
|
|
1500
|
+
if (typeof pattern !== "string") {
|
|
1501
|
+
return { ok: false, reason: "pattern must be a string" };
|
|
1502
|
+
}
|
|
1503
|
+
if (pattern.length === 0) {
|
|
1504
|
+
return { ok: false, reason: "pattern is empty" };
|
|
1505
|
+
}
|
|
1506
|
+
if (pattern.length > MAX_PATTERN_LEN) {
|
|
1507
|
+
return { ok: false, reason: `pattern exceeds ${MAX_PATTERN_LEN} characters` };
|
|
1508
|
+
}
|
|
1509
|
+
for (const rx of DANGEROUS_PATTERNS) {
|
|
1510
|
+
if (rx.test(pattern)) {
|
|
1511
|
+
return {
|
|
1512
|
+
ok: false,
|
|
1513
|
+
reason: "pattern looks vulnerable to catastrophic backtracking \u2014 rewrite without nested quantifiers"
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
try {
|
|
1518
|
+
return { ok: true, regex: new RegExp(pattern, flags) };
|
|
1519
|
+
} catch (err) {
|
|
1520
|
+
return {
|
|
1521
|
+
ok: false,
|
|
1522
|
+
reason: err instanceof Error ? err.message : "invalid regex"
|
|
1523
|
+
};
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1483
1527
|
// src/storage/session-reader.ts
|
|
1484
1528
|
var DefaultSessionReader = class {
|
|
1485
1529
|
store;
|
|
@@ -1574,7 +1618,11 @@ function buildMatcher(q) {
|
|
|
1574
1618
|
const ci = q.caseInsensitive ?? true;
|
|
1575
1619
|
if (q.regex) {
|
|
1576
1620
|
const flags = ci ? "i" : "";
|
|
1577
|
-
const
|
|
1621
|
+
const compiled = compileUserRegex(q.query, flags);
|
|
1622
|
+
if (!compiled.ok) {
|
|
1623
|
+
throw new Error(`Invalid search regex "${q.query}": ${compiled.reason}`);
|
|
1624
|
+
}
|
|
1625
|
+
const re = compiled.regex;
|
|
1578
1626
|
return (text) => {
|
|
1579
1627
|
const m = re.exec(text);
|
|
1580
1628
|
return m ? { start: m.index, end: m.index + m[0].length } : null;
|
|
@@ -2074,6 +2122,10 @@ var DirectorStateCheckpoint = class {
|
|
|
2074
2122
|
this.timer = null;
|
|
2075
2123
|
}
|
|
2076
2124
|
await this.persist();
|
|
2125
|
+
if (this.rewriteRequested) {
|
|
2126
|
+
this.rewriteRequested = false;
|
|
2127
|
+
await this.persist();
|
|
2128
|
+
}
|
|
2077
2129
|
}
|
|
2078
2130
|
bumpUpdatedAt() {
|
|
2079
2131
|
this.snapshot = { ...this.snapshot, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
@@ -2299,7 +2351,7 @@ function walk2(node, vault, transform) {
|
|
|
2299
2351
|
if (Array.isArray(node)) {
|
|
2300
2352
|
return node.map((item) => walk2(item, vault, transform));
|
|
2301
2353
|
}
|
|
2302
|
-
const out =
|
|
2354
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
2303
2355
|
for (const [k, v] of Object.entries(node)) {
|
|
2304
2356
|
if (typeof v === "string" && isSecretField2(k)) {
|
|
2305
2357
|
out[k] = transform(v, k);
|
|
@@ -2410,7 +2462,11 @@ function getCachedGlob(pattern) {
|
|
|
2410
2462
|
COMPILED_GLOB_CACHE.set(pattern, re);
|
|
2411
2463
|
return re;
|
|
2412
2464
|
}
|
|
2465
|
+
var MAX_GLOB_PATTERN_LEN = 1024;
|
|
2413
2466
|
function compileGlob(pattern) {
|
|
2467
|
+
if (pattern.length > MAX_GLOB_PATTERN_LEN) {
|
|
2468
|
+
throw new Error(`Glob pattern exceeds ${MAX_GLOB_PATTERN_LEN} characters`);
|
|
2469
|
+
}
|
|
2414
2470
|
let i = 0;
|
|
2415
2471
|
let re = "^";
|
|
2416
2472
|
while (i < pattern.length) {
|
|
@@ -2469,12 +2525,49 @@ var DefaultPermissionPolicy = class {
|
|
|
2469
2525
|
loaded = false;
|
|
2470
2526
|
trustFile;
|
|
2471
2527
|
yolo;
|
|
2528
|
+
/**
|
|
2529
|
+
* Session-scoped "soft deny" map. When the user presses 'n' (block once),
|
|
2530
|
+
* the tool+pattern is added here. If the LLM retries in the same session,
|
|
2531
|
+
* we return deny directly without asking again.
|
|
2532
|
+
*
|
|
2533
|
+
* Cleared on reload() since reload = fresh trust file snapshot.
|
|
2534
|
+
*/
|
|
2535
|
+
sessionDenied = /* @__PURE__ */ new Map();
|
|
2536
|
+
/**
|
|
2537
|
+
* Session-scoped "soft trust" map. When the user presses 'a' (allow once),
|
|
2538
|
+
* the tool+pattern is added here. If the LLM retries in the same session,
|
|
2539
|
+
* we return auto directly without asking again.
|
|
2540
|
+
*
|
|
2541
|
+
* Cleared on reload().
|
|
2542
|
+
*/
|
|
2543
|
+
sessionAllowed = /* @__PURE__ */ new Map();
|
|
2544
|
+
/**
|
|
2545
|
+
* Interactive prompt delegate. When set, `evaluate()` calls it to get a
|
|
2546
|
+
* user decision synchronously (CLI REPL path). When cleared (TUI / WebUI),
|
|
2547
|
+
* `evaluate()` returns `confirm` so the caller can emit
|
|
2548
|
+
* `tool.confirm_needed` for the UI layer to handle.
|
|
2549
|
+
*
|
|
2550
|
+
* Mutable so the host can switch from CLI-prompt to event-driven
|
|
2551
|
+
* confirmation at runtime (e.g. when `--goal` forces TUI mode after
|
|
2552
|
+
* the agent was already constructed).
|
|
2553
|
+
*/
|
|
2472
2554
|
promptDelegate;
|
|
2555
|
+
/** Pre-compiled wildcard patterns — rebuilt on reload for O(1) lookup. */
|
|
2556
|
+
wildcardEntries = [];
|
|
2473
2557
|
constructor(opts) {
|
|
2474
2558
|
this.trustFile = opts.trustFile;
|
|
2475
2559
|
this.yolo = opts.yolo ?? false;
|
|
2476
2560
|
this.promptDelegate = opts.promptDelegate;
|
|
2477
2561
|
}
|
|
2562
|
+
/**
|
|
2563
|
+
* Replace (or clear) the interactive prompt delegate at runtime.
|
|
2564
|
+
* Used by the CLI to switch from inline prompts (REPL) to event-driven
|
|
2565
|
+
* confirmation (TUI) when the run mode is determined after the policy
|
|
2566
|
+
* was constructed (e.g. `--goal` auto-flipping to TUI).
|
|
2567
|
+
*/
|
|
2568
|
+
setPromptDelegate(delegate) {
|
|
2569
|
+
this.promptDelegate = delegate;
|
|
2570
|
+
}
|
|
2478
2571
|
async reload() {
|
|
2479
2572
|
try {
|
|
2480
2573
|
const raw = await fsp.readFile(this.trustFile, "utf8");
|
|
@@ -2483,13 +2576,26 @@ var DefaultPermissionPolicy = class {
|
|
|
2483
2576
|
} catch {
|
|
2484
2577
|
this.policy = {};
|
|
2485
2578
|
}
|
|
2579
|
+
this.wildcardEntries = [];
|
|
2580
|
+
for (const [key, val] of Object.entries(this.policy)) {
|
|
2581
|
+
if (key.includes("*")) this.wildcardEntries.push({ pattern: key, value: val });
|
|
2582
|
+
}
|
|
2583
|
+
this.sessionDenied.clear();
|
|
2584
|
+
this.sessionAllowed.clear();
|
|
2486
2585
|
this.loaded = true;
|
|
2487
2586
|
}
|
|
2488
|
-
async evaluate(tool, input,
|
|
2587
|
+
async evaluate(tool, input, ctx) {
|
|
2489
2588
|
if (!this.loaded) await this.reload();
|
|
2490
2589
|
const namespaceEntry = this.findNamespaceEntry(tool.name);
|
|
2491
2590
|
const entry = this.policy[tool.name] ?? namespaceEntry;
|
|
2492
2591
|
const subject = this.subjectFor(tool.name, input, tool.subjectKey);
|
|
2592
|
+
const subjectKey = `${tool.name}::${subject ?? tool.name}`;
|
|
2593
|
+
if (this.sessionDenied.has(subjectKey)) {
|
|
2594
|
+
return { permission: "deny", source: "deny", reason: "session soft deny (user pressed no)" };
|
|
2595
|
+
}
|
|
2596
|
+
if (this.sessionAllowed.has(subjectKey)) {
|
|
2597
|
+
return { permission: "auto", source: "trust", reason: "session soft allow (user pressed yes)" };
|
|
2598
|
+
}
|
|
2493
2599
|
if (entry?.deny && subject && matchAny(entry.deny, subject)) {
|
|
2494
2600
|
return { permission: "deny", source: "deny", reason: "matched deny pattern" };
|
|
2495
2601
|
}
|
|
@@ -2505,6 +2611,11 @@ var DefaultPermissionPolicy = class {
|
|
|
2505
2611
|
if (this.yolo) {
|
|
2506
2612
|
return { permission: "auto", source: "yolo" };
|
|
2507
2613
|
}
|
|
2614
|
+
if (tool.name === "write" && subject) {
|
|
2615
|
+
if (ctx.hasRead(subject)) {
|
|
2616
|
+
return { permission: "auto", source: "context", reason: "file already read in this session" };
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2508
2619
|
if (tool.permission === "auto") {
|
|
2509
2620
|
return { permission: "auto", source: "default" };
|
|
2510
2621
|
}
|
|
@@ -2515,6 +2626,7 @@ var DefaultPermissionPolicy = class {
|
|
|
2515
2626
|
return { permission: "auto", source: "user", reason: "user always-allowed" };
|
|
2516
2627
|
}
|
|
2517
2628
|
if (decision === "deny") {
|
|
2629
|
+
await this.deny({ tool: tool.name, pattern: subject ?? tool.name });
|
|
2518
2630
|
return { permission: "deny", source: "user", reason: "user denied" };
|
|
2519
2631
|
}
|
|
2520
2632
|
return { permission: decision === "yes" ? "auto" : "deny", source: "user" };
|
|
@@ -2537,6 +2649,31 @@ var DefaultPermissionPolicy = class {
|
|
|
2537
2649
|
throw err;
|
|
2538
2650
|
}
|
|
2539
2651
|
}
|
|
2652
|
+
/** Persist a deny rule — this tool+pattern pair is permanently blocked. */
|
|
2653
|
+
async deny(rule) {
|
|
2654
|
+
if (!this.loaded) await this.reload();
|
|
2655
|
+
const entry = this.policy[rule.tool] ?? {};
|
|
2656
|
+
entry.deny = Array.from(/* @__PURE__ */ new Set([...entry.deny ?? [], rule.pattern]));
|
|
2657
|
+
this.policy[rule.tool] = entry;
|
|
2658
|
+
try {
|
|
2659
|
+
await atomicWrite(this.trustFile, JSON.stringify(this.policy, null, 2));
|
|
2660
|
+
} catch (err) {
|
|
2661
|
+
const existing = this.policy[rule.tool];
|
|
2662
|
+
if (existing?.deny) {
|
|
2663
|
+
const idx = existing.deny.indexOf(rule.pattern);
|
|
2664
|
+
if (idx !== -1) existing.deny.splice(idx, 1);
|
|
2665
|
+
}
|
|
2666
|
+
throw err;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
/** Block this tool+pattern for the rest of this session (no trust file). */
|
|
2670
|
+
denyOnce(rule) {
|
|
2671
|
+
this.sessionDenied.set(`${rule.tool}::${rule.pattern}`, true);
|
|
2672
|
+
}
|
|
2673
|
+
/** Auto-approve this tool+pattern for the rest of this session (no trust file). */
|
|
2674
|
+
allowOnce(rule) {
|
|
2675
|
+
this.sessionAllowed.set(`${rule.tool}::${rule.pattern}`, true);
|
|
2676
|
+
}
|
|
2540
2677
|
subjectFor(toolName, input, subjectKey) {
|
|
2541
2678
|
if (!input || typeof input !== "object") return void 0;
|
|
2542
2679
|
const obj = input;
|
|
@@ -2564,10 +2701,8 @@ var DefaultPermissionPolicy = class {
|
|
|
2564
2701
|
return void 0;
|
|
2565
2702
|
}
|
|
2566
2703
|
findNamespaceEntry(toolName) {
|
|
2567
|
-
for (const
|
|
2568
|
-
if (
|
|
2569
|
-
return this.policy[key];
|
|
2570
|
-
}
|
|
2704
|
+
for (const { pattern, value } of this.wildcardEntries) {
|
|
2705
|
+
if (matchGlob(pattern, toolName)) return value;
|
|
2571
2706
|
}
|
|
2572
2707
|
return void 0;
|
|
2573
2708
|
}
|
|
@@ -2581,6 +2716,12 @@ var AutoApprovePermissionPolicy = class {
|
|
|
2581
2716
|
}
|
|
2582
2717
|
async trust() {
|
|
2583
2718
|
}
|
|
2719
|
+
async deny() {
|
|
2720
|
+
}
|
|
2721
|
+
denyOnce() {
|
|
2722
|
+
}
|
|
2723
|
+
allowOnce() {
|
|
2724
|
+
}
|
|
2584
2725
|
async reload() {
|
|
2585
2726
|
}
|
|
2586
2727
|
};
|
|
@@ -4167,6 +4308,15 @@ var ToolExecutor = class {
|
|
|
4167
4308
|
opts;
|
|
4168
4309
|
serializer;
|
|
4169
4310
|
iterationTimeoutMs;
|
|
4311
|
+
/**
|
|
4312
|
+
* Clear the interactive confirm awaiter so the executor returns
|
|
4313
|
+
* `ToolConfirmPendingResult` instead of blocking on stdin. Used by
|
|
4314
|
+
* the CLI to switch from inline prompts (REPL) to event-driven
|
|
4315
|
+
* confirmation (TUI) at runtime.
|
|
4316
|
+
*/
|
|
4317
|
+
clearConfirmAwaiter() {
|
|
4318
|
+
this.opts.confirmAwaiter = void 0;
|
|
4319
|
+
}
|
|
4170
4320
|
/**
|
|
4171
4321
|
* Execute a batch of tool uses using the configured strategy.
|
|
4172
4322
|
* Returns the execution results and the remaining output budget.
|
|
@@ -4419,7 +4569,15 @@ var ToolExecutor = class {
|
|
|
4419
4569
|
var DoneConditionChecker = class {
|
|
4420
4570
|
constructor(condition) {
|
|
4421
4571
|
this.condition = condition;
|
|
4422
|
-
|
|
4572
|
+
if (condition.type === "output_match" && condition.pattern) {
|
|
4573
|
+
const result = compileUserRegex(condition.pattern, "");
|
|
4574
|
+
this.compiledRegex = result.ok ? result.regex : null;
|
|
4575
|
+
if (!result.ok) {
|
|
4576
|
+
console.warn(`[DoneConditionChecker] Invalid regex pattern "${condition.pattern}": ${result.reason}`);
|
|
4577
|
+
}
|
|
4578
|
+
} else {
|
|
4579
|
+
this.compiledRegex = null;
|
|
4580
|
+
}
|
|
4423
4581
|
}
|
|
4424
4582
|
condition;
|
|
4425
4583
|
compiledRegex;
|
|
@@ -4657,6 +4815,13 @@ var InMemoryAgentBridge = class {
|
|
|
4657
4815
|
this.pendingRequests.delete(correlationId);
|
|
4658
4816
|
reject(new Error(`Request ${correlationId} timed out after ${timeout}ms`));
|
|
4659
4817
|
}, timeout);
|
|
4818
|
+
if (this.stopped) {
|
|
4819
|
+
clearTimeout(timer);
|
|
4820
|
+
this.inflightGuards.delete(correlationId);
|
|
4821
|
+
this.pendingRequests.delete(correlationId);
|
|
4822
|
+
reject(new Error("Bridge stopped"));
|
|
4823
|
+
return;
|
|
4824
|
+
}
|
|
4660
4825
|
this.pendingRequests.set(correlationId, {
|
|
4661
4826
|
resolve: resolve2,
|
|
4662
4827
|
reject,
|
|
@@ -5176,8 +5341,8 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5176
5341
|
// --- internal dispatching ---------------------------------------------
|
|
5177
5342
|
tryDispatchNext() {
|
|
5178
5343
|
while (this.canDispatch()) {
|
|
5179
|
-
const
|
|
5180
|
-
if (!
|
|
5344
|
+
const dispatchable = this.takeNextDispatchableTask();
|
|
5345
|
+
if (!dispatchable) {
|
|
5181
5346
|
if (this.pendingTasks.length > 0 && !this.hasLiveSubagent()) {
|
|
5182
5347
|
this.drainPendingAsAborted(
|
|
5183
5348
|
"No live subagent available \u2014 all stopped or mid-termination"
|
|
@@ -5185,8 +5350,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5185
5350
|
}
|
|
5186
5351
|
return;
|
|
5187
5352
|
}
|
|
5188
|
-
const task =
|
|
5189
|
-
if (!task) return;
|
|
5353
|
+
const { subagentId, task } = dispatchable;
|
|
5190
5354
|
this.runDispatched(subagentId, task).catch((err) => {
|
|
5191
5355
|
this.recordCompletion({
|
|
5192
5356
|
subagentId,
|
|
@@ -5204,12 +5368,26 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5204
5368
|
const max = this.config.maxConcurrent ?? 4;
|
|
5205
5369
|
return this.inFlight < max && this.pendingTasks.length > 0;
|
|
5206
5370
|
}
|
|
5371
|
+
takeNextDispatchableTask() {
|
|
5372
|
+
for (let i = 0; i < this.pendingTasks.length; i++) {
|
|
5373
|
+
const task = this.pendingTasks[i];
|
|
5374
|
+
const subagentId = task.subagentId ? this.isIdleSubagent(task.subagentId) ? task.subagentId : null : this.findIdleSubagent();
|
|
5375
|
+
if (!subagentId) continue;
|
|
5376
|
+
this.pendingTasks.splice(i, 1);
|
|
5377
|
+
return { subagentId, task };
|
|
5378
|
+
}
|
|
5379
|
+
return null;
|
|
5380
|
+
}
|
|
5207
5381
|
findIdleSubagent() {
|
|
5208
5382
|
for (const [id, s] of this.subagents) {
|
|
5209
5383
|
if (s.status === "idle" && !this.terminating.has(id)) return id;
|
|
5210
5384
|
}
|
|
5211
5385
|
return null;
|
|
5212
5386
|
}
|
|
5387
|
+
isIdleSubagent(id) {
|
|
5388
|
+
const subagent = this.subagents.get(id);
|
|
5389
|
+
return !!subagent && subagent.status === "idle" && !this.terminating.has(id);
|
|
5390
|
+
}
|
|
5213
5391
|
/**
|
|
5214
5392
|
* Returns true iff at least one spawned subagent could still
|
|
5215
5393
|
* process a task. A "live" subagent is one that is not stopped
|
|
@@ -5394,10 +5572,11 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5394
5572
|
};
|
|
5395
5573
|
function classifySubagentError(err, hints = {}) {
|
|
5396
5574
|
const cause = err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : void 0;
|
|
5397
|
-
const baseMessage = err instanceof Error ? err.message : String(err);
|
|
5398
5575
|
if (err instanceof ProviderError) {
|
|
5399
|
-
|
|
5576
|
+
const baseMessage2 = err.describe();
|
|
5577
|
+
return providerErrorToSubagentError(err, baseMessage2, cause);
|
|
5400
5578
|
}
|
|
5579
|
+
const baseMessage = err instanceof Error ? err.message : String(err);
|
|
5401
5580
|
if (err instanceof BudgetExceededError) {
|
|
5402
5581
|
const map = {
|
|
5403
5582
|
iterations: "budget_iterations",
|
|
@@ -5514,7 +5693,7 @@ function makeSpawnTool(director, roster) {
|
|
|
5514
5693
|
if (role && !base) {
|
|
5515
5694
|
return { error: `unknown role "${role}". roster has: ${roster ? Object.keys(roster).join(", ") : "(empty)"}` };
|
|
5516
5695
|
}
|
|
5517
|
-
const cfg =
|
|
5696
|
+
const cfg = base ? instantiateRosterConfig(role, base) : { name: i.name ?? "subagent" };
|
|
5518
5697
|
if (typeof i.name === "string") cfg.name = i.name;
|
|
5519
5698
|
if (typeof i.provider === "string") cfg.provider = i.provider;
|
|
5520
5699
|
if (typeof i.model === "string") cfg.model = i.model;
|
|
@@ -5534,6 +5713,14 @@ function makeSpawnTool(director, roster) {
|
|
|
5534
5713
|
}
|
|
5535
5714
|
};
|
|
5536
5715
|
}
|
|
5716
|
+
function instantiateRosterConfig(role, base) {
|
|
5717
|
+
return {
|
|
5718
|
+
...base,
|
|
5719
|
+
// Roster entries are templates. A director may spawn several
|
|
5720
|
+
// workers with the same role, so never reuse the template id.
|
|
5721
|
+
id: `${role}-${randomUUID().slice(0, 8)}`
|
|
5722
|
+
};
|
|
5723
|
+
}
|
|
5537
5724
|
function makeAssignTool(director) {
|
|
5538
5725
|
const inputSchema = {
|
|
5539
5726
|
type: "object",
|
|
@@ -5851,8 +6038,8 @@ var Director = class {
|
|
|
5851
6038
|
if (this.spawnCount >= this.maxSpawns) {
|
|
5852
6039
|
throw new DirectorBudgetError("max_spawns", this.maxSpawns, this.spawnCount + 1);
|
|
5853
6040
|
}
|
|
5854
|
-
this.spawnCount += 1;
|
|
5855
6041
|
const result = await this.coordinator.spawn(config);
|
|
6042
|
+
this.spawnCount += 1;
|
|
5856
6043
|
this.subagentMeta.set(result.subagentId, {
|
|
5857
6044
|
provider: config.provider,
|
|
5858
6045
|
model: config.model
|
|
@@ -6295,7 +6482,7 @@ function createDelegateTool(opts) {
|
|
|
6295
6482
|
error: `Unknown role "${i.role}". Available: ${rosterIds.join(", ") || "(no roster configured)"}.`
|
|
6296
6483
|
};
|
|
6297
6484
|
}
|
|
6298
|
-
cfg =
|
|
6485
|
+
cfg = instantiateRosterConfig2(i.role, base);
|
|
6299
6486
|
if (i.systemPromptOverride) cfg.systemPromptOverride = i.systemPromptOverride;
|
|
6300
6487
|
if (i.provider) cfg.provider = i.provider;
|
|
6301
6488
|
if (i.model) cfg.model = i.model;
|
|
@@ -6381,6 +6568,14 @@ function createDelegateTool(opts) {
|
|
|
6381
6568
|
}
|
|
6382
6569
|
};
|
|
6383
6570
|
}
|
|
6571
|
+
function instantiateRosterConfig2(role, base) {
|
|
6572
|
+
return {
|
|
6573
|
+
...base,
|
|
6574
|
+
// Roster entries are templates. Give each spawn a fresh id so
|
|
6575
|
+
// parallel or repeated delegates can use the same role safely.
|
|
6576
|
+
id: `${role}-${randomUUID().slice(0, 8)}`
|
|
6577
|
+
};
|
|
6578
|
+
}
|
|
6384
6579
|
function hintForKind(kind, retryable, backoffMs) {
|
|
6385
6580
|
if (!kind) return void 0;
|
|
6386
6581
|
switch (kind) {
|
|
@@ -6789,6 +6984,7 @@ var FAMILY_BY_NPM = {
|
|
|
6789
6984
|
"@ai-sdk/xai": "openai-compatible",
|
|
6790
6985
|
"@ai-sdk/cerebras": "openai-compatible",
|
|
6791
6986
|
"@ai-sdk/togetherai": "openai-compatible",
|
|
6987
|
+
"@ai-sdk/mistral": "openai-compatible",
|
|
6792
6988
|
"@ai-sdk/perplexity": "openai-compatible",
|
|
6793
6989
|
"@ai-sdk/deepinfra": "openai-compatible",
|
|
6794
6990
|
"@openrouter/ai-sdk-provider": "openai-compatible",
|