@wrongstack/core 0.4.1 → 0.5.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-DaOnnHNW.d.ts → agent-bridge-EiUFe3if.d.ts} +1 -1
- package/dist/{compactor-CFky6JKM.d.ts → compactor-BP4xhKVi.d.ts} +1 -1
- package/dist/{config-RlhKLjme.d.ts → config-BOD_HQBw.d.ts} +1 -1
- package/dist/{context-B1kBj1lY.d.ts → context-PH4DvBZV.d.ts} +60 -1
- package/dist/coordination/index.d.ts +10 -891
- package/dist/coordination/index.js +500 -238
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +20 -19
- package/dist/defaults/index.js +2210 -264
- package/dist/defaults/index.js.map +1 -1
- package/dist/director-state-CVzkjKRZ.d.ts +539 -0
- package/dist/{events-BBaKeMfb.d.ts → events-oxn-Wkub.d.ts} +58 -1
- package/dist/execution/index.d.ts +19 -13
- package/dist/execution/index.js +15 -6
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/index-CcbWbcpy.d.ts +899 -0
- package/dist/{index-meJRuQtc.d.ts → index-a12jc7-r.d.ts} +8 -6
- package/dist/index.d.ts +33 -28
- package/dist/index.js +3798 -1237
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/infrastructure/index.js +67 -2
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +10 -9
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-Cf4-bJnd.d.ts → mcp-servers-uPmBxZ1B.d.ts} +18 -3
- package/dist/models/index.d.ts +2 -2
- package/dist/models/index.js +106 -0
- package/dist/models/index.js.map +1 -1
- package/dist/{multi-agent-D5m66hzB.d.ts → multi-agent-D6S4Z7H8.d.ts} +71 -16
- package/dist/observability/index.d.ts +2 -2
- package/dist/{path-resolver-Bg4OP5fi.d.ts → path-resolver-CprD5DhS.d.ts} +9 -2
- package/dist/{provider-runner-CU9gnU2E.d.ts → provider-runner-DGisz_lG.d.ts} +3 -3
- package/dist/{skill-DayhFUBb.d.ts → retry-policy-DUJ8-Qc_.d.ts} +2 -28
- package/dist/sdd/index.d.ts +419 -5
- package/dist/sdd/index.js +1580 -1
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-scrubber-DyUAWS09.d.ts → secret-scrubber-CB11A2P7.d.ts} +1 -1
- package/dist/{secret-scrubber-Dyh5LVYL.d.ts → secret-scrubber-EqFa0SyI.d.ts} +1 -1
- package/dist/security/index.d.ts +8 -4
- package/dist/security/index.js +8 -0
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-DBEiwXBk.d.ts → selector-yqyxt-Ii.d.ts} +1 -1
- package/dist/{session-reader-D-z0AgHs.d.ts → session-reader-1tOyoY1s.d.ts} +1 -1
- package/dist/session-rewinder-C9HnMkhP.d.ts +23 -0
- package/dist/skill-CxuWrsKK.d.ts +29 -0
- package/dist/skills/index.d.ts +136 -0
- package/dist/skills/index.js +478 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/storage/index.d.ts +21 -534
- package/dist/storage/index.js +246 -3
- package/dist/storage/index.js.map +1 -1
- package/dist/{system-prompt-DNetCecu.d.ts → system-prompt-BJlzKGO6.d.ts} +1 -1
- package/dist/{tool-executor-B5bgmEgE.d.ts → tool-executor-B6kRcWeF.d.ts} +4 -4
- package/dist/types/index.d.ts +17 -15
- package/dist/types/index.js +116 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +35 -2
- package/dist/utils/index.js +49 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +5 -1
- package/skills/sdd/SKILL.md +93 -6
- package/skills/skill-creator/SKILL.md +98 -0
|
@@ -450,7 +450,9 @@ var FleetBus = class {
|
|
|
450
450
|
"session.damaged",
|
|
451
451
|
"compaction.fired",
|
|
452
452
|
"compaction.failed",
|
|
453
|
-
"token.threshold"
|
|
453
|
+
"token.threshold",
|
|
454
|
+
// Subagent hit a soft budget limit — coordinator can extend or stop.
|
|
455
|
+
"budget.threshold_reached"
|
|
454
456
|
];
|
|
455
457
|
const offs = [];
|
|
456
458
|
for (const t of FORWARDED_TYPES) {
|
|
@@ -713,6 +715,21 @@ var BudgetExceededError = class extends Error {
|
|
|
713
715
|
this.observed = observed;
|
|
714
716
|
}
|
|
715
717
|
};
|
|
718
|
+
var BudgetThresholdSignal = class extends Error {
|
|
719
|
+
kind;
|
|
720
|
+
limit;
|
|
721
|
+
used;
|
|
722
|
+
/** Resolves to 'extend' (with optional new limits) or 'stop' */
|
|
723
|
+
decision;
|
|
724
|
+
constructor(kind, limit, used, decision) {
|
|
725
|
+
super(`Budget soft limit: ${kind} (limit=${limit}, used=${used})`);
|
|
726
|
+
this.name = "BudgetThresholdSignal";
|
|
727
|
+
this.kind = kind;
|
|
728
|
+
this.limit = limit;
|
|
729
|
+
this.used = used;
|
|
730
|
+
this.decision = decision;
|
|
731
|
+
}
|
|
732
|
+
};
|
|
716
733
|
var SubagentBudget = class {
|
|
717
734
|
limits;
|
|
718
735
|
iterations = 0;
|
|
@@ -721,22 +738,111 @@ var SubagentBudget = class {
|
|
|
721
738
|
tokenOutput = 0;
|
|
722
739
|
costUsd = 0;
|
|
723
740
|
startTime = null;
|
|
741
|
+
_onThreshold;
|
|
742
|
+
/**
|
|
743
|
+
* Injected by the runner when wiring the budget to its EventBus.
|
|
744
|
+
* Used by `checkLimitAsync` to emit `budget.threshold_reached` events.
|
|
745
|
+
*/
|
|
746
|
+
_events;
|
|
747
|
+
/**
|
|
748
|
+
* Optional callback for soft-limit handling. When set, the budget will
|
|
749
|
+
* call this instead of throwing when a limit is first reached. The
|
|
750
|
+
* handler decides whether to throw, continue, or ask the coordinator.
|
|
751
|
+
*/
|
|
752
|
+
get onThreshold() {
|
|
753
|
+
return this._onThreshold;
|
|
754
|
+
}
|
|
755
|
+
set onThreshold(fn) {
|
|
756
|
+
this._onThreshold = fn;
|
|
757
|
+
}
|
|
724
758
|
constructor(limits = {}) {
|
|
725
759
|
this.limits = Object.freeze({ ...limits });
|
|
726
760
|
}
|
|
727
761
|
start() {
|
|
728
762
|
this.startTime = Date.now();
|
|
729
763
|
}
|
|
764
|
+
/** Returns true if we're within 10% of any limit — useful for pre-flight checks. */
|
|
765
|
+
isNearLimit() {
|
|
766
|
+
const { maxIterations, maxToolCalls, maxTokens, maxCostUsd } = this.limits;
|
|
767
|
+
if (maxIterations && this.iterations >= maxIterations * 0.9) return true;
|
|
768
|
+
if (maxToolCalls && this.toolCalls >= maxToolCalls * 0.9) return true;
|
|
769
|
+
if (maxTokens && this.tokenInput + this.tokenOutput >= maxTokens * 0.9) return true;
|
|
770
|
+
if (maxCostUsd && this.costUsd >= maxCostUsd * 0.9) return true;
|
|
771
|
+
return false;
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Synchronous budget check — always throws synchronously so callers
|
|
775
|
+
* (especially test event handlers using `expect().toThrow()`) get an
|
|
776
|
+
* unhandled rejection when the budget is exceeded without a handler.
|
|
777
|
+
* When `onThreshold` IS configured, the actual async threshold-handling
|
|
778
|
+
* is dispatched as a fire-and-forget promise.
|
|
779
|
+
*/
|
|
780
|
+
checkLimit(kind, used, limit) {
|
|
781
|
+
if (kind === "timeout" || !this._onThreshold) {
|
|
782
|
+
throw new BudgetExceededError(kind, limit, used);
|
|
783
|
+
}
|
|
784
|
+
void this.checkLimitAsync(kind, used, limit);
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Async threshold negotiation with the coordinator. Fire-and-forget —
|
|
788
|
+
* any error thrown here becomes an unhandled rejection in the test environment
|
|
789
|
+
* because the runner's catch only handles the synchronous throw from `checkLimit`.
|
|
790
|
+
*/
|
|
791
|
+
async checkLimitAsync(kind, used, limit) {
|
|
792
|
+
const result = this._onThreshold({
|
|
793
|
+
kind,
|
|
794
|
+
used,
|
|
795
|
+
limit,
|
|
796
|
+
// Inject a requestDecision helper the handler can call to emit the
|
|
797
|
+
// budget.threshold_reached event and wait for the coordinator's verdict.
|
|
798
|
+
// The runner wires this by injecting its EventBus into ctx.budget._events.
|
|
799
|
+
requestDecision: () => {
|
|
800
|
+
return new Promise((resolve) => {
|
|
801
|
+
this._events?.emit("budget.threshold_reached", {
|
|
802
|
+
kind,
|
|
803
|
+
used,
|
|
804
|
+
limit,
|
|
805
|
+
timeoutMs: 3e4,
|
|
806
|
+
extend: (extra) => resolve({ extend: extra }),
|
|
807
|
+
deny: () => resolve("stop")
|
|
808
|
+
});
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
if (result === "throw") {
|
|
813
|
+
throw new BudgetExceededError(kind, limit, used);
|
|
814
|
+
}
|
|
815
|
+
if (result === "continue") {
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
const decision = await result;
|
|
819
|
+
if (decision === "stop") {
|
|
820
|
+
throw new BudgetExceededError(kind, limit, used);
|
|
821
|
+
}
|
|
822
|
+
const ext = decision.extend;
|
|
823
|
+
if (ext.maxIterations !== void 0) {
|
|
824
|
+
this.limits.maxIterations = ext.maxIterations;
|
|
825
|
+
}
|
|
826
|
+
if (ext.maxToolCalls !== void 0) {
|
|
827
|
+
this.limits.maxToolCalls = ext.maxToolCalls;
|
|
828
|
+
}
|
|
829
|
+
if (ext.maxTokens !== void 0) {
|
|
830
|
+
this.limits.maxTokens = ext.maxTokens;
|
|
831
|
+
}
|
|
832
|
+
if (ext.maxCostUsd !== void 0) {
|
|
833
|
+
this.limits.maxCostUsd = ext.maxCostUsd;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
730
836
|
recordIteration() {
|
|
731
837
|
this.iterations++;
|
|
732
838
|
if (this.limits.maxIterations !== void 0 && this.iterations > this.limits.maxIterations) {
|
|
733
|
-
|
|
839
|
+
void this.checkLimit("iterations", this.iterations, this.limits.maxIterations);
|
|
734
840
|
}
|
|
735
841
|
}
|
|
736
842
|
recordToolCall() {
|
|
737
843
|
this.toolCalls++;
|
|
738
844
|
if (this.limits.maxToolCalls !== void 0 && this.toolCalls > this.limits.maxToolCalls) {
|
|
739
|
-
|
|
845
|
+
void this.checkLimit("tool_calls", this.toolCalls, this.limits.maxToolCalls);
|
|
740
846
|
}
|
|
741
847
|
}
|
|
742
848
|
recordUsage(usage, costUsd = 0) {
|
|
@@ -745,10 +851,10 @@ var SubagentBudget = class {
|
|
|
745
851
|
this.costUsd += costUsd;
|
|
746
852
|
const totalTokens = this.tokenInput + this.tokenOutput;
|
|
747
853
|
if (this.limits.maxTokens !== void 0 && totalTokens > this.limits.maxTokens) {
|
|
748
|
-
|
|
854
|
+
void this.checkLimit("tokens", totalTokens, this.limits.maxTokens);
|
|
749
855
|
}
|
|
750
856
|
if (this.limits.maxCostUsd !== void 0 && this.costUsd > this.limits.maxCostUsd) {
|
|
751
|
-
|
|
857
|
+
void this.checkLimit("cost", this.costUsd, this.limits.maxCostUsd);
|
|
752
858
|
}
|
|
753
859
|
}
|
|
754
860
|
/**
|
|
@@ -782,6 +888,198 @@ var SubagentBudget = class {
|
|
|
782
888
|
}
|
|
783
889
|
};
|
|
784
890
|
|
|
891
|
+
// src/coordination/fleet.ts
|
|
892
|
+
var AUDIT_LOG_AGENT = {
|
|
893
|
+
id: "audit-log",
|
|
894
|
+
name: "Audit Log",
|
|
895
|
+
role: "audit-log",
|
|
896
|
+
prompt: `You are the Audit Log agent. Your job is to analyze structured JSONL
|
|
897
|
+
session logs and produce actionable markdown reports.
|
|
898
|
+
|
|
899
|
+
Scope:
|
|
900
|
+
- Parse session logs (iteration counts, tool calls, errors, usage)
|
|
901
|
+
- Detect repeated failure patterns across multiple runs
|
|
902
|
+
- Identify tool usage anomalies (over-use, failures, unexpected chains)
|
|
903
|
+
- Track token consumption trends
|
|
904
|
+
- Generate structured audit reports with severity ratings
|
|
905
|
+
|
|
906
|
+
Input format you accept:
|
|
907
|
+
{ "task": "analyze | report | trends", "sessionPath": "<path>", "focus": "errors | tools | usage | all" }
|
|
908
|
+
|
|
909
|
+
Output: Markdown audit report with sections:
|
|
910
|
+
- ## Summary (totals, error rate)
|
|
911
|
+
- ## Top Errors (count + context)
|
|
912
|
+
- ## Tool Usage (table with calls, failures, avg duration)
|
|
913
|
+
- ## Anomalies (pattern \u2192 severity)
|
|
914
|
+
|
|
915
|
+
Working rules:
|
|
916
|
+
- Never fabricate numbers \u2014 read the actual logs first
|
|
917
|
+
- Always include file:line references for errors
|
|
918
|
+
- If sessionPath is missing, ask the director to provide it
|
|
919
|
+
- Report confidence level: high (>90% accuracy), medium, low`
|
|
920
|
+
// No hardcoded budgets — the orchestrator (delegate tool or
|
|
921
|
+
// spawn_subagent) decides per-task how much room a subagent gets.
|
|
922
|
+
// A monorepo audit needs hours; a single-file lint check needs
|
|
923
|
+
// seconds. Pinning a number here forces the orchestrator to fight
|
|
924
|
+
// the role's default instead of just asking for what it needs.
|
|
925
|
+
};
|
|
926
|
+
var BUG_HUNTER_AGENT = {
|
|
927
|
+
id: "bug-hunter",
|
|
928
|
+
name: "Bug Hunter",
|
|
929
|
+
role: "bug-hunter",
|
|
930
|
+
prompt: `You are the Bug Hunter agent. Your job is to systematically scan
|
|
931
|
+
source code for bugs, anti-patterns, and code smells using pattern matching
|
|
932
|
+
and heuristics. Output a prioritized hit list with file:line references.
|
|
933
|
+
|
|
934
|
+
Scope:
|
|
935
|
+
- Detect common bug patterns (uncaught errors, resource leaks, race conditions)
|
|
936
|
+
- Identify anti-patterns (callback hell, God objects, circular deps)
|
|
937
|
+
- Find TypeScript-specific issues (unsafe any, missing null checks, branded types)
|
|
938
|
+
- Flag security-sensitive constructs (eval, innerHTML, hardcoded secrets)
|
|
939
|
+
- Rank findings: critical > high > medium > low
|
|
940
|
+
|
|
941
|
+
Input format you accept:
|
|
942
|
+
{ "task": "scan | hunt | check", "paths": ["src/**/*.ts"], "focus": "bugs | patterns | security | all", "severityThreshold": "medium" }
|
|
943
|
+
|
|
944
|
+
Output: Markdown bug hunt report:
|
|
945
|
+
- ## Critical (must fix first)
|
|
946
|
+
- ## High (should fix)
|
|
947
|
+
- ## Medium
|
|
948
|
+
- ## Low (consider)
|
|
949
|
+
Each entry: **[TYPE]** \`file:line\` \u2014 description + suggested fix
|
|
950
|
+
|
|
951
|
+
Bug pattern reference you know:
|
|
952
|
+
| Pattern | Regex hint | Severity |
|
|
953
|
+
|---------|------------|----------|
|
|
954
|
+
| Uncaught promise | /.then\\(.*\\)/ without catch | high |
|
|
955
|
+
| Event leak | on\\( without off/removeListener | high |
|
|
956
|
+
| Hardcoded secret | [a-zA-Z0-9/_-]{20,} in config files | critical |
|
|
957
|
+
| unsafe any | : any\\b or <any> | medium |
|
|
958
|
+
| innerHTML | innerHTML\\s*= | high |
|
|
959
|
+
|
|
960
|
+
Working rules:
|
|
961
|
+
- Never scan node_modules \u2014 it's noise
|
|
962
|
+
- Always include file:line for every finding
|
|
963
|
+
- If >30% of findings are false positives, note the confidence level
|
|
964
|
+
- Ask director for clarification if paths are ambiguous`
|
|
965
|
+
// Budgets are set by the orchestrator per task — see fleet.ts header.
|
|
966
|
+
};
|
|
967
|
+
var REFACTOR_PLANNER_AGENT = {
|
|
968
|
+
id: "refactor-planner",
|
|
969
|
+
name: "Refactor Planner",
|
|
970
|
+
role: "refactor-planner",
|
|
971
|
+
prompt: `You are the Refactor Planner agent. Your job is to analyze code
|
|
972
|
+
structure and produce a concrete, phased refactoring plan with risk
|
|
973
|
+
assessment, dependency ordering, and rollback strategy.
|
|
974
|
+
|
|
975
|
+
Scope:
|
|
976
|
+
- Map module-level dependencies (import graph)
|
|
977
|
+
- Identify coupling hotspots (high fan-in/out modules)
|
|
978
|
+
- Assess refactoring risk by complexity and test coverage
|
|
979
|
+
- Generate phased plans with checkpoint milestones
|
|
980
|
+
- Produce diff-friendly task lists (one task = one concern)
|
|
981
|
+
|
|
982
|
+
Input format you accept:
|
|
983
|
+
{ "task": "plan | assess | roadmap", "target": "src/core", "constraint": "no-breaking-changes | minimal-downtime | full-rewrite", "focus": "architecture | performance | maintainability" }
|
|
984
|
+
|
|
985
|
+
Output: Markdown refactor plan:
|
|
986
|
+
- ## Phase 1: Low Risk / High Payoff (do first)
|
|
987
|
+
Table: | # | Task | Module | Risk | Est. Time |
|
|
988
|
+
- ## Phase 2: Medium Risk
|
|
989
|
+
- ## Phase 3: High Risk (requires full regression)
|
|
990
|
+
- ## Dependency Graph (abbreviated ASCII)
|
|
991
|
+
- ## Rollback Strategy
|
|
992
|
+
- ## Exit Criteria (checkbox list)
|
|
993
|
+
|
|
994
|
+
Risk scoring criteria:
|
|
995
|
+
| Factor | Low | Medium | High |
|
|
996
|
+
|--------|-----|--------|------|
|
|
997
|
+
| Cyclomatic complexity | <10 | 10-20 | >20 |
|
|
998
|
+
| Test coverage | >80% | 50-80% | <50% |
|
|
999
|
+
| Fan-out (imports) | <5 | 5-15 | >15 |
|
|
1000
|
+
|
|
1001
|
+
Working rules:
|
|
1002
|
+
- Always include rollback strategy \u2014 every refactor can fail
|
|
1003
|
+
- Merge tasks that take <1h into a single phase
|
|
1004
|
+
- Respect team constraints (reviewer availability, parallelization)
|
|
1005
|
+
- Never plan without analyzing the actual code first`
|
|
1006
|
+
// Budgets are set by the orchestrator per task — see fleet.ts header.
|
|
1007
|
+
};
|
|
1008
|
+
var SECURITY_SCANNER_AGENT = {
|
|
1009
|
+
id: "security-scanner",
|
|
1010
|
+
name: "Security Scanner",
|
|
1011
|
+
role: "security-scanner",
|
|
1012
|
+
prompt: `You are the Security Scanner agent. Your job is to scan code,
|
|
1013
|
+
configs, and dependencies for security issues from hardcoded secrets to
|
|
1014
|
+
supply chain risks.
|
|
1015
|
+
|
|
1016
|
+
Scope:
|
|
1017
|
+
- Detect hardcoded secrets: API keys, tokens, passwords, private keys
|
|
1018
|
+
- Find injection vectors: eval, innerHTML, SQL concat, shell injection
|
|
1019
|
+
- Identify insecure patterns: weak crypto, hardcoded IVs, disabled TLS
|
|
1020
|
+
- Scan dependencies for known CVEs (via npm/pnpm audit)
|
|
1021
|
+
- Flag supply chain risks: postinstall hooks, unverified scripts, .npmrc
|
|
1022
|
+
|
|
1023
|
+
Input format you accept:
|
|
1024
|
+
{ "task": "scan | audit | secrets | dependencies", "paths": ["src", "config"], "depth": "quick | normal | deep" }
|
|
1025
|
+
|
|
1026
|
+
Output: Markdown security report:
|
|
1027
|
+
- ## CRITICAL: Secrets Found (with code snippets)
|
|
1028
|
+
- ## HIGH: Injection Vectors
|
|
1029
|
+
- ## MEDIUM: Insecure Patterns
|
|
1030
|
+
- ## Dependency Issues (CVE list)
|
|
1031
|
+
- ## Summary table (severity \u2192 count)
|
|
1032
|
+
- ## Remediation Checklist (with checkboxes)
|
|
1033
|
+
|
|
1034
|
+
Secret patterns you detect:
|
|
1035
|
+
| Pattern | Example | Severity |
|
|
1036
|
+
|---------|---------|----------|
|
|
1037
|
+
| AWS Access Key | AKIAIOSFODNN7EXAMPLE | critical |
|
|
1038
|
+
| AWS Secret Key | [a-zA-Z0-9/+=]{40} base64 | critical |
|
|
1039
|
+
| GitHub Token | ghp_[a-zA-Z0-9]{36} | critical |
|
|
1040
|
+
| Private Key PEM | -----BEGIN.*PRIVATE KEY----- | critical |
|
|
1041
|
+
| JWT | eyJ[a-zA-Z0-9_-]+ | high |
|
|
1042
|
+
|
|
1043
|
+
Injection patterns:
|
|
1044
|
+
| Construct | Safe alternative |
|
|
1045
|
+
|-----------|-----------------|
|
|
1046
|
+
| eval(str) | new Function() or parse |
|
|
1047
|
+
| innerHTML = x | textContent or sanitize |
|
|
1048
|
+
| exec(\`cmd \${x}\`) | execFile with args array |
|
|
1049
|
+
|
|
1050
|
+
Working rules:
|
|
1051
|
+
- Never scan node_modules \u2014 use npm audit instead
|
|
1052
|
+
- Always provide remediation steps, not just findings
|
|
1053
|
+
- Verify regex-based secrets before flagging (false positive risk)
|
|
1054
|
+
- When in doubt, flag as medium rather than ignoring potential issues`
|
|
1055
|
+
// Budgets are set by the orchestrator per task — see fleet.ts header.
|
|
1056
|
+
};
|
|
1057
|
+
var FLEET_ROSTER = {
|
|
1058
|
+
"audit-log": AUDIT_LOG_AGENT,
|
|
1059
|
+
"bug-hunter": BUG_HUNTER_AGENT,
|
|
1060
|
+
"refactor-planner": REFACTOR_PLANNER_AGENT,
|
|
1061
|
+
"security-scanner": SECURITY_SCANNER_AGENT
|
|
1062
|
+
};
|
|
1063
|
+
var FLEET_ROSTER_BUDGETS = {
|
|
1064
|
+
"audit-log": { timeoutMs: 5 * 60 * 1e3, maxIterations: 80, maxToolCalls: 300 },
|
|
1065
|
+
"bug-hunter": { timeoutMs: 10 * 60 * 1e3, maxIterations: 120, maxToolCalls: 400 },
|
|
1066
|
+
"refactor-planner": { timeoutMs: 8 * 60 * 1e3, maxIterations: 100, maxToolCalls: 350 },
|
|
1067
|
+
"security-scanner": { timeoutMs: 10 * 60 * 1e3, maxIterations: 120, maxToolCalls: 400 }
|
|
1068
|
+
};
|
|
1069
|
+
function applyRosterBudget(cfg) {
|
|
1070
|
+
const defaultBudget = FLEET_ROSTER_BUDGETS[cfg.role ?? ""];
|
|
1071
|
+
if (!defaultBudget) return cfg;
|
|
1072
|
+
return {
|
|
1073
|
+
...cfg,
|
|
1074
|
+
timeoutMs: cfg.timeoutMs ?? defaultBudget.timeoutMs,
|
|
1075
|
+
maxIterations: cfg.maxIterations ?? defaultBudget.maxIterations,
|
|
1076
|
+
maxToolCalls: cfg.maxToolCalls ?? defaultBudget.maxToolCalls,
|
|
1077
|
+
maxTokens: cfg.maxTokens ?? defaultBudget.maxTokens,
|
|
1078
|
+
maxCostUsd: cfg.maxCostUsd ?? defaultBudget.maxCostUsd
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
var ALL_FLEET_AGENTS = Object.values(FLEET_ROSTER);
|
|
1082
|
+
|
|
785
1083
|
// src/coordination/multi-agent-coordinator.ts
|
|
786
1084
|
var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
787
1085
|
coordinatorId;
|
|
@@ -1022,12 +1320,13 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
1022
1320
|
task.subagentId = subagentId;
|
|
1023
1321
|
subagent.context.tasks.push(task);
|
|
1024
1322
|
this.emit("task.assigned", { task, subagentId });
|
|
1323
|
+
const configWithRosterDefaults = applyRosterBudget(subagent.config);
|
|
1025
1324
|
const budget = new SubagentBudget({
|
|
1026
|
-
maxIterations:
|
|
1027
|
-
maxToolCalls: task.maxToolCalls ??
|
|
1028
|
-
maxTokens:
|
|
1029
|
-
maxCostUsd:
|
|
1030
|
-
timeoutMs: task.timeoutMs ??
|
|
1325
|
+
maxIterations: configWithRosterDefaults.maxIterations ?? this.config.defaultBudget?.maxIterations,
|
|
1326
|
+
maxToolCalls: task.maxToolCalls ?? configWithRosterDefaults.maxToolCalls ?? this.config.defaultBudget?.maxToolCalls,
|
|
1327
|
+
maxTokens: configWithRosterDefaults.maxTokens ?? this.config.defaultBudget?.maxTokens,
|
|
1328
|
+
maxCostUsd: configWithRosterDefaults.maxCostUsd ?? this.config.defaultBudget?.maxCostUsd,
|
|
1329
|
+
timeoutMs: task.timeoutMs ?? configWithRosterDefaults.timeoutMs ?? this.config.defaultBudget?.timeoutMs
|
|
1031
1330
|
});
|
|
1032
1331
|
subagent.activeBudget = budget;
|
|
1033
1332
|
if (!this.runner) {
|
|
@@ -1565,6 +1864,36 @@ var Director = class {
|
|
|
1565
1864
|
this.scheduleManifest();
|
|
1566
1865
|
};
|
|
1567
1866
|
this.coordinator.on("task.completed", this.taskCompletedListener);
|
|
1867
|
+
const extendCounts = /* @__PURE__ */ new Map();
|
|
1868
|
+
this.fleet.filter("budget.threshold_reached", (e) => {
|
|
1869
|
+
const payload = e.payload;
|
|
1870
|
+
const guardKey = `${e.subagentId}:${payload.kind}`;
|
|
1871
|
+
const prior = extendCounts.get(guardKey) ?? 0;
|
|
1872
|
+
if (prior >= 2) {
|
|
1873
|
+
payload.deny();
|
|
1874
|
+
extendCounts.delete(guardKey);
|
|
1875
|
+
return;
|
|
1876
|
+
}
|
|
1877
|
+
extendCounts.set(guardKey, prior + 1);
|
|
1878
|
+
setTimeout(() => {
|
|
1879
|
+
const extra = {};
|
|
1880
|
+
switch (payload.kind) {
|
|
1881
|
+
case "iterations":
|
|
1882
|
+
extra.maxIterations = Math.min(payload.used + 50, 500);
|
|
1883
|
+
break;
|
|
1884
|
+
case "tool_calls":
|
|
1885
|
+
extra.maxToolCalls = Math.min(Math.ceil(payload.limit * 1.5), 1e3);
|
|
1886
|
+
break;
|
|
1887
|
+
case "tokens":
|
|
1888
|
+
extra.maxTokens = Math.min(Math.ceil(payload.limit * 1.5), 5e5);
|
|
1889
|
+
break;
|
|
1890
|
+
case "cost":
|
|
1891
|
+
extra.maxCostUsd = Math.min(payload.limit * 1.5, 10);
|
|
1892
|
+
break;
|
|
1893
|
+
}
|
|
1894
|
+
payload.extend(extra);
|
|
1895
|
+
}, Math.min(payload.timeoutMs, 3e4));
|
|
1896
|
+
});
|
|
1568
1897
|
}
|
|
1569
1898
|
/** Best-effort session-writer append. Swallows failures — the director
|
|
1570
1899
|
* must not break a fleet run because the session JSONL handle closed. */
|
|
@@ -2024,65 +2353,68 @@ function createDelegateTool(opts) {
|
|
|
2024
2353
|
if (typeof i.task !== "string" || !i.task.trim()) {
|
|
2025
2354
|
return { ok: false, error: "`task` is required." };
|
|
2026
2355
|
}
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
ok: false,
|
|
2035
|
-
error: reason ?? "Director could not be activated \u2014 multi-agent host already running in legacy non-director mode. Restart with `--director` for fleet support."
|
|
2036
|
-
};
|
|
2037
|
-
}
|
|
2038
|
-
const timeoutMs = i.timeoutMs ?? defaultTimeoutMs;
|
|
2039
|
-
let cfg;
|
|
2040
|
-
if (i.role) {
|
|
2041
|
-
const base = opts.roster?.[i.role];
|
|
2042
|
-
if (!base) {
|
|
2356
|
+
try {
|
|
2357
|
+
let director = await opts.host.ensureDirector();
|
|
2358
|
+
if (!director) {
|
|
2359
|
+
director = await opts.host.promoteToDirector();
|
|
2360
|
+
}
|
|
2361
|
+
if (!director) {
|
|
2362
|
+
const reason = opts.host.getPromotionBlockReason?.();
|
|
2043
2363
|
return {
|
|
2044
2364
|
ok: false,
|
|
2045
|
-
error:
|
|
2365
|
+
error: reason ?? "Director could not be activated \u2014 multi-agent host already running in legacy non-director mode. Restart with `--director` for fleet support."
|
|
2046
2366
|
};
|
|
2047
2367
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
if (i.
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2368
|
+
const timeoutMs = i.timeoutMs ?? defaultTimeoutMs;
|
|
2369
|
+
let cfg;
|
|
2370
|
+
if (i.role) {
|
|
2371
|
+
const base = opts.roster?.[i.role];
|
|
2372
|
+
if (!base) {
|
|
2373
|
+
return {
|
|
2374
|
+
ok: false,
|
|
2375
|
+
error: `Unknown role "${i.role}". Available: ${rosterIds.join(", ") || "(no roster configured)"}.`
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
cfg = instantiateRosterConfig2(i.role, base);
|
|
2379
|
+
if (i.systemPromptOverride) cfg.systemPromptOverride = i.systemPromptOverride;
|
|
2380
|
+
if (i.provider) cfg.provider = i.provider;
|
|
2381
|
+
if (i.model) cfg.model = i.model;
|
|
2382
|
+
} else {
|
|
2383
|
+
if (!i.name) {
|
|
2384
|
+
return {
|
|
2385
|
+
ok: false,
|
|
2386
|
+
error: "Either `role` (from the roster) or `name` is required."
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2389
|
+
cfg = {
|
|
2390
|
+
name: i.name,
|
|
2391
|
+
provider: i.provider,
|
|
2392
|
+
model: i.model,
|
|
2393
|
+
systemPromptOverride: i.systemPromptOverride
|
|
2057
2394
|
};
|
|
2058
2395
|
}
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
cfg.
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
cfg.maxToolCalls = i.maxToolCalls;
|
|
2071
|
-
}
|
|
2072
|
-
const SUBAGENT_TIMEOUT_BUFFER_MS = 3e4;
|
|
2073
|
-
const desiredSubTimeout = Math.max(3e4, timeoutMs - SUBAGENT_TIMEOUT_BUFFER_MS);
|
|
2074
|
-
if (!cfg.timeoutMs || cfg.timeoutMs > desiredSubTimeout) {
|
|
2075
|
-
cfg.timeoutMs = desiredSubTimeout;
|
|
2076
|
-
}
|
|
2077
|
-
try {
|
|
2396
|
+
if (typeof i.maxIterations === "number" && i.maxIterations > 0) {
|
|
2397
|
+
cfg.maxIterations = i.maxIterations;
|
|
2398
|
+
}
|
|
2399
|
+
if (typeof i.maxToolCalls === "number" && i.maxToolCalls > 0) {
|
|
2400
|
+
cfg.maxToolCalls = i.maxToolCalls;
|
|
2401
|
+
}
|
|
2402
|
+
const SUBAGENT_TIMEOUT_BUFFER_MS = 3e4;
|
|
2403
|
+
const desiredSubTimeout = Math.max(3e4, timeoutMs - SUBAGENT_TIMEOUT_BUFFER_MS);
|
|
2404
|
+
if (!cfg.timeoutMs || cfg.timeoutMs > desiredSubTimeout) {
|
|
2405
|
+
cfg.timeoutMs = desiredSubTimeout;
|
|
2406
|
+
}
|
|
2078
2407
|
const subagentId = await director.spawn(cfg);
|
|
2079
2408
|
const taskId = await director.assign({
|
|
2080
|
-
id:
|
|
2409
|
+
id: `${randomUUID()}`,
|
|
2081
2410
|
description: i.task,
|
|
2082
2411
|
subagentId
|
|
2083
2412
|
});
|
|
2084
2413
|
const result = await Promise.race([
|
|
2085
|
-
director.awaitTasks([taskId]).then((r) =>
|
|
2414
|
+
director.awaitTasks([taskId]).then((r) => {
|
|
2415
|
+
if (!r[0]) throw new Error(`Task "${taskId}" not found in completed results`);
|
|
2416
|
+
return r[0];
|
|
2417
|
+
}),
|
|
2086
2418
|
new Promise(
|
|
2087
2419
|
(resolve) => setTimeout(() => resolve({ __timeout: true }), timeoutMs)
|
|
2088
2420
|
)
|
|
@@ -2156,7 +2488,7 @@ function hintForKind(kind, retryable, backoffMs) {
|
|
|
2156
2488
|
case "budget_tool_calls":
|
|
2157
2489
|
case "budget_tokens":
|
|
2158
2490
|
case "budget_cost":
|
|
2159
|
-
return "Subagent exhausted its budget.
|
|
2491
|
+
return "Subagent exhausted its budget. The coordinator may auto-extend; otherwise raise the matching `max*` field (e.g. maxToolCalls: 600) on the next delegate, or split the task.";
|
|
2160
2492
|
case "budget_timeout":
|
|
2161
2493
|
return "Subagent hit its wall-clock budget. Raise `timeoutMs` on the next delegate or split the task.";
|
|
2162
2494
|
case "aborted_by_parent":
|
|
@@ -2229,8 +2561,21 @@ function makeAgentSubagentRunner(opts) {
|
|
|
2229
2561
|
const { agent, events } = factoryResult;
|
|
2230
2562
|
const detachFleet = opts.fleetBus?.attach(ctx.subagentId, events, task.id);
|
|
2231
2563
|
const aborter = new AbortController();
|
|
2564
|
+
ctx.budget._events = events;
|
|
2232
2565
|
let budgetError = null;
|
|
2233
2566
|
const onBudgetError = (err) => {
|
|
2567
|
+
if (err instanceof BudgetThresholdSignal) {
|
|
2568
|
+
err.decision.then((decision) => {
|
|
2569
|
+
if (decision === "stop") {
|
|
2570
|
+
budgetError = new BudgetExceededError(err.kind, err.limit, err.used);
|
|
2571
|
+
aborter.abort();
|
|
2572
|
+
}
|
|
2573
|
+
}).catch(() => {
|
|
2574
|
+
budgetError = new BudgetExceededError(err.kind, err.limit, err.used);
|
|
2575
|
+
aborter.abort();
|
|
2576
|
+
});
|
|
2577
|
+
return;
|
|
2578
|
+
}
|
|
2234
2579
|
aborter.abort();
|
|
2235
2580
|
budgetError = err instanceof BudgetExceededError ? err : new BudgetExceededError(
|
|
2236
2581
|
"tool_calls",
|
|
@@ -2260,7 +2605,7 @@ function makeAgentSubagentRunner(opts) {
|
|
|
2260
2605
|
try {
|
|
2261
2606
|
ctx.budget.recordUsage(e.usage);
|
|
2262
2607
|
} catch (e2) {
|
|
2263
|
-
onBudgetError(e2);
|
|
2608
|
+
void onBudgetError(e2);
|
|
2264
2609
|
}
|
|
2265
2610
|
}),
|
|
2266
2611
|
events.on("iteration.started", () => {
|
|
@@ -2268,7 +2613,7 @@ function makeAgentSubagentRunner(opts) {
|
|
|
2268
2613
|
ctx.budget.recordIteration();
|
|
2269
2614
|
ctx.budget.checkTimeout();
|
|
2270
2615
|
} catch (e) {
|
|
2271
|
-
onBudgetError(e);
|
|
2616
|
+
void onBudgetError(e);
|
|
2272
2617
|
}
|
|
2273
2618
|
}),
|
|
2274
2619
|
// D3: cooperative timeout enforcement DURING a long tool call.
|
|
@@ -2288,7 +2633,7 @@ function makeAgentSubagentRunner(opts) {
|
|
|
2288
2633
|
try {
|
|
2289
2634
|
ctx.budget.checkTimeout();
|
|
2290
2635
|
} catch (e) {
|
|
2291
|
-
onBudgetError(e);
|
|
2636
|
+
void onBudgetError(e);
|
|
2292
2637
|
}
|
|
2293
2638
|
})
|
|
2294
2639
|
);
|
|
@@ -2454,7 +2799,7 @@ var DefaultSessionStore = class {
|
|
|
2454
2799
|
);
|
|
2455
2800
|
}
|
|
2456
2801
|
try {
|
|
2457
|
-
return new FileSessionWriter(id, handle, startedAt, meta, { dir: this.dir, filePath: file });
|
|
2802
|
+
return new FileSessionWriter(id, handle, startedAt, meta, this.events, { dir: this.dir, filePath: file });
|
|
2458
2803
|
} catch (err) {
|
|
2459
2804
|
await handle.close().catch(() => {
|
|
2460
2805
|
});
|
|
@@ -2482,6 +2827,7 @@ var DefaultSessionStore = class {
|
|
|
2482
2827
|
model: data.metadata.model,
|
|
2483
2828
|
provider: data.metadata.provider
|
|
2484
2829
|
},
|
|
2830
|
+
this.events,
|
|
2485
2831
|
{ resumed: true, dir: this.dir, filePath: file }
|
|
2486
2832
|
);
|
|
2487
2833
|
return { writer, data };
|
|
@@ -2645,11 +2991,12 @@ var DefaultSessionStore = class {
|
|
|
2645
2991
|
}
|
|
2646
2992
|
};
|
|
2647
2993
|
var FileSessionWriter = class {
|
|
2648
|
-
constructor(id, handle, startedAt, meta, opts = {}) {
|
|
2994
|
+
constructor(id, handle, startedAt, meta, events, opts = {}) {
|
|
2649
2995
|
this.id = id;
|
|
2650
2996
|
this.handle = handle;
|
|
2651
2997
|
this.startedAt = startedAt;
|
|
2652
2998
|
this.meta = meta;
|
|
2999
|
+
this.events = events;
|
|
2653
3000
|
this.resumed = opts.resumed ?? false;
|
|
2654
3001
|
this.manifestFile = opts.dir ? path4.join(opts.dir, `${id}.summary.json`) : "";
|
|
2655
3002
|
this.filePath = opts.filePath ?? "";
|
|
@@ -2666,6 +3013,7 @@ var FileSessionWriter = class {
|
|
|
2666
3013
|
handle;
|
|
2667
3014
|
startedAt;
|
|
2668
3015
|
meta;
|
|
3016
|
+
events;
|
|
2669
3017
|
closed = false;
|
|
2670
3018
|
closing = false;
|
|
2671
3019
|
manifestFile;
|
|
@@ -2683,6 +3031,13 @@ var FileSessionWriter = class {
|
|
|
2683
3031
|
resumed;
|
|
2684
3032
|
appendFailCount = 0;
|
|
2685
3033
|
lastAppendWarnAt = 0;
|
|
3034
|
+
// Rewind support: track pending file changes and prompt index
|
|
3035
|
+
promptIndex = 0;
|
|
3036
|
+
pendingFileSnapshots = [];
|
|
3037
|
+
// Register a pending file change. Call recordFileChange() from tools.
|
|
3038
|
+
recordFileChange(input) {
|
|
3039
|
+
this.pendingFileSnapshots.push(input);
|
|
3040
|
+
}
|
|
2686
3041
|
async writeSessionStartLazy() {
|
|
2687
3042
|
const record = `${JSON.stringify({
|
|
2688
3043
|
type: this.resumed ? "session_resumed" : "session_start",
|
|
@@ -2758,6 +3113,87 @@ var FileSessionWriter = class {
|
|
|
2758
3113
|
} catch {
|
|
2759
3114
|
}
|
|
2760
3115
|
}
|
|
3116
|
+
async writeCheckpoint(promptIndex, promptPreview) {
|
|
3117
|
+
const fileCount = this.pendingFileSnapshots.length;
|
|
3118
|
+
if (fileCount > 0) {
|
|
3119
|
+
await this.writeFileSnapshot(promptIndex, [...this.pendingFileSnapshots]);
|
|
3120
|
+
this.pendingFileSnapshots = [];
|
|
3121
|
+
}
|
|
3122
|
+
this.promptIndex = promptIndex + 1;
|
|
3123
|
+
await this.append({
|
|
3124
|
+
type: "checkpoint",
|
|
3125
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3126
|
+
promptIndex,
|
|
3127
|
+
promptPreview
|
|
3128
|
+
});
|
|
3129
|
+
this.events?.emit("checkpoint.written", {
|
|
3130
|
+
promptIndex,
|
|
3131
|
+
promptPreview,
|
|
3132
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3133
|
+
fileCount
|
|
3134
|
+
});
|
|
3135
|
+
}
|
|
3136
|
+
async writeFileSnapshot(promptIndex, files) {
|
|
3137
|
+
await this.append({
|
|
3138
|
+
type: "file_snapshot",
|
|
3139
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3140
|
+
promptIndex,
|
|
3141
|
+
files
|
|
3142
|
+
});
|
|
3143
|
+
}
|
|
3144
|
+
async truncateToCheckpoint(targetPromptIndex) {
|
|
3145
|
+
if (!this.filePath) return 0;
|
|
3146
|
+
const raw = await fsp4.readFile(this.filePath, "utf8");
|
|
3147
|
+
const lines = raw.split("\n");
|
|
3148
|
+
const kept = [];
|
|
3149
|
+
let removedCount = 0;
|
|
3150
|
+
let targetCheckpointLine = -1;
|
|
3151
|
+
let afterTarget = false;
|
|
3152
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3153
|
+
const line = lines[i];
|
|
3154
|
+
if (!line.trim()) continue;
|
|
3155
|
+
let event;
|
|
3156
|
+
try {
|
|
3157
|
+
event = JSON.parse(line);
|
|
3158
|
+
} catch {
|
|
3159
|
+
kept.push(line);
|
|
3160
|
+
continue;
|
|
3161
|
+
}
|
|
3162
|
+
if (event.type === "checkpoint") {
|
|
3163
|
+
if (event.promptIndex === targetPromptIndex) {
|
|
3164
|
+
targetCheckpointLine = kept.length;
|
|
3165
|
+
afterTarget = true;
|
|
3166
|
+
} else if (event.promptIndex > targetPromptIndex) {
|
|
3167
|
+
afterTarget = true;
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
if (event.promptIndex !== void 0 && event.promptIndex > targetPromptIndex) {
|
|
3171
|
+
removedCount++;
|
|
3172
|
+
} else if (event.promptIndex === void 0) {
|
|
3173
|
+
if (!afterTarget || targetCheckpointLine === -1) {
|
|
3174
|
+
kept.push(line);
|
|
3175
|
+
} else {
|
|
3176
|
+
removedCount++;
|
|
3177
|
+
}
|
|
3178
|
+
} else {
|
|
3179
|
+
kept.push(line);
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
const truncated = kept.join("\n");
|
|
3183
|
+
await fsp4.writeFile(this.filePath, truncated + "\n", "utf8");
|
|
3184
|
+
await this.append({
|
|
3185
|
+
type: "rewound",
|
|
3186
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3187
|
+
toPromptIndex: targetPromptIndex,
|
|
3188
|
+
revertedFiles: []
|
|
3189
|
+
});
|
|
3190
|
+
this.events?.emit("session.rewound", {
|
|
3191
|
+
toPromptIndex: targetPromptIndex,
|
|
3192
|
+
revertedFiles: [],
|
|
3193
|
+
removedEvents: removedCount
|
|
3194
|
+
});
|
|
3195
|
+
return removedCount;
|
|
3196
|
+
}
|
|
2761
3197
|
};
|
|
2762
3198
|
function userInputTitle(content) {
|
|
2763
3199
|
if (typeof content === "string") return content.slice(0, 60);
|
|
@@ -2793,180 +3229,6 @@ function makeDirectorSessionFactory(opts) {
|
|
|
2793
3229
|
};
|
|
2794
3230
|
}
|
|
2795
3231
|
|
|
2796
|
-
|
|
2797
|
-
var AUDIT_LOG_AGENT = {
|
|
2798
|
-
id: "audit-log",
|
|
2799
|
-
name: "Audit Log",
|
|
2800
|
-
role: "audit-log",
|
|
2801
|
-
prompt: `You are the Audit Log agent. Your job is to analyze structured JSONL
|
|
2802
|
-
session logs and produce actionable markdown reports.
|
|
2803
|
-
|
|
2804
|
-
Scope:
|
|
2805
|
-
- Parse session logs (iteration counts, tool calls, errors, usage)
|
|
2806
|
-
- Detect repeated failure patterns across multiple runs
|
|
2807
|
-
- Identify tool usage anomalies (over-use, failures, unexpected chains)
|
|
2808
|
-
- Track token consumption trends
|
|
2809
|
-
- Generate structured audit reports with severity ratings
|
|
2810
|
-
|
|
2811
|
-
Input format you accept:
|
|
2812
|
-
{ "task": "analyze | report | trends", "sessionPath": "<path>", "focus": "errors | tools | usage | all" }
|
|
2813
|
-
|
|
2814
|
-
Output: Markdown audit report with sections:
|
|
2815
|
-
- ## Summary (totals, error rate)
|
|
2816
|
-
- ## Top Errors (count + context)
|
|
2817
|
-
- ## Tool Usage (table with calls, failures, avg duration)
|
|
2818
|
-
- ## Anomalies (pattern \u2192 severity)
|
|
2819
|
-
|
|
2820
|
-
Working rules:
|
|
2821
|
-
- Never fabricate numbers \u2014 read the actual logs first
|
|
2822
|
-
- Always include file:line references for errors
|
|
2823
|
-
- If sessionPath is missing, ask the director to provide it
|
|
2824
|
-
- Report confidence level: high (>90% accuracy), medium, low`
|
|
2825
|
-
// No hardcoded budgets — the orchestrator (delegate tool or
|
|
2826
|
-
// spawn_subagent) decides per-task how much room a subagent gets.
|
|
2827
|
-
// A monorepo audit needs hours; a single-file lint check needs
|
|
2828
|
-
// seconds. Pinning a number here forces the orchestrator to fight
|
|
2829
|
-
// the role's default instead of just asking for what it needs.
|
|
2830
|
-
};
|
|
2831
|
-
var BUG_HUNTER_AGENT = {
|
|
2832
|
-
id: "bug-hunter",
|
|
2833
|
-
name: "Bug Hunter",
|
|
2834
|
-
role: "bug-hunter",
|
|
2835
|
-
prompt: `You are the Bug Hunter agent. Your job is to systematically scan
|
|
2836
|
-
source code for bugs, anti-patterns, and code smells using pattern matching
|
|
2837
|
-
and heuristics. Output a prioritized hit list with file:line references.
|
|
2838
|
-
|
|
2839
|
-
Scope:
|
|
2840
|
-
- Detect common bug patterns (uncaught errors, resource leaks, race conditions)
|
|
2841
|
-
- Identify anti-patterns (callback hell, God objects, circular deps)
|
|
2842
|
-
- Find TypeScript-specific issues (unsafe any, missing null checks, branded types)
|
|
2843
|
-
- Flag security-sensitive constructs (eval, innerHTML, hardcoded secrets)
|
|
2844
|
-
- Rank findings: critical > high > medium > low
|
|
2845
|
-
|
|
2846
|
-
Input format you accept:
|
|
2847
|
-
{ "task": "scan | hunt | check", "paths": ["src/**/*.ts"], "focus": "bugs | patterns | security | all", "severityThreshold": "medium" }
|
|
2848
|
-
|
|
2849
|
-
Output: Markdown bug hunt report:
|
|
2850
|
-
- ## Critical (must fix first)
|
|
2851
|
-
- ## High (should fix)
|
|
2852
|
-
- ## Medium
|
|
2853
|
-
- ## Low (consider)
|
|
2854
|
-
Each entry: **[TYPE]** \`file:line\` \u2014 description + suggested fix
|
|
2855
|
-
|
|
2856
|
-
Bug pattern reference you know:
|
|
2857
|
-
| Pattern | Regex hint | Severity |
|
|
2858
|
-
|---------|------------|----------|
|
|
2859
|
-
| Uncaught promise | /.then\\(.*\\)/ without catch | high |
|
|
2860
|
-
| Event leak | on\\( without off/removeListener | high |
|
|
2861
|
-
| Hardcoded secret | [a-zA-Z0-9/_-]{20,} in config files | critical |
|
|
2862
|
-
| unsafe any | : any\\b or <any> | medium |
|
|
2863
|
-
| innerHTML | innerHTML\\s*= | high |
|
|
2864
|
-
|
|
2865
|
-
Working rules:
|
|
2866
|
-
- Never scan node_modules \u2014 it's noise
|
|
2867
|
-
- Always include file:line for every finding
|
|
2868
|
-
- If >30% of findings are false positives, note the confidence level
|
|
2869
|
-
- Ask director for clarification if paths are ambiguous`
|
|
2870
|
-
// Budgets are set by the orchestrator per task — see fleet.ts header.
|
|
2871
|
-
};
|
|
2872
|
-
var REFACTOR_PLANNER_AGENT = {
|
|
2873
|
-
id: "refactor-planner",
|
|
2874
|
-
name: "Refactor Planner",
|
|
2875
|
-
role: "refactor-planner",
|
|
2876
|
-
prompt: `You are the Refactor Planner agent. Your job is to analyze code
|
|
2877
|
-
structure and produce a concrete, phased refactoring plan with risk
|
|
2878
|
-
assessment, dependency ordering, and rollback strategy.
|
|
2879
|
-
|
|
2880
|
-
Scope:
|
|
2881
|
-
- Map module-level dependencies (import graph)
|
|
2882
|
-
- Identify coupling hotspots (high fan-in/out modules)
|
|
2883
|
-
- Assess refactoring risk by complexity and test coverage
|
|
2884
|
-
- Generate phased plans with checkpoint milestones
|
|
2885
|
-
- Produce diff-friendly task lists (one task = one concern)
|
|
2886
|
-
|
|
2887
|
-
Input format you accept:
|
|
2888
|
-
{ "task": "plan | assess | roadmap", "target": "src/core", "constraint": "no-breaking-changes | minimal-downtime | full-rewrite", "focus": "architecture | performance | maintainability" }
|
|
2889
|
-
|
|
2890
|
-
Output: Markdown refactor plan:
|
|
2891
|
-
- ## Phase 1: Low Risk / High Payoff (do first)
|
|
2892
|
-
Table: | # | Task | Module | Risk | Est. Time |
|
|
2893
|
-
- ## Phase 2: Medium Risk
|
|
2894
|
-
- ## Phase 3: High Risk (requires full regression)
|
|
2895
|
-
- ## Dependency Graph (abbreviated ASCII)
|
|
2896
|
-
- ## Rollback Strategy
|
|
2897
|
-
- ## Exit Criteria (checkbox list)
|
|
2898
|
-
|
|
2899
|
-
Risk scoring criteria:
|
|
2900
|
-
| Factor | Low | Medium | High |
|
|
2901
|
-
|--------|-----|--------|------|
|
|
2902
|
-
| Cyclomatic complexity | <10 | 10-20 | >20 |
|
|
2903
|
-
| Test coverage | >80% | 50-80% | <50% |
|
|
2904
|
-
| Fan-out (imports) | <5 | 5-15 | >15 |
|
|
2905
|
-
|
|
2906
|
-
Working rules:
|
|
2907
|
-
- Always include rollback strategy \u2014 every refactor can fail
|
|
2908
|
-
- Merge tasks that take <1h into a single phase
|
|
2909
|
-
- Respect team constraints (reviewer availability, parallelization)
|
|
2910
|
-
- Never plan without analyzing the actual code first`
|
|
2911
|
-
// Budgets are set by the orchestrator per task — see fleet.ts header.
|
|
2912
|
-
};
|
|
2913
|
-
var SECURITY_SCANNER_AGENT = {
|
|
2914
|
-
id: "security-scanner",
|
|
2915
|
-
name: "Security Scanner",
|
|
2916
|
-
role: "security-scanner",
|
|
2917
|
-
prompt: `You are the Security Scanner agent. Your job is to scan code,
|
|
2918
|
-
configs, and dependencies for security issues from hardcoded secrets to
|
|
2919
|
-
supply chain risks.
|
|
2920
|
-
|
|
2921
|
-
Scope:
|
|
2922
|
-
- Detect hardcoded secrets: API keys, tokens, passwords, private keys
|
|
2923
|
-
- Find injection vectors: eval, innerHTML, SQL concat, shell injection
|
|
2924
|
-
- Identify insecure patterns: weak crypto, hardcoded IVs, disabled TLS
|
|
2925
|
-
- Scan dependencies for known CVEs (via npm/pnpm audit)
|
|
2926
|
-
- Flag supply chain risks: postinstall hooks, unverified scripts, .npmrc
|
|
2927
|
-
|
|
2928
|
-
Input format you accept:
|
|
2929
|
-
{ "task": "scan | audit | secrets | dependencies", "paths": ["src", "config"], "depth": "quick | normal | deep" }
|
|
2930
|
-
|
|
2931
|
-
Output: Markdown security report:
|
|
2932
|
-
- ## CRITICAL: Secrets Found (with code snippets)
|
|
2933
|
-
- ## HIGH: Injection Vectors
|
|
2934
|
-
- ## MEDIUM: Insecure Patterns
|
|
2935
|
-
- ## Dependency Issues (CVE list)
|
|
2936
|
-
- ## Summary table (severity \u2192 count)
|
|
2937
|
-
- ## Remediation Checklist (with checkboxes)
|
|
2938
|
-
|
|
2939
|
-
Secret patterns you detect:
|
|
2940
|
-
| Pattern | Example | Severity |
|
|
2941
|
-
|---------|---------|----------|
|
|
2942
|
-
| AWS Access Key | AKIAIOSFODNN7EXAMPLE | critical |
|
|
2943
|
-
| AWS Secret Key | [a-zA-Z0-9/+=]{40} base64 | critical |
|
|
2944
|
-
| GitHub Token | ghp_[a-zA-Z0-9]{36} | critical |
|
|
2945
|
-
| Private Key PEM | -----BEGIN.*PRIVATE KEY----- | critical |
|
|
2946
|
-
| JWT | eyJ[a-zA-Z0-9_-]+ | high |
|
|
2947
|
-
|
|
2948
|
-
Injection patterns:
|
|
2949
|
-
| Construct | Safe alternative |
|
|
2950
|
-
|-----------|-----------------|
|
|
2951
|
-
| eval(str) | new Function() or parse |
|
|
2952
|
-
| innerHTML = x | textContent or sanitize |
|
|
2953
|
-
| exec(\`cmd \${x}\`) | execFile with args array |
|
|
2954
|
-
|
|
2955
|
-
Working rules:
|
|
2956
|
-
- Never scan node_modules \u2014 use npm audit instead
|
|
2957
|
-
- Always provide remediation steps, not just findings
|
|
2958
|
-
- Verify regex-based secrets before flagging (false positive risk)
|
|
2959
|
-
- When in doubt, flag as medium rather than ignoring potential issues`
|
|
2960
|
-
// Budgets are set by the orchestrator per task — see fleet.ts header.
|
|
2961
|
-
};
|
|
2962
|
-
var FLEET_ROSTER = {
|
|
2963
|
-
"audit-log": AUDIT_LOG_AGENT,
|
|
2964
|
-
"bug-hunter": BUG_HUNTER_AGENT,
|
|
2965
|
-
"refactor-planner": REFACTOR_PLANNER_AGENT,
|
|
2966
|
-
"security-scanner": SECURITY_SCANNER_AGENT
|
|
2967
|
-
};
|
|
2968
|
-
var ALL_FLEET_AGENTS = Object.values(FLEET_ROSTER);
|
|
2969
|
-
|
|
2970
|
-
export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, BUG_HUNTER_AGENT, BudgetExceededError, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultMultiAgentCoordinator, Director, DirectorBudgetError, FLEET_ROSTER, FleetBus, FleetUsageAggregator, InMemoryAgentBridge, InMemoryBridgeTransport, REFACTOR_PLANNER_AGENT, SECURITY_SCANNER_AGENT, SubagentBudget, composeDirectorPrompt, composeSubagentPrompt, createDelegateTool, createMessage, makeAgentSubagentRunner, makeDirectorSessionFactory, rosterSummaryFromConfigs };
|
|
3232
|
+
export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, BUG_HUNTER_AGENT, BudgetExceededError, BudgetThresholdSignal, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultMultiAgentCoordinator, Director, DirectorBudgetError, FLEET_ROSTER, FleetBus, FleetUsageAggregator, InMemoryAgentBridge, InMemoryBridgeTransport, REFACTOR_PLANNER_AGENT, SECURITY_SCANNER_AGENT, SubagentBudget, composeDirectorPrompt, composeSubagentPrompt, createDelegateTool, createMessage, makeAgentSubagentRunner, makeDirectorSessionFactory, rosterSummaryFromConfigs };
|
|
2971
3233
|
//# sourceMappingURL=index.js.map
|
|
2972
3234
|
//# sourceMappingURL=index.js.map
|