opencode-swarm-plugin 0.56.0 → 0.57.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 (186) hide show
  1. package/README.md +21 -0
  2. package/claude-plugin/.claude-plugin/plugin.json +1 -4
  3. package/claude-plugin/agents/background-worker.md +1 -0
  4. package/claude-plugin/agents/coordinator.md +1 -0
  5. package/claude-plugin/agents/worker.md +1 -0
  6. package/claude-plugin/bin/swarm-mcp-server.ts +47 -8
  7. package/claude-plugin/commands/hive.md +1 -1
  8. package/claude-plugin/commands/swarm.md +5 -1
  9. package/claude-plugin/dist/agent-mail.d.ts +480 -0
  10. package/claude-plugin/dist/agent-mail.d.ts.map +1 -0
  11. package/claude-plugin/dist/anti-patterns.d.ts +257 -0
  12. package/claude-plugin/dist/anti-patterns.d.ts.map +1 -0
  13. package/claude-plugin/dist/bin/swarm.js +373128 -0
  14. package/claude-plugin/dist/cass-tools.d.ts +74 -0
  15. package/claude-plugin/dist/cass-tools.d.ts.map +1 -0
  16. package/claude-plugin/dist/claude-plugin/claude-plugin-assets.d.ts +10 -0
  17. package/claude-plugin/dist/claude-plugin/claude-plugin-assets.d.ts.map +1 -0
  18. package/claude-plugin/dist/compaction-hook.d.ts +178 -0
  19. package/claude-plugin/dist/compaction-hook.d.ts.map +1 -0
  20. package/claude-plugin/dist/compaction-observability.d.ts +173 -0
  21. package/claude-plugin/dist/compaction-observability.d.ts.map +1 -0
  22. package/claude-plugin/dist/compaction-prompt-scoring.d.ts +125 -0
  23. package/claude-plugin/dist/compaction-prompt-scoring.d.ts.map +1 -0
  24. package/claude-plugin/dist/compaction-prompt-scoring.js +139 -0
  25. package/claude-plugin/dist/contributor-tools.d.ts +42 -0
  26. package/claude-plugin/dist/contributor-tools.d.ts.map +1 -0
  27. package/claude-plugin/dist/coordinator-guard.d.ts +79 -0
  28. package/claude-plugin/dist/coordinator-guard.d.ts.map +1 -0
  29. package/claude-plugin/dist/dashboard.d.ts +82 -0
  30. package/claude-plugin/dist/dashboard.d.ts.map +1 -0
  31. package/claude-plugin/dist/decision-trace-integration.d.ts +204 -0
  32. package/claude-plugin/dist/decision-trace-integration.d.ts.map +1 -0
  33. package/claude-plugin/dist/error-enrichment.d.ts +49 -0
  34. package/claude-plugin/dist/error-enrichment.d.ts.map +1 -0
  35. package/claude-plugin/dist/eval-capture.d.ts +494 -0
  36. package/claude-plugin/dist/eval-capture.d.ts.map +1 -0
  37. package/claude-plugin/dist/eval-capture.js +12844 -0
  38. package/claude-plugin/dist/eval-gates.d.ts +84 -0
  39. package/claude-plugin/dist/eval-gates.d.ts.map +1 -0
  40. package/claude-plugin/dist/eval-history.d.ts +117 -0
  41. package/claude-plugin/dist/eval-history.d.ts.map +1 -0
  42. package/claude-plugin/dist/eval-learning.d.ts +216 -0
  43. package/claude-plugin/dist/eval-learning.d.ts.map +1 -0
  44. package/claude-plugin/dist/eval-runner.d.ts +134 -0
  45. package/claude-plugin/dist/eval-runner.d.ts.map +1 -0
  46. package/claude-plugin/dist/examples/plugin-wrapper-template.ts +3341 -0
  47. package/claude-plugin/dist/export-tools.d.ts +76 -0
  48. package/claude-plugin/dist/export-tools.d.ts.map +1 -0
  49. package/claude-plugin/dist/hive.d.ts +949 -0
  50. package/claude-plugin/dist/hive.d.ts.map +1 -0
  51. package/claude-plugin/dist/hive.js +15009 -0
  52. package/claude-plugin/dist/hivemind-tools.d.ts +479 -0
  53. package/claude-plugin/dist/hivemind-tools.d.ts.map +1 -0
  54. package/claude-plugin/dist/hooks/atomic-write.d.ts +21 -0
  55. package/claude-plugin/dist/hooks/atomic-write.d.ts.map +1 -0
  56. package/claude-plugin/dist/hooks/constants.d.ts +28 -0
  57. package/claude-plugin/dist/hooks/constants.d.ts.map +1 -0
  58. package/claude-plugin/dist/hooks/index.d.ts +16 -0
  59. package/claude-plugin/dist/hooks/index.d.ts.map +1 -0
  60. package/claude-plugin/dist/hooks/session-start.d.ts +30 -0
  61. package/claude-plugin/dist/hooks/session-start.d.ts.map +1 -0
  62. package/claude-plugin/dist/hooks/tool-complete.d.ts +54 -0
  63. package/claude-plugin/dist/hooks/tool-complete.d.ts.map +1 -0
  64. package/claude-plugin/dist/index.d.ts +2017 -0
  65. package/claude-plugin/dist/index.d.ts.map +1 -0
  66. package/claude-plugin/dist/index.js +73453 -0
  67. package/claude-plugin/dist/learning.d.ts +700 -0
  68. package/claude-plugin/dist/learning.d.ts.map +1 -0
  69. package/claude-plugin/dist/logger.d.ts +38 -0
  70. package/claude-plugin/dist/logger.d.ts.map +1 -0
  71. package/claude-plugin/dist/mandate-promotion.d.ts +93 -0
  72. package/claude-plugin/dist/mandate-promotion.d.ts.map +1 -0
  73. package/claude-plugin/dist/mandate-storage.d.ts +209 -0
  74. package/claude-plugin/dist/mandate-storage.d.ts.map +1 -0
  75. package/claude-plugin/dist/mandates.d.ts +230 -0
  76. package/claude-plugin/dist/mandates.d.ts.map +1 -0
  77. package/claude-plugin/dist/memory-tools.d.ts +281 -0
  78. package/claude-plugin/dist/memory-tools.d.ts.map +1 -0
  79. package/claude-plugin/dist/memory.d.ts +164 -0
  80. package/claude-plugin/dist/memory.d.ts.map +1 -0
  81. package/claude-plugin/dist/model-selection.d.ts +37 -0
  82. package/claude-plugin/dist/model-selection.d.ts.map +1 -0
  83. package/claude-plugin/dist/observability-health.d.ts +87 -0
  84. package/claude-plugin/dist/observability-health.d.ts.map +1 -0
  85. package/claude-plugin/dist/observability-tools.d.ts +184 -0
  86. package/claude-plugin/dist/observability-tools.d.ts.map +1 -0
  87. package/claude-plugin/dist/output-guardrails.d.ts +125 -0
  88. package/claude-plugin/dist/output-guardrails.d.ts.map +1 -0
  89. package/claude-plugin/dist/pattern-maturity.d.ts +246 -0
  90. package/claude-plugin/dist/pattern-maturity.d.ts.map +1 -0
  91. package/claude-plugin/dist/planning-guardrails.d.ts +183 -0
  92. package/claude-plugin/dist/planning-guardrails.d.ts.map +1 -0
  93. package/claude-plugin/dist/plugin.d.ts +22 -0
  94. package/claude-plugin/dist/plugin.d.ts.map +1 -0
  95. package/claude-plugin/dist/plugin.js +72295 -0
  96. package/claude-plugin/dist/post-compaction-tracker.d.ts +133 -0
  97. package/claude-plugin/dist/post-compaction-tracker.d.ts.map +1 -0
  98. package/claude-plugin/dist/query-tools.d.ts +90 -0
  99. package/claude-plugin/dist/query-tools.d.ts.map +1 -0
  100. package/claude-plugin/dist/rate-limiter.d.ts +218 -0
  101. package/claude-plugin/dist/rate-limiter.d.ts.map +1 -0
  102. package/claude-plugin/dist/regression-detection.d.ts +58 -0
  103. package/claude-plugin/dist/regression-detection.d.ts.map +1 -0
  104. package/claude-plugin/dist/replay-tools.d.ts +28 -0
  105. package/claude-plugin/dist/replay-tools.d.ts.map +1 -0
  106. package/claude-plugin/dist/repo-crawl.d.ts +146 -0
  107. package/claude-plugin/dist/repo-crawl.d.ts.map +1 -0
  108. package/claude-plugin/dist/schemas/cell-events.d.ts +1352 -0
  109. package/claude-plugin/dist/schemas/cell-events.d.ts.map +1 -0
  110. package/claude-plugin/dist/schemas/cell.d.ts +413 -0
  111. package/claude-plugin/dist/schemas/cell.d.ts.map +1 -0
  112. package/claude-plugin/dist/schemas/evaluation.d.ts +161 -0
  113. package/claude-plugin/dist/schemas/evaluation.d.ts.map +1 -0
  114. package/claude-plugin/dist/schemas/index.d.ts +46 -0
  115. package/claude-plugin/dist/schemas/index.d.ts.map +1 -0
  116. package/claude-plugin/dist/schemas/mandate.d.ts +336 -0
  117. package/claude-plugin/dist/schemas/mandate.d.ts.map +1 -0
  118. package/claude-plugin/dist/schemas/swarm-context.d.ts +131 -0
  119. package/claude-plugin/dist/schemas/swarm-context.d.ts.map +1 -0
  120. package/claude-plugin/dist/schemas/task.d.ts +189 -0
  121. package/claude-plugin/dist/schemas/task.d.ts.map +1 -0
  122. package/claude-plugin/dist/schemas/worker-handoff.d.ts +78 -0
  123. package/claude-plugin/dist/schemas/worker-handoff.d.ts.map +1 -0
  124. package/claude-plugin/dist/sessions/agent-discovery.d.ts +59 -0
  125. package/claude-plugin/dist/sessions/agent-discovery.d.ts.map +1 -0
  126. package/claude-plugin/dist/sessions/index.d.ts +10 -0
  127. package/claude-plugin/dist/sessions/index.d.ts.map +1 -0
  128. package/claude-plugin/dist/skills.d.ts +490 -0
  129. package/claude-plugin/dist/skills.d.ts.map +1 -0
  130. package/claude-plugin/dist/storage.d.ts +260 -0
  131. package/claude-plugin/dist/storage.d.ts.map +1 -0
  132. package/claude-plugin/dist/structured.d.ts +206 -0
  133. package/claude-plugin/dist/structured.d.ts.map +1 -0
  134. package/claude-plugin/dist/swarm-adversarial-review.d.ts +104 -0
  135. package/claude-plugin/dist/swarm-adversarial-review.d.ts.map +1 -0
  136. package/claude-plugin/dist/swarm-decompose.d.ts +297 -0
  137. package/claude-plugin/dist/swarm-decompose.d.ts.map +1 -0
  138. package/claude-plugin/dist/swarm-insights.d.ts +390 -0
  139. package/claude-plugin/dist/swarm-insights.d.ts.map +1 -0
  140. package/claude-plugin/dist/swarm-mail.d.ts +274 -0
  141. package/claude-plugin/dist/swarm-mail.d.ts.map +1 -0
  142. package/claude-plugin/dist/swarm-orchestrate.d.ts +924 -0
  143. package/claude-plugin/dist/swarm-orchestrate.d.ts.map +1 -0
  144. package/claude-plugin/dist/swarm-prompts.d.ts +467 -0
  145. package/claude-plugin/dist/swarm-prompts.d.ts.map +1 -0
  146. package/claude-plugin/dist/swarm-prompts.js +45283 -0
  147. package/claude-plugin/dist/swarm-research.d.ts +125 -0
  148. package/claude-plugin/dist/swarm-research.d.ts.map +1 -0
  149. package/claude-plugin/dist/swarm-review.d.ts +214 -0
  150. package/claude-plugin/dist/swarm-review.d.ts.map +1 -0
  151. package/claude-plugin/dist/swarm-signature.d.ts +106 -0
  152. package/claude-plugin/dist/swarm-signature.d.ts.map +1 -0
  153. package/claude-plugin/dist/swarm-strategies.d.ts +113 -0
  154. package/claude-plugin/dist/swarm-strategies.d.ts.map +1 -0
  155. package/claude-plugin/dist/swarm-validation.d.ts +127 -0
  156. package/claude-plugin/dist/swarm-validation.d.ts.map +1 -0
  157. package/claude-plugin/dist/swarm-worktree.d.ts +185 -0
  158. package/claude-plugin/dist/swarm-worktree.d.ts.map +1 -0
  159. package/claude-plugin/dist/swarm.d.ts +590 -0
  160. package/claude-plugin/dist/swarm.d.ts.map +1 -0
  161. package/claude-plugin/dist/tool-availability.d.ts +91 -0
  162. package/claude-plugin/dist/tool-availability.d.ts.map +1 -0
  163. package/claude-plugin/dist/utils/tree-renderer.d.ts +61 -0
  164. package/claude-plugin/dist/utils/tree-renderer.d.ts.map +1 -0
  165. package/claude-plugin/dist/validators/index.d.ts +7 -0
  166. package/claude-plugin/dist/validators/index.d.ts.map +1 -0
  167. package/claude-plugin/dist/validators/schema-validator.d.ts +58 -0
  168. package/claude-plugin/dist/validators/schema-validator.d.ts.map +1 -0
  169. package/claude-plugin/skills/always-on-guidance/SKILL.md +44 -0
  170. package/dist/agent-mail.d.ts +4 -4
  171. package/dist/agent-mail.d.ts.map +1 -1
  172. package/dist/bin/swarm.js +477 -22
  173. package/dist/claude-plugin/claude-plugin-assets.d.ts +10 -0
  174. package/dist/claude-plugin/claude-plugin-assets.d.ts.map +1 -0
  175. package/dist/compaction-hook.d.ts +1 -1
  176. package/dist/compaction-hook.d.ts.map +1 -1
  177. package/dist/index.js +375 -265
  178. package/dist/plugin.js +374 -264
  179. package/dist/skills.d.ts +15 -0
  180. package/dist/skills.d.ts.map +1 -1
  181. package/dist/swarm-mail.d.ts.map +1 -1
  182. package/dist/swarm-prompts.d.ts +4 -2
  183. package/dist/swarm-prompts.d.ts.map +1 -1
  184. package/dist/swarm-prompts.js +84 -7
  185. package/global-skills/swarm-coordination/SKILL.md +21 -20
  186. package/package.json +2 -1
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Post-Compaction Tool Call Tracker
3
+ *
4
+ * Tracks tool calls after compaction resumption to detect coordinator violations
5
+ * and provide learning signals for eval-driven development.
6
+ *
7
+ * ## Purpose
8
+ *
9
+ * When context is compacted, the continuation agent needs observation to learn
10
+ * if it's following coordinator discipline. This tracker:
11
+ *
12
+ * 1. Emits resumption_started on first tool call (marks compaction exit)
13
+ * 2. Tracks up to N tool calls (default 20) with violation detection
14
+ * 3. Stops tracking after limit to avoid noise in long sessions
15
+ *
16
+ * ## Coordinator Violations Detected
17
+ *
18
+ * - **Edit/Write**: Coordinators NEVER edit files - spawn worker instead
19
+ * - **swarmmail_reserve/agentmail_reserve**: Workers reserve, not coordinators
20
+ *
21
+ * ## Integration
22
+ *
23
+ * Used by compaction hook to wire tool.call events → eval capture.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const tracker = createPostCompactionTracker({
28
+ * sessionId: "session-123",
29
+ * epicId: "bd-epic-456",
30
+ * onEvent: captureCompactionEvent,
31
+ * });
32
+ *
33
+ * // Wire to OpenCode hook
34
+ * hooks["tool.call"] = (input) => {
35
+ * tracker.trackToolCall({
36
+ * tool: input.tool,
37
+ * args: input.args,
38
+ * timestamp: Date.now(),
39
+ * });
40
+ * };
41
+ * ```
42
+ */
43
+ /**
44
+ * Tool call event structure
45
+ */
46
+ export interface ToolCallEvent {
47
+ tool: string;
48
+ args: Record<string, unknown>;
49
+ timestamp: number;
50
+ }
51
+ /**
52
+ * Compaction event payload (matches eval-capture.ts structure)
53
+ */
54
+ export interface CompactionEvent {
55
+ session_id: string;
56
+ epic_id: string;
57
+ compaction_type: "detection_complete" | "prompt_generated" | "context_injected" | "resumption_started" | "tool_call_tracked";
58
+ payload: {
59
+ session_id?: string;
60
+ epic_id?: string;
61
+ tool?: string;
62
+ args?: Record<string, unknown>;
63
+ call_number?: number;
64
+ is_coordinator_violation?: boolean;
65
+ violation_reason?: string;
66
+ timestamp?: number;
67
+ };
68
+ }
69
+ /**
70
+ * Tracker configuration
71
+ */
72
+ export interface PostCompactionTrackerConfig {
73
+ sessionId: string;
74
+ epicId: string;
75
+ onEvent: (event: CompactionEvent) => void;
76
+ maxCalls?: number;
77
+ }
78
+ /**
79
+ * Post-compaction tracker instance
80
+ */
81
+ export interface PostCompactionTracker {
82
+ trackToolCall(event: ToolCallEvent): void;
83
+ isTracking(): boolean;
84
+ }
85
+ /**
86
+ * Default maximum number of tool calls to track
87
+ *
88
+ * Chosen to balance:
89
+ * - Enough data for pattern detection (20 calls is ~2-3 minutes of coordinator work)
90
+ * - Avoiding noise pollution in long sessions
91
+ */
92
+ export declare const DEFAULT_MAX_TRACKED_CALLS = 20;
93
+ /**
94
+ * Check if tool call is a coordinator violation
95
+ *
96
+ * @param tool - Tool name from OpenCode tool.call hook
97
+ * @returns Violation status with reason if forbidden
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const result = isCoordinatorViolation("edit");
102
+ * // { isViolation: true, reason: "Coordinators NEVER edit..." }
103
+ *
104
+ * const result = isCoordinatorViolation("read");
105
+ * // { isViolation: false }
106
+ * ```
107
+ */
108
+ export declare function isCoordinatorViolation(tool: string): {
109
+ isViolation: boolean;
110
+ reason?: string;
111
+ };
112
+ /**
113
+ * Create a post-compaction tool call tracker
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * const tracker = createPostCompactionTracker({
118
+ * sessionId: "session-123",
119
+ * epicId: "bd-epic-456",
120
+ * onEvent: (event) => captureCompactionEvent(event),
121
+ * maxCalls: 20
122
+ * });
123
+ *
124
+ * // Track tool calls
125
+ * tracker.trackToolCall({
126
+ * tool: "read",
127
+ * args: { filePath: "/test.ts" },
128
+ * timestamp: Date.now()
129
+ * });
130
+ * ```
131
+ */
132
+ export declare function createPostCompactionTracker(config: PostCompactionTrackerConfig): PostCompactionTracker;
133
+ //# sourceMappingURL=post-compaction-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-compaction-tracker.d.ts","sourceRoot":"","sources":["../src/post-compaction-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EACX,oBAAoB,GACpB,kBAAkB,GAClB,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,CAAC;IACxB,OAAO,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,wBAAwB,CAAC,EAAE,OAAO,CAAC;QACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IAC1C,UAAU,IAAI,OAAO,CAAC;CACvB;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAoB5C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG;IACpD,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAMA;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,2BAA2B,GAClC,qBAAqB,CA2DvB"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * GREEN PHASE: SQL Query Tools Implementation
3
+ *
4
+ * Provides:
5
+ * - 13 preset queries for observability insights (10 base + 3 decision trace)
6
+ * - Custom SQL execution with timing
7
+ * - 3 output formats: Table (box-drawing), CSV, JSON
8
+ */
9
+ import type { DatabaseAdapter } from "swarm-mail";
10
+ export type PresetQueryName = "failed_decompositions" | "duration_by_strategy" | "file_conflicts" | "worker_success_rate" | "review_rejections" | "blocked_tasks" | "agent_activity" | "event_frequency" | "error_patterns" | "compaction_stats" | "decision_quality" | "strategy_success_rates" | "decisions_by_pattern";
11
+ export interface QueryResult {
12
+ columns: string[];
13
+ rows: Record<string, unknown>[];
14
+ rowCount: number;
15
+ executionTimeMs: number;
16
+ }
17
+ export declare const presetQueries: Record<PresetQueryName, string>;
18
+ /**
19
+ * Get database path from project path.
20
+ * Uses global database (~/.config/swarm-tools/swarm.db)
21
+ */
22
+ export declare function getDbPath(): string;
23
+ /**
24
+ * Execute custom SQL against the events table (low-level).
25
+ *
26
+ * @param db - DatabaseAdapter instance
27
+ * @param sql - SQL query string
28
+ * @param params - Optional parameterized query values
29
+ * @returns QueryResult with rows, columns, timing
30
+ */
31
+ export declare function executeQuery(db: DatabaseAdapter, sql: string, params?: unknown[]): Promise<QueryResult>;
32
+ /**
33
+ * Execute a preset query by name (low-level, requires DatabaseAdapter).
34
+ *
35
+ * @param db - DatabaseAdapter instance
36
+ * @param presetName - Name of the preset query
37
+ * @returns QueryResult with rows, columns, timing
38
+ */
39
+ export declare function executePresetQuery(db: DatabaseAdapter, presetName: string): Promise<QueryResult>;
40
+ /**
41
+ * Execute custom SQL query (CLI wrapper).
42
+ * Creates database adapter automatically.
43
+ *
44
+ * @param projectPath - Project path (unused, queries global database)
45
+ * @param sql - SQL query string
46
+ * @returns Raw rows array for CLI formatting
47
+ */
48
+ export declare function executeQueryCLI(projectPath: string, sql: string): Promise<any[]>;
49
+ /**
50
+ * Execute a preset query by name (CLI wrapper).
51
+ * Creates database adapter automatically.
52
+ *
53
+ * @param projectPath - Project path (unused, queries global database)
54
+ * @param presetName - Name of the preset query
55
+ * @returns Raw rows array for CLI formatting
56
+ */
57
+ export declare function executePreset(projectPath: string, presetName: string): Promise<any[]>;
58
+ /**
59
+ * Format query result as aligned table with box-drawing characters.
60
+ *
61
+ * Example output:
62
+ * ┌──────────┬───────┐
63
+ * │ name │ count │
64
+ * ├──────────┼───────┤
65
+ * │ AgentA │ 5 │
66
+ * │ AgentB │ 3 │
67
+ * └──────────┴───────┘
68
+ * 2 rows (12.5ms)
69
+ */
70
+ export declare function formatAsTable(result: QueryResult): string;
71
+ /**
72
+ * Format query result as CSV with proper escaping.
73
+ *
74
+ * Escapes:
75
+ * - Commas → wrap in quotes
76
+ * - Quotes → double them
77
+ * - Newlines → wrap in quotes
78
+ */
79
+ export declare function formatAsCSV(result: QueryResult): string;
80
+ /**
81
+ * Format query result as pretty-printed JSON array.
82
+ *
83
+ * Example:
84
+ * [
85
+ * { "name": "AgentA", "count": 5 },
86
+ * { "name": "AgentB", "count": 3 }
87
+ * ]
88
+ */
89
+ export declare function formatAsJSON(result: QueryResult): string;
90
+ //# sourceMappingURL=query-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-tools.d.ts","sourceRoot":"","sources":["../src/query-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlD,MAAM,MAAM,eAAe,GACxB,uBAAuB,GACvB,sBAAsB,GACtB,gBAAgB,GAChB,qBAAqB,GACrB,mBAAmB,GACnB,eAAe,GACf,gBAAgB,GAChB,iBAAiB,GACjB,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,GAClB,wBAAwB,GACxB,sBAAsB,CAAC;AAE1B,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACxB;AAMD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAgKzD,CAAC;AAMF;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAeD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CACjC,EAAE,EAAE,eAAe,EACnB,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GAChB,OAAO,CAAC,WAAW,CAAC,CAiBtB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACvC,EAAE,EAAE,eAAe,EACnB,UAAU,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAStB;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACpC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,GACT,OAAO,CAAC,GAAG,EAAE,CAAC,CAIhB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAClC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GAChB,OAAO,CAAC,GAAG,EAAE,CAAC,CAIhB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAkEzD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CA2BvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAExD"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Rate Limiter Module - Distributed rate limiting for Agent Mail
3
+ *
4
+ * Provides sliding window rate limiting with dual backends:
5
+ * - Redis (primary) - Distributed, uses sorted sets for sliding window
6
+ * - SQLite (fallback) - Local, file-based persistence
7
+ *
8
+ * Features:
9
+ * - Dual window enforcement: per-minute AND per-hour limits
10
+ * - Automatic backend fallback (Redis → SQLite)
11
+ * - Configurable limits per endpoint via env vars
12
+ * - Auto-cleanup of expired entries
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // Create rate limiter (auto-selects backend)
17
+ * const limiter = await createRateLimiter();
18
+ *
19
+ * // Check if request is allowed
20
+ * const result = await limiter.checkLimit("BlueLake", "send");
21
+ * if (!result.allowed) {
22
+ * console.log(`Rate limited. Reset at ${result.resetAt}`);
23
+ * }
24
+ *
25
+ * // Record a request after it completes
26
+ * await limiter.recordRequest("BlueLake", "send");
27
+ * ```
28
+ */
29
+ import Redis from "ioredis";
30
+ /**
31
+ * Result of checking a rate limit
32
+ */
33
+ export interface RateLimitResult {
34
+ /** Whether the request is allowed */
35
+ allowed: boolean;
36
+ /** Remaining requests in the most restrictive window */
37
+ remaining: number;
38
+ /** Unix timestamp (ms) when the limit resets */
39
+ resetAt: number;
40
+ }
41
+ /**
42
+ * Rate limiter interface
43
+ */
44
+ export interface RateLimiter {
45
+ /**
46
+ * Check if a request is allowed under rate limits
47
+ * Checks BOTH minute and hour windows - both must pass
48
+ *
49
+ * @param agentName - The agent making the request
50
+ * @param endpoint - The endpoint being accessed
51
+ * @returns Rate limit check result
52
+ */
53
+ checkLimit(agentName: string, endpoint: string): Promise<RateLimitResult>;
54
+ /**
55
+ * Record a request against the rate limit
56
+ * Should be called AFTER the request succeeds
57
+ *
58
+ * @param agentName - The agent making the request
59
+ * @param endpoint - The endpoint being accessed
60
+ */
61
+ recordRequest(agentName: string, endpoint: string): Promise<void>;
62
+ /**
63
+ * Close the rate limiter and release resources
64
+ */
65
+ close(): Promise<void>;
66
+ }
67
+ /**
68
+ * Rate limit configuration for an endpoint
69
+ */
70
+ export interface EndpointLimits {
71
+ /** Requests allowed per minute */
72
+ perMinute: number;
73
+ /** Requests allowed per hour */
74
+ perHour: number;
75
+ }
76
+ /**
77
+ * Default rate limits per endpoint
78
+ * Can be overridden via OPENCODE_RATE_LIMIT_{ENDPOINT}_PER_MIN and _PER_HOUR
79
+ */
80
+ export declare const DEFAULT_LIMITS: Record<string, EndpointLimits>;
81
+ /**
82
+ * Get rate limits for an endpoint, with env var overrides
83
+ *
84
+ * @param endpoint - The endpoint name
85
+ * @returns Rate limits for the endpoint
86
+ */
87
+ export declare function getLimitsForEndpoint(endpoint: string): EndpointLimits;
88
+ /**
89
+ * Redis-backed rate limiter using sorted sets
90
+ *
91
+ * Uses sliding window algorithm:
92
+ * 1. Store each request as a member with timestamp as score
93
+ * 2. Remove expired entries (outside window)
94
+ * 3. Count remaining entries
95
+ *
96
+ * Key format: ratelimit:{agent}:{endpoint}:{window}
97
+ * Window values: "minute" or "hour"
98
+ */
99
+ export declare class RedisRateLimiter implements RateLimiter {
100
+ private redis;
101
+ private connected;
102
+ constructor(redis: Redis);
103
+ /**
104
+ * Build Redis key for rate limiting
105
+ */
106
+ private buildKey;
107
+ /**
108
+ * Get window duration in milliseconds
109
+ */
110
+ private getWindowDuration;
111
+ checkLimit(agentName: string, endpoint: string): Promise<RateLimitResult>;
112
+ /**
113
+ * Check a single window's rate limit
114
+ */
115
+ private checkWindow;
116
+ recordRequest(agentName: string, endpoint: string): Promise<void>;
117
+ close(): Promise<void>;
118
+ }
119
+ /**
120
+ * SQLite-backed rate limiter for local/fallback use
121
+ *
122
+ * Table schema:
123
+ * - agent_name: TEXT
124
+ * - endpoint: TEXT
125
+ * - window: TEXT ('minute' or 'hour')
126
+ * - timestamp: INTEGER (Unix ms)
127
+ *
128
+ * Uses sliding window via COUNT query with timestamp filter.
129
+ */
130
+ export declare class SqliteRateLimiter implements RateLimiter {
131
+ private db;
132
+ constructor(dbPath: string);
133
+ /**
134
+ * Initialize the database schema and cleanup old entries
135
+ */
136
+ private initialize;
137
+ checkLimit(agentName: string, endpoint: string): Promise<RateLimitResult>;
138
+ /**
139
+ * Check a single window's rate limit
140
+ */
141
+ private checkWindow;
142
+ /**
143
+ * Clean up old rate limit entries in bounded batches
144
+ *
145
+ * Limits cleanup to prevent blocking recordRequest on large datasets:
146
+ * - BATCH_SIZE: 1000 rows per iteration
147
+ * - MAX_BATCHES: 10 (max 10k rows per cleanup invocation)
148
+ *
149
+ * Stops early if fewer than BATCH_SIZE rows deleted (no more to clean).
150
+ */
151
+ private cleanup;
152
+ recordRequest(agentName: string, endpoint: string): Promise<void>;
153
+ close(): Promise<void>;
154
+ }
155
+ /**
156
+ * In-memory rate limiter for testing
157
+ *
158
+ * Uses Map storage with timestamp arrays per key.
159
+ * No persistence - resets on process restart.
160
+ */
161
+ export declare class InMemoryRateLimiter implements RateLimiter {
162
+ private storage;
163
+ private buildKey;
164
+ checkLimit(agentName: string, endpoint: string): Promise<RateLimitResult>;
165
+ private checkWindow;
166
+ recordRequest(agentName: string, endpoint: string): Promise<void>;
167
+ close(): Promise<void>;
168
+ /**
169
+ * Reset all rate limits (for testing)
170
+ */
171
+ reset(): void;
172
+ }
173
+ /**
174
+ * Create a rate limiter with automatic backend selection
175
+ *
176
+ * Tries Redis first, falls back to SQLite on connection failure.
177
+ * Warns once when falling back to SQLite.
178
+ *
179
+ * @returns Configured rate limiter instance
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * // Auto-select backend
184
+ * const limiter = await createRateLimiter();
185
+ *
186
+ * // Force SQLite
187
+ * const limiter = await createRateLimiter({ backend: "sqlite" });
188
+ *
189
+ * // Force in-memory (testing)
190
+ * const limiter = await createRateLimiter({ backend: "memory" });
191
+ * ```
192
+ */
193
+ export declare function createRateLimiter(options?: {
194
+ backend?: "redis" | "sqlite" | "memory";
195
+ redisUrl?: string;
196
+ sqlitePath?: string;
197
+ }): Promise<RateLimiter>;
198
+ /**
199
+ * Reset the fallback warning flag (for testing)
200
+ */
201
+ export declare function resetFallbackWarning(): void;
202
+ /**
203
+ * Get or create the global rate limiter instance
204
+ *
205
+ * Uses auto-selection (Redis → SQLite) by default.
206
+ */
207
+ export declare function getRateLimiter(): Promise<RateLimiter>;
208
+ /**
209
+ * Set the global rate limiter instance
210
+ *
211
+ * Useful for testing or custom configurations.
212
+ */
213
+ export declare function setRateLimiter(limiter: RateLimiter): void;
214
+ /**
215
+ * Reset the global rate limiter instance
216
+ */
217
+ export declare function resetRateLimiter(): Promise<void>;
218
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,MAAM,SAAS,CAAC;AA0C5B;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;;;OAOG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE1E;;;;;;OAMG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CASzD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAmBrE;AAMD;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAClD,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,SAAS,CAAkB;gBAEvB,KAAK,EAAE,KAAK;IAKxB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAQhB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAInB,UAAU,CACd,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC;IAwB3B;;OAEG;YACW,WAAW;IAuCnB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAM7B;AAMD;;;;;;;;;;GAUG;AACH,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,EAAE,CAAc;gBAEZ,MAAM,EAAE,MAAM;IAe1B;;OAEG;IACH,OAAO,CAAC,UAAU;IAuBZ,UAAU,CACd,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC;IAkC3B;;OAEG;IACH,OAAO,CAAC,WAAW;IAmDnB;;;;;;;;OAQG;IACH,OAAO,CAAC,OAAO;IA2BT,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAMD;;;;;GAKG;AACH,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,OAAO,CAAoC;IAEnD,OAAO,CAAC,QAAQ;IAQV,UAAU,CACd,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC;IA4B3B,OAAO,CAAC,WAAW;IA4Bb,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd;AASD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,CAAC,EAAE;IAChD,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,WAAW,CAAC,CA6EvB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAQD;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAK3D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAEzD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAKtD"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Regression detection result
3
+ */
4
+ export interface RegressionResult {
5
+ /** Name of the eval that regressed */
6
+ evalName: string;
7
+ /** Previous run score */
8
+ oldScore: number;
9
+ /** Latest run score */
10
+ newScore: number;
11
+ /** Absolute delta (oldScore - newScore) */
12
+ delta: number;
13
+ /** Percentage change ((newScore - oldScore) / oldScore * 100) */
14
+ deltaPercent: number;
15
+ }
16
+ /**
17
+ * Detect regressions by comparing latest run to previous run
18
+ *
19
+ * Scans all evals in eval-history.jsonl and compares the last two runs
20
+ * for each eval. Returns evals where the score dropped more than the
21
+ * threshold.
22
+ *
23
+ * **Algorithm**:
24
+ * 1. Read all eval history records
25
+ * 2. Group by eval name
26
+ * 3. For each eval with ≥2 runs:
27
+ * - Get last 2 runs
28
+ * - Calculate delta and deltaPercent
29
+ * - If delta exceeds threshold AND score dropped, record regression
30
+ * 4. Sort results by severity (largest delta first)
31
+ *
32
+ * **Delta calculation**:
33
+ * - delta = oldScore - newScore (absolute drop)
34
+ * - deltaPercent = (newScore - oldScore) / oldScore * 100 (negative for regression)
35
+ *
36
+ * **Threshold**: Specified as absolute value (e.g., 0.10 = 10% drop required to report)
37
+ *
38
+ * @param projectPath - Absolute path to project root
39
+ * @param threshold - Minimum delta to report (default: 0.10 = 10%)
40
+ * @returns List of regressions sorted by severity (largest delta first)
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * import { detectRegressions } from "./regression-detection.js";
45
+ *
46
+ * const regressions = detectRegressions("/path/to/project", 0.10);
47
+ *
48
+ * if (regressions.length > 0) {
49
+ * console.error("⚠️ REGRESSION DETECTED");
50
+ * for (const reg of regressions) {
51
+ * console.error(`├── ${reg.evalName}: ${(reg.oldScore * 100).toFixed(1)}% → ${(reg.newScore * 100).toFixed(1)}% (${reg.deltaPercent.toFixed(1)}%)`);
52
+ * }
53
+ * console.error(`└── Threshold: ${(threshold * 100).toFixed(0)}%`);
54
+ * }
55
+ * ```
56
+ */
57
+ export declare function detectRegressions(projectPath: string, threshold?: number): RegressionResult[];
58
+ //# sourceMappingURL=regression-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regression-detection.d.ts","sourceRoot":"","sources":["../src/regression-detection.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,YAAY,EAAE,MAAM,CAAC;CACtB;AA6CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAY,GACtB,gBAAgB,EAAE,CA0CpB"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Replay Tools - Event replay with timing simulation
3
+ *
4
+ * TDD GREEN: Minimal implementation to pass tests
5
+ */
6
+ export type ReplaySpeed = "1x" | "2x" | "instant";
7
+ export interface ReplayEvent {
8
+ session_id: string;
9
+ epic_id: string;
10
+ timestamp: string;
11
+ event_type: "DECISION" | "VIOLATION" | "OUTCOME" | "COMPACTION";
12
+ decision_type?: string;
13
+ violation_type?: string;
14
+ outcome_type?: string;
15
+ payload: Record<string, unknown>;
16
+ delta_ms: number;
17
+ }
18
+ export interface ReplayFilter {
19
+ type?: Array<"DECISION" | "VIOLATION" | "OUTCOME" | "COMPACTION">;
20
+ agent?: string;
21
+ since?: Date;
22
+ until?: Date;
23
+ }
24
+ export declare function fetchEpicEvents(epicId: string, sessionFile: string): Promise<ReplayEvent[]>;
25
+ export declare function filterEvents(events: ReplayEvent[], filter: ReplayFilter): ReplayEvent[];
26
+ export declare function replayWithTiming(events: ReplayEvent[], speed: ReplaySpeed): AsyncGenerator<ReplayEvent>;
27
+ export declare function formatReplayEvent(event: ReplayEvent): string;
28
+ //# sourceMappingURL=replay-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-tools.d.ts","sourceRoot":"","sources":["../src/replay-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;AAElD,MAAM,WAAW,WAAW;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,CAAC,EAAE,KAAK,CAAC,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,KAAK,CAAC,EAAE,IAAI,CAAC;CACb;AAMD,wBAAsB,eAAe,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CA4CxB;AAMD,wBAAgB,YAAY,CAC3B,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,YAAY,GAClB,WAAW,EAAE,CAiCf;AAMD,wBAAuB,gBAAgB,CACtC,MAAM,EAAE,WAAW,EAAE,EACrB,KAAK,EAAE,WAAW,GAChB,cAAc,CAAC,WAAW,CAAC,CAuC7B;AAMD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA0D5D"}