@wrongstack/core 0.309.0 → 0.310.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.
Files changed (129) hide show
  1. package/dist/chronicle/index.js +113 -41
  2. package/dist/chronicle/metrics-ingest.d.ts +7 -0
  3. package/dist/chronicle/metrics-schema.d.ts +4 -1
  4. package/dist/chronicle/project-server.js +94 -38
  5. package/dist/chronicle/query.d.ts +1 -0
  6. package/dist/chronicle/sqlite-journal-schema.d.ts +2 -1
  7. package/dist/chronicle/types.d.ts +2 -0
  8. package/dist/{agent-status-helpers.d.ts → coordination/agent-status-helpers.d.ts} +1 -1
  9. package/dist/{agent-status-tracker.d.ts → coordination/agent-status-tracker.d.ts} +2 -2
  10. package/dist/{middleware → coordination}/collab-pause.d.ts +1 -1
  11. package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -1
  12. package/dist/coordination/director.d.ts +7 -0
  13. package/dist/coordination/explore-companion.d.ts +9 -6
  14. package/dist/coordination/fleet-status-tool.d.ts +1 -1
  15. package/dist/coordination/index.d.ts +5 -1
  16. package/dist/coordination/index.js +2392 -405
  17. package/dist/coordination/kanban-dispatch-port.d.ts +30 -0
  18. package/dist/coordination/kanban-ops-port.d.ts +21 -0
  19. package/dist/coordination/mailbox-hooks.d.ts +1 -1
  20. package/dist/coordination/mailbox-project-server.js +14 -9
  21. package/dist/coordination/mutation-engine.d.ts +5 -3
  22. package/dist/core/context.d.ts +35 -44
  23. package/dist/core/conversation-state.d.ts +16 -52
  24. package/dist/core/index.js +92 -25
  25. package/dist/core/provider-runner.d.ts +2 -2
  26. package/dist/core/run-env.d.ts +7 -28
  27. package/dist/core/streaming-response-builder.d.ts +2 -2
  28. package/dist/execution/index.js +138 -162
  29. package/dist/goal/index.js +100 -22
  30. package/dist/hq/auth-store.d.ts +9 -0
  31. package/dist/hq/cost-bridge.d.ts +1 -1
  32. package/dist/hq/index.js +69 -7
  33. package/dist/index.d.ts +12 -5
  34. package/dist/index.js +21185 -26807
  35. package/dist/infrastructure/index.js +232 -135
  36. package/dist/infrastructure/provider-cache-ledger.d.ts +1 -1
  37. package/dist/infrastructure/token-counter.d.ts +5 -1
  38. package/dist/kernel/events/file-events.d.ts +6 -0
  39. package/dist/kernel/events/provider-events.d.ts +10 -7
  40. package/dist/kernel/events/session-events.d.ts +4 -4
  41. package/dist/kernel/events/tool-events.d.ts +12 -2
  42. package/dist/observability/index.js +1 -1
  43. package/dist/plugin/index.js +218 -47
  44. package/dist/prompts/index.js +360 -3
  45. package/dist/security/auto-approve-policy.d.ts +2 -2
  46. package/dist/security/index.d.ts +1 -0
  47. package/dist/security/index.js +224 -68
  48. package/dist/security/kanban-boundary.d.ts +1 -1
  49. package/dist/security/kanban-governance-port.d.ts +28 -0
  50. package/dist/security/permission-helpers.d.ts +11 -0
  51. package/dist/security/permission-policy.d.ts +10 -1
  52. package/dist/security/yolo-risk.d.ts +17 -0
  53. package/dist/session-catalog/index.js +34 -5
  54. package/dist/session-catalog/project-server.js +34 -5
  55. package/dist/session-catalog/protocol.d.ts +1 -1
  56. package/dist/session-catalog/registry.d.ts +1 -1
  57. package/dist/session-catalog/store-schema.d.ts +1 -1
  58. package/dist/session-catalog/store.d.ts +1 -1
  59. package/dist/skills/index.js +39 -6
  60. package/dist/storage/annotations-store.d.ts +1 -1
  61. package/dist/storage/board-store-port.d.ts +45 -0
  62. package/dist/storage/completed-work-checkpoint.d.ts +1 -1
  63. package/dist/storage/config-loader/types.d.ts +1 -1
  64. package/dist/storage/event-bus-port.d.ts +27 -0
  65. package/dist/storage/file-session-writer.d.ts +47 -5
  66. package/dist/storage/goal-coordination.d.ts +1 -1
  67. package/dist/storage/goal-store.d.ts +1 -1
  68. package/dist/storage/index.d.ts +3 -4
  69. package/dist/storage/index.js +1107 -1462
  70. package/dist/storage/plan-store.d.ts +1 -1
  71. package/dist/storage/queue-store.d.ts +1 -1
  72. package/dist/storage/replay-log-store.d.ts +1 -1
  73. package/dist/storage/session-recovery.d.ts +10 -0
  74. package/dist/storage/session-resume-validation.d.ts +13 -1
  75. package/dist/storage/session-store/events.d.ts +1 -1
  76. package/dist/storage/session-store/load-session-data.d.ts +1 -1
  77. package/dist/storage/session-store/rename-session.d.ts +1 -1
  78. package/dist/storage/session-store/resume-session.d.ts +3 -1
  79. package/dist/storage/session-store/session-store-index.d.ts +2 -1
  80. package/dist/storage/session-store/types.d.ts +1 -1
  81. package/dist/storage/session-store.d.ts +70 -0
  82. package/dist/storage/session-summary-tracker.d.ts +8 -0
  83. package/dist/storage/session-write-buffer.d.ts +31 -2
  84. package/dist/storage/task-store.d.ts +1 -1
  85. package/dist/storage/todos-checkpoint.d.ts +1 -1
  86. package/dist/storage/tool-audit-log.d.ts +1 -1
  87. package/dist/tasking/index.js +100 -22
  88. package/dist/tasking/task-tracker.d.ts +24 -1
  89. package/dist/types/compactor.d.ts +2 -2
  90. package/dist/types/context.d.ts +212 -0
  91. package/dist/types/conversation-state.d.ts +109 -0
  92. package/dist/types/error-handler.d.ts +2 -2
  93. package/dist/types/file-event-record.d.ts +6 -0
  94. package/dist/types/index.d.ts +3 -3
  95. package/dist/types/index.js +17 -1
  96. package/dist/types/permission.d.ts +3 -3
  97. package/dist/types/plugin.d.ts +3 -3
  98. package/dist/types/provider-runner.d.ts +2 -2
  99. package/dist/types/provider.d.ts +10 -0
  100. package/dist/types/run-env.d.ts +32 -0
  101. package/dist/types/session.d.ts +3 -0
  102. package/dist/types/slash-command.d.ts +2 -2
  103. package/dist/types/token-counter.d.ts +30 -1
  104. package/dist/types/tool-executor.d.ts +2 -2
  105. package/dist/types/tool.d.ts +20 -5
  106. package/dist/utils/context-breakdown.d.ts +2 -2
  107. package/dist/utils/context-evidence.d.ts +12 -12
  108. package/dist/utils/crash-shield.d.ts +9 -0
  109. package/dist/utils/heap-watchdog.js +11 -3
  110. package/dist/utils/index.d.ts +2 -1
  111. package/dist/utils/index.js +126 -160
  112. package/dist/utils/regex-guard.d.ts +7 -30
  113. package/dist/utils/terminal-sanitize.d.ts +41 -0
  114. package/dist/utils/todos-format.d.ts +1 -1
  115. package/dist/utils/tool-subject.d.ts +1 -1
  116. package/dist/utils/tree-kill.d.ts +2 -0
  117. package/dist/utils/tree-kill.js +1 -0
  118. package/instructions/agents/chaos-monkey.md +5 -1
  119. package/instructions/coordination/subagent-baseline.md +10 -0
  120. package/instructions/system-lite.md +2 -0
  121. package/instructions/system-pro.md +40 -0
  122. package/instructions/system.md +15 -0
  123. package/package.json +7 -10
  124. package/dist/defaults/index.d.ts +0 -69
  125. package/dist/defaults/index.js +0 -37755
  126. /package/dist/{fleet-notifier.d.ts → coordination/fleet-notifier.d.ts} +0 -0
  127. /package/dist/{session-registry-atomic-file.d.ts → session-catalog/session-registry-atomic-file.d.ts} +0 -0
  128. /package/dist/{session-registry-types.d.ts → session-catalog/session-registry-types.d.ts} +0 -0
  129. /package/dist/{session-registry.d.ts → session-catalog/session-registry.d.ts} +0 -0
