@wrongstack/core 0.7.8 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-bridge-hXRN-GO_.d.ts → agent-bridge-DPxcUVkn.d.ts} +1 -1
- package/dist/{agent-subagent-runner-B2zguWzh.d.ts → agent-subagent-runner-Cav3yEJM.d.ts} +9 -10
- package/dist/coordination/index.d.ts +9 -9
- package/dist/coordination/index.js +393 -179
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +13 -13
- package/dist/defaults/index.js +261 -64
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-D4pGukpI.d.ts → events-DyhxkstG.d.ts} +33 -0
- package/dist/execution/index.d.ts +24 -7
- package/dist/execution/index.js +158 -37
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +3 -3
- package/dist/{index-BtNRyJft.d.ts → index-oYZeWsuJ.d.ts} +2 -2
- package/dist/index.d.ts +16 -16
- package/dist/index.js +365 -68
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +2 -2
- package/dist/kernel/index.d.ts +3 -3
- package/dist/kernel/index.js +23 -0
- package/dist/kernel/index.js.map +1 -1
- package/dist/{multi-agent-7OK4pEKW.d.ts → multi-agent-CRMznZmf.d.ts} +64 -30
- package/dist/{multi-agent-coordinator-3Ypfg-hr.d.ts → multi-agent-coordinator-IQKrMfXz.d.ts} +11 -1
- package/dist/{null-fleet-bus-BZUrXVcd.d.ts → null-fleet-bus-sKnVwEd8.d.ts} +92 -6
- package/dist/observability/index.d.ts +1 -1
- package/dist/{path-resolver-DPUjF10O.d.ts → path-resolver-1CIYbH2Q.d.ts} +1 -1
- package/dist/{permission-policy-D5Gj1o2K.d.ts → permission-policy-BBa1M1xc.d.ts} +10 -1
- package/dist/{plan-templates-C-IOLJ8Q.d.ts → plan-templates-BnlpEkX8.d.ts} +1 -1
- package/dist/{provider-runner-iST8U3ni.d.ts → provider-runner-BrA0XR-l.d.ts} +1 -1
- package/dist/sdd/index.d.ts +5 -5
- package/dist/sdd/index.js +114 -28
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-scrubber-DXkhwuka.d.ts → secret-scrubber-C0n1EqrC.d.ts} +1 -1
- package/dist/{secret-scrubber-nI8qjaqW.d.ts → secret-scrubber-CyE1-EMG.d.ts} +1 -1
- package/dist/security/index.d.ts +3 -3
- package/dist/security/index.js +29 -3
- package/dist/security/index.js.map +1 -1
- package/dist/storage/index.d.ts +2 -2
- package/dist/{tool-executor-CSwXjifK.d.ts → tool-executor-QwfWnQZ8.d.ts} +1 -1
- package/dist/types/index.d.ts +9 -9
- package/package.json +1 -1
package/dist/defaults/index.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
export { D as DefaultLogger, a as DefaultLoggerOptions } from '../logger-bOzkF5LL.js';
|
|
2
|
-
export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, M as MemoryStoreOptions, j as MigrationContext, k as MigrationResult, P as PersistedQueueItem, l as PlanFile, m as PlanItem, n as PlanTemplate, Q as QueueStore, R as RecoveryLock, o as RecoveryLockOptions, S as SessionAnalyzer, p as SessionStoreOptions, T as TodosCheckpointFile, q as addPlanItem, r as attachPlanCheckpoint, s as attachTodosCheckpoint, t as clearPlan, u as deriveTodosFromPlanItem, v as emptyPlan, w as formatPlan, x as formatPlanTemplates, y as getPlanTemplate, z as listPlanTemplates, B as loadPlan, E as loadTodosCheckpoint, F as removePlanItem, G as runConfigMigrations, H as savePlan, I as saveTodosCheckpoint, J as setPlanItemStatus } from '../plan-templates-
|
|
2
|
+
export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, M as MemoryStoreOptions, j as MigrationContext, k as MigrationResult, P as PersistedQueueItem, l as PlanFile, m as PlanItem, n as PlanTemplate, Q as QueueStore, R as RecoveryLock, o as RecoveryLockOptions, S as SessionAnalyzer, p as SessionStoreOptions, T as TodosCheckpointFile, q as addPlanItem, r as attachPlanCheckpoint, s as attachTodosCheckpoint, t as clearPlan, u as deriveTodosFromPlanItem, v as emptyPlan, w as formatPlan, x as formatPlanTemplates, y as getPlanTemplate, z as listPlanTemplates, B as loadPlan, E as loadTodosCheckpoint, F as removePlanItem, G as runConfigMigrations, H as savePlan, I as saveTodosCheckpoint, J as setPlanItemStatus } from '../plan-templates-BnlpEkX8.js';
|
|
3
3
|
export { D as DefaultSessionReader } from '../session-reader-DsadjyF9.js';
|
|
4
4
|
export { D as DirectorStateCheckpoint, a as DirectorStateSnapshot, b as DirectorSubagentState, c as DirectorTaskState, l as loadDirectorState } from '../director-state-BmYi3DGA.js';
|
|
5
|
-
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-
|
|
6
|
-
export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-
|
|
7
|
-
export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-
|
|
5
|
+
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-C0n1EqrC.js';
|
|
6
|
+
export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-BBa1M1xc.js';
|
|
7
|
+
export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-QwfWnQZ8.js';
|
|
8
8
|
export { AutoCompactionMiddleware, AutonomousRunner, AutonomousRunnerOptions, AutonomyPromptContributorOptions, DefaultSkillLoader, DoneCheckResult, DoneConditionChecker, EternalAutonomyEngine, EternalAutonomyOptions, EternalEngineState, IntelligentCompactor, IntelligentCompactorOptions, ParallelEngineState, ParallelEternalEngine, ParallelEternalOptions, SelectiveCompactor, SelectiveCompactorOptions, SkillLoaderOptions, buildGoalPreamble, makeAutonomyPromptContributor } from '../execution/index.js';
|
|
9
|
-
import { P as ProviderRunner, R as RunProviderOptions } from '../provider-runner-
|
|
9
|
+
import { P as ProviderRunner, R as RunProviderOptions } from '../provider-runner-BrA0XR-l.js';
|
|
10
10
|
import { q as Response } from '../context-z2x5gv_V.js';
|
|
11
|
-
export { a as AGENTS_BY_PHASE, b as AGENT_CATALOG, c as ALL_AGENT_DEFINITIONS, d as ALL_FLEET_AGENTS, e as AUDIT_LOG_AGENT, f as AutoExtendCeiling, g as AutoExtendPolicy, B as BUG_HUNTER_AGENT, C as CreateDelegateToolOptions, D as DEFAULT_DIRECTOR_PREAMBLE, h as DEFAULT_SUBAGENT_BASELINE, i as DelegateHost, j as Director, k as DirectorPromptParts, l as DirectorSessionFactory, m as DirectorSessionFactoryOptions, F as FLEET_ROSTER, n as FLEET_ROSTER_BUDGETS, s as FleetRosterBudget, t as FleetSpawnBudgetError, I as ICoordinator, u as IFleetManager, N as NULL_FLEET_BUS, R as REFACTOR_PLANNER_AGENT, S as SECURITY_SCANNER_AGENT, v as SubagentPromptParts, w as applyRosterBudget, x as attachAutoExtend, y as composeDirectorPrompt, z as composeSubagentPrompt, E as createDelegateTool, G as getAgentDefinition, H as makeDirectorSessionFactory, J as rosterSummaryFromConfigs } from '../null-fleet-bus-
|
|
12
|
-
export { A as AgentBudgetTier, a as AgentCapability, b as AgentDefinition, c as AgentPhase, D as DEFAULT_DISPATCH_ROLE, d as DefaultMultiAgentCoordinator, e as DispatchCandidate, f as DispatchClassifier, g as DispatchMethod, h as DispatchOptions, i as DispatchResult, j as MultiAgentCoordinatorOptions, k as dispatchAgent, m as makeLLMClassifier, s as scoreAgents } from '../multi-agent-coordinator-
|
|
13
|
-
export { c as BudgetExceededError, d as BudgetKind, e as BudgetLimits,
|
|
14
|
-
export { A as AgentFactory, a as AgentFactoryResult, b as AgentRunnerOptions, F as FleetBus, c as FleetEvent, d as FleetHandler, e as FleetUsage, f as FleetUsageAggregator, S as SubagentUsageSnapshot, m as makeAgentSubagentRunner } from '../agent-subagent-runner-
|
|
15
|
-
export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-
|
|
11
|
+
export { a as AGENTS_BY_PHASE, b as AGENT_CATALOG, c as ALL_AGENT_DEFINITIONS, d as ALL_FLEET_AGENTS, e as AUDIT_LOG_AGENT, f as AutoExtendCeiling, g as AutoExtendPolicy, B as BUG_HUNTER_AGENT, C as CreateDelegateToolOptions, D as DEFAULT_DIRECTOR_PREAMBLE, h as DEFAULT_SUBAGENT_BASELINE, i as DelegateHost, j as Director, k as DirectorPromptParts, l as DirectorSessionFactory, m as DirectorSessionFactoryOptions, F as FLEET_ROSTER, n as FLEET_ROSTER_BUDGETS, s as FleetRosterBudget, t as FleetSpawnBudgetError, I as ICoordinator, u as IFleetManager, N as NULL_FLEET_BUS, R as REFACTOR_PLANNER_AGENT, S as SECURITY_SCANNER_AGENT, v as SubagentPromptParts, w as applyRosterBudget, x as attachAutoExtend, y as composeDirectorPrompt, z as composeSubagentPrompt, E as createDelegateTool, G as getAgentDefinition, H as makeDirectorSessionFactory, J as rosterSummaryFromConfigs } from '../null-fleet-bus-sKnVwEd8.js';
|
|
12
|
+
export { A as AgentBudgetTier, a as AgentCapability, b as AgentDefinition, c as AgentPhase, D as DEFAULT_DISPATCH_ROLE, d as DefaultMultiAgentCoordinator, e as DispatchCandidate, f as DispatchClassifier, g as DispatchMethod, h as DispatchOptions, i as DispatchResult, j as MultiAgentCoordinatorOptions, k as dispatchAgent, m as makeLLMClassifier, s as scoreAgents } from '../multi-agent-coordinator-IQKrMfXz.js';
|
|
13
|
+
export { c as BudgetExceededError, d as BudgetKind, e as BudgetLimits, j as BudgetUsage, m as SubagentBudget } from '../multi-agent-CRMznZmf.js';
|
|
14
|
+
export { A as AgentFactory, a as AgentFactoryResult, b as AgentRunnerOptions, F as FleetBus, c as FleetEvent, d as FleetHandler, e as FleetUsage, f as FleetUsageAggregator, S as SubagentUsageSnapshot, m as makeAgentSubagentRunner } from '../agent-subagent-runner-Cav3yEJM.js';
|
|
15
|
+
export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-DPxcUVkn.js';
|
|
16
16
|
export { D as DefaultModelsRegistry, a as DefaultModelsRegistryOptions, c as classifyFamily } from '../models-registry-OG_30xqZ.js';
|
|
17
17
|
export { DefaultModeStore, LLMSelector, LLMSelectorOptions, ModeLoaderOptions, loadProjectModes, loadUserModes } from '../models/index.js';
|
|
18
18
|
export { AISpecBuilder, AISpecBuilderOptions, AISpecPhase, AISpecSession, AutoExecutor, AutoExecutorOptions, BottleneckTask, CollectedAnswer, CriticalPathAnalysis, DefaultTaskStore, ExecutionSummary, GeneratedTask, RunResult, SPEC_TEMPLATES, SddParallelRun, SddParallelRunOptions, SddProgress, SddTaskDecomposer, SddTaskDecomposerOptions, SpecDiff, SpecDrivenDev, SpecDrivenDevOptions, SpecIndexEntry, SpecParser, SpecStore, SpecStoreOptions, SpecVersion, SpecVersioning, TaskBatch, TaskExecutionContext, TaskExecutionResult, TaskFlow, TaskFlowEventMap, TaskFlowEventName, TaskFlowExecutionContext, TaskFlowOptions, TaskFlowPhase, TaskGenerator, TaskGeneratorOptions, TaskGraphIndexEntry, TaskGraphStore, TaskGraphStoreOptions, TaskStore, TaskTracker, TaskTrackerOptions, TaskTransition, WaveResult, analyzeCriticalPath, createAutoExecutor, getTemplate, listTemplates, renderProgress, renderSpecAnalysis, renderTaskGraph, renderTaskList, templateToMarkdown } from '../sdd/index.js';
|
|
@@ -20,17 +20,17 @@ export { DefaultHealthRegistry, InMemoryMetricsSink, MetricsServerHandle, Metric
|
|
|
20
20
|
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-n2L9ohMX.js';
|
|
21
21
|
export { D as DEFAULT_CONTEXT_CONFIG, a as DEFAULT_TOOLS_CONFIG } from '../default-config-DvRSTELf.js';
|
|
22
22
|
import '../logger-DDd5C--Z.js';
|
|
23
|
-
import '../events-
|
|
23
|
+
import '../events-DyhxkstG.js';
|
|
24
24
|
import '../memory-CEXuo7sz.js';
|
|
25
25
|
import '../wstack-paths-gCrJ631C.js';
|
|
26
26
|
import '../config-Bi4Q0fnz.js';
|
|
27
27
|
import '../models-registry-BcYJDKLm.js';
|
|
28
28
|
import '../secret-vault-DoISxaKO.js';
|
|
29
|
-
import '../secret-scrubber-
|
|
29
|
+
import '../secret-scrubber-CyE1-EMG.js';
|
|
30
30
|
import '../input-reader-E-ffP2ee.js';
|
|
31
31
|
import '../compactor-Mw7-rNyb.js';
|
|
32
32
|
import '../retry-policy-OwtKNxo8.js';
|
|
33
|
-
import '../index-
|
|
33
|
+
import '../index-oYZeWsuJ.js';
|
|
34
34
|
import '../system-prompt-CWA6ml-d.js';
|
|
35
35
|
import '../observability-BhnVLBLS.js';
|
|
36
36
|
import '../selector-DkvgYVS4.js';
|
package/dist/defaults/index.js
CHANGED
|
@@ -3213,10 +3213,36 @@ var DefaultPermissionPolicy = class {
|
|
|
3213
3213
|
return void 0;
|
|
3214
3214
|
}
|
|
3215
3215
|
};
|
|
3216
|
-
var AutoApprovePermissionPolicy = class {
|
|
3216
|
+
var AutoApprovePermissionPolicy = class _AutoApprovePermissionPolicy {
|
|
3217
|
+
/**
|
|
3218
|
+
* Tools that are too dangerous to auto-approve even in a delegated
|
|
3219
|
+
* subagent context. Subagents run non-interactively under a director
|
|
3220
|
+
* and cannot answer prompts, but inherited authorization does not
|
|
3221
|
+
* imply blanket permission for destructive or privilege-escalating
|
|
3222
|
+
* operations. These tools remain at their declared `permission`
|
|
3223
|
+
* level so the leader must explicitly allow them per-spawn.
|
|
3224
|
+
*/
|
|
3225
|
+
static DENY = /* @__PURE__ */ new Set([
|
|
3226
|
+
"bash",
|
|
3227
|
+
// arbitrary shell — use exec for constrained shell
|
|
3228
|
+
"write",
|
|
3229
|
+
// arbitrary file write
|
|
3230
|
+
"scaffold",
|
|
3231
|
+
// arbitrary file generation outside project root
|
|
3232
|
+
"patch",
|
|
3233
|
+
// arbitrary diff application
|
|
3234
|
+
"install",
|
|
3235
|
+
// installs from arbitrary package sources
|
|
3236
|
+
"exec"
|
|
3237
|
+
// restricted shell but with arbitrary command args
|
|
3238
|
+
]);
|
|
3217
3239
|
async evaluate(tool) {
|
|
3218
|
-
if (tool.permission === "deny") {
|
|
3219
|
-
return {
|
|
3240
|
+
if (tool.permission === "deny" || _AutoApprovePermissionPolicy.DENY.has(tool.name)) {
|
|
3241
|
+
return {
|
|
3242
|
+
permission: "deny",
|
|
3243
|
+
source: "subagent_guard",
|
|
3244
|
+
reason: _AutoApprovePermissionPolicy.DENY.has(tool.name) ? `tool ${tool.name} is not auto-approved for subagents \u2014 ask the leader to allow it explicitly` : "tool default deny"
|
|
3245
|
+
};
|
|
3220
3246
|
}
|
|
3221
3247
|
return { permission: "auto", source: "yolo" };
|
|
3222
3248
|
}
|
|
@@ -4801,6 +4827,7 @@ Summarize the following message range:`;
|
|
|
4801
4827
|
};
|
|
4802
4828
|
|
|
4803
4829
|
// src/execution/auto-compaction-middleware.ts
|
|
4830
|
+
var LEVEL_RANK2 = { warn: 0, soft: 1, hard: 2 };
|
|
4804
4831
|
var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
4805
4832
|
name = "AutoCompaction";
|
|
4806
4833
|
compactor;
|
|
@@ -4821,6 +4848,16 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
4821
4848
|
* short conversations, causing premature compaction triggers.
|
|
4822
4849
|
*/
|
|
4823
4850
|
static OVERHEAD_FACTOR = 1.3;
|
|
4851
|
+
/**
|
|
4852
|
+
* Once a compaction attempt reduces nothing (preserveK protects everything,
|
|
4853
|
+
* no oversized tool_results remain to elide), retrying on every iteration
|
|
4854
|
+
* just spams `compaction.fired` events without making progress. We remember
|
|
4855
|
+
* the no-op and skip until either the pressure level escalates or context
|
|
4856
|
+
* has grown by at least this many tokens since the failed attempt.
|
|
4857
|
+
*/
|
|
4858
|
+
static NOOP_RETRY_DELTA_TOKENS = 2e3;
|
|
4859
|
+
/** Tracks the most recent no-op attempt so we can avoid re-firing per turn. */
|
|
4860
|
+
lastNoopAttempt = null;
|
|
4824
4861
|
/**
|
|
4825
4862
|
* @param compactor Compactor to use for compaction.
|
|
4826
4863
|
* @param maxContext Provider's max context window in tokens.
|
|
@@ -4862,19 +4899,44 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
4862
4899
|
hard: this.hardThreshold
|
|
4863
4900
|
};
|
|
4864
4901
|
const aggressiveOn = policy?.aggressiveOn ?? this.aggressiveOn;
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
}
|
|
4870
|
-
|
|
4902
|
+
const level = load >= thresholds.hard ? "hard" : load >= thresholds.soft ? "soft" : load >= thresholds.warn ? "warn" : null;
|
|
4903
|
+
if (!level) {
|
|
4904
|
+
this.lastNoopAttempt = null;
|
|
4905
|
+
return next(ctx);
|
|
4906
|
+
}
|
|
4907
|
+
if (this.shouldSkipNoopRetry(level, tokens)) {
|
|
4908
|
+
return next(ctx);
|
|
4871
4909
|
}
|
|
4910
|
+
const aggressive = level === "hard" ? true : level === "soft" ? aggressiveOn !== "hard" : aggressiveOn === "warn";
|
|
4911
|
+
await this.compact(ctx, aggressive, { level, tokens, load });
|
|
4872
4912
|
return next(ctx);
|
|
4873
4913
|
};
|
|
4874
4914
|
}
|
|
4915
|
+
/**
|
|
4916
|
+
* Returns true when the previous compaction at the same or higher pressure
|
|
4917
|
+
* level reduced nothing and context has not grown materially since. Prevents
|
|
4918
|
+
* a stuck preserveK window from spamming compaction events every iteration.
|
|
4919
|
+
*/
|
|
4920
|
+
shouldSkipNoopRetry(level, tokens) {
|
|
4921
|
+
const stuck = this.lastNoopAttempt;
|
|
4922
|
+
if (!stuck) return false;
|
|
4923
|
+
if (LEVEL_RANK2[level] > LEVEL_RANK2[stuck.level]) return false;
|
|
4924
|
+
const delta = tokens - stuck.tokens;
|
|
4925
|
+
return delta < _AutoCompactionMiddleware.NOOP_RETRY_DELTA_TOKENS;
|
|
4926
|
+
}
|
|
4927
|
+
recordAttempt(level, tokens, report) {
|
|
4928
|
+
const reduced = report.before > report.after;
|
|
4929
|
+
const repaired = !!report.repaired;
|
|
4930
|
+
if (reduced || repaired) {
|
|
4931
|
+
this.lastNoopAttempt = null;
|
|
4932
|
+
} else {
|
|
4933
|
+
this.lastNoopAttempt = { level, tokens };
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4875
4936
|
async compact(ctx, aggressive, pressure) {
|
|
4876
4937
|
try {
|
|
4877
4938
|
const report = await this.compactor.compact(ctx, { aggressive });
|
|
4939
|
+
this.recordAttempt(pressure.level, pressure.tokens, report);
|
|
4878
4940
|
this.events?.emit("compaction.fired", {
|
|
4879
4941
|
level: pressure.level,
|
|
4880
4942
|
tokens: pressure.tokens,
|
|
@@ -6094,29 +6156,35 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
6094
6156
|
* same kind are no-ops — without this dedup, every `recordIteration`
|
|
6095
6157
|
* after the limit is reached spawns a fresh decision Promise (until
|
|
6096
6158
|
* the first one lands and patches limits), flooding the FleetBus
|
|
6097
|
-
* with redundant threshold events. Cleared in `
|
|
6159
|
+
* with redundant threshold events. Cleared in `negotiateExtension`'s
|
|
6098
6160
|
* `finally`.
|
|
6099
6161
|
*/
|
|
6100
6162
|
pendingExtensions = /* @__PURE__ */ new Set();
|
|
6101
6163
|
/**
|
|
6102
|
-
* Hard cap on how long `
|
|
6164
|
+
* Hard cap on how long `negotiateExtension` waits for the coordinator to
|
|
6103
6165
|
* respond before defaulting to 'stop'. Without this fallback an absent
|
|
6104
6166
|
* or hung listener (Director not built / event filter detached mid-run)
|
|
6105
|
-
* leaves the budget over-limit and never enforces anything
|
|
6106
|
-
* `checkLimit` returns synchronously via `void this.checkLimitAsync`.
|
|
6107
|
-
* Raised from 30s to 60s to give subagents more headroom before
|
|
6108
|
-
* the threshold negotiation times out and triggers a hard stop.
|
|
6167
|
+
* leaves the budget over-limit and never enforces anything.
|
|
6109
6168
|
*/
|
|
6110
6169
|
static DECISION_TIMEOUT_MS = 6e4;
|
|
6111
6170
|
/**
|
|
6112
6171
|
* Injected by the runner when wiring the budget to its EventBus.
|
|
6113
|
-
* Used
|
|
6172
|
+
* Used to emit `budget.threshold_reached` events in `'auto'` mode.
|
|
6114
6173
|
*/
|
|
6115
6174
|
_events;
|
|
6175
|
+
/**
|
|
6176
|
+
* Negotiation mode — controls whether a threshold hit tries to emit
|
|
6177
|
+
* `budget.threshold_reached` and wait for a coordinator decision, or
|
|
6178
|
+
* falls straight through to a synchronous hard stop.
|
|
6179
|
+
*
|
|
6180
|
+
* `'auto'` (default) — emit on the EventBus and wait; times out to 'stop'.
|
|
6181
|
+
* `'sync'` — throw `BudgetExceededError` immediately regardless of listeners.
|
|
6182
|
+
*/
|
|
6183
|
+
_mode;
|
|
6116
6184
|
/**
|
|
6117
6185
|
* Optional callback for soft-limit handling. When set, the budget will
|
|
6118
|
-
*
|
|
6119
|
-
*
|
|
6186
|
+
* invoke it rather than throw immediately. The handler decides whether to
|
|
6187
|
+
* throw synchronously, continue, or ask the coordinator for an extension.
|
|
6120
6188
|
*/
|
|
6121
6189
|
get onThreshold() {
|
|
6122
6190
|
return this._onThreshold;
|
|
@@ -6124,7 +6192,12 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
6124
6192
|
set onThreshold(fn) {
|
|
6125
6193
|
this._onThreshold = fn;
|
|
6126
6194
|
}
|
|
6127
|
-
|
|
6195
|
+
/** Returns the current negotiation mode. */
|
|
6196
|
+
get mode() {
|
|
6197
|
+
return this._mode;
|
|
6198
|
+
}
|
|
6199
|
+
constructor(limits = {}, mode = "auto") {
|
|
6200
|
+
this._mode = mode;
|
|
6128
6201
|
this.limits = { ...limits };
|
|
6129
6202
|
}
|
|
6130
6203
|
start() {
|
|
@@ -6140,16 +6213,23 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
6140
6213
|
return false;
|
|
6141
6214
|
}
|
|
6142
6215
|
/**
|
|
6143
|
-
* Synchronous budget check
|
|
6144
|
-
*
|
|
6145
|
-
*
|
|
6146
|
-
*
|
|
6147
|
-
*
|
|
6216
|
+
* Synchronous budget check. Always throws synchronously so callers (especially
|
|
6217
|
+
* test event handlers using `expect().toThrow()`) get an unhandled rejection
|
|
6218
|
+
* when the budget is exceeded without a handler.
|
|
6219
|
+
*
|
|
6220
|
+
* Decision table:
|
|
6221
|
+
* - no `onThreshold` handler → throw `BudgetExceededError` (hard stop, always)
|
|
6222
|
+
* - `mode === 'sync'` → throw `BudgetExceededError` (hard stop, always)
|
|
6223
|
+
* - `mode === 'auto'` + no listener → throw `BudgetExceededError` (hard stop; no one to ask)
|
|
6224
|
+
* - `mode === 'auto'` + listener → throw `BudgetThresholdSignal` with async decision promise
|
|
6148
6225
|
*/
|
|
6149
6226
|
checkLimit(kind, used, limit) {
|
|
6150
6227
|
if (!this._onThreshold) {
|
|
6151
6228
|
throw new BudgetExceededError(kind, limit, used);
|
|
6152
6229
|
}
|
|
6230
|
+
if (this._mode === "sync") {
|
|
6231
|
+
throw new BudgetExceededError(kind, limit, used);
|
|
6232
|
+
}
|
|
6153
6233
|
const bus = this._events;
|
|
6154
6234
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
6155
6235
|
throw new BudgetExceededError(kind, limit, used);
|
|
@@ -6166,8 +6246,8 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
6166
6246
|
* `pendingExtensions` slot in `finally`.
|
|
6167
6247
|
*
|
|
6168
6248
|
* The 'continue' return from a sync handler is treated as
|
|
6169
|
-
* `{ extend: {} }` — keep going without patching
|
|
6170
|
-
*
|
|
6249
|
+
* `{ extend: {} }` — keep going without patching; next overrun fires
|
|
6250
|
+
* a fresh signal.
|
|
6171
6251
|
*/
|
|
6172
6252
|
async negotiateExtension(kind, used, limit) {
|
|
6173
6253
|
try {
|
|
@@ -6175,11 +6255,6 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
6175
6255
|
kind,
|
|
6176
6256
|
used,
|
|
6177
6257
|
limit,
|
|
6178
|
-
// Inject a requestDecision helper the handler can call to emit the
|
|
6179
|
-
// budget.threshold_reached event and wait for the coordinator's verdict.
|
|
6180
|
-
// A hard fallback timer guarantees the promise eventually resolves
|
|
6181
|
-
// even if no listener responds — without it, an absent/detached
|
|
6182
|
-
// Director would leave the budget permanently in "asking" state.
|
|
6183
6258
|
requestDecision: () => {
|
|
6184
6259
|
const bus = this._events;
|
|
6185
6260
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
@@ -6263,12 +6338,12 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
6263
6338
|
}
|
|
6264
6339
|
}
|
|
6265
6340
|
/**
|
|
6266
|
-
* Wall-clock budget check. Unlike other limits, timeout
|
|
6267
|
-
*
|
|
6268
|
-
*
|
|
6269
|
-
*
|
|
6270
|
-
*
|
|
6271
|
-
*
|
|
6341
|
+
* Wall-clock budget check. Unlike other limits, timeout check passes through
|
|
6342
|
+
* `checkLimit` and is subject to the same negotiation-mode decision table.
|
|
6343
|
+
* In practice, `'sync'` mode (the usual test configuration) means a timeout
|
|
6344
|
+
* immediately throws `BudgetExceededError`. In production with a coordinator,
|
|
6345
|
+
* a timeout emits `budget.threshold_reached` so the Director can decide whether
|
|
6346
|
+
* to extend or abort.
|
|
6272
6347
|
*/
|
|
6273
6348
|
checkTimeout() {
|
|
6274
6349
|
if (this.startTime === null || this.limits.timeoutMs === void 0) return;
|
|
@@ -8649,8 +8724,7 @@ function scoreAgents(task, catalog = AGENT_CATALOG) {
|
|
|
8649
8724
|
const hay = normalize(task);
|
|
8650
8725
|
const out = [];
|
|
8651
8726
|
for (const def of Object.values(catalog)) {
|
|
8652
|
-
|
|
8653
|
-
if (!role) continue;
|
|
8727
|
+
if (!def?.config?.role) continue;
|
|
8654
8728
|
let score = 0;
|
|
8655
8729
|
const matched = [];
|
|
8656
8730
|
for (const kw of def.capability.keywords) {
|
|
@@ -8662,7 +8736,7 @@ function scoreAgents(task, catalog = AGENT_CATALOG) {
|
|
|
8662
8736
|
}
|
|
8663
8737
|
}
|
|
8664
8738
|
if (score > 0) {
|
|
8665
|
-
out.push({ role, name: def.config.name, score, matched });
|
|
8739
|
+
out.push({ role: def.config.role, name: def.config.name, score, matched });
|
|
8666
8740
|
}
|
|
8667
8741
|
}
|
|
8668
8742
|
out.sort((a, b) => b.score - a.score);
|
|
@@ -9033,6 +9107,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9033
9107
|
coordinatorId;
|
|
9034
9108
|
config;
|
|
9035
9109
|
runner;
|
|
9110
|
+
fleetBus;
|
|
9036
9111
|
subagents = /* @__PURE__ */ new Map();
|
|
9037
9112
|
pendingTasks = [];
|
|
9038
9113
|
completedResults = [];
|
|
@@ -9061,6 +9136,14 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9061
9136
|
setRunner(runner) {
|
|
9062
9137
|
this.runner = runner;
|
|
9063
9138
|
}
|
|
9139
|
+
/**
|
|
9140
|
+
* Wire a FleetBus for director-mode event emission. Call after the
|
|
9141
|
+
* FleetManager is constructed so the coordinator can emit lifecycle
|
|
9142
|
+
* events the TUI and monitoring tools subscribe to.
|
|
9143
|
+
*/
|
|
9144
|
+
setFleetBus(fleet) {
|
|
9145
|
+
this.fleetBus = fleet;
|
|
9146
|
+
}
|
|
9064
9147
|
/**
|
|
9065
9148
|
* Change the in-flight dispatch ceiling at runtime. Lowering does NOT
|
|
9066
9149
|
* preempt running tasks — already-dispatched subagents finish their
|
|
@@ -9096,6 +9179,18 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9096
9179
|
abortController: new AbortController()
|
|
9097
9180
|
});
|
|
9098
9181
|
this.emit("subagent.started", { subagent: { ...subagent, id } });
|
|
9182
|
+
this.fleetBus?.emit({
|
|
9183
|
+
subagentId: id,
|
|
9184
|
+
ts: Date.now(),
|
|
9185
|
+
type: "subagent.assigned",
|
|
9186
|
+
payload: {
|
|
9187
|
+
subagentId: id,
|
|
9188
|
+
name: subagent.name,
|
|
9189
|
+
provider: subagent.provider,
|
|
9190
|
+
model: subagent.model
|
|
9191
|
+
}
|
|
9192
|
+
});
|
|
9193
|
+
this.emitCoordinatorStats();
|
|
9099
9194
|
return { subagentId: id, agentId: id };
|
|
9100
9195
|
}
|
|
9101
9196
|
async assign(task) {
|
|
@@ -9128,6 +9223,13 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9128
9223
|
subagent.currentTask = void 0;
|
|
9129
9224
|
subagent.context.parentBridge = null;
|
|
9130
9225
|
this.emit("subagent.stopped", { subagentId, reason: "stopped by coordinator" });
|
|
9226
|
+
this.fleetBus?.emit({
|
|
9227
|
+
subagentId,
|
|
9228
|
+
ts: Date.now(),
|
|
9229
|
+
type: "subagent.stopped",
|
|
9230
|
+
payload: { subagentId, reason: "stopped by coordinator" }
|
|
9231
|
+
});
|
|
9232
|
+
this.emitCoordinatorStats();
|
|
9131
9233
|
}
|
|
9132
9234
|
async stopAll() {
|
|
9133
9235
|
this.drainPendingAsAborted("Coordinator stopAll() drained the pending queue");
|
|
@@ -9159,6 +9261,22 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9159
9261
|
completed: this.completedResults.length
|
|
9160
9262
|
};
|
|
9161
9263
|
}
|
|
9264
|
+
/** Emit a reactive coordinator.stats event on FleetBus so the TUI can subscribe. */
|
|
9265
|
+
emitCoordinatorStats() {
|
|
9266
|
+
const stats = this.getStats();
|
|
9267
|
+
const subagentStatuses = Array.from(this.subagents.entries()).map(([id, s]) => ({
|
|
9268
|
+
subagentId: id,
|
|
9269
|
+
taskId: s.currentTask ?? "",
|
|
9270
|
+
status: s.status,
|
|
9271
|
+
assigned: s.context.parentBridge !== null
|
|
9272
|
+
}));
|
|
9273
|
+
this.fleetBus?.emit({
|
|
9274
|
+
subagentId: this.coordinatorId,
|
|
9275
|
+
ts: Date.now(),
|
|
9276
|
+
type: "coordinator.stats",
|
|
9277
|
+
payload: { ...stats, subagentStatuses }
|
|
9278
|
+
});
|
|
9279
|
+
}
|
|
9162
9280
|
getStatus() {
|
|
9163
9281
|
return {
|
|
9164
9282
|
coordinatorId: this.coordinatorId,
|
|
@@ -9333,7 +9451,15 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9333
9451
|
subagent.currentTask = task.id;
|
|
9334
9452
|
task.subagentId = subagentId;
|
|
9335
9453
|
subagent.context.tasks.push(task);
|
|
9454
|
+
this.fleetBus?.emit({
|
|
9455
|
+
subagentId,
|
|
9456
|
+
taskId: task.id,
|
|
9457
|
+
ts: Date.now(),
|
|
9458
|
+
type: "subagent.running",
|
|
9459
|
+
payload: { subagentId, taskId: task.id }
|
|
9460
|
+
});
|
|
9336
9461
|
this.emit("task.assigned", { task, subagentId });
|
|
9462
|
+
this.emitCoordinatorStats();
|
|
9337
9463
|
const rawMaxIterations = subagent.config.maxIterations;
|
|
9338
9464
|
const rawMaxToolCalls = subagent.config.maxToolCalls;
|
|
9339
9465
|
const rawMaxTokens = subagent.config.maxTokens;
|
|
@@ -9477,13 +9603,34 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9477
9603
|
if (subagent.abortController.signal.aborted) {
|
|
9478
9604
|
subagent.abortController = new AbortController();
|
|
9479
9605
|
}
|
|
9606
|
+
this.fleetBus?.emit({
|
|
9607
|
+
subagentId: result.subagentId,
|
|
9608
|
+
ts: Date.now(),
|
|
9609
|
+
type: "subagent.idle",
|
|
9610
|
+
payload: { subagentId: result.subagentId }
|
|
9611
|
+
});
|
|
9480
9612
|
}
|
|
9481
9613
|
this.terminating.delete(result.subagentId);
|
|
9482
9614
|
this.emit("task.completed", {
|
|
9483
9615
|
task: subagent?.context.tasks.find((t) => t.id === result.taskId) ?? { id: result.taskId },
|
|
9484
9616
|
result
|
|
9485
9617
|
});
|
|
9618
|
+
this.fleetBus?.emit({
|
|
9619
|
+
subagentId: result.subagentId,
|
|
9620
|
+
taskId: result.taskId,
|
|
9621
|
+
ts: Date.now(),
|
|
9622
|
+
type: "subagent.completed",
|
|
9623
|
+
payload: {
|
|
9624
|
+
subagentId: result.subagentId,
|
|
9625
|
+
taskId: result.taskId,
|
|
9626
|
+
status: result.status,
|
|
9627
|
+
iterations: result.iterations,
|
|
9628
|
+
toolCalls: result.toolCalls,
|
|
9629
|
+
durationMs: result.durationMs
|
|
9630
|
+
}
|
|
9631
|
+
});
|
|
9486
9632
|
this.tryDispatchNext();
|
|
9633
|
+
this.emitCoordinatorStats();
|
|
9487
9634
|
if (this.isDone()) {
|
|
9488
9635
|
this.emit("done", {
|
|
9489
9636
|
results: this.completedResults,
|
|
@@ -10334,18 +10481,17 @@ var FleetBus = class {
|
|
|
10334
10481
|
byType = /* @__PURE__ */ new Map();
|
|
10335
10482
|
any = /* @__PURE__ */ new Set();
|
|
10336
10483
|
/**
|
|
10337
|
-
* Hook a subagent's EventBus into the fleet.
|
|
10338
|
-
*
|
|
10339
|
-
*
|
|
10340
|
-
*
|
|
10341
|
-
*
|
|
10342
|
-
* the wire format clear.
|
|
10484
|
+
* Hook a subagent's EventBus into the fleet. Uses `onAny()` (an alias for
|
|
10485
|
+
* `onPattern('*')`) to forward all events with subagent attribution, so
|
|
10486
|
+
* new kernel event types are automatically forwarded without any manual
|
|
10487
|
+
* registration. `subagent.*` events are excluded because they originate
|
|
10488
|
+
* from MultiAgentHost on the parent bus, not the subagent's own bus.
|
|
10343
10489
|
*
|
|
10344
10490
|
* Returns a disposer that detaches every subscription; call on
|
|
10345
10491
|
* subagent teardown so the listeners don't outlive the run.
|
|
10346
10492
|
*/
|
|
10347
10493
|
attach(subagentId, bus, taskId) {
|
|
10348
|
-
const off = bus.
|
|
10494
|
+
const off = bus.onAny((type, payload) => {
|
|
10349
10495
|
if (type.startsWith("subagent.")) return;
|
|
10350
10496
|
this.emit({ subagentId, taskId, ts: Date.now(), type, payload });
|
|
10351
10497
|
});
|
|
@@ -10467,7 +10613,7 @@ var FleetUsageAggregator = class {
|
|
|
10467
10613
|
this.total.output += usage.output ?? 0;
|
|
10468
10614
|
this.total.cacheRead += usage.cacheRead ?? 0;
|
|
10469
10615
|
this.total.cacheWrite += usage.cacheWrite ?? 0;
|
|
10470
|
-
const price = this.priceLookup?.(e.subagentId);
|
|
10616
|
+
const price = this.priceLookup?.(e.subagentId, snap.provider, snap.model);
|
|
10471
10617
|
if (price) {
|
|
10472
10618
|
const delta = (usage.input ?? 0) / 1e6 * (price.input ?? 0) + (usage.output ?? 0) / 1e6 * (price.output ?? 0) + (usage.cacheRead ?? 0) / 1e6 * (price.cacheRead ?? 0) + (usage.cacheWrite ?? 0) / 1e6 * (price.cacheWrite ?? 0);
|
|
10473
10619
|
snap.cost += delta;
|
|
@@ -10490,8 +10636,9 @@ function makeSpawnTool(director, roster) {
|
|
|
10490
10636
|
const inputSchema = {
|
|
10491
10637
|
type: "object",
|
|
10492
10638
|
properties: {
|
|
10493
|
-
role: { type: "string", description: "Roster role id
|
|
10494
|
-
|
|
10639
|
+
role: { type: "string", description: "Roster role id. When set, the spawn uses the matching config from the roster and ignores other fields." },
|
|
10640
|
+
description: { type: "string", description: "Free-form task description. When `role` is not set, the director uses the smart dispatcher to route this to the best-matching catalog agent. Use this when you don't know the exact role name." },
|
|
10641
|
+
name: { type: "string", description: "Display name for the subagent. Used as a fallback when description-based dispatch does not resolve a role." },
|
|
10495
10642
|
provider: { type: "string", description: 'Provider id (e.g. "anthropic", "openai"). Defaults to the leader provider when omitted.' },
|
|
10496
10643
|
model: { type: "string", description: "Model id within the provider. Defaults to the leader model when omitted." },
|
|
10497
10644
|
systemPromptOverride: { type: "string", description: "Extra prompt text appended after the role-base prompt." },
|
|
@@ -10504,18 +10651,38 @@ function makeSpawnTool(director, roster) {
|
|
|
10504
10651
|
return {
|
|
10505
10652
|
name: "spawn_subagent",
|
|
10506
10653
|
description: "Create a new subagent under this director. Returns the subagent id.",
|
|
10507
|
-
usageHint: "
|
|
10654
|
+
usageHint: "Pass `role` (matches the roster), `description` (smart dispatch to best agent), or `name` + `provider`/`model`. Returns `{ subagentId }`.",
|
|
10508
10655
|
permission: "auto",
|
|
10509
10656
|
mutating: false,
|
|
10510
10657
|
inputSchema,
|
|
10511
10658
|
async execute(input) {
|
|
10512
10659
|
const i = input ?? {};
|
|
10513
10660
|
const role = typeof i.role === "string" ? i.role : void 0;
|
|
10514
|
-
const
|
|
10515
|
-
|
|
10516
|
-
|
|
10661
|
+
const description = typeof i.description === "string" ? i.description : void 0;
|
|
10662
|
+
let cfg;
|
|
10663
|
+
if (role && roster) {
|
|
10664
|
+
const base = roster[role];
|
|
10665
|
+
if (!base) return { error: `unknown role "${role}". roster has: ${Object.keys(roster).join(", ")}` };
|
|
10666
|
+
cfg = instantiateRosterConfig(role, base);
|
|
10667
|
+
} else if (description && !role) {
|
|
10668
|
+
const dispatchResult = await dispatchAgent(description, {
|
|
10669
|
+
classifier: director.dispatchClassifier,
|
|
10670
|
+
catalog: roster
|
|
10671
|
+
});
|
|
10672
|
+
const dispatchRole = dispatchResult.role;
|
|
10673
|
+
if (roster && roster[dispatchRole]) {
|
|
10674
|
+
cfg = instantiateRosterConfig(dispatchRole, roster[dispatchRole]);
|
|
10675
|
+
} else {
|
|
10676
|
+
const def = dispatchResult.definition;
|
|
10677
|
+
cfg = {
|
|
10678
|
+
name: def.config.name ?? dispatchRole,
|
|
10679
|
+
role: dispatchRole,
|
|
10680
|
+
provider: def.config.provider,
|
|
10681
|
+
model: def.config.model
|
|
10682
|
+
};
|
|
10683
|
+
}
|
|
10517
10684
|
}
|
|
10518
|
-
|
|
10685
|
+
cfg ??= { name: i.name ?? "subagent" };
|
|
10519
10686
|
if (typeof i.name === "string") cfg.name = i.name;
|
|
10520
10687
|
if (typeof i.provider === "string") cfg.provider = i.provider;
|
|
10521
10688
|
if (typeof i.model === "string") cfg.model = i.model;
|
|
@@ -10525,7 +10692,7 @@ function makeSpawnTool(director, roster) {
|
|
|
10525
10692
|
if (typeof i.maxCostUsd === "number") cfg.maxCostUsd = i.maxCostUsd;
|
|
10526
10693
|
try {
|
|
10527
10694
|
const subagentId = await director.spawn(cfg);
|
|
10528
|
-
return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name };
|
|
10695
|
+
return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name, role: cfg.role };
|
|
10529
10696
|
} catch (err) {
|
|
10530
10697
|
if (err instanceof FleetSpawnBudgetError) {
|
|
10531
10698
|
return { error: err.message, kind: err.kind, limit: err.limit, observed: err.observed };
|
|
@@ -10649,12 +10816,21 @@ function makeTerminateTool(director) {
|
|
|
10649
10816
|
function makeFleetStatusTool(director) {
|
|
10650
10817
|
return {
|
|
10651
10818
|
name: "fleet_status",
|
|
10652
|
-
description: "Snapshot of the fleet \u2014 every subagent's current status,
|
|
10819
|
+
description: "Snapshot of the fleet \u2014 every subagent's current status, coordinator counts (total/running/idle/stopped), pending task descriptions, and usage rollup.",
|
|
10653
10820
|
permission: "auto",
|
|
10654
10821
|
mutating: false,
|
|
10655
10822
|
inputSchema: { type: "object", properties: {}, required: [] },
|
|
10656
10823
|
async execute() {
|
|
10657
|
-
|
|
10824
|
+
const base = director.status();
|
|
10825
|
+
const fm = director.fleetManager;
|
|
10826
|
+
const stats = fm?.getFleetStats();
|
|
10827
|
+
const fleetStatus = fm?.getFleetStatus();
|
|
10828
|
+
return {
|
|
10829
|
+
subagents: base.subagents,
|
|
10830
|
+
coordinatorStats: stats ? { total: stats.total, running: stats.running, idle: stats.idle, stopped: stats.stopped } : void 0,
|
|
10831
|
+
pending: fleetStatus?.pending ?? [],
|
|
10832
|
+
usage: fm?.snapshot()
|
|
10833
|
+
};
|
|
10658
10834
|
}
|
|
10659
10835
|
};
|
|
10660
10836
|
}
|
|
@@ -10856,6 +11032,8 @@ var Director = class {
|
|
|
10856
11032
|
* default cap.
|
|
10857
11033
|
*/
|
|
10858
11034
|
taskCompletedListener = null;
|
|
11035
|
+
/** Optional LLM classifier for smart dispatch. Passed from options. */
|
|
11036
|
+
dispatchClassifier;
|
|
10859
11037
|
constructor(opts) {
|
|
10860
11038
|
this.id = opts.config.coordinatorId || randomUUID();
|
|
10861
11039
|
this.manifestPath = opts.manifestPath;
|
|
@@ -10868,6 +11046,7 @@ var Director = class {
|
|
|
10868
11046
|
this.spawnDepth = opts.spawnDepth ?? 0;
|
|
10869
11047
|
this.sessionWriter = opts.sessionWriter ?? null;
|
|
10870
11048
|
this.manifestDebounceMs = opts.manifestDebounceMs ?? 2e3;
|
|
11049
|
+
this.dispatchClassifier = opts.dispatchClassifier;
|
|
10871
11050
|
this.maxFleetCostUsd = opts.directorBudget?.maxCostUsd ?? Number.POSITIVE_INFINITY;
|
|
10872
11051
|
this.maxBudgetExtensions = opts.maxBudgetExtensions ?? 5;
|
|
10873
11052
|
this.sessionsRoot = opts.sessionsRoot;
|
|
@@ -10897,7 +11076,10 @@ var Director = class {
|
|
|
10897
11076
|
this.fleet = new FleetBus();
|
|
10898
11077
|
this.usage = new FleetUsageAggregator(
|
|
10899
11078
|
this.fleet,
|
|
10900
|
-
(id) =>
|
|
11079
|
+
(id, provider, model) => {
|
|
11080
|
+
if (provider && model) return this.priceLookups.get(`${provider}/${model}`);
|
|
11081
|
+
return void 0;
|
|
11082
|
+
},
|
|
10901
11083
|
(id) => this.subagentMeta.get(id)
|
|
10902
11084
|
);
|
|
10903
11085
|
}
|
|
@@ -10905,6 +11087,8 @@ var Director = class {
|
|
|
10905
11087
|
{ ...opts.config, coordinatorId: this.id },
|
|
10906
11088
|
{ runner: opts.runner }
|
|
10907
11089
|
);
|
|
11090
|
+
this.coordinator.setFleetBus(this.fleet);
|
|
11091
|
+
this.fleetManager?.setCoordinator(this.coordinator);
|
|
10908
11092
|
this.taskCompletedListener = (payload) => {
|
|
10909
11093
|
const r = payload.result;
|
|
10910
11094
|
this.completed.set(r.taskId, r);
|
|
@@ -10939,7 +11123,11 @@ var Director = class {
|
|
|
10939
11123
|
title
|
|
10940
11124
|
}
|
|
10941
11125
|
);
|
|
10942
|
-
this.
|
|
11126
|
+
if (this.fleetManager) {
|
|
11127
|
+
this.fleetManager.flushManifest();
|
|
11128
|
+
} else {
|
|
11129
|
+
this.scheduleManifest();
|
|
11130
|
+
}
|
|
10943
11131
|
};
|
|
10944
11132
|
this.coordinator.on("task.completed", this.taskCompletedListener);
|
|
10945
11133
|
const extendCounts = /* @__PURE__ */ new Map();
|
|
@@ -11031,10 +11219,17 @@ var Director = class {
|
|
|
11031
11219
|
}
|
|
11032
11220
|
}
|
|
11033
11221
|
/** Debounced manifest writer. A burst of spawn/assign/complete events
|
|
11034
|
-
* collapses into one write. Set `manifestDebounceMs` to 0 to
|
|
11222
|
+
* collapses into one write. Set `manifestDebounceMs` to 0 to write
|
|
11223
|
+
* synchronously (no debounce); set to negative to disable entirely. */
|
|
11035
11224
|
scheduleManifest() {
|
|
11036
|
-
if (!this.manifestPath
|
|
11037
|
-
if (this.
|
|
11225
|
+
if (!this.manifestPath) return;
|
|
11226
|
+
if (this.manifestDebounceMs === 0) {
|
|
11227
|
+
void this.writeManifest().catch(
|
|
11228
|
+
(err) => this.logShutdownError("manifest_write_debounced", err)
|
|
11229
|
+
);
|
|
11230
|
+
return;
|
|
11231
|
+
}
|
|
11232
|
+
if (this.manifestDebounceMs < 0) return;
|
|
11038
11233
|
this.manifestTimer = setTimeout(() => {
|
|
11039
11234
|
this.manifestTimer = null;
|
|
11040
11235
|
void this.writeManifest().catch(
|
|
@@ -11083,7 +11278,9 @@ var Director = class {
|
|
|
11083
11278
|
provider: config.provider,
|
|
11084
11279
|
model: config.model
|
|
11085
11280
|
});
|
|
11086
|
-
if (priceLookup
|
|
11281
|
+
if (priceLookup && config.provider && config.model) {
|
|
11282
|
+
this.priceLookups.set(`${config.provider}/${config.model}`, priceLookup);
|
|
11283
|
+
}
|
|
11087
11284
|
}
|
|
11088
11285
|
const subagentBridge = new InMemoryAgentBridge(
|
|
11089
11286
|
{ agentId: result.subagentId, coordinatorId: this.id },
|