blitzstrike 1.0.52 → 1.0.54
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/CHANGELOG.md +32 -0
- package/dist/index.js +116 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,38 @@ All notable changes to Blitz Strike are documented here.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [1.0.54] — 2026-09-13
|
|
9
|
+
|
|
10
|
+
### Added — Autonomous Security Engine (phase 14: budget controller)
|
|
11
|
+
|
|
12
|
+
- **Budget Controller** (`src/mission/budget.ts`, §22):
|
|
13
|
+
- `budgetStatus()` — tracks time / tasks / requests / tokens / cost with
|
|
14
|
+
per-dimension overrun flags.
|
|
15
|
+
- `budgetOverrun()` — detects overruns and returns a specific reason
|
|
16
|
+
(e.g. `budget overrun: tasks, requests`).
|
|
17
|
+
- `consumeTasks()` / `consumeTokens()` — increment consumption counters.
|
|
18
|
+
- `perTaskOverrun()` — enforces the per-task request budget.
|
|
19
|
+
- Extended the `Budget` type with `max_tokens`, `max_cost_usd`,
|
|
20
|
+
`per_task_budget`, `started_at`, and `used_tokens`/`used_cost_usd`.
|
|
21
|
+
- Mission Control now terminates gracefully on ANY budget dimension overrun
|
|
22
|
+
(not just tasks) and records a final budget snapshot in the decision log.
|
|
23
|
+
|
|
24
|
+
## [1.0.53] — 2026-09-13
|
|
25
|
+
|
|
26
|
+
### Added — Autonomous Security Engine (phase 13: model router)
|
|
27
|
+
|
|
28
|
+
- **Model Router** (`src/mission/router.ts`, §21):
|
|
29
|
+
- Pure routing layer — never calls a model. Deterministic by default.
|
|
30
|
+
- `routeTask()` — maps an agent type to a model tier (`large`/`medium`/`small`)
|
|
31
|
+
only when a provider is configured; otherwise routes to `none`.
|
|
32
|
+
- `AGENT_TIER` — §21 mapping (planning/source/review → large; attack execution
|
|
33
|
+
→ medium; verification → small).
|
|
34
|
+
- `loadRouterConfig()` — reads `BLITZSTRIKE_MODEL_PROVIDER` / `_LARGE` /
|
|
35
|
+
`_MEDIUM` / `_SMALL` env vars.
|
|
36
|
+
- `routingPlan()` — full plan (all `none` when deterministic).
|
|
37
|
+
- Mission Control records the routing decision (tier) per task and the overall
|
|
38
|
+
routing plan in the mission `decision_log`.
|
|
39
|
+
|
|
8
40
|
## [1.0.52] — 2026-09-13
|
|
9
41
|
|
|
10
42
|
### Added — Autonomous Security Engine (phase 12: browser automation agent)
|
package/dist/index.js
CHANGED
|
@@ -18097,10 +18097,16 @@ function newMission(id, target, scope, mode, budget) {
|
|
|
18097
18097
|
max_time_seconds: 3600,
|
|
18098
18098
|
max_tasks: 200,
|
|
18099
18099
|
max_requests: 1000,
|
|
18100
|
+
max_tokens: 2000000,
|
|
18101
|
+
max_cost_usd: 5,
|
|
18100
18102
|
max_parallel_workers: 4,
|
|
18101
18103
|
risk: "medium",
|
|
18104
|
+
per_task_budget: { max_time_seconds: 60, max_requests: 50 },
|
|
18105
|
+
started_at: Date.now(),
|
|
18102
18106
|
used_tasks: 0,
|
|
18103
18107
|
used_requests: 0,
|
|
18108
|
+
used_tokens: 0,
|
|
18109
|
+
used_cost_usd: 0,
|
|
18104
18110
|
...budget ?? {}
|
|
18105
18111
|
},
|
|
18106
18112
|
discovered_assets: [],
|
|
@@ -19085,6 +19091,97 @@ var init_memory2 = __esm(() => {
|
|
|
19085
19091
|
init_memory();
|
|
19086
19092
|
});
|
|
19087
19093
|
|
|
19094
|
+
// src/mission/router.ts
|
|
19095
|
+
function isModelConfigured(config) {
|
|
19096
|
+
return Boolean(config?.provider);
|
|
19097
|
+
}
|
|
19098
|
+
function routeTask(agent, config) {
|
|
19099
|
+
if (!isModelConfigured(config)) {
|
|
19100
|
+
return { agent, tier: "none", model: null, deterministic: true };
|
|
19101
|
+
}
|
|
19102
|
+
const tier = AGENT_TIER[agent] ?? "medium";
|
|
19103
|
+
const key = `model_${tier}`;
|
|
19104
|
+
const model = config?.[key] ?? null;
|
|
19105
|
+
return { agent, tier, model, deterministic: model === null };
|
|
19106
|
+
}
|
|
19107
|
+
function loadRouterConfig(env = process.env) {
|
|
19108
|
+
return {
|
|
19109
|
+
provider: env.BLITZSTRIKE_MODEL_PROVIDER || undefined,
|
|
19110
|
+
model_large: env.BLITZSTRIKE_MODEL_LARGE || undefined,
|
|
19111
|
+
model_medium: env.BLITZSTRIKE_MODEL_MEDIUM || undefined,
|
|
19112
|
+
model_small: env.BLITZSTRIKE_MODEL_SMALL || undefined
|
|
19113
|
+
};
|
|
19114
|
+
}
|
|
19115
|
+
function routingPlan(config) {
|
|
19116
|
+
if (!isModelConfigured(config)) {
|
|
19117
|
+
const out = {};
|
|
19118
|
+
for (const k of Object.keys(AGENT_TIER))
|
|
19119
|
+
out[k] = "none";
|
|
19120
|
+
return out;
|
|
19121
|
+
}
|
|
19122
|
+
return { ...AGENT_TIER };
|
|
19123
|
+
}
|
|
19124
|
+
var AGENT_TIER;
|
|
19125
|
+
var init_router = __esm(() => {
|
|
19126
|
+
AGENT_TIER = {
|
|
19127
|
+
commander: "large",
|
|
19128
|
+
source: "large",
|
|
19129
|
+
analysis: "large",
|
|
19130
|
+
reviewer: "large",
|
|
19131
|
+
recon: "medium",
|
|
19132
|
+
web: "medium",
|
|
19133
|
+
api: "medium",
|
|
19134
|
+
auth: "medium",
|
|
19135
|
+
mobile: "medium",
|
|
19136
|
+
cloud: "medium",
|
|
19137
|
+
reporter: "medium",
|
|
19138
|
+
validator: "small",
|
|
19139
|
+
browser: "small"
|
|
19140
|
+
};
|
|
19141
|
+
});
|
|
19142
|
+
|
|
19143
|
+
// src/mission/budget.ts
|
|
19144
|
+
function clampRatio(used, max) {
|
|
19145
|
+
if (max <= 0)
|
|
19146
|
+
return 0;
|
|
19147
|
+
return Math.max(0, Math.min(1, used / max));
|
|
19148
|
+
}
|
|
19149
|
+
function budgetStatus(budget, now = Date.now()) {
|
|
19150
|
+
const elapsed = Math.max(0, (now - budget.started_at) / 1000);
|
|
19151
|
+
const dims = [
|
|
19152
|
+
["time", "time (s)", elapsed, budget.max_time_seconds],
|
|
19153
|
+
["tasks", "tasks", budget.used_tasks, budget.max_tasks],
|
|
19154
|
+
["requests", "requests", budget.used_requests, budget.max_requests],
|
|
19155
|
+
["tokens", "tokens", budget.used_tokens, budget.max_tokens],
|
|
19156
|
+
["cost", "cost (USD)", budget.used_cost_usd, budget.max_cost_usd]
|
|
19157
|
+
];
|
|
19158
|
+
return dims.map(([key, label, used, max]) => ({
|
|
19159
|
+
key,
|
|
19160
|
+
label,
|
|
19161
|
+
used: Number(used.toFixed(2)),
|
|
19162
|
+
max,
|
|
19163
|
+
overrun: used >= max,
|
|
19164
|
+
ratio: clampRatio(used, max)
|
|
19165
|
+
}));
|
|
19166
|
+
}
|
|
19167
|
+
function budgetOverrun(budget, now = Date.now()) {
|
|
19168
|
+
const dims = budgetStatus(budget, now).filter((d) => d.overrun);
|
|
19169
|
+
if (dims.length === 0)
|
|
19170
|
+
return { overrun: false, reason: null, dimensions: [] };
|
|
19171
|
+
return {
|
|
19172
|
+
overrun: true,
|
|
19173
|
+
reason: `budget overrun: ${dims.map((d) => d.key).join(", ")}`,
|
|
19174
|
+
dimensions: dims.map((d) => d.key)
|
|
19175
|
+
};
|
|
19176
|
+
}
|
|
19177
|
+
function consumeTasks(budget, tasks, requests) {
|
|
19178
|
+
return {
|
|
19179
|
+
...budget,
|
|
19180
|
+
used_tasks: budget.used_tasks + tasks,
|
|
19181
|
+
used_requests: budget.used_requests + requests
|
|
19182
|
+
};
|
|
19183
|
+
}
|
|
19184
|
+
|
|
19088
19185
|
// src/mission/control.ts
|
|
19089
19186
|
import { existsSync as existsSync8, statSync as statSync4 } from "node:fs";
|
|
19090
19187
|
function scopeAllowed(mission) {
|
|
@@ -19155,7 +19252,10 @@ async function executeTask(task, mission, scope) {
|
|
|
19155
19252
|
}
|
|
19156
19253
|
}
|
|
19157
19254
|
function budgetExhausted(mission) {
|
|
19158
|
-
return mission.budget.
|
|
19255
|
+
return budgetOverrun(mission.budget).overrun;
|
|
19256
|
+
}
|
|
19257
|
+
function budgetReason(mission) {
|
|
19258
|
+
return budgetOverrun(mission.budget).reason ?? "budget_exhausted";
|
|
19159
19259
|
}
|
|
19160
19260
|
async function runMission(mission) {
|
|
19161
19261
|
if (/^https?:\/\//i.test(mission.target) && !scopeAllowed(mission)) {
|
|
@@ -19164,6 +19264,11 @@ async function runMission(mission) {
|
|
|
19164
19264
|
let m = { ...mission, status: "running" };
|
|
19165
19265
|
m.tasks = buildInitialTasks(m);
|
|
19166
19266
|
m.graph = loadEscalationGraph(m.graph);
|
|
19267
|
+
const routerCfg = loadRouterConfig();
|
|
19268
|
+
m.decision_log = [
|
|
19269
|
+
...m.decision_log,
|
|
19270
|
+
{ at: new Date().toISOString(), agent: "router", decision: isModelConfigured(routerCfg) ? `model routing active: ${JSON.stringify(routingPlan(routerCfg))}` : "deterministic (no model provider configured)" }
|
|
19271
|
+
];
|
|
19167
19272
|
m = saveMission(m);
|
|
19168
19273
|
const scope = m.scope.join(",");
|
|
19169
19274
|
let iterations = 0;
|
|
@@ -19171,7 +19276,7 @@ async function runMission(mission) {
|
|
|
19171
19276
|
while (iterations < maxIterations) {
|
|
19172
19277
|
iterations += 1;
|
|
19173
19278
|
if (budgetExhausted(m)) {
|
|
19174
|
-
m = { ...m, termination_reason:
|
|
19279
|
+
m = { ...m, termination_reason: budgetReason(m) };
|
|
19175
19280
|
break;
|
|
19176
19281
|
}
|
|
19177
19282
|
const { ready, blocked } = schedule(m.tasks);
|
|
@@ -19193,20 +19298,22 @@ async function runMission(mission) {
|
|
|
19193
19298
|
const results = await Promise.all(batch.map((t) => executeTask(t, m, scope)));
|
|
19194
19299
|
for (const r of results) {
|
|
19195
19300
|
const decision = r.ok ? `${r.task.agent_type} completed (${Object.keys(r.output).length} output fields, ${r.hypotheses.length} hypotheses)` : `${r.task.agent_type} failed: ${r.error ?? "unknown"}`;
|
|
19301
|
+
const route = routeTask(r.task.agent_type, routerCfg);
|
|
19302
|
+
const logEntry = (entryDecision) => ({ at: new Date().toISOString(), agent: r.task.agent_type, decision: entryDecision, tier: route.tier });
|
|
19196
19303
|
if (r.ok) {
|
|
19197
19304
|
m = {
|
|
19198
19305
|
...m,
|
|
19199
19306
|
tasks: setTask(m.tasks, r.task.task_id, { status: "success", result: r.output }),
|
|
19200
19307
|
hypotheses: mergeHypotheses(m.hypotheses, r.hypotheses),
|
|
19201
19308
|
graph: mergeGraphs(m.graph, r.graph),
|
|
19202
|
-
decision_log: [...m.decision_log,
|
|
19309
|
+
decision_log: [...m.decision_log, logEntry(decision)]
|
|
19203
19310
|
};
|
|
19204
19311
|
if (r.task.agent_type === "reporter") {
|
|
19205
19312
|
m = { ...m, report: r.output };
|
|
19206
19313
|
}
|
|
19207
19314
|
} else {
|
|
19208
19315
|
const rec = recoveryDecision(r.task, r.error ?? "unknown error");
|
|
19209
|
-
const stamp =
|
|
19316
|
+
const stamp = logEntry(decision);
|
|
19210
19317
|
if (rec.action === "retry") {
|
|
19211
19318
|
const retried = setTask(m.tasks, r.task.task_id, { status: "retry", error: r.error ?? null });
|
|
19212
19319
|
m = { ...m, tasks: retried, decision_log: [...m.decision_log, stamp] };
|
|
@@ -19230,7 +19337,7 @@ async function runMission(mission) {
|
|
|
19230
19337
|
}
|
|
19231
19338
|
}
|
|
19232
19339
|
}
|
|
19233
|
-
m.budget.
|
|
19340
|
+
m.budget = consumeTasks(m.budget, batch.length, 0);
|
|
19234
19341
|
m = saveMission(m);
|
|
19235
19342
|
}
|
|
19236
19343
|
return finalize2(m);
|
|
@@ -19238,7 +19345,7 @@ async function runMission(mission) {
|
|
|
19238
19345
|
function finalize2(mission) {
|
|
19239
19346
|
let m = mission;
|
|
19240
19347
|
if (budgetExhausted(m)) {
|
|
19241
|
-
m = { ...m, status: "terminated", termination_reason:
|
|
19348
|
+
m = { ...m, status: "terminated", termination_reason: budgetReason(m) };
|
|
19242
19349
|
} else {
|
|
19243
19350
|
m = { ...m, status: "completed", termination_reason: "all tasks resolved" };
|
|
19244
19351
|
}
|
|
@@ -19251,6 +19358,8 @@ function finalize2(mission) {
|
|
|
19251
19358
|
if (mem.saved > 0) {
|
|
19252
19359
|
m = { ...m, memory_refs: [...m.memory_refs, `persisted:${mem.saved} (${mem.deduped} deduped)`] };
|
|
19253
19360
|
}
|
|
19361
|
+
const budgetSummary = budgetStatus(m.budget).map((d) => `${d.key}=${d.used}/${d.max}`).join(", ");
|
|
19362
|
+
m = { ...m, decision_log: [...m.decision_log, { at: new Date().toISOString(), agent: "budget", decision: `final budget: ${budgetSummary}` }] };
|
|
19254
19363
|
return saveMission(m);
|
|
19255
19364
|
}
|
|
19256
19365
|
async function startMission(target, mode, opts = {}) {
|
|
@@ -19274,6 +19383,7 @@ var init_control = __esm(() => {
|
|
|
19274
19383
|
init_coverage();
|
|
19275
19384
|
init_recovery();
|
|
19276
19385
|
init_memory2();
|
|
19386
|
+
init_router();
|
|
19277
19387
|
MODE_PROFILES = {
|
|
19278
19388
|
web: { agents: ["recon", "web", "api", "auth", "validator", "reviewer", "reporter"], verify: true, risk: "medium" },
|
|
19279
19389
|
api: { agents: ["recon", "api", "auth", "validator", "reviewer", "reporter"], verify: true, risk: "medium" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.54",
|
|
4
4
|
"description": "Blitz Strike — a universal MCP security-audit toolbelt. BLITZ sweeps the attack surface, EAGLE-EYE traces source-to-sink, STRIKE verifies live. 57 attack chains, 130-tool catalog, intelligence data layer. One server, every agent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|