@@ -207,6 +207,13 @@ var TaskTracker = class _TaskTracker {
207
207
  graph = null;
208
208
  transitions = [];
209
209
  listeners = [];
210
+ /**
211
+ * Re-entrancy guard for status cascades: true while an auto-block /
212
+ * auto-unblock cascade is running. Listener-driven mutations during a
213
+ * cascade still record their own primary transition — only their
214
+ * cascading is skipped (prevents unbounded recursion).
215
+ */
216
+ cascading = false;
210
217
  static MAX_TRANSITIONS = 1e4;
211
218
  /**
212
219
  * Subscribe to live task mutations (add / update / status change). Returns an
@@ -282,6 +289,28 @@ var TaskTracker = class _TaskTracker {
282
289
  message: "No graph loaded",
283
290
  code: ERROR_CODES.SDD_INVALID_STATE
284
291
  });
292
+ if (!this.graph.nodes.has(from) || !this.graph.nodes.has(to)) {
293
+ throw new SddError({
294
+ message: `Cannot add ${type} edge ${from} -> ${to}: endpoint task is not in the graph`,
295
+ code: ERROR_CODES.SDD_NOT_READY,
296
+ context: { from, to, type }
297
+ });
298
+ }
299
+ if (from === to) {
300
+ throw new SddError({
301
+ message: `Cannot add ${type} edge: self-loop on task ${from}`,
302
+ code: ERROR_CODES.SDD_INVALID_STATE,
303
+ context: { nodeId: from, type }
304
+ });
305
+ }
306
+ if (this.graph.edges.some((e) => e.from === from && e.to === to && e.type === type)) return;
307
+ if (type === "depends_on" && this.dependsOnTransitively(from, to, /* @__PURE__ */ new Set())) {
308
+ throw new SddError({
309
+ message: `Cannot add depends_on edge ${from} -> ${to}: it would create a dependency cycle`,
310
+ code: ERROR_CODES.SDD_INVALID_STATE,
311
+ context: { from, to }
312
+ });
313
+ }
285
314
  this.graph.edges.push({
286
315
  id: crypto.randomUUID(),
287
316
  from,
@@ -382,7 +411,7 @@ var TaskTracker = class _TaskTracker {
382
411
  if (status === "in_progress") {
383
412
  node.startedAt = now;
384
413
  }
385
- this.transitions.push({ from, to: status, timestamp: now, reason });
414
+ this.transitions.push({ nodeId: id, from, to: status, timestamp: now, reason });
386
415
  if (this.transitions.length > _TaskTracker.MAX_TRANSITIONS) {
387
416
  this.transitions.splice(0, this.transitions.length - _TaskTracker.MAX_TRANSITIONS);
388
417
  }
@@ -398,7 +427,7 @@ var TaskTracker = class _TaskTracker {
398
427
  type: "status_changed",
399
428
  nodeId: id,
400
429
  node,
401
- transition: { from, to: status, timestamp: now, reason }
430
+ transition: { nodeId: id, from, to: status, timestamp: now, reason }
402
431
  });
403
432
  }
404
433
  updateNode(id, patch) {
@@ -489,40 +518,89 @@ var TaskTracker = class _TaskTracker {
489
518
  }
490
519
  return computeTaskProgress(this.graph);
491
520
  }
492
- getTransitions(_taskId) {
493
- return [...this.transitions];
521
+ /**
522
+ * Recorded transitions in insertion order (oldest first — the array is
523
+ * trimmed from the front). With `taskId`, only that task's transitions are
524
+ * returned, still oldest-first; a consumer wanting newest-first reverses
525
+ * the result. Per-task filtering is possible because every TaskTransition
526
+ * carries `nodeId` (BIZ-005).
527
+ */
528
+ getTransitions(taskId) {
529
+ return taskId === void 0 ? [...this.transitions] : this.transitions.filter((t) => t.nodeId === taskId);
530
+ }
531
+ /**
532
+ * Record a cascade-driven status change (BIZ-003): mutate the node, push a
533
+ * TaskTransition, persist, and notify subscribers — the same effects an
534
+ * explicit updateNodeStatus produces — so the board projector's live
535
+ * snapshot and the transition log observe auto-block/auto-unblock.
536
+ */
537
+ recordCascadeStatusChange(nodeId, node, to, reason) {
538
+ const from = node.status;
539
+ if (from === to) return;
540
+ const now = Date.now();
541
+ node.status = to;
542
+ node.updatedAt = now;
543
+ if (this.graph) this.graph.updatedAt = now;
544
+ this.transitions.push({ nodeId, from, to, timestamp: now, reason });
545
+ if (this.transitions.length > _TaskTracker.MAX_TRANSITIONS) {
546
+ this.transitions.splice(0, this.transitions.length - _TaskTracker.MAX_TRANSITIONS);
547
+ }
548
+ this.persist();
549
+ this.notifyChange({
550
+ type: "status_changed",
551
+ nodeId,
552
+ node,
553
+ transition: { nodeId, from, to, timestamp: now, reason }
554
+ });
494
555
  }
495
556
  unblockDependents(completedId) {
496
- if (!this.graph) return;
497
- const dependents = this.getDependents(completedId);
498
- for (const depId of dependents) {
499
- const dep = this.graph.nodes.get(depId);
500
- if (dep?.status === "blocked") {
557
+ if (!this.graph || this.cascading) return;
558
+ this.cascading = true;
559
+ try {
560
+ const dependents = this.getDependents(completedId);
561
+ for (const depId of dependents) {
562
+ const dep = this.graph.nodes.get(depId);
563
+ if (dep?.status !== "blocked") continue;
501
564
  const remainingBlockers = this.getBlockers(depId);
502
565
  const allUnblocked = remainingBlockers.every((id) => {
503
566
  const blocker = this.graph?.nodes.get(id);
504
567
  return blocker?.status === "completed" || blocker?.status === "failed";
505
568
  });
506
569
  if (allUnblocked) {
507
- dep.status = "pending";
508
- dep.updatedAt = Date.now();
570
+ this.recordCascadeStatusChange(
571
+ depId,
572
+ dep,
573
+ "pending",
574
+ `auto-unblocked: blocker ${completedId} reached a terminal state`
575
+ );
509
576
  }
510
577
  }
578
+ } finally {
579
+ this.cascading = false;
511
580
  }
512
581
  }
513
582
  checkAndBlockIfNeeded(taskId) {
514
- if (!this.graph) return;
515
- const blockers = this.getBlockers(taskId);
516
- const someBlocked = blockers.some((id) => {
517
- const blocker = this.graph?.nodes.get(id);
518
- return blocker?.status !== "completed" && blocker?.status !== "failed";
519
- });
520
- if (someBlocked) {
521
- const node = this.graph.nodes.get(taskId);
522
- if (node) {
523
- node.status = "blocked";
524
- node.updatedAt = Date.now();
583
+ if (!this.graph || this.cascading) return;
584
+ this.cascading = true;
585
+ try {
586
+ const blockers = this.getBlockers(taskId);
587
+ const incomplete = blockers.filter((id) => {
588
+ const blocker = this.graph?.nodes.get(id);
589
+ return blocker?.status !== "completed" && blocker?.status !== "failed";
590
+ });
591
+ if (incomplete.length > 0) {
592
+ const node = this.graph.nodes.get(taskId);
593
+ if (node) {
594
+ this.recordCascadeStatusChange(
595
+ taskId,
596
+ node,
597
+ "blocked",
598
+ `auto-blocked: incomplete blocker(s) ${incomplete.join(", ")}`
599
+ );
600
+ }
525
601
  }
602
+ } finally {
603
+ this.cascading = false;
526
604
  }
527
605
  }
528
606
  /**
@@ -167,6 +167,15 @@ export interface HqAuthFile {
167
167
  * reveal unused codes. Each code is consumed on first successful use.
168
168
  */
169
169
  totpRecoveryCodes?: string[];
170
+ /**
171
+ * Highest TOTP time-step counter already consumed by a successful 2FA
172
+ * verification (SEC-002: persisted to prevent replay after restart).
173
+ * Written by the 2FA verification route (`totp-routes.ts`) — not the
174
+ * initial password check — and read there to reject any counter <= this
175
+ * value, so an observed code cannot be replayed within its validity
176
+ * window even across a server restart.
177
+ */
178
+ totpLastUsedCounter?: number;
170
179
  /**
171
180
  * Operator-configured alert-rule thresholds. When present, these override
172
181
  * the built-in defaults for the alert engine (cost ceiling, stale-machine
@@ -16,8 +16,8 @@
16
16
  * @module hq/cost-bridge
17
17
  */
18
18
  import type { EventBus } from '../kernel/events.js';
19
- import type { HqEventEnvelope } from './protocol.js';
20
19
  import { type BridgeContextOptions } from './bridge-context.js';
20
+ import type { HqEventEnvelope } from './protocol.js';
21
21
  export interface CostTelemetryBridgeOptions extends BridgeContextOptions {
22
22
  /** Local EventBus emitting `token.accounted`. */
23
23
  events: EventBus;
package/dist/hq/index.js CHANGED
@@ -702,6 +702,14 @@ var PATTERNS = [
702
702
  anchor: "sk-ant-"
703
703
  },
704
704
  { type: "openai_key", regex: /(?<![A-Za-z0-9])sk-(?:proj-)?[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g, anchor: "sk-" },
705
+ {
706
+ // `xai` is a first-class provider in this codebase, but its key shape was
707
+ // absent here — so the one credential format WrongStack itself hands users
708
+ // was the one the scrubber could not recognize (audit 2026-08-20).
709
+ type: "xai_key",
710
+ regex: /(?<![A-Za-z0-9])xai-[A-Za-z0-9]{20,}(?![A-Za-z0-9])/g,
711
+ anchor: "xai-"
712
+ },
705
713
  { type: "github_pat", regex: /(?<![A-Za-z0-9])ghp_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g, anchor: "ghp_" },
706
714
  { type: "github_pat_v2", regex: /(?<![A-Za-z0-9])github_pat_[A-Za-z0-9_]{50,}(?![A-Za-z0-9])/g, anchor: "github_pat_" },
707
715
  { type: "aws_access_key", regex: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{16}(?![A-Za-z0-9])/g, anchor: "AKIA" },
@@ -792,8 +800,8 @@ var PATTERNS = [
792
800
  // replacement so the separator between adjacent secrets is preserved
793
801
  // rather than collapsed. Capture groups are therefore: 1=leading
794
802
  // delimiter, 2=key name, 3=value.
795
- regex: /(^|\s)([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,512})['"]?(?=\s|$)/g,
796
- anchor: ["KEY", "TOKEN", "SECRET", "PASSWORD", "PWD"]
803
+ regex: /(^|\s)([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD|PASSPHRASE))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,512})['"]?(?=\s|$)/g,
804
+ anchor: ["KEY", "TOKEN", "SECRET", "PASSWORD", "PWD", "PASSPHRASE"]
797
805
  },
798
806
  {
799
807
  type: "json_credential_key",
@@ -910,6 +918,27 @@ var JSON_CREDENTIAL_REGEX = PATTERNS.find((p) => p.type === "json_credential_key
910
918
  var COMBINED_REPLACEMENTS = SIMPLE_PATTERNS.map((p) => `[REDACTED:${p.type}]`);
911
919
  var SCRUB_CHUNK_BYTES = 64 * 1024;
912
920
  var SCRUB_OVERLAP_BYTES = 1024;
921
+ var PEM_PRIVATE_KEY_BEGIN_RE = /-----BEGIN (?:RSA|EC|OPENSSH|DSA|PGP)? ?PRIVATE KEY-----/;
922
+ var PEM_END_MARKER = "-----END";
923
+ var MAX_PEM_BLOCK_BYTES = 64 * 1024;
924
+ var PEM_END_LINE_TOLERANCE = 64;
925
+ function extendChunkBoundaryPastPem(text, chunkStart, proposedEnd) {
926
+ const head = text.slice(chunkStart, proposedEnd);
927
+ const lastBegin = head.lastIndexOf("-----BEGIN ");
928
+ if (lastBegin === -1) return proposedEnd;
929
+ const fromBegin = text.slice(chunkStart + lastBegin);
930
+ const marker = PEM_PRIVATE_KEY_BEGIN_RE.exec(fromBegin);
931
+ if (!marker || marker.index !== 0) return proposedEnd;
932
+ const bodyStart = marker[0].length;
933
+ const cap = Math.min(text.length, chunkStart + lastBegin + MAX_PEM_BLOCK_BYTES);
934
+ const closeIdx = fromBegin.indexOf(PEM_END_MARKER, bodyStart);
935
+ if (closeIdx === -1 || chunkStart + lastBegin + closeIdx >= cap + PEM_END_LINE_TOLERANCE) {
936
+ return proposedEnd;
937
+ }
938
+ const lineEnd = fromBegin.indexOf("\n", closeIdx);
939
+ const end = lineEnd === -1 ? text.length : chunkStart + lastBegin + lineEnd + 1;
940
+ return Math.max(proposedEnd, end);
941
+ }
913
942
  var PATTERN_ANCHORS = [
914
943
  ...new Set(
915
944
  PATTERNS.flatMap(
@@ -946,6 +975,7 @@ var DefaultSecretScrubber = class {
946
975
  }
947
976
  }
948
977
  end = safe === -1 ? end : safe + 1;
978
+ end = extendChunkBoundaryPastPem(text, i, end);
949
979
  }
950
980
  out.push(this.scrubOne(text.slice(i, end)));
951
981
  i = end;
@@ -2348,6 +2378,7 @@ function hqAuthContentHash(file) {
2348
2378
  ...file.totpSecret !== void 0 ? { totpSecret: REDACTED } : {},
2349
2379
  ...file.totpPendingSecret !== void 0 ? { totpPendingSecret: REDACTED } : {},
2350
2380
  ...file.totpRecoveryCodes !== void 0 ? { totpRecoveryCodes: file.totpRecoveryCodes.map(() => REDACTED) } : {},
2381
+ ...file.totpLastUsedCounter !== void 0 ? { totpLastUsedCounter: file.totpLastUsedCounter } : {},
2351
2382
  ...file.alertRules !== void 0 ? { alertRules: file.alertRules } : {}
2352
2383
  };
2353
2384
  const payload = JSON.stringify(projection);
@@ -3080,6 +3111,15 @@ function deriveSessionStatus(agents) {
3080
3111
  (a) => a.status === "running" || a.status === "streaming" || a.status === "waiting_user"
3081
3112
  ) ? "active" : "idle";
3082
3113
  }
3114
+ function downgradeStaleAgentStatuses(agents, nowMs) {
3115
+ const cutoff = nowMs - HQ_STALE_SNAPSHOT_WINDOW_MS;
3116
+ return agents.map((agent) => {
3117
+ if (agent.status !== "running" && agent.status !== "streaming") return agent;
3118
+ const lastActivityAt = Date.parse(agent.lastActivityAt);
3119
+ if (!Number.isFinite(lastActivityAt) || lastActivityAt >= cutoff) return agent;
3120
+ return { ...agent, status: "idle" };
3121
+ });
3122
+ }
3083
3123
  function startSessionTelemetryBridge(opts) {
3084
3124
  const now = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
3085
3125
  const publisher = opts.publisher;
@@ -3100,6 +3140,7 @@ function startSessionTelemetryBridge(opts) {
3100
3140
  let lastPublishedAtMs = Date.now();
3101
3141
  let disposed = false;
3102
3142
  function buildSnapshot() {
3143
+ const effectiveAgents = downgradeStaleAgentStatuses(agents, Date.parse(now()));
3103
3144
  return {
3104
3145
  sessionId: opts.sessionId,
3105
3146
  clientKind: identity.kind,
@@ -3107,11 +3148,11 @@ function startSessionTelemetryBridge(opts) {
3107
3148
  projectId: project.projectId,
3108
3149
  projectName: opts.projectName ?? project.projectName,
3109
3150
  projectRoot: opts.projectRoot,
3110
- status: deriveSessionStatus(agents),
3151
+ status: deriveSessionStatus(effectiveAgents),
3111
3152
  startedAt,
3112
3153
  lastActivityAt,
3113
- agentCount: agents.length,
3114
- agents,
3154
+ agentCount: effectiveAgents.length,
3155
+ agents: effectiveAgents,
3115
3156
  ...identity.hostname !== void 0 ? { hostname: identity.hostname } : {},
3116
3157
  ...identity.pid !== void 0 ? { pid: identity.pid } : {},
3117
3158
  ...opts.gitBranch !== void 0 ? { gitBranch: opts.gitBranch } : {}
@@ -3643,16 +3684,37 @@ function truncateForSummary(output, policy, max = 280) {
3643
3684
  return scrubAndTruncateHqPreview(output, limit) ?? "";
3644
3685
  }
3645
3686
 
3687
+ // src/types/provider.ts
3688
+ function effectiveInputTokens(usage) {
3689
+ return usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
3690
+ }
3691
+ var MAX_RESET_HINT_MS = 7 * 24 * 60 * 60 * 1e3;
3692
+ var KIND_TO_CODE = {
3693
+ network: ERROR_CODES.PROVIDER_NETWORK_ERROR,
3694
+ timeout: ERROR_CODES.PROVIDER_NETWORK_ERROR,
3695
+ rate_limit: ERROR_CODES.PROVIDER_RATE_LIMITED,
3696
+ quota_exhausted: ERROR_CODES.PROVIDER_RATE_LIMITED,
3697
+ auth: ERROR_CODES.PROVIDER_AUTH_FAILED,
3698
+ overloaded: ERROR_CODES.PROVIDER_OVERLOADED,
3699
+ context_overflow: ERROR_CODES.PROVIDER_CONTEXT_OVERFLOW,
3700
+ server: ERROR_CODES.PROVIDER_SERVER_ERROR,
3701
+ stream_hang: ERROR_CODES.PROVIDER_SERVER_ERROR,
3702
+ content_filter: ERROR_CODES.PROVIDER_INVALID_REQUEST,
3703
+ invalid_request: ERROR_CODES.PROVIDER_INVALID_REQUEST,
3704
+ unknown: ERROR_CODES.PROVIDER_INVALID_REQUEST
3705
+ };
3706
+
3646
3707
  // src/hq/cost-bridge.ts
3647
3708
  function startCostTelemetryBridge(opts) {
3648
3709
  const { events } = opts;
3649
3710
  const ctx = createBridgeContext(opts);
3650
3711
  const off = events.on("token.accounted", (p) => {
3651
3712
  const usage = p.deltaUsage ?? p.usage;
3713
+ const totalPromptTokens = effectiveInputTokens(usage);
3652
3714
  const payload = {
3653
- inputTokens: usage.input,
3715
+ inputTokens: totalPromptTokens,
3654
3716
  outputTokens: usage.output,
3655
- totalTokens: usage.input + usage.output,
3717
+ totalTokens: totalPromptTokens + usage.output,
3656
3718
  costUsd: p.cost.total
3657
3719
  };
3658
3720
  if (p.provider !== void 0) payload.provider = p.provider;
package/dist/index.d.ts CHANGED
@@ -61,8 +61,15 @@ export { buildQueuedMessagesBlock, consumeQueuedMessagesUpdate, peekQueuedMessag
61
61
  export { extractRunEnv, type RunEnv } from './core/run-env.js';
62
62
  export { DefaultSystemPromptBuilder, type DefaultSystemPromptBuilderOptions, LAYER_1_IDENTITY, SYSTEM_BLOCK_SOURCE, type SystemBlockSource, } from './core/system-prompt-builder.js';
63
63
  export { type DomainGlossaryOptions, renderDomainGlossary, } from './core/system-prompt-glossary.js';
64
- export * from './defaults/index.js';
65
- export { AutoCompactionMiddleware, type CompactorOptions, type CompactorStrategy, createStrategyCompactor, HybridCompactor, IntelligentCompactor, type IntelligentCompactorOptions, installSubagentAutoCompaction, SelectiveCompactor, type SelectiveCompactorOptions, type StrategyCompactorOptions, } from './defaults/index.js';
64
+ export { AutoCompactionMiddleware } from './execution/auto-compaction-middleware.js';
65
+ export { DefaultErrorHandler } from './execution/error-handler.js';
66
+ export { DefaultSkillLoader, type SkillLoaderOptions } from './execution/skill-loader.js';
67
+ export { DefaultLogger, type DefaultLoggerOptions, type LogFormat, } from './infrastructure/logger.js';
68
+ export { type CompactorOptions, HybridCompactor } from './execution/compactor.js';
69
+ export { type CompactorStrategy, createStrategyCompactor, type StrategyCompactorOptions, } from './execution/strategy-compactor.js';
70
+ export { IntelligentCompactor, type IntelligentCompactorOptions, } from './execution/intelligent-compactor.js';
71
+ export { installSubagentAutoCompaction } from './execution/subagent-compaction.js';
72
+ export { SelectiveCompactor, type SelectiveCompactorOptions, } from './execution/selective-compactor.js';
66
73
  export { type AutonomyBrainOptions, type BrainAutoRisk, type BrainLlmTarget, buildBrainUserMessage, completeBrainLlm, createAutonomyBrain, createTieredBrainArbiter, formatDecisionSummary, parseOptionDecision, type TieredBrainArbiterOptions, } from './execution/autonomy-brain.js';
67
74
  export { assembleBrainTiers, type BrainTierAssembly, type BrainTierAssemblyOptions, } from './execution/brain-chain.js';
68
75
  export { BrainCircuitBreaker, type BrainCircuitOptions, type BrainCircuitSnapshot, type BrainCircuitState, } from './execution/brain-circuit.js';
@@ -87,7 +94,7 @@ export { allServers } from './infrastructure/mcp-servers.js';
87
94
  export { type ProviderCacheEntry, ProviderCacheLedger, } from './infrastructure/provider-cache-ledger.js';
88
95
  export * from './kernel/index.js';
89
96
  export { attachMailboxChecker } from './mailbox-attach.js';
90
- export { type CollabPauseMiddlewareOptions, collabInjectMiddleware, collabPauseMiddleware, type InjectedToolResult as CollabInjectedToolResult, } from './middleware/collab-pause.js';
97
+ export { type CollabPauseMiddlewareOptions, collabInjectMiddleware, collabPauseMiddleware, type InjectedToolResult as CollabInjectedToolResult, } from './coordination/collab-pause.js';
91
98
  export { type NotificationChannel, type NotificationChannelStatus, type NotificationLevel, type NotificationMessage, type NotificationResult, type Notifier, type NotifierCounters, NotifierImpl, } from './notifications/index.js';
92
99
  export * from './observability/network-telemetry.js';
93
100
  export * from './observability/process-telemetry.js';
@@ -121,7 +128,7 @@ export { TRUST_POLICY_JSON_SCHEMA, TRUST_POLICY_LIMITS, TRUST_POLICY_SCHEMA_VERS
121
128
  export { DefaultSecretScrubber } from './security/secret-scrubber.js';
122
129
  export * from './session-catalog/index.js';
123
130
  export { getProjectSessionRegistry as getSessionRegistry, hasProjectSessionRegistry as hasSessionRegistry, ProjectSessionRegistry as SessionRegistry, } from './session-catalog/registry.js';
124
- export type { SessionLiveStatus, SessionRegistryEntry, } from './session-registry.js';
131
+ export type { SessionLiveStatus, SessionRegistryEntry, } from './session-catalog/session-registry.js';
125
132
  export * from './skills/index.js';
126
133
  export * from './storage/index.js';
127
134
  export { type AuditLevel, createSessionEventBridge, resolveAuditLevel, resolveSessionLoggingConfig, type SessionEventBridge, type SessionEventBridgeOptions, type SessionSamplingOptions, type ToolProgressSamplingOptions, } from './storage/session-event-bridge.js';
@@ -144,7 +151,7 @@ export type { ProviderRunner, RunProviderOptions } from './types/provider-runner
144
151
  export type { SecretScrubber } from './types/secret-scrubber.js';
145
152
  export type { RotatableSecretVault, SecretVault } from './types/secret-vault.js';
146
153
  export { encryptedPrefixForVersion, noOpVault, parseEncryptedVersion, } from './types/secret-vault.js';
147
- export type { CacheStats, TokenCounter } from './types/token-counter.js';
154
+ export type { CacheStats, ProviderCacheStats, TokenCounter } from './types/token-counter.js';
148
155
  export { expectDefined } from './utils/expect-defined.js';
149
156
  export * from './utils/index.js';
150
157
  export { readBundledInstructionText, renderInstructionTemplate, } from './utils/instruction-file.js';