@wrongstack/core 0.63.4 → 0.68.0
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-B5rxWrg3.d.ts → agent-bridge-D-j6OOBT.d.ts} +1 -1
- package/dist/agent-subagent-runner-DRZ9-NnR.d.ts +1042 -0
- package/dist/{compactor-0vjZ8KTk.d.ts → compactor-D_ExJajC.d.ts} +1 -1
- package/dist/{config-BdDuaZmB.d.ts → config--86aHSln.d.ts} +1 -1
- package/dist/{context-iFMEO2rN.d.ts → context-y87Jc5ei.d.ts} +3 -3
- package/dist/coordination/index.d.ts +12 -12
- package/dist/coordination/index.js +265 -275
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +22 -22
- package/dist/defaults/index.js +181 -180
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-k8CHjcrN.d.ts → events-CIplI98R.d.ts} +1 -1
- package/dist/execution/index.d.ts +16 -385
- package/dist/execution/index.js +124 -146
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/goal-store-C7jcumEh.d.ts +96 -0
- package/dist/{index-Bc6BiP5q.d.ts → index-DKUvyTvV.d.ts} +28 -442
- package/dist/{index-CWdW_CJt.d.ts → index-b5uhfTSl.d.ts} +8 -8
- package/dist/index.d.ts +34 -32
- package/dist/index.js +692 -750
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/kernel/index.d.ts +9 -9
- package/dist/{mcp-servers-CwqQDMYy.d.ts → mcp-servers-DwoNBf6r.d.ts} +3 -3
- package/dist/models/index.d.ts +2 -2
- package/dist/{multi-agent-coordinator-CNUJYq7U.d.ts → multi-agent-coordinator-CWnH-CiX.d.ts} +10 -2
- package/dist/{null-fleet-bus-DRoJ0uOY.d.ts → null-fleet-bus-CuN0ObJr.d.ts} +24 -31
- package/dist/observability/index.d.ts +2 -2
- package/dist/parallel-eternal-engine-0UwotoSx.d.ts +483 -0
- package/dist/{path-resolver-C5sPVne8.d.ts → path-resolver-DVkEcIw8.d.ts} +2 -2
- package/dist/{permission-Ld-i5ugf.d.ts → permission-C1A5whY5.d.ts} +5 -1
- package/dist/{permission-policy-CL-mPufp.d.ts → permission-policy-B2dK-T5N.d.ts} +19 -5
- package/dist/{plan-templates-ThBHOjaM.d.ts → plan-templates-Bprrzhbu.d.ts} +4 -4
- package/dist/{provider-runner-DJQa211J.d.ts → provider-runner-mXvXGSIw.d.ts} +3 -3
- package/dist/{retry-policy-BfBScewS.d.ts → retry-policy-CG3qvH_e.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -8
- package/dist/sdd/index.js +123 -146
- package/dist/sdd/index.js.map +1 -1
- package/dist/security/index.d.ts +3 -3
- package/dist/security/index.js +31 -22
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-DxhW7ML3.d.ts → selector-RvBR_YRW.d.ts} +1 -1
- package/dist/session-event-bridge-CDHxcmQU.d.ts +93 -0
- package/dist/{session-reader-q2ThszgG.d.ts → session-reader-BIpwM60D.d.ts} +1 -1
- package/dist/storage/index.d.ts +7 -6
- package/dist/{system-prompt-7LHyBbIf.d.ts → system-prompt-b61lOd49.d.ts} +2 -2
- package/dist/types/index.d.ts +23 -14
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/multi-agent/SKILL.md +0 -2
- package/dist/agent-subagent-runner-Zc3f37Sg.d.ts +0 -182
- package/dist/goal-store-iHltMi5n.d.ts +0 -188
- package/dist/multi-agent-SASYOrWA.d.ts +0 -554
- package/dist/tool-executor-CIjpGaRA.d.ts +0 -111
|
@@ -1174,6 +1174,10 @@ Emit each evaluation immediately. Do not wait until you have read all reports.`;
|
|
|
1174
1174
|
return lines.join("\n");
|
|
1175
1175
|
}
|
|
1176
1176
|
cleanup() {
|
|
1177
|
+
if (this._timeoutTimer) {
|
|
1178
|
+
clearTimeout(this._timeoutTimer);
|
|
1179
|
+
this._timeoutTimer = void 0;
|
|
1180
|
+
}
|
|
1177
1181
|
for (const dispose of this.disposers) dispose();
|
|
1178
1182
|
this.disposers.length = 0;
|
|
1179
1183
|
}
|
|
@@ -4280,116 +4284,6 @@ function resolveModelMatrix(matrix, role) {
|
|
|
4280
4284
|
return void 0;
|
|
4281
4285
|
}
|
|
4282
4286
|
|
|
4283
|
-
// src/types/errors.ts
|
|
4284
|
-
var ERROR_CODES = {
|
|
4285
|
-
// Provider
|
|
4286
|
-
PROVIDER_RATE_LIMITED: "PROVIDER_RATE_LIMITED",
|
|
4287
|
-
PROVIDER_AUTH_FAILED: "PROVIDER_AUTH_FAILED",
|
|
4288
|
-
PROVIDER_OVERLOADED: "PROVIDER_OVERLOADED",
|
|
4289
|
-
PROVIDER_INVALID_REQUEST: "PROVIDER_INVALID_REQUEST",
|
|
4290
|
-
PROVIDER_SERVER_ERROR: "PROVIDER_SERVER_ERROR",
|
|
4291
|
-
PROVIDER_NETWORK_ERROR: "PROVIDER_NETWORK_ERROR"};
|
|
4292
|
-
var WrongStackError = class extends Error {
|
|
4293
|
-
code;
|
|
4294
|
-
subsystem;
|
|
4295
|
-
severity;
|
|
4296
|
-
recoverable;
|
|
4297
|
-
context;
|
|
4298
|
-
constructor(opts) {
|
|
4299
|
-
super(opts.message, { cause: opts.cause });
|
|
4300
|
-
this.name = "WrongStackError";
|
|
4301
|
-
this.code = opts.code;
|
|
4302
|
-
this.subsystem = opts.subsystem;
|
|
4303
|
-
this.severity = opts.severity ?? "error";
|
|
4304
|
-
this.recoverable = opts.recoverable ?? false;
|
|
4305
|
-
this.context = opts.context;
|
|
4306
|
-
}
|
|
4307
|
-
/**
|
|
4308
|
-
* Render a one-line user-facing description.
|
|
4309
|
-
* Subclasses should override for domain-specific formatting.
|
|
4310
|
-
*/
|
|
4311
|
-
describe() {
|
|
4312
|
-
const ctx = this.context ? ` ${formatContext(this.context)}` : "";
|
|
4313
|
-
return `${this.code}: ${this.message}${ctx}`;
|
|
4314
|
-
}
|
|
4315
|
-
};
|
|
4316
|
-
function formatContext(ctx) {
|
|
4317
|
-
const parts = Object.entries(ctx).filter(([, v]) => v !== void 0).slice(0, 3).map(([k, v]) => `${k}=${String(v)}`);
|
|
4318
|
-
return parts.length > 0 ? `[${parts.join(" ")}]` : "";
|
|
4319
|
-
}
|
|
4320
|
-
|
|
4321
|
-
// src/types/provider.ts
|
|
4322
|
-
var ProviderError = class extends WrongStackError {
|
|
4323
|
-
status;
|
|
4324
|
-
retryable;
|
|
4325
|
-
providerId;
|
|
4326
|
-
body;
|
|
4327
|
-
constructor(message, status, retryable, providerId, opts = {}) {
|
|
4328
|
-
super({
|
|
4329
|
-
message,
|
|
4330
|
-
code: providerStatusToCode(status, opts.body?.type),
|
|
4331
|
-
subsystem: "provider",
|
|
4332
|
-
severity: status >= 500 ? "error" : "warning",
|
|
4333
|
-
recoverable: retryable,
|
|
4334
|
-
context: { providerId, status },
|
|
4335
|
-
cause: opts.cause
|
|
4336
|
-
});
|
|
4337
|
-
this.name = "ProviderError";
|
|
4338
|
-
this.status = status;
|
|
4339
|
-
this.retryable = retryable;
|
|
4340
|
-
this.providerId = providerId;
|
|
4341
|
-
this.body = opts.body;
|
|
4342
|
-
}
|
|
4343
|
-
/**
|
|
4344
|
-
* Render a one-line, user-facing description. Designed for the CLI/TUI
|
|
4345
|
-
* status line and the agent's retry warning. Avoids dumping raw JSON
|
|
4346
|
-
* (which is what users see today when a 529 lands and the log message
|
|
4347
|
-
* includes the full `{"type":"error",...}` body).
|
|
4348
|
-
*
|
|
4349
|
-
* Examples:
|
|
4350
|
-
* "minimax-coding-plan overloaded (529): High traffic detected. Upgrade for highspeed model. [req 06534785201de9c0…]"
|
|
4351
|
-
* "openai rate limited (429): Retry after 12s"
|
|
4352
|
-
* "anthropic invalid request (400): messages.0.role must be one of 'user'|'assistant'"
|
|
4353
|
-
* "groq HTTP 500 (server error)"
|
|
4354
|
-
*/
|
|
4355
|
-
describe() {
|
|
4356
|
-
const kind = describeStatus(this.status, this.body?.type);
|
|
4357
|
-
const head = `${this.providerId} ${kind}`;
|
|
4358
|
-
const detail = this.body?.message?.trim();
|
|
4359
|
-
const reqId = this.body?.requestId ? ` [req ${this.body.requestId.slice(0, 16)}${this.body.requestId.length > 16 ? "\u2026" : ""}]` : "";
|
|
4360
|
-
if (detail && detail.length > 0) {
|
|
4361
|
-
return `${head}: ${truncate(detail, 240)}${reqId}`;
|
|
4362
|
-
}
|
|
4363
|
-
return `${head}${reqId}`;
|
|
4364
|
-
}
|
|
4365
|
-
};
|
|
4366
|
-
function describeStatus(status, type) {
|
|
4367
|
-
if (status === 0) return "network error";
|
|
4368
|
-
if (type === "overloaded_error" || status === 529) return `overloaded (${status})`;
|
|
4369
|
-
if (type === "rate_limit_error" || status === 429) return `rate limited (${status})`;
|
|
4370
|
-
if (type === "authentication_error" || status === 401) return `auth failed (${status})`;
|
|
4371
|
-
if (type === "permission_error" || status === 403) return `forbidden (${status})`;
|
|
4372
|
-
if (type === "not_found_error" || status === 404) return `not found (${status})`;
|
|
4373
|
-
if (type === "invalid_request_error" || status === 400) return `invalid request (${status})`;
|
|
4374
|
-
if (status === 408) return `timeout (${status})`;
|
|
4375
|
-
if (status >= 500 && status < 600) return `HTTP ${status} (server error)`;
|
|
4376
|
-
if (type) return `${type} (${status})`;
|
|
4377
|
-
return `HTTP ${status}`;
|
|
4378
|
-
}
|
|
4379
|
-
function truncate(s, n) {
|
|
4380
|
-
return s.length <= n ? s : `${s.slice(0, n - 1)}\u2026`;
|
|
4381
|
-
}
|
|
4382
|
-
function providerStatusToCode(status, type) {
|
|
4383
|
-
if (status === 0) return ERROR_CODES.PROVIDER_NETWORK_ERROR;
|
|
4384
|
-
if (type === "rate_limit_error" || status === 429) return ERROR_CODES.PROVIDER_RATE_LIMITED;
|
|
4385
|
-
if (type === "authentication_error" || status === 401) return ERROR_CODES.PROVIDER_AUTH_FAILED;
|
|
4386
|
-
if (type === "overloaded_error" || status === 529) return ERROR_CODES.PROVIDER_OVERLOADED;
|
|
4387
|
-
if (type === "invalid_request_error" || status === 400) return ERROR_CODES.PROVIDER_INVALID_REQUEST;
|
|
4388
|
-
if (status === 408) return ERROR_CODES.PROVIDER_NETWORK_ERROR;
|
|
4389
|
-
if (status >= 500) return ERROR_CODES.PROVIDER_SERVER_ERROR;
|
|
4390
|
-
return ERROR_CODES.PROVIDER_INVALID_REQUEST;
|
|
4391
|
-
}
|
|
4392
|
-
|
|
4393
4287
|
// src/coordination/subagent-budget.ts
|
|
4394
4288
|
var BudgetExceededError = class extends Error {
|
|
4395
4289
|
kind;
|
|
@@ -4679,15 +4573,22 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
4679
4573
|
void this.checkLimits();
|
|
4680
4574
|
}
|
|
4681
4575
|
/**
|
|
4682
|
-
* Wall-clock budget check.
|
|
4683
|
-
*
|
|
4684
|
-
*
|
|
4576
|
+
* Wall-clock / idle budget check. Delegates to `checkLimits(elapsed)`, so
|
|
4577
|
+
* `timeout` and `idle_timeout` follow the SAME negotiation path as the other
|
|
4578
|
+
* kinds — they are NOT a special-cased hard stop. This is deliberate: a
|
|
4579
|
+
* heartbeat-aware policy (see `attachAutoExtend` and `CollabSession`) grants
|
|
4580
|
+
* a timeout extension only while the agent is making progress and denies it
|
|
4581
|
+
* once the agent is genuinely stuck, which is safer than an unconditional
|
|
4582
|
+
* hard kill of a long-but-working agent. The runner translates the resulting
|
|
4583
|
+
* `BudgetThresholdSignal` decision (`extend` → patch limits in place,
|
|
4584
|
+
* `stop` → abort) just like every other kind.
|
|
4685
4585
|
*
|
|
4686
|
-
* Decision table:
|
|
4687
|
-
* - no `onThreshold` handler
|
|
4688
|
-
* - `mode === 'sync'` → throw `BudgetExceededError`
|
|
4689
|
-
* - `mode === 'auto'` + no listener
|
|
4690
|
-
* - `mode === 'auto'` + listener
|
|
4586
|
+
* Decision table (same as `checkLimits`):
|
|
4587
|
+
* - no `onThreshold` handler → throw `BudgetExceededError` (hard stop)
|
|
4588
|
+
* - `mode === 'sync'` → throw `BudgetExceededError` (hard stop)
|
|
4589
|
+
* - `mode === 'auto'` + no listener → throw `BudgetExceededError` (no one to ask)
|
|
4590
|
+
* - `mode === 'auto'` + listener → throw `BudgetThresholdSignal` (negotiated;
|
|
4591
|
+
* a heartbeat-aware policy may extend the timeout)
|
|
4691
4592
|
*/
|
|
4692
4593
|
checkTimeout() {
|
|
4693
4594
|
if (this.startTime === null) return;
|
|
@@ -4722,6 +4623,181 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
4722
4623
|
}
|
|
4723
4624
|
};
|
|
4724
4625
|
|
|
4626
|
+
// src/types/errors.ts
|
|
4627
|
+
var ERROR_CODES = {
|
|
4628
|
+
// Provider
|
|
4629
|
+
PROVIDER_RATE_LIMITED: "PROVIDER_RATE_LIMITED",
|
|
4630
|
+
PROVIDER_AUTH_FAILED: "PROVIDER_AUTH_FAILED",
|
|
4631
|
+
PROVIDER_OVERLOADED: "PROVIDER_OVERLOADED",
|
|
4632
|
+
PROVIDER_INVALID_REQUEST: "PROVIDER_INVALID_REQUEST",
|
|
4633
|
+
PROVIDER_SERVER_ERROR: "PROVIDER_SERVER_ERROR",
|
|
4634
|
+
PROVIDER_NETWORK_ERROR: "PROVIDER_NETWORK_ERROR"};
|
|
4635
|
+
var WrongStackError = class extends Error {
|
|
4636
|
+
code;
|
|
4637
|
+
subsystem;
|
|
4638
|
+
severity;
|
|
4639
|
+
recoverable;
|
|
4640
|
+
context;
|
|
4641
|
+
constructor(opts) {
|
|
4642
|
+
super(opts.message, { cause: opts.cause });
|
|
4643
|
+
this.name = "WrongStackError";
|
|
4644
|
+
this.code = opts.code;
|
|
4645
|
+
this.subsystem = opts.subsystem;
|
|
4646
|
+
this.severity = opts.severity ?? "error";
|
|
4647
|
+
this.recoverable = opts.recoverable ?? false;
|
|
4648
|
+
this.context = opts.context;
|
|
4649
|
+
}
|
|
4650
|
+
/**
|
|
4651
|
+
* Render a one-line user-facing description.
|
|
4652
|
+
* Subclasses should override for domain-specific formatting.
|
|
4653
|
+
*/
|
|
4654
|
+
describe() {
|
|
4655
|
+
const ctx = this.context ? ` ${formatContext(this.context)}` : "";
|
|
4656
|
+
return `${this.code}: ${this.message}${ctx}`;
|
|
4657
|
+
}
|
|
4658
|
+
};
|
|
4659
|
+
function formatContext(ctx) {
|
|
4660
|
+
const parts = Object.entries(ctx).filter(([, v]) => v !== void 0).slice(0, 3).map(([k, v]) => `${k}=${String(v)}`);
|
|
4661
|
+
return parts.length > 0 ? `[${parts.join(" ")}]` : "";
|
|
4662
|
+
}
|
|
4663
|
+
|
|
4664
|
+
// src/types/provider.ts
|
|
4665
|
+
var ProviderError = class extends WrongStackError {
|
|
4666
|
+
status;
|
|
4667
|
+
retryable;
|
|
4668
|
+
providerId;
|
|
4669
|
+
body;
|
|
4670
|
+
constructor(message, status, retryable, providerId, opts = {}) {
|
|
4671
|
+
super({
|
|
4672
|
+
message,
|
|
4673
|
+
code: providerStatusToCode(status, opts.body?.type),
|
|
4674
|
+
subsystem: "provider",
|
|
4675
|
+
severity: status >= 500 ? "error" : "warning",
|
|
4676
|
+
recoverable: retryable,
|
|
4677
|
+
context: { providerId, status },
|
|
4678
|
+
cause: opts.cause
|
|
4679
|
+
});
|
|
4680
|
+
this.name = "ProviderError";
|
|
4681
|
+
this.status = status;
|
|
4682
|
+
this.retryable = retryable;
|
|
4683
|
+
this.providerId = providerId;
|
|
4684
|
+
this.body = opts.body;
|
|
4685
|
+
}
|
|
4686
|
+
/**
|
|
4687
|
+
* Render a one-line, user-facing description. Designed for the CLI/TUI
|
|
4688
|
+
* status line and the agent's retry warning. Avoids dumping raw JSON
|
|
4689
|
+
* (which is what users see today when a 529 lands and the log message
|
|
4690
|
+
* includes the full `{"type":"error",...}` body).
|
|
4691
|
+
*
|
|
4692
|
+
* Examples:
|
|
4693
|
+
* "minimax-coding-plan overloaded (529): High traffic detected. Upgrade for highspeed model. [req 06534785201de9c0…]"
|
|
4694
|
+
* "openai rate limited (429): Retry after 12s"
|
|
4695
|
+
* "anthropic invalid request (400): messages.0.role must be one of 'user'|'assistant'"
|
|
4696
|
+
* "groq HTTP 500 (server error)"
|
|
4697
|
+
*/
|
|
4698
|
+
describe() {
|
|
4699
|
+
const kind = describeStatus(this.status, this.body?.type);
|
|
4700
|
+
const head = `${this.providerId} ${kind}`;
|
|
4701
|
+
const detail = this.body?.message?.trim();
|
|
4702
|
+
const reqId = this.body?.requestId ? ` [req ${this.body.requestId.slice(0, 16)}${this.body.requestId.length > 16 ? "\u2026" : ""}]` : "";
|
|
4703
|
+
if (detail && detail.length > 0) {
|
|
4704
|
+
return `${head}: ${truncate(detail, 240)}${reqId}`;
|
|
4705
|
+
}
|
|
4706
|
+
return `${head}${reqId}`;
|
|
4707
|
+
}
|
|
4708
|
+
};
|
|
4709
|
+
function describeStatus(status, type) {
|
|
4710
|
+
if (status === 0) return "network error";
|
|
4711
|
+
if (type === "overloaded_error" || status === 529) return `overloaded (${status})`;
|
|
4712
|
+
if (type === "rate_limit_error" || status === 429) return `rate limited (${status})`;
|
|
4713
|
+
if (type === "authentication_error" || status === 401) return `auth failed (${status})`;
|
|
4714
|
+
if (type === "permission_error" || status === 403) return `forbidden (${status})`;
|
|
4715
|
+
if (type === "not_found_error" || status === 404) return `not found (${status})`;
|
|
4716
|
+
if (type === "invalid_request_error" || status === 400) return `invalid request (${status})`;
|
|
4717
|
+
if (status === 408) return `timeout (${status})`;
|
|
4718
|
+
if (status >= 500 && status < 600) return `HTTP ${status} (server error)`;
|
|
4719
|
+
if (type) return `${type} (${status})`;
|
|
4720
|
+
return `HTTP ${status}`;
|
|
4721
|
+
}
|
|
4722
|
+
function truncate(s, n) {
|
|
4723
|
+
return s.length <= n ? s : `${s.slice(0, n - 1)}\u2026`;
|
|
4724
|
+
}
|
|
4725
|
+
function providerStatusToCode(status, type) {
|
|
4726
|
+
if (status === 0) return ERROR_CODES.PROVIDER_NETWORK_ERROR;
|
|
4727
|
+
if (type === "rate_limit_error" || status === 429) return ERROR_CODES.PROVIDER_RATE_LIMITED;
|
|
4728
|
+
if (type === "authentication_error" || status === 401) return ERROR_CODES.PROVIDER_AUTH_FAILED;
|
|
4729
|
+
if (type === "overloaded_error" || status === 529) return ERROR_CODES.PROVIDER_OVERLOADED;
|
|
4730
|
+
if (type === "invalid_request_error" || status === 400) return ERROR_CODES.PROVIDER_INVALID_REQUEST;
|
|
4731
|
+
if (status === 408) return ERROR_CODES.PROVIDER_NETWORK_ERROR;
|
|
4732
|
+
if (status >= 500) return ERROR_CODES.PROVIDER_SERVER_ERROR;
|
|
4733
|
+
return ERROR_CODES.PROVIDER_INVALID_REQUEST;
|
|
4734
|
+
}
|
|
4735
|
+
|
|
4736
|
+
// src/coordination/coordinator/error-classifier.ts
|
|
4737
|
+
function classifySubagentError(err, hints = {}) {
|
|
4738
|
+
const cause = err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : void 0;
|
|
4739
|
+
if (err instanceof ProviderError) {
|
|
4740
|
+
const baseMessage2 = err.describe();
|
|
4741
|
+
return providerErrorToSubagentError(err, baseMessage2, cause);
|
|
4742
|
+
}
|
|
4743
|
+
const baseMessage = err instanceof Error ? err.message : String(err);
|
|
4744
|
+
if (err instanceof BudgetExceededError) {
|
|
4745
|
+
const map = {
|
|
4746
|
+
iterations: "budget_iterations",
|
|
4747
|
+
tool_calls: "budget_tool_calls",
|
|
4748
|
+
tokens: "budget_tokens",
|
|
4749
|
+
cost: "budget_cost",
|
|
4750
|
+
timeout: "budget_timeout",
|
|
4751
|
+
idle_timeout: "budget_timeout"
|
|
4752
|
+
};
|
|
4753
|
+
return {
|
|
4754
|
+
kind: map[err.kind],
|
|
4755
|
+
message: baseMessage,
|
|
4756
|
+
retryable: false,
|
|
4757
|
+
cause
|
|
4758
|
+
};
|
|
4759
|
+
}
|
|
4760
|
+
if (hints.parentAborted) {
|
|
4761
|
+
return { kind: "aborted_by_parent", message: baseMessage, retryable: false, cause };
|
|
4762
|
+
}
|
|
4763
|
+
const lower = baseMessage.toLowerCase();
|
|
4764
|
+
if (/agent aborted$/i.test(baseMessage)) {
|
|
4765
|
+
return { kind: "aborted_by_parent", message: baseMessage, retryable: false, cause };
|
|
4766
|
+
}
|
|
4767
|
+
if (/agent exhausted iteration limit$/i.test(baseMessage)) {
|
|
4768
|
+
return { kind: "budget_iterations", message: baseMessage, retryable: false, cause };
|
|
4769
|
+
}
|
|
4770
|
+
if (/empty response$/i.test(baseMessage)) {
|
|
4771
|
+
return { kind: "empty_response", message: baseMessage, retryable: false, cause };
|
|
4772
|
+
}
|
|
4773
|
+
if (/^tool failed: /i.test(baseMessage)) {
|
|
4774
|
+
return { kind: "tool_failed", message: baseMessage, retryable: false, cause };
|
|
4775
|
+
}
|
|
4776
|
+
if (lower.includes("bridge transport") || /bridge.*(closed|disconnect)/i.test(baseMessage)) {
|
|
4777
|
+
return { kind: "bridge_failed", message: baseMessage, retryable: false, cause };
|
|
4778
|
+
}
|
|
4779
|
+
if (/context length|max.*tokens?.*exceeded|prompt is too long/i.test(baseMessage)) {
|
|
4780
|
+
return { kind: "context_overflow", message: baseMessage, retryable: false, cause };
|
|
4781
|
+
}
|
|
4782
|
+
return { kind: "unknown", message: baseMessage, retryable: false, cause };
|
|
4783
|
+
}
|
|
4784
|
+
function providerErrorToSubagentError(err, message, cause) {
|
|
4785
|
+
const status = err.status;
|
|
4786
|
+
if (status === 429 || err.body?.type === "rate_limit_error") {
|
|
4787
|
+
return { kind: "provider_rate_limit", message, retryable: true, backoffMs: 5e3, cause };
|
|
4788
|
+
}
|
|
4789
|
+
if (status === 401 || status === 403 || err.body?.type === "authentication_error") {
|
|
4790
|
+
return { kind: "provider_auth", message, retryable: false, cause };
|
|
4791
|
+
}
|
|
4792
|
+
if (status === 408 || status === 0) {
|
|
4793
|
+
return { kind: "provider_timeout", message, retryable: true, cause };
|
|
4794
|
+
}
|
|
4795
|
+
if (status >= 500 && status < 600) {
|
|
4796
|
+
return { kind: "provider_5xx", message, retryable: true, backoffMs: 3e3, cause };
|
|
4797
|
+
}
|
|
4798
|
+
return { kind: "unknown", message, retryable: err.retryable, cause };
|
|
4799
|
+
}
|
|
4800
|
+
|
|
4725
4801
|
// src/coordination/fleet.ts
|
|
4726
4802
|
var AUDIT_LOG_AGENT = {
|
|
4727
4803
|
id: "audit-log",
|
|
@@ -5086,7 +5162,10 @@ var NICKNAME_POOL = {
|
|
|
5086
5162
|
"lavoisier": { name: "Lavoisier", domain: "chemistry" },
|
|
5087
5163
|
"mendeleev": { name: "Mendeleev", domain: "chemistry" }
|
|
5088
5164
|
};
|
|
5089
|
-
var ALL_NICKNAMES = Object.
|
|
5165
|
+
var ALL_NICKNAMES = Object.entries(NICKNAME_POOL);
|
|
5166
|
+
var NAME_TO_KEY = Object.fromEntries(
|
|
5167
|
+
ALL_NICKNAMES.map(([key, entry]) => [entry.name, key])
|
|
5168
|
+
);
|
|
5090
5169
|
var DOMAIN_PREFERENCES = {
|
|
5091
5170
|
"security": ["shannon", "turing", "lamarr", "stallman"],
|
|
5092
5171
|
"bug-hunter": ["darwin", "curie", "feynman", "fermi"],
|
|
@@ -5119,17 +5198,23 @@ function assignNickname(role, used) {
|
|
|
5119
5198
|
for (const key of preferences) {
|
|
5120
5199
|
const entry = NICKNAME_POOL[key];
|
|
5121
5200
|
if (entry && !used.has(key)) {
|
|
5122
|
-
return `${entry.name} (${formatRole(role)})
|
|
5201
|
+
return { key, display: `${entry.name} (${formatRole(role)})` };
|
|
5123
5202
|
}
|
|
5124
5203
|
}
|
|
5125
|
-
for (const entry of ALL_NICKNAMES) {
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
return `${entry.name} (${formatRole(role)})`;
|
|
5204
|
+
for (const [key, entry] of ALL_NICKNAMES) {
|
|
5205
|
+
if (!used.has(key)) {
|
|
5206
|
+
return { key, display: `${entry.name} (${formatRole(role)})` };
|
|
5129
5207
|
}
|
|
5130
5208
|
}
|
|
5131
5209
|
const counter = used.size + 1;
|
|
5132
|
-
return `Scientist #${counter} (${formatRole(role)})
|
|
5210
|
+
return { key: `scientist-${counter}`, display: `Scientist #${counter} (${formatRole(role)})` };
|
|
5211
|
+
}
|
|
5212
|
+
function nicknameKeyFromDisplay(display) {
|
|
5213
|
+
const base = display.replace(/\s*\([^)]*\)\s*$/, "").trim();
|
|
5214
|
+
const key = NAME_TO_KEY[base];
|
|
5215
|
+
if (key) return key;
|
|
5216
|
+
const synthesized = base.match(/^Scientist #(\d+)$/);
|
|
5217
|
+
return synthesized ? `scientist-${synthesized[1]}` : void 0;
|
|
5133
5218
|
}
|
|
5134
5219
|
function formatRole(role) {
|
|
5135
5220
|
return role.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
@@ -5216,11 +5301,10 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
5216
5301
|
const name = subagent.name?.trim() ?? "";
|
|
5217
5302
|
const isPlaceholder = name === "" || name.toLowerCase() === role.toLowerCase() || name === "subagent" || name === "adhoc" || name === "generic" || /^slot-/.test(name);
|
|
5218
5303
|
if (!isPlaceholder) return subagent;
|
|
5219
|
-
const
|
|
5220
|
-
|
|
5221
|
-
this.
|
|
5222
|
-
|
|
5223
|
-
return { ...subagent, name: nickname };
|
|
5304
|
+
const { key, display } = assignNickname(role, this.usedNicknames);
|
|
5305
|
+
this.usedNicknames.add(key);
|
|
5306
|
+
this.subagentNicknames.set(subagentId, key);
|
|
5307
|
+
return { ...subagent, name: display };
|
|
5224
5308
|
}
|
|
5225
5309
|
async spawn(subagent) {
|
|
5226
5310
|
const id = subagent.id || randomUUID();
|
|
@@ -5472,23 +5556,32 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
5472
5556
|
*/
|
|
5473
5557
|
drainPendingAsAborted(message) {
|
|
5474
5558
|
const dropped = this.pendingTasks.splice(0, this.pendingTasks.length);
|
|
5475
|
-
for (const t of dropped)
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5559
|
+
for (const t of dropped) this.emitPendingAborted(t, message);
|
|
5560
|
+
}
|
|
5561
|
+
/**
|
|
5562
|
+
* Emit a synthetic `stopped`/`aborted_by_parent` completion for a single
|
|
5563
|
+
* PENDING task — one that was never counted in `inFlight`. This MUST bypass
|
|
5564
|
+
* `recordCompletion`: that path does `inFlight--`, which for a pending task
|
|
5565
|
+
* steals a decrement from a genuinely in-flight task and trips the underflow
|
|
5566
|
+
* guard — suppressing that real task's `task.completed` and hanging its
|
|
5567
|
+
* `awaitTasks()` caller. Pushes the result and fires the event directly.
|
|
5568
|
+
*/
|
|
5569
|
+
emitPendingAborted(task, message) {
|
|
5570
|
+
const synthetic = {
|
|
5571
|
+
subagentId: task.subagentId ?? "unassigned",
|
|
5572
|
+
taskId: task.id,
|
|
5573
|
+
status: "stopped",
|
|
5574
|
+
error: {
|
|
5575
|
+
kind: "aborted_by_parent",
|
|
5576
|
+
message,
|
|
5577
|
+
retryable: false
|
|
5578
|
+
},
|
|
5579
|
+
iterations: 0,
|
|
5580
|
+
toolCalls: 0,
|
|
5581
|
+
durationMs: 0
|
|
5582
|
+
};
|
|
5583
|
+
this.completedResults.push(synthetic);
|
|
5584
|
+
this.emit("task.completed", { task, result: synthetic });
|
|
5492
5585
|
}
|
|
5493
5586
|
async runDispatched(subagentId, task) {
|
|
5494
5587
|
const subagent = this.subagents.get(subagentId);
|
|
@@ -5749,20 +5842,10 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
5749
5842
|
const orphaned = this.pendingTasks.filter((t) => t.subagentId === subagentId);
|
|
5750
5843
|
this.pendingTasks = this.pendingTasks.filter((t) => t.subagentId !== subagentId);
|
|
5751
5844
|
for (const t of orphaned) {
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
error: {
|
|
5757
|
-
kind: "aborted_by_parent",
|
|
5758
|
-
message: `Subagent "${subagentId}" was removed while task "${t.id}" was pending`,
|
|
5759
|
-
retryable: false
|
|
5760
|
-
},
|
|
5761
|
-
iterations: 0,
|
|
5762
|
-
toolCalls: 0,
|
|
5763
|
-
durationMs: 0
|
|
5764
|
-
};
|
|
5765
|
-
this.recordCompletion(synthetic);
|
|
5845
|
+
this.emitPendingAborted(
|
|
5846
|
+
t,
|
|
5847
|
+
`Subagent "${subagentId}" was removed while task "${t.id}" was pending`
|
|
5848
|
+
);
|
|
5766
5849
|
}
|
|
5767
5850
|
this.fleetBus?.emit({
|
|
5768
5851
|
subagentId,
|
|
@@ -5782,103 +5865,8 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
5782
5865
|
return false;
|
|
5783
5866
|
}
|
|
5784
5867
|
};
|
|
5785
|
-
function classifySubagentError(err, hints = {}) {
|
|
5786
|
-
const cause = err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : void 0;
|
|
5787
|
-
if (err instanceof ProviderError) {
|
|
5788
|
-
const baseMessage2 = err.describe();
|
|
5789
|
-
return providerErrorToSubagentError(err, baseMessage2, cause);
|
|
5790
|
-
}
|
|
5791
|
-
const baseMessage = err instanceof Error ? err.message : String(err);
|
|
5792
|
-
if (err instanceof BudgetExceededError) {
|
|
5793
|
-
const map = {
|
|
5794
|
-
iterations: "budget_iterations",
|
|
5795
|
-
tool_calls: "budget_tool_calls",
|
|
5796
|
-
tokens: "budget_tokens",
|
|
5797
|
-
cost: "budget_cost",
|
|
5798
|
-
timeout: "budget_timeout",
|
|
5799
|
-
idle_timeout: "budget_timeout"
|
|
5800
|
-
};
|
|
5801
|
-
return {
|
|
5802
|
-
kind: map[err.kind],
|
|
5803
|
-
message: baseMessage,
|
|
5804
|
-
// Budgets are user-configured ceilings, not transient failures —
|
|
5805
|
-
// retrying with the same budget will hit the same ceiling. The
|
|
5806
|
-
// orchestrator must raise the budget or narrow the task first.
|
|
5807
|
-
retryable: false,
|
|
5808
|
-
cause
|
|
5809
|
-
};
|
|
5810
|
-
}
|
|
5811
|
-
if (hints.parentAborted) {
|
|
5812
|
-
return {
|
|
5813
|
-
kind: "aborted_by_parent",
|
|
5814
|
-
message: baseMessage,
|
|
5815
|
-
retryable: false,
|
|
5816
|
-
cause
|
|
5817
|
-
};
|
|
5818
|
-
}
|
|
5819
|
-
const lower = baseMessage.toLowerCase();
|
|
5820
|
-
if (/agent aborted$/i.test(baseMessage)) {
|
|
5821
|
-
return {
|
|
5822
|
-
kind: "aborted_by_parent",
|
|
5823
|
-
message: baseMessage,
|
|
5824
|
-
retryable: false,
|
|
5825
|
-
cause
|
|
5826
|
-
};
|
|
5827
|
-
}
|
|
5828
|
-
if (/agent exhausted iteration limit$/i.test(baseMessage)) {
|
|
5829
|
-
return { kind: "budget_iterations", message: baseMessage, retryable: false, cause };
|
|
5830
|
-
}
|
|
5831
|
-
if (/empty response$/i.test(baseMessage)) {
|
|
5832
|
-
return { kind: "empty_response", message: baseMessage, retryable: false, cause };
|
|
5833
|
-
}
|
|
5834
|
-
if (/^tool failed: /i.test(baseMessage)) {
|
|
5835
|
-
return { kind: "tool_failed", message: baseMessage, retryable: false, cause };
|
|
5836
|
-
}
|
|
5837
|
-
if (lower.includes("bridge transport") || /bridge.*(closed|disconnect)/i.test(baseMessage)) {
|
|
5838
|
-
return { kind: "bridge_failed", message: baseMessage, retryable: false, cause };
|
|
5839
|
-
}
|
|
5840
|
-
if (/context length|max.*tokens?.*exceeded|prompt is too long/i.test(baseMessage)) {
|
|
5841
|
-
return { kind: "context_overflow", message: baseMessage, retryable: false, cause };
|
|
5842
|
-
}
|
|
5843
|
-
return {
|
|
5844
|
-
kind: "unknown",
|
|
5845
|
-
message: baseMessage,
|
|
5846
|
-
retryable: false,
|
|
5847
|
-
cause
|
|
5848
|
-
};
|
|
5849
|
-
}
|
|
5850
|
-
function providerErrorToSubagentError(err, message, cause) {
|
|
5851
|
-
const status = err.status;
|
|
5852
|
-
if (status === 429 || err.body?.type === "rate_limit_error") {
|
|
5853
|
-
return {
|
|
5854
|
-
kind: "provider_rate_limit",
|
|
5855
|
-
message,
|
|
5856
|
-
retryable: true,
|
|
5857
|
-
// Conservative default: 5s. Provider-specific code can override
|
|
5858
|
-
// by emitting an error whose body carries an explicit hint.
|
|
5859
|
-
backoffMs: 5e3,
|
|
5860
|
-
cause
|
|
5861
|
-
};
|
|
5862
|
-
}
|
|
5863
|
-
if (status === 401 || status === 403 || err.body?.type === "authentication_error") {
|
|
5864
|
-
return { kind: "provider_auth", message, retryable: false, cause };
|
|
5865
|
-
}
|
|
5866
|
-
if (status === 408 || status === 0) {
|
|
5867
|
-
return { kind: "provider_timeout", message, retryable: true, cause };
|
|
5868
|
-
}
|
|
5869
|
-
if (status >= 500 && status < 600) {
|
|
5870
|
-
return {
|
|
5871
|
-
kind: "provider_5xx",
|
|
5872
|
-
message,
|
|
5873
|
-
retryable: true,
|
|
5874
|
-
backoffMs: 3e3,
|
|
5875
|
-
cause
|
|
5876
|
-
};
|
|
5877
|
-
}
|
|
5878
|
-
return { kind: "unknown", message, retryable: err.retryable, cause };
|
|
5879
|
-
}
|
|
5880
5868
|
|
|
5881
|
-
// src/coordination/director.ts
|
|
5869
|
+
// src/coordination/director/director-errors.ts
|
|
5882
5870
|
var FleetSpawnBudgetError = class extends Error {
|
|
5883
5871
|
kind;
|
|
5884
5872
|
limit;
|
|
@@ -5920,6 +5908,8 @@ var FleetContextOverflowError = class extends Error {
|
|
|
5920
5908
|
this.observed = observed;
|
|
5921
5909
|
}
|
|
5922
5910
|
};
|
|
5911
|
+
|
|
5912
|
+
// src/coordination/director.ts
|
|
5923
5913
|
var Director = class _Director {
|
|
5924
5914
|
/** Alias for the ICoordinator contract. `id` is retained for backward compatibility. */
|
|
5925
5915
|
get coordinatorId() {
|
|
@@ -6188,18 +6178,20 @@ var Director = class _Director {
|
|
|
6188
6178
|
if (e.subagentId.startsWith("bug-hunter-") || e.subagentId.startsWith("refactor-planner-") || e.subagentId.startsWith("critic-")) {
|
|
6189
6179
|
return;
|
|
6190
6180
|
}
|
|
6191
|
-
if (payload.kind === "timeout") {
|
|
6181
|
+
if (payload.kind === "timeout" || payload.kind === "idle_timeout") {
|
|
6182
|
+
const heartbeatKey = `${e.subagentId}:${payload.kind}`;
|
|
6192
6183
|
const progress = progressBySubagent.get(e.subagentId) ?? 0;
|
|
6193
|
-
const lastProgress = lastTimeoutProgress.get(
|
|
6184
|
+
const lastProgress = lastTimeoutProgress.get(heartbeatKey) ?? -1;
|
|
6194
6185
|
if (progress <= lastProgress) {
|
|
6195
6186
|
payload.deny();
|
|
6196
6187
|
return;
|
|
6197
6188
|
}
|
|
6198
|
-
lastTimeoutProgress.set(
|
|
6189
|
+
lastTimeoutProgress.set(heartbeatKey, progress);
|
|
6190
|
+
const field = payload.kind === "timeout" ? "timeoutMs" : "idleTimeoutMs";
|
|
6199
6191
|
setImmediate(() => {
|
|
6200
6192
|
const newLimit = Math.min(Math.ceil(payload.limit * 2), 24 * 60 * 6e4);
|
|
6201
|
-
this.recordExtension(e.subagentId, e.taskId,
|
|
6202
|
-
payload.extend({
|
|
6193
|
+
this.recordExtension(e.subagentId, e.taskId, payload.kind, newLimit);
|
|
6194
|
+
payload.extend({ [field]: newLimit });
|
|
6203
6195
|
});
|
|
6204
6196
|
return;
|
|
6205
6197
|
}
|
|
@@ -6515,10 +6507,9 @@ var Director = class _Director {
|
|
|
6515
6507
|
if (this.fleetManager) {
|
|
6516
6508
|
this.fleetManager.assignNicknameAndRecord(config);
|
|
6517
6509
|
} else {
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
);
|
|
6510
|
+
const { key, display } = assignNickname(role, this._usedNicknames);
|
|
6511
|
+
config.name = display;
|
|
6512
|
+
this._usedNicknames.add(key);
|
|
6522
6513
|
}
|
|
6523
6514
|
}
|
|
6524
6515
|
result = await this.coordinator.spawn(config);
|
|
@@ -6840,8 +6831,8 @@ var Director = class _Director {
|
|
|
6840
6831
|
} else {
|
|
6841
6832
|
const entry = this.manifestEntries.get(subagentId);
|
|
6842
6833
|
if (entry?.name) {
|
|
6843
|
-
const nicknameKey = entry.name
|
|
6844
|
-
this._usedNicknames.delete(nicknameKey);
|
|
6834
|
+
const nicknameKey = nicknameKeyFromDisplay(entry.name);
|
|
6835
|
+
if (nicknameKey) this._usedNicknames.delete(nicknameKey);
|
|
6845
6836
|
}
|
|
6846
6837
|
}
|
|
6847
6838
|
this.manifestEntries.delete(subagentId);
|
|
@@ -8453,11 +8444,10 @@ var FleetManager = class {
|
|
|
8453
8444
|
*/
|
|
8454
8445
|
assignNicknameAndRecord(config) {
|
|
8455
8446
|
const role = config.role ?? "subagent";
|
|
8456
|
-
const
|
|
8457
|
-
|
|
8458
|
-
|
|
8459
|
-
|
|
8460
|
-
return nickname;
|
|
8447
|
+
const { key, display } = assignNickname(role, this._usedNicknames);
|
|
8448
|
+
this._usedNicknames.add(key);
|
|
8449
|
+
config.name = display;
|
|
8450
|
+
return display;
|
|
8461
8451
|
}
|
|
8462
8452
|
/**
|
|
8463
8453
|
* Returns the set of already-assigned nickname keys — useful for debugging
|
|
@@ -8642,8 +8632,8 @@ var FleetManager = class {
|
|
|
8642
8632
|
removeSubagent(subagentId) {
|
|
8643
8633
|
const entry = this.manifestEntries.get(subagentId);
|
|
8644
8634
|
if (entry?.name) {
|
|
8645
|
-
const nicknameKey = entry.name
|
|
8646
|
-
this._usedNicknames.delete(nicknameKey);
|
|
8635
|
+
const nicknameKey = nicknameKeyFromDisplay(entry.name);
|
|
8636
|
+
if (nicknameKey) this._usedNicknames.delete(nicknameKey);
|
|
8647
8637
|
}
|
|
8648
8638
|
for (const [taskId, task] of this.pendingTasks) {
|
|
8649
8639
|
if (task.subagentId === subagentId) {
|