opencode-swarm-plugin 0.44.0 → 0.44.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/swarm.serve.test.ts +6 -4
- package/bin/swarm.ts +18 -12
- package/dist/compaction-prompt-scoring.js +139 -0
- package/dist/eval-capture.js +12811 -0
- package/dist/hive.d.ts.map +1 -1
- package/dist/hive.js +14834 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7743 -62593
- package/dist/plugin.js +24052 -78907
- package/dist/swarm-orchestrate.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm-prompts.js +39407 -0
- package/dist/swarm-review.d.ts.map +1 -1
- package/dist/swarm-validation.d.ts +127 -0
- package/dist/swarm-validation.d.ts.map +1 -0
- package/dist/validators/index.d.ts +7 -0
- package/dist/validators/index.d.ts.map +1 -0
- package/dist/validators/schema-validator.d.ts +58 -0
- package/dist/validators/schema-validator.d.ts.map +1 -0
- package/package.json +17 -5
- package/.changeset/swarm-insights-data-layer.md +0 -63
- package/.hive/analysis/eval-failure-analysis-2025-12-25.md +0 -331
- package/.hive/analysis/session-data-quality-audit.md +0 -320
- package/.hive/eval-results.json +0 -483
- package/.hive/issues.jsonl +0 -138
- package/.hive/memories.jsonl +0 -729
- package/.opencode/eval-history.jsonl +0 -327
- package/.turbo/turbo-build.log +0 -9
- package/CHANGELOG.md +0 -2286
- package/SCORER-ANALYSIS.md +0 -598
- package/docs/analysis/subagent-coordination-patterns.md +0 -902
- package/docs/analysis-socratic-planner-pattern.md +0 -504
- package/docs/planning/ADR-001-monorepo-structure.md +0 -171
- package/docs/planning/ADR-002-package-extraction.md +0 -393
- package/docs/planning/ADR-003-performance-improvements.md +0 -451
- package/docs/planning/ADR-004-message-queue-features.md +0 -187
- package/docs/planning/ADR-005-devtools-observability.md +0 -202
- package/docs/planning/ADR-007-swarm-enhancements-worktree-review.md +0 -168
- package/docs/planning/ADR-008-worker-handoff-protocol.md +0 -293
- package/docs/planning/ADR-009-oh-my-opencode-patterns.md +0 -353
- package/docs/planning/ADR-010-cass-inhousing.md +0 -1215
- package/docs/planning/ROADMAP.md +0 -368
- package/docs/semantic-memory-cli-syntax.md +0 -123
- package/docs/swarm-mail-architecture.md +0 -1147
- package/docs/testing/context-recovery-test.md +0 -470
- package/evals/ARCHITECTURE.md +0 -1189
- package/evals/README.md +0 -768
- package/evals/compaction-prompt.eval.ts +0 -149
- package/evals/compaction-resumption.eval.ts +0 -289
- package/evals/coordinator-behavior.eval.ts +0 -307
- package/evals/coordinator-session.eval.ts +0 -154
- package/evals/evalite.config.ts.bak +0 -15
- package/evals/example.eval.ts +0 -31
- package/evals/fixtures/cass-baseline.ts +0 -217
- package/evals/fixtures/compaction-cases.ts +0 -350
- package/evals/fixtures/compaction-prompt-cases.ts +0 -311
- package/evals/fixtures/coordinator-sessions.ts +0 -328
- package/evals/fixtures/decomposition-cases.ts +0 -105
- package/evals/lib/compaction-loader.test.ts +0 -248
- package/evals/lib/compaction-loader.ts +0 -320
- package/evals/lib/data-loader.evalite-test.ts +0 -289
- package/evals/lib/data-loader.test.ts +0 -345
- package/evals/lib/data-loader.ts +0 -281
- package/evals/lib/llm.ts +0 -115
- package/evals/scorers/compaction-prompt-scorers.ts +0 -145
- package/evals/scorers/compaction-scorers.ts +0 -305
- package/evals/scorers/coordinator-discipline.evalite-test.ts +0 -539
- package/evals/scorers/coordinator-discipline.ts +0 -325
- package/evals/scorers/index.test.ts +0 -146
- package/evals/scorers/index.ts +0 -328
- package/evals/scorers/outcome-scorers.evalite-test.ts +0 -27
- package/evals/scorers/outcome-scorers.ts +0 -349
- package/evals/swarm-decomposition.eval.ts +0 -121
- package/examples/commands/swarm.md +0 -745
- package/examples/plugin-wrapper-template.ts +0 -2515
- package/examples/skills/hive-workflow/SKILL.md +0 -212
- package/examples/skills/skill-creator/SKILL.md +0 -223
- package/examples/skills/swarm-coordination/SKILL.md +0 -292
- package/global-skills/cli-builder/SKILL.md +0 -344
- package/global-skills/cli-builder/references/advanced-patterns.md +0 -244
- package/global-skills/learning-systems/SKILL.md +0 -644
- package/global-skills/skill-creator/LICENSE.txt +0 -202
- package/global-skills/skill-creator/SKILL.md +0 -352
- package/global-skills/skill-creator/references/output-patterns.md +0 -82
- package/global-skills/skill-creator/references/workflows.md +0 -28
- package/global-skills/swarm-coordination/SKILL.md +0 -995
- package/global-skills/swarm-coordination/references/coordinator-patterns.md +0 -235
- package/global-skills/swarm-coordination/references/strategies.md +0 -138
- package/global-skills/system-design/SKILL.md +0 -213
- package/global-skills/testing-patterns/SKILL.md +0 -430
- package/global-skills/testing-patterns/references/dependency-breaking-catalog.md +0 -586
- package/opencode-swarm-plugin-0.30.7.tgz +0 -0
- package/opencode-swarm-plugin-0.31.0.tgz +0 -0
- package/scripts/cleanup-test-memories.ts +0 -346
- package/scripts/init-skill.ts +0 -222
- package/scripts/migrate-unknown-sessions.ts +0 -349
- package/scripts/validate-skill.ts +0 -204
- package/src/agent-mail.ts +0 -1724
- package/src/anti-patterns.test.ts +0 -1167
- package/src/anti-patterns.ts +0 -448
- package/src/compaction-capture.integration.test.ts +0 -257
- package/src/compaction-hook.test.ts +0 -838
- package/src/compaction-hook.ts +0 -1204
- package/src/compaction-observability.integration.test.ts +0 -139
- package/src/compaction-observability.test.ts +0 -187
- package/src/compaction-observability.ts +0 -324
- package/src/compaction-prompt-scorers.test.ts +0 -475
- package/src/compaction-prompt-scoring.ts +0 -300
- package/src/contributor-tools.test.ts +0 -133
- package/src/contributor-tools.ts +0 -201
- package/src/dashboard.test.ts +0 -611
- package/src/dashboard.ts +0 -462
- package/src/error-enrichment.test.ts +0 -403
- package/src/error-enrichment.ts +0 -219
- package/src/eval-capture.test.ts +0 -1015
- package/src/eval-capture.ts +0 -929
- package/src/eval-gates.test.ts +0 -306
- package/src/eval-gates.ts +0 -218
- package/src/eval-history.test.ts +0 -508
- package/src/eval-history.ts +0 -214
- package/src/eval-learning.test.ts +0 -378
- package/src/eval-learning.ts +0 -360
- package/src/eval-runner.test.ts +0 -223
- package/src/eval-runner.ts +0 -402
- package/src/export-tools.test.ts +0 -476
- package/src/export-tools.ts +0 -257
- package/src/hive.integration.test.ts +0 -2241
- package/src/hive.ts +0 -1628
- package/src/index.ts +0 -940
- package/src/learning.integration.test.ts +0 -1815
- package/src/learning.ts +0 -1079
- package/src/logger.test.ts +0 -189
- package/src/logger.ts +0 -135
- package/src/mandate-promotion.test.ts +0 -473
- package/src/mandate-promotion.ts +0 -239
- package/src/mandate-storage.integration.test.ts +0 -601
- package/src/mandate-storage.test.ts +0 -578
- package/src/mandate-storage.ts +0 -794
- package/src/mandates.ts +0 -540
- package/src/memory-tools.test.ts +0 -195
- package/src/memory-tools.ts +0 -344
- package/src/memory.integration.test.ts +0 -334
- package/src/memory.test.ts +0 -158
- package/src/memory.ts +0 -527
- package/src/model-selection.test.ts +0 -188
- package/src/model-selection.ts +0 -68
- package/src/observability-tools.test.ts +0 -359
- package/src/observability-tools.ts +0 -871
- package/src/output-guardrails.test.ts +0 -438
- package/src/output-guardrails.ts +0 -381
- package/src/pattern-maturity.test.ts +0 -1160
- package/src/pattern-maturity.ts +0 -525
- package/src/planning-guardrails.test.ts +0 -491
- package/src/planning-guardrails.ts +0 -438
- package/src/plugin.ts +0 -23
- package/src/post-compaction-tracker.test.ts +0 -251
- package/src/post-compaction-tracker.ts +0 -237
- package/src/query-tools.test.ts +0 -636
- package/src/query-tools.ts +0 -324
- package/src/rate-limiter.integration.test.ts +0 -466
- package/src/rate-limiter.ts +0 -774
- package/src/replay-tools.test.ts +0 -496
- package/src/replay-tools.ts +0 -240
- package/src/repo-crawl.integration.test.ts +0 -441
- package/src/repo-crawl.ts +0 -610
- package/src/schemas/cell-events.test.ts +0 -347
- package/src/schemas/cell-events.ts +0 -807
- package/src/schemas/cell.ts +0 -257
- package/src/schemas/evaluation.ts +0 -166
- package/src/schemas/index.test.ts +0 -199
- package/src/schemas/index.ts +0 -286
- package/src/schemas/mandate.ts +0 -232
- package/src/schemas/swarm-context.ts +0 -115
- package/src/schemas/task.ts +0 -161
- package/src/schemas/worker-handoff.test.ts +0 -302
- package/src/schemas/worker-handoff.ts +0 -131
- package/src/sessions/agent-discovery.test.ts +0 -137
- package/src/sessions/agent-discovery.ts +0 -112
- package/src/sessions/index.ts +0 -15
- package/src/skills.integration.test.ts +0 -1192
- package/src/skills.test.ts +0 -643
- package/src/skills.ts +0 -1549
- package/src/storage.integration.test.ts +0 -341
- package/src/storage.ts +0 -884
- package/src/structured.integration.test.ts +0 -817
- package/src/structured.test.ts +0 -1046
- package/src/structured.ts +0 -762
- package/src/swarm-decompose.test.ts +0 -188
- package/src/swarm-decompose.ts +0 -1302
- package/src/swarm-deferred.integration.test.ts +0 -157
- package/src/swarm-deferred.test.ts +0 -38
- package/src/swarm-insights.test.ts +0 -214
- package/src/swarm-insights.ts +0 -459
- package/src/swarm-mail.integration.test.ts +0 -970
- package/src/swarm-mail.ts +0 -739
- package/src/swarm-orchestrate.integration.test.ts +0 -282
- package/src/swarm-orchestrate.test.ts +0 -548
- package/src/swarm-orchestrate.ts +0 -3084
- package/src/swarm-prompts.test.ts +0 -1270
- package/src/swarm-prompts.ts +0 -2077
- package/src/swarm-research.integration.test.ts +0 -701
- package/src/swarm-research.test.ts +0 -698
- package/src/swarm-research.ts +0 -472
- package/src/swarm-review.integration.test.ts +0 -285
- package/src/swarm-review.test.ts +0 -879
- package/src/swarm-review.ts +0 -709
- package/src/swarm-strategies.ts +0 -407
- package/src/swarm-worktree.test.ts +0 -501
- package/src/swarm-worktree.ts +0 -575
- package/src/swarm.integration.test.ts +0 -2377
- package/src/swarm.ts +0 -38
- package/src/tool-adapter.integration.test.ts +0 -1221
- package/src/tool-availability.ts +0 -461
- package/tsconfig.json +0 -28
package/src/query-tools.ts
DELETED
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GREEN PHASE: SQL Query Tools Implementation
|
|
3
|
-
*
|
|
4
|
-
* Provides:
|
|
5
|
-
* - 10 preset queries for observability insights
|
|
6
|
-
* - Custom SQL execution with timing
|
|
7
|
-
* - 3 output formats: Table (box-drawing), CSV, JSON
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { DatabaseAdapter } from "swarm-mail";
|
|
11
|
-
|
|
12
|
-
// ============================================================================
|
|
13
|
-
// TYPES
|
|
14
|
-
// ============================================================================
|
|
15
|
-
|
|
16
|
-
export type PresetQueryName =
|
|
17
|
-
| "failed_decompositions"
|
|
18
|
-
| "duration_by_strategy"
|
|
19
|
-
| "file_conflicts"
|
|
20
|
-
| "worker_success_rate"
|
|
21
|
-
| "review_rejections"
|
|
22
|
-
| "blocked_tasks"
|
|
23
|
-
| "agent_activity"
|
|
24
|
-
| "event_frequency"
|
|
25
|
-
| "error_patterns"
|
|
26
|
-
| "compaction_stats";
|
|
27
|
-
|
|
28
|
-
export interface QueryResult {
|
|
29
|
-
columns: string[];
|
|
30
|
-
rows: Record<string, unknown>[];
|
|
31
|
-
rowCount: number;
|
|
32
|
-
executionTimeMs: number;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ============================================================================
|
|
36
|
-
// PRESET QUERIES
|
|
37
|
-
// ============================================================================
|
|
38
|
-
|
|
39
|
-
export const presetQueries: Record<PresetQueryName, string> = {
|
|
40
|
-
failed_decompositions: `
|
|
41
|
-
SELECT
|
|
42
|
-
json_extract(data, '$.strategy') as strategy,
|
|
43
|
-
json_extract(data, '$.error') as error,
|
|
44
|
-
COUNT(*) as count
|
|
45
|
-
FROM events
|
|
46
|
-
WHERE type = 'decomposition_failed'
|
|
47
|
-
GROUP BY strategy, error
|
|
48
|
-
ORDER BY count DESC
|
|
49
|
-
`,
|
|
50
|
-
|
|
51
|
-
duration_by_strategy: `
|
|
52
|
-
SELECT
|
|
53
|
-
json_extract(data, '$.strategy') as strategy,
|
|
54
|
-
AVG(CAST(json_extract(data, '$.durationMs') AS REAL)) as avg_duration_ms,
|
|
55
|
-
COUNT(*) as count
|
|
56
|
-
FROM events
|
|
57
|
-
WHERE type = 'subtask_outcome'
|
|
58
|
-
GROUP BY strategy
|
|
59
|
-
ORDER BY avg_duration_ms DESC
|
|
60
|
-
`,
|
|
61
|
-
|
|
62
|
-
file_conflicts: `
|
|
63
|
-
SELECT
|
|
64
|
-
json_extract(value, '$') as file_path,
|
|
65
|
-
COUNT(*) as reservation_count,
|
|
66
|
-
GROUP_CONCAT(DISTINCT json_extract(data, '$.agent_name')) as agents
|
|
67
|
-
FROM events,
|
|
68
|
-
json_each(json_extract(data, '$.paths'))
|
|
69
|
-
WHERE type = 'reservation_created'
|
|
70
|
-
GROUP BY file_path
|
|
71
|
-
HAVING COUNT(*) > 1
|
|
72
|
-
ORDER BY reservation_count DESC
|
|
73
|
-
`,
|
|
74
|
-
|
|
75
|
-
worker_success_rate: `
|
|
76
|
-
SELECT
|
|
77
|
-
json_extract(data, '$.agent_name') as agent_name,
|
|
78
|
-
COUNT(*) as total,
|
|
79
|
-
SUM(CAST(json_extract(data, '$.success') AS INTEGER)) as successes,
|
|
80
|
-
CAST(SUM(CAST(json_extract(data, '$.success') AS INTEGER)) AS REAL) / COUNT(*) * 100 as success_rate
|
|
81
|
-
FROM events
|
|
82
|
-
WHERE type = 'subtask_outcome'
|
|
83
|
-
GROUP BY agent_name
|
|
84
|
-
ORDER BY success_rate DESC
|
|
85
|
-
`,
|
|
86
|
-
|
|
87
|
-
review_rejections: `
|
|
88
|
-
SELECT
|
|
89
|
-
json_extract(data, '$.bead_id') as bead_id,
|
|
90
|
-
json_extract(data, '$.agent_name') as agent_name,
|
|
91
|
-
json_extract(data, '$.issues') as issues,
|
|
92
|
-
timestamp
|
|
93
|
-
FROM events
|
|
94
|
-
WHERE type = 'review_feedback'
|
|
95
|
-
AND json_extract(data, '$.status') = 'needs_changes'
|
|
96
|
-
ORDER BY timestamp DESC
|
|
97
|
-
`,
|
|
98
|
-
|
|
99
|
-
blocked_tasks: `
|
|
100
|
-
SELECT
|
|
101
|
-
json_extract(data, '$.bead_id') as bead_id,
|
|
102
|
-
json_extract(data, '$.agent_name') as agent_name,
|
|
103
|
-
json_extract(data, '$.epic_id') as epic_id,
|
|
104
|
-
json_extract(data, '$.status') as status,
|
|
105
|
-
timestamp
|
|
106
|
-
FROM events
|
|
107
|
-
WHERE json_extract(data, '$.status') = 'blocked'
|
|
108
|
-
ORDER BY timestamp DESC
|
|
109
|
-
`,
|
|
110
|
-
|
|
111
|
-
agent_activity: `
|
|
112
|
-
SELECT
|
|
113
|
-
json_extract(data, '$.agent_name') as agent_name,
|
|
114
|
-
COUNT(*) as event_count,
|
|
115
|
-
COUNT(DISTINCT type) as unique_event_types,
|
|
116
|
-
MIN(timestamp) as first_seen,
|
|
117
|
-
MAX(timestamp) as last_seen
|
|
118
|
-
FROM events
|
|
119
|
-
WHERE json_extract(data, '$.agent_name') IS NOT NULL
|
|
120
|
-
GROUP BY agent_name
|
|
121
|
-
ORDER BY event_count DESC
|
|
122
|
-
`,
|
|
123
|
-
|
|
124
|
-
event_frequency: `
|
|
125
|
-
SELECT
|
|
126
|
-
strftime('%Y-%m-%d %H:00:00', datetime(timestamp / 1000, 'unixepoch')) as hour,
|
|
127
|
-
type,
|
|
128
|
-
COUNT(*) as count
|
|
129
|
-
FROM events
|
|
130
|
-
GROUP BY hour, type
|
|
131
|
-
ORDER BY hour DESC, count DESC
|
|
132
|
-
`,
|
|
133
|
-
|
|
134
|
-
error_patterns: `
|
|
135
|
-
SELECT
|
|
136
|
-
json_extract(data, '$.error') as error_message,
|
|
137
|
-
type as event_type,
|
|
138
|
-
COUNT(*) as occurrences,
|
|
139
|
-
GROUP_CONCAT(DISTINCT json_extract(data, '$.agent_name')) as affected_agents
|
|
140
|
-
FROM events
|
|
141
|
-
WHERE json_extract(data, '$.error') IS NOT NULL
|
|
142
|
-
GROUP BY error_message, event_type
|
|
143
|
-
ORDER BY occurrences DESC
|
|
144
|
-
`,
|
|
145
|
-
|
|
146
|
-
compaction_stats: `
|
|
147
|
-
SELECT
|
|
148
|
-
AVG(CAST(json_extract(data, '$.beforeSize') AS REAL)) as avg_before_size,
|
|
149
|
-
AVG(CAST(json_extract(data, '$.afterSize') AS REAL)) as avg_after_size,
|
|
150
|
-
AVG(CAST(json_extract(data, '$.ratio') AS REAL)) as avg_compression_ratio,
|
|
151
|
-
COUNT(*) as compaction_count
|
|
152
|
-
FROM events
|
|
153
|
-
WHERE type = 'compaction'
|
|
154
|
-
`,
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
// ============================================================================
|
|
158
|
-
// QUERY EXECUTION
|
|
159
|
-
// ============================================================================
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Execute custom SQL against the events table.
|
|
163
|
-
*
|
|
164
|
-
* @param db - DatabaseAdapter instance
|
|
165
|
-
* @param sql - SQL query string
|
|
166
|
-
* @param params - Optional parameterized query values
|
|
167
|
-
* @returns QueryResult with rows, columns, timing
|
|
168
|
-
*/
|
|
169
|
-
export async function executeQuery(
|
|
170
|
-
db: DatabaseAdapter,
|
|
171
|
-
sql: string,
|
|
172
|
-
params?: unknown[],
|
|
173
|
-
): Promise<QueryResult> {
|
|
174
|
-
const startTime = performance.now();
|
|
175
|
-
|
|
176
|
-
const result = await db.query<Record<string, unknown>>(sql, params);
|
|
177
|
-
|
|
178
|
-
const endTime = performance.now();
|
|
179
|
-
const executionTimeMs = endTime - startTime;
|
|
180
|
-
|
|
181
|
-
// Extract column names from first row
|
|
182
|
-
const columns = result.rows.length > 0 ? Object.keys(result.rows[0]) : [];
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
columns,
|
|
186
|
-
rows: result.rows,
|
|
187
|
-
rowCount: result.rows.length,
|
|
188
|
-
executionTimeMs,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// ============================================================================
|
|
193
|
-
// OUTPUT FORMATTERS
|
|
194
|
-
// ============================================================================
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Format query result as aligned table with box-drawing characters.
|
|
198
|
-
*
|
|
199
|
-
* Example output:
|
|
200
|
-
* ┌──────────┬───────┐
|
|
201
|
-
* │ name │ count │
|
|
202
|
-
* ├──────────┼───────┤
|
|
203
|
-
* │ AgentA │ 5 │
|
|
204
|
-
* │ AgentB │ 3 │
|
|
205
|
-
* └──────────┴───────┘
|
|
206
|
-
* 2 rows in 5.2ms
|
|
207
|
-
*/
|
|
208
|
-
export function formatAsTable(result: QueryResult): string {
|
|
209
|
-
const { columns, rows, rowCount, executionTimeMs } = result;
|
|
210
|
-
|
|
211
|
-
// Handle empty result set
|
|
212
|
-
if (rows.length === 0) {
|
|
213
|
-
const header = columns.join(" │ ");
|
|
214
|
-
const width = header.length + 4;
|
|
215
|
-
const footer = `0 rows in ${executionTimeMs.toFixed(1)}ms`;
|
|
216
|
-
return [
|
|
217
|
-
`┌${"─".repeat(width - 2)}┐`,
|
|
218
|
-
`│ ${header} │`,
|
|
219
|
-
`└${"─".repeat(width - 2)}┘`,
|
|
220
|
-
footer.padEnd(width),
|
|
221
|
-
].join("\n");
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Calculate column widths
|
|
225
|
-
const widths: number[] = columns.map((col, idx) => {
|
|
226
|
-
const colWidth = col.length;
|
|
227
|
-
const maxDataWidth = Math.max(
|
|
228
|
-
...rows.map((row) => {
|
|
229
|
-
const val = row[col];
|
|
230
|
-
return String(val ?? "NULL").length;
|
|
231
|
-
}),
|
|
232
|
-
);
|
|
233
|
-
return Math.max(colWidth, maxDataWidth);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// Build rows
|
|
237
|
-
const lines: string[] = [];
|
|
238
|
-
|
|
239
|
-
// Top border
|
|
240
|
-
const topBorder = `┌${widths.map((w) => "─".repeat(w + 2)).join("┬")}┐`;
|
|
241
|
-
lines.push(topBorder);
|
|
242
|
-
|
|
243
|
-
// Header
|
|
244
|
-
const headerCells = columns.map((col, idx) =>
|
|
245
|
-
` ${col.padEnd(widths[idx])} `
|
|
246
|
-
);
|
|
247
|
-
lines.push(`│${headerCells.join("│")}│`);
|
|
248
|
-
|
|
249
|
-
// Separator
|
|
250
|
-
lines.push(
|
|
251
|
-
`├${widths.map((w) => "─".repeat(w + 2)).join("┼")}┤`,
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
// Data rows
|
|
255
|
-
for (const row of rows) {
|
|
256
|
-
const cells = columns.map((col, idx) => {
|
|
257
|
-
const val = row[col];
|
|
258
|
-
const str = val === null || val === undefined ? "NULL" : String(val);
|
|
259
|
-
return ` ${str.padEnd(widths[idx])} `;
|
|
260
|
-
});
|
|
261
|
-
lines.push(`│${cells.join("│")}│`);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Bottom border
|
|
265
|
-
const bottomBorder = `└${widths.map((w) => "─".repeat(w + 2)).join("┴")}┘`;
|
|
266
|
-
lines.push(bottomBorder);
|
|
267
|
-
|
|
268
|
-
// Footer - pad to match table width
|
|
269
|
-
const footer = `${rowCount} rows in ${executionTimeMs.toFixed(1)}ms`;
|
|
270
|
-
const tableWidth = topBorder.length;
|
|
271
|
-
lines.push(footer.padEnd(tableWidth));
|
|
272
|
-
|
|
273
|
-
return lines.join("\n");
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Format query result as CSV with proper escaping.
|
|
278
|
-
*
|
|
279
|
-
* Escapes:
|
|
280
|
-
* - Commas → wrap in quotes
|
|
281
|
-
* - Quotes → double them
|
|
282
|
-
* - Newlines → wrap in quotes
|
|
283
|
-
*/
|
|
284
|
-
export function formatAsCSV(result: QueryResult): string {
|
|
285
|
-
const { columns, rows } = result;
|
|
286
|
-
|
|
287
|
-
const lines: string[] = [];
|
|
288
|
-
|
|
289
|
-
// Header
|
|
290
|
-
lines.push(columns.join(","));
|
|
291
|
-
|
|
292
|
-
// Data rows
|
|
293
|
-
for (const row of rows) {
|
|
294
|
-
const cells = columns.map((col) => {
|
|
295
|
-
const val = row[col];
|
|
296
|
-
const str = val === null || val === undefined ? "" : String(val);
|
|
297
|
-
|
|
298
|
-
// Check if escaping needed
|
|
299
|
-
if (str.includes(",") || str.includes('"') || str.includes("\n")) {
|
|
300
|
-
// Escape quotes by doubling them
|
|
301
|
-
const escaped = str.replace(/"/g, '""');
|
|
302
|
-
return `"${escaped}"`;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
return str;
|
|
306
|
-
});
|
|
307
|
-
lines.push(cells.join(","));
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return lines.join("\n");
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Format query result as pretty-printed JSON array.
|
|
315
|
-
*
|
|
316
|
-
* Example:
|
|
317
|
-
* [
|
|
318
|
-
* { "name": "AgentA", "count": 5 },
|
|
319
|
-
* { "name": "AgentB", "count": 3 }
|
|
320
|
-
* ]
|
|
321
|
-
*/
|
|
322
|
-
export function formatAsJSON(result: QueryResult): string {
|
|
323
|
-
return JSON.stringify(result.rows, null, 2);
|
|
324
|
-
}
|