@winspan/claude-forge 8.33.5 → 8.35.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/README.md +10 -30
- package/dist/agents/definition.d.ts +3 -0
- package/dist/agents/definition.d.ts.map +1 -1
- package/dist/agents/definition.js +3 -0
- package/dist/agents/definition.js.map +1 -1
- package/dist/agents/official-agents.d.ts.map +1 -1
- package/dist/agents/official-agents.js +6 -3
- package/dist/agents/official-agents.js.map +1 -1
- package/dist/agents/registry.d.ts +17 -1
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +106 -7
- package/dist/agents/registry.js.map +1 -1
- package/dist/capability/index.d.ts +6 -5
- package/dist/capability/index.d.ts.map +1 -1
- package/dist/capability/index.js +6 -5
- package/dist/capability/index.js.map +1 -1
- package/dist/capability/types.d.ts +5 -74
- package/dist/capability/types.d.ts.map +1 -1
- package/dist/capability/types.js +4 -1
- package/dist/capability/types.js.map +1 -1
- package/dist/cli/commands/executions.d.ts +3 -0
- package/dist/cli/commands/executions.d.ts.map +1 -0
- package/dist/cli/commands/executions.js +109 -0
- package/dist/cli/commands/executions.js.map +1 -0
- package/dist/cli/commands/skills.d.ts.map +1 -1
- package/dist/cli/commands/skills.js +83 -20
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/storage/rows.d.ts +14 -36
- package/dist/core/storage/rows.d.ts.map +1 -1
- package/dist/core/storage/schema.sql +27 -45
- package/dist/core/storage/sqlite.d.ts +11 -79
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +35 -362
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/utils/token-tracker.d.ts +0 -1
- package/dist/core/utils/token-tracker.d.ts.map +1 -1
- package/dist/core/utils/token-tracker.js +0 -1
- package/dist/core/utils/token-tracker.js.map +1 -1
- package/dist/daemon/handlers/post-tool-use.d.ts +1 -9
- package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use.js +2 -99
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/stop.d.ts +5 -15
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +25 -93
- package/dist/daemon/handlers/stop.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +3 -5
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +39 -98
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +11 -56
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/routing-observer.d.ts.map +1 -1
- package/dist/daemon/routing-observer.js +24 -1
- package/dist/daemon/routing-observer.js.map +1 -1
- package/dist/intelligence/execution-doc-builder.d.ts +61 -0
- package/dist/intelligence/execution-doc-builder.d.ts.map +1 -0
- package/dist/intelligence/execution-doc-builder.js +601 -0
- package/dist/intelligence/execution-doc-builder.js.map +1 -0
- package/dist/skills/invocation-guard.d.ts +45 -0
- package/dist/skills/invocation-guard.d.ts.map +1 -0
- package/dist/skills/invocation-guard.js +82 -0
- package/dist/skills/invocation-guard.js.map +1 -0
- package/dist/skills/official-skills.d.ts.map +1 -1
- package/dist/skills/official-skills.js +218 -20
- package/dist/skills/official-skills.js.map +1 -1
- package/dist/skills/registry.d.ts +22 -0
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +30 -2
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/tools/skill-invoke.d.ts +36 -0
- package/dist/skills/tools/skill-invoke.d.ts.map +1 -0
- package/dist/skills/tools/skill-invoke.js +82 -0
- package/dist/skills/tools/skill-invoke.js.map +1 -0
- package/dist/skills/tools/skill-list.d.ts +26 -0
- package/dist/skills/tools/skill-list.d.ts.map +1 -0
- package/dist/skills/tools/skill-list.js +35 -0
- package/dist/skills/tools/skill-list.js.map +1 -0
- package/dist/web/routes/execution-trace.d.ts.map +1 -1
- package/dist/web/routes/execution-trace.js +16 -0
- package/dist/web/routes/execution-trace.js.map +1 -1
- package/dist/web/routes/skill-stats.d.ts +12 -0
- package/dist/web/routes/skill-stats.d.ts.map +1 -0
- package/dist/web/routes/skill-stats.js +72 -0
- package/dist/web/routes/skill-stats.js.map +1 -0
- package/dist/web/routes/status.d.ts.map +1 -1
- package/dist/web/routes/status.js +8 -10
- package/dist/web/routes/status.js.map +1 -1
- package/dist/web/routes/token-usage.d.ts +1 -1
- package/dist/web/routes/token-usage.d.ts.map +1 -1
- package/dist/web/routes/token-usage.js +1 -16
- package/dist/web/routes/token-usage.js.map +1 -1
- package/dist/web/routes/types.d.ts +0 -6
- package/dist/web/routes/types.d.ts.map +1 -1
- package/dist/web/routes/types.js.map +1 -1
- package/dist/web/server.d.ts +0 -6
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +0 -5
- package/dist/web/server.js.map +1 -1
- package/dist/web/static/assets/{AIConfig-BbwRuWzm.js → AIConfig-DiUFET_Q.js} +2 -2
- package/dist/web/static/assets/{AIConfig-BbwRuWzm.js.map → AIConfig-DiUFET_Q.js.map} +1 -1
- package/dist/web/static/assets/{Agents-FyKzsN-g.js → Agents-bNNGbQnL.js} +2 -2
- package/dist/web/static/assets/{Agents-FyKzsN-g.js.map → Agents-bNNGbQnL.js.map} +1 -1
- package/dist/web/static/assets/{Events-C2OCOKAD.js → Events-DQHP6Uaq.js} +2 -2
- package/dist/web/static/assets/{Events-C2OCOKAD.js.map → Events-DQHP6Uaq.js.map} +1 -1
- package/dist/web/static/assets/ExecutionTrace-Co8ARdg-.js +3 -0
- package/dist/web/static/assets/ExecutionTrace-Co8ARdg-.js.map +1 -0
- package/dist/web/static/assets/{Methodologies-DwYLXc8o.js → Methodologies-CXNrDXwG.js} +2 -2
- package/dist/web/static/assets/{Methodologies-DwYLXc8o.js.map → Methodologies-CXNrDXwG.js.map} +1 -1
- package/dist/web/static/assets/{Sessions-CFpFk-5I.js → Sessions-ZQSCgXyy.js} +2 -2
- package/dist/web/static/assets/{Sessions-CFpFk-5I.js.map → Sessions-ZQSCgXyy.js.map} +1 -1
- package/dist/web/static/assets/{Skills-BkbegTV1.js → Skills-C5-5zOSH.js} +2 -2
- package/dist/web/static/assets/{Skills-BkbegTV1.js.map → Skills-C5-5zOSH.js.map} +1 -1
- package/dist/web/static/assets/{index-CIRlno4E.js → index-DJK5beK6.js} +3 -3
- package/dist/web/static/assets/{index-CIRlno4E.js.map → index-DJK5beK6.js.map} +1 -1
- package/dist/web/static/assets/index-phpuytMI.css +1 -0
- package/dist/web/static/index.html +2 -2
- package/package.json +2 -2
- package/dist/capability/execution-manager.d.ts +0 -96
- package/dist/capability/execution-manager.d.ts.map +0 -1
- package/dist/capability/execution-manager.js +0 -260
- package/dist/capability/execution-manager.js.map +0 -1
- package/dist/capability/executor/background-executor.d.ts +0 -58
- package/dist/capability/executor/background-executor.d.ts.map +0 -1
- package/dist/capability/executor/background-executor.js +0 -322
- package/dist/capability/executor/background-executor.js.map +0 -1
- package/dist/capability/executor/foreground-executor.d.ts +0 -26
- package/dist/capability/executor/foreground-executor.d.ts.map +0 -1
- package/dist/capability/executor/foreground-executor.js +0 -82
- package/dist/capability/executor/foreground-executor.js.map +0 -1
- package/dist/capability/executor/orchestrator.d.ts +0 -38
- package/dist/capability/executor/orchestrator.d.ts.map +0 -1
- package/dist/capability/executor/orchestrator.js +0 -158
- package/dist/capability/executor/orchestrator.js.map +0 -1
- package/dist/capability/executor/stream-parser.d.ts +0 -73
- package/dist/capability/executor/stream-parser.d.ts.map +0 -1
- package/dist/capability/executor/stream-parser.js +0 -56
- package/dist/capability/executor/stream-parser.js.map +0 -1
- package/dist/capability/executor/types.d.ts +0 -44
- package/dist/capability/executor/types.d.ts.map +0 -1
- package/dist/capability/executor/types.js +0 -9
- package/dist/capability/executor/types.js.map +0 -1
- package/dist/capability/executor/worker-auth-probe.d.ts +0 -30
- package/dist/capability/executor/worker-auth-probe.d.ts.map +0 -1
- package/dist/capability/executor/worker-auth-probe.js +0 -108
- package/dist/capability/executor/worker-auth-probe.js.map +0 -1
- package/dist/capability/methodologies/bmad.yaml +0 -81
- package/dist/capability/methodologies/code-quality-audit.yaml +0 -26
- package/dist/capability/methodologies/harness-engineering.yaml +0 -75
- package/dist/capability/methodologies/test-coverage-scan.yaml +0 -26
- package/dist/capability/methodology-planner.d.ts +0 -49
- package/dist/capability/methodology-planner.d.ts.map +0 -1
- package/dist/capability/methodology-planner.js +0 -306
- package/dist/capability/methodology-planner.js.map +0 -1
- package/dist/capability/methodology-registry.d.ts +0 -32
- package/dist/capability/methodology-registry.d.ts.map +0 -1
- package/dist/capability/methodology-registry.js +0 -113
- package/dist/capability/methodology-registry.js.map +0 -1
- package/dist/daemon/handlers/methodology-formatter.d.ts +0 -16
- package/dist/daemon/handlers/methodology-formatter.d.ts.map +0 -1
- package/dist/daemon/handlers/methodology-formatter.js +0 -119
- package/dist/daemon/handlers/methodology-formatter.js.map +0 -1
- package/dist/daemon/idle-detector.d.ts +0 -35
- package/dist/daemon/idle-detector.d.ts.map +0 -1
- package/dist/daemon/idle-detector.js +0 -56
- package/dist/daemon/idle-detector.js.map +0 -1
- package/dist/daemon/idle-trigger.d.ts +0 -53
- package/dist/daemon/idle-trigger.d.ts.map +0 -1
- package/dist/daemon/idle-trigger.js +0 -153
- package/dist/daemon/idle-trigger.js.map +0 -1
- package/dist/daemon/methodology-pending-queue.d.ts +0 -33
- package/dist/daemon/methodology-pending-queue.d.ts.map +0 -1
- package/dist/daemon/methodology-pending-queue.js +0 -120
- package/dist/daemon/methodology-pending-queue.js.map +0 -1
- package/dist/web/routes/methodology.d.ts +0 -12
- package/dist/web/routes/methodology.d.ts.map +0 -1
- package/dist/web/routes/methodology.js +0 -228
- package/dist/web/routes/methodology.js.map +0 -1
- package/dist/web/static/assets/ExecutionTrace-BsWSpu2v.js +0 -3
- package/dist/web/static/assets/ExecutionTrace-BsWSpu2v.js.map +0 -1
- package/dist/web/static/assets/index-N1EByy_h.css +0 -1
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import yaml from 'js-yaml';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import { WorkerAuthError } from '../../capability/executor/worker-auth-probe.js';
|
|
6
|
-
import { logger } from '../../core/utils/logger.js';
|
|
7
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
/**
|
|
9
|
-
* /api/methodology-executions/* and /api/methodologies.
|
|
10
|
-
*
|
|
11
|
-
* Also owns the SSE stream for live execution updates. Note: the SSE route
|
|
12
|
-
* `/api/methodology-executions/events` must be registered before the
|
|
13
|
-
* parameterized `/:id` route on Express 4 (Express matches in definition
|
|
14
|
-
* order and `:id` would otherwise swallow the literal `events` segment).
|
|
15
|
-
*/
|
|
16
|
-
export function registerMethodologyRoutes(app, ctx) {
|
|
17
|
-
const { storage, executionManager, methodologyRegistry } = ctx;
|
|
18
|
-
// List executions
|
|
19
|
-
app.get('/api/methodology-executions', (req, res) => {
|
|
20
|
-
const limit = parseInt(req.query.limit) || 50;
|
|
21
|
-
const sessionId = req.query.session;
|
|
22
|
-
const db = storage.getDatabase();
|
|
23
|
-
const query = sessionId
|
|
24
|
-
? 'SELECT * FROM methodology_executions WHERE session_id = ? ORDER BY started_at DESC LIMIT ?'
|
|
25
|
-
: 'SELECT * FROM methodology_executions ORDER BY started_at DESC LIMIT ?';
|
|
26
|
-
const params = sessionId ? [sessionId, limit] : [limit];
|
|
27
|
-
const executions = db.prepare(query).all(...params);
|
|
28
|
-
res.json(executions);
|
|
29
|
-
});
|
|
30
|
-
// SSE stream — MUST be before `/:id`
|
|
31
|
-
app.get('/api/methodology-executions/events', (req, res) => {
|
|
32
|
-
if (!executionManager) {
|
|
33
|
-
res.status(503).json({ error: 'Execution manager not available' });
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const filterId = req.query.execution_id ? parseInt(String(req.query.execution_id)) : null;
|
|
37
|
-
res.setHeader('Content-Type', 'text/event-stream');
|
|
38
|
-
res.setHeader('Cache-Control', 'no-cache');
|
|
39
|
-
res.setHeader('Connection', 'keep-alive');
|
|
40
|
-
res.flushHeaders();
|
|
41
|
-
const unsub = executionManager.subscribe(ev => {
|
|
42
|
-
if (filterId !== null && ev.execution_id !== filterId)
|
|
43
|
-
return;
|
|
44
|
-
try {
|
|
45
|
-
res.write(`event: ${ev.type}\ndata: ${JSON.stringify(ev)}\n\n`);
|
|
46
|
-
}
|
|
47
|
-
catch { /* client gone */ }
|
|
48
|
-
});
|
|
49
|
-
const heartbeat = setInterval(() => {
|
|
50
|
-
try {
|
|
51
|
-
res.write(`: heartbeat ${Date.now()}\n\n`);
|
|
52
|
-
}
|
|
53
|
-
catch { /* ignore */ }
|
|
54
|
-
}, 25_000);
|
|
55
|
-
req.on('close', () => {
|
|
56
|
-
clearInterval(heartbeat);
|
|
57
|
-
unsub();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
// Execution detail: get single execution with phases
|
|
61
|
-
app.get('/api/methodology-executions/:id', (req, res) => {
|
|
62
|
-
const executionId = parseInt(req.params.id);
|
|
63
|
-
const db = storage.getDatabase();
|
|
64
|
-
const execution = db.prepare('SELECT * FROM methodology_executions WHERE id = ?').get(executionId);
|
|
65
|
-
if (!execution) {
|
|
66
|
-
res.status(404).json({ error: 'Execution not found' });
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const phases = db.prepare(`
|
|
70
|
-
SELECT * FROM phase_executions
|
|
71
|
-
WHERE methodology_execution_id = ?
|
|
72
|
-
ORDER BY phase_index ASC
|
|
73
|
-
`).all(executionId);
|
|
74
|
-
res.json({
|
|
75
|
-
...execution,
|
|
76
|
-
plan: JSON.parse(execution.plan_json),
|
|
77
|
-
phases,
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
// Cancel a running execution
|
|
81
|
-
app.post('/api/methodology-executions/:id/cancel', async (req, res) => {
|
|
82
|
-
const executionId = parseInt(req.params.id);
|
|
83
|
-
const db = storage.getDatabase();
|
|
84
|
-
const execution = db.prepare('SELECT * FROM methodology_executions WHERE id = ?').get(executionId);
|
|
85
|
-
if (!execution) {
|
|
86
|
-
res.status(404).json({ error: 'Execution not found' });
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
if (execution.status !== 'running') {
|
|
90
|
-
res.status(400).json({ error: `Cannot cancel execution in ${execution.status} state` });
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
// Prefer ExecutionManager — it kills the worker process for background mode
|
|
94
|
-
if (executionManager) {
|
|
95
|
-
try {
|
|
96
|
-
await executionManager.cancel(executionId);
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
logger.warn(`[web] cancel via ExecutionManager failed: ${err}`);
|
|
100
|
-
res.status(500).json({ error: `Cancel failed: ${err instanceof Error ? err.message : String(err)}` });
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
// Fallback: DB-only cancel (pre-Phase-C behavior)
|
|
106
|
-
db.prepare(`
|
|
107
|
-
UPDATE methodology_executions
|
|
108
|
-
SET status = 'cancelled', completed_at = ?
|
|
109
|
-
WHERE id = ?
|
|
110
|
-
`).run(Date.now(), executionId);
|
|
111
|
-
}
|
|
112
|
-
// Mark any still-running phase rows as cancelled
|
|
113
|
-
db.prepare(`
|
|
114
|
-
UPDATE phase_executions
|
|
115
|
-
SET status = 'cancelled', completed_at = ?
|
|
116
|
-
WHERE methodology_execution_id = ? AND status = 'running'
|
|
117
|
-
`).run(Date.now(), executionId);
|
|
118
|
-
res.json({ success: true, message: 'Execution cancelled' });
|
|
119
|
-
});
|
|
120
|
-
// Start a new execution (Phase C)
|
|
121
|
-
app.post('/api/methodology-executions', async (req, res) => {
|
|
122
|
-
if (!executionManager || !methodologyRegistry) {
|
|
123
|
-
res.status(503).json({ error: 'Execution manager not available' });
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const { session_id, methodology_id, plan, mode } = req.body ?? {};
|
|
127
|
-
if (!session_id) {
|
|
128
|
-
res.status(400).json({ error: 'session_id is required' });
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
if (mode !== 'foreground' && mode !== 'background') {
|
|
132
|
-
res.status(400).json({ error: 'mode must be foreground or background' });
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
let planObj = null;
|
|
136
|
-
if (plan && typeof plan === 'object' && Array.isArray(plan.phases)) {
|
|
137
|
-
planObj = plan;
|
|
138
|
-
}
|
|
139
|
-
else if (methodology_id) {
|
|
140
|
-
const methodology = methodologyRegistry.get(methodology_id);
|
|
141
|
-
if (!methodology) {
|
|
142
|
-
res.status(404).json({ error: `methodology ${methodology_id} not found` });
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
const templates = methodology.phase_templates ?? {};
|
|
146
|
-
const phaseIds = Object.keys(templates);
|
|
147
|
-
if (phaseIds.length === 0) {
|
|
148
|
-
res.status(400).json({ error: `methodology ${methodology_id} has no phase_templates` });
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
planObj = {
|
|
152
|
-
methodology_id: methodology.id,
|
|
153
|
-
rationale: `Started via API (default phases from ${methodology.id})`,
|
|
154
|
-
phases: phaseIds.map(id => {
|
|
155
|
-
const tpl = templates[id];
|
|
156
|
-
return {
|
|
157
|
-
id,
|
|
158
|
-
agent: tpl.agent,
|
|
159
|
-
prompt: tpl.description ?? tpl.prompt_template.slice(0, 400),
|
|
160
|
-
rationale: 'default phase from methodology template',
|
|
161
|
-
};
|
|
162
|
-
}),
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
res.status(400).json({ error: 'either methodology_id or plan must be provided' });
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
try {
|
|
170
|
-
const id = executionManager.start({
|
|
171
|
-
session_id,
|
|
172
|
-
methodology_id: planObj.methodology_id,
|
|
173
|
-
plan: planObj,
|
|
174
|
-
mode,
|
|
175
|
-
});
|
|
176
|
-
res.status(201).json({ id, mode });
|
|
177
|
-
}
|
|
178
|
-
catch (err) {
|
|
179
|
-
logger.warn(`[web] start execution failed: ${err}`);
|
|
180
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
181
|
-
const isAuthError = err instanceof WorkerAuthError
|
|
182
|
-
|| (err instanceof Error && err.code === 'AUTH_REQUIRED')
|
|
183
|
-
|| message.includes('Background mode requires');
|
|
184
|
-
if (isAuthError) {
|
|
185
|
-
res.status(503).json({ error: message, code: 'AUTH_REQUIRED' });
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
res.status(500).json({ error: message });
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
// Delete an execution
|
|
193
|
-
app.delete('/api/methodology-executions/:id', (req, res) => {
|
|
194
|
-
const executionId = parseInt(req.params.id);
|
|
195
|
-
const db = storage.getDatabase();
|
|
196
|
-
db.prepare('DELETE FROM phase_executions WHERE methodology_execution_id = ?').run(executionId);
|
|
197
|
-
const result = db.prepare('DELETE FROM methodology_executions WHERE id = ?').run(executionId);
|
|
198
|
-
if (result.changes === 0) {
|
|
199
|
-
res.status(404).json({ error: 'Execution not found' });
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
res.json({ success: true });
|
|
203
|
-
});
|
|
204
|
-
// Methodology: list all available methodologies
|
|
205
|
-
app.get('/api/methodologies', (_req, res) => {
|
|
206
|
-
try {
|
|
207
|
-
const candidates = [
|
|
208
|
-
path.join(__dirname, '../../capability/methodologies'), // dist/web/routes -> dist/capability/methodologies
|
|
209
|
-
path.join(__dirname, '../../../src/capability/methodologies'), // dev: src/web/routes -> src/capability/methodologies
|
|
210
|
-
];
|
|
211
|
-
const dir = candidates.find(d => fs.existsSync(d));
|
|
212
|
-
if (!dir) {
|
|
213
|
-
res.json([]);
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
const files = fs.readdirSync(dir).filter(f => f.endsWith('.yaml'));
|
|
217
|
-
const methodologies = files.map(f => {
|
|
218
|
-
const content = fs.readFileSync(path.join(dir, f), 'utf-8');
|
|
219
|
-
return yaml.load(content);
|
|
220
|
-
});
|
|
221
|
-
res.json(methodologies);
|
|
222
|
-
}
|
|
223
|
-
catch (err) {
|
|
224
|
-
res.status(500).json({ error: err.message });
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
//# sourceMappingURL=methodology.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"methodology.js","sourceRoot":"","sources":["../../../src/web/routes/methodology.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{r as y,j as e}from"./react-vendor-CSp-GLFF.js";import{b as D,u as k}from"./query-C99w429o.js";import{d as E}from"./vendor-CMMjVdZs.js";import{D as M}from"./Drawer-DOUcx6m1.js";import{C as b}from"./CodeBlock--H53gk46.js";import{S as A,g as J,d as L,a as q}from"./export-CbQTOt71.js";import{u as W}from"./index-CIRlno4E.js";import{W as $,l as B,D as O,A as R}from"./lucide-BanPULT1.js";import{f as T}from"./date-fns-CZ_bHujz.js";import"./syntax-highlighter-44FakypI.js";import"./react-router-I-HqunH7.js";async function G(m){let l="/api/routing/events?limit=200";m==="obeyed"?l+="&obeyed=1":m==="refused"?l+="&obeyed=0":m==="unknown"&&(l+="&obeyed=null");const h=await fetch(l);if(!h.ok)throw new Error("Failed to fetch");return h.json()}const V=[{value:"",label:"全部"},{value:"obeyed",label:"✓ 遵守"},{value:"refused",label:"✗ 违抗"},{value:"unknown",label:"? 未判定"}],H={obeyed:{label:"✓ 遵守",className:"bg-green-100 text-green-800 border border-green-200",title:"调用了推荐的 agent"},disobeyed:{label:"✗ 违抗",className:"bg-red-100 text-red-800 border border-red-200",title:"使用了其他工具而非推荐 agent"},investigation_only:{label:"◎ 仅侦察",className:"bg-orange-100 text-orange-800 border border-orange-200",title:"只做了代码调查(Read/Grep/Glob),未调用推荐 agent"},timeout:{label:"⏱ 超时",className:"bg-gray-100 text-gray-700 border border-gray-200",title:"30 秒内未检测到任何工具调用"},no_action:{label:"— 纯对话",className:"bg-gray-100 text-gray-600 border border-gray-200",title:"未使用任何工具(纯文字回答)"},not_applicable:{label:"· 未适用",className:"bg-gray-50 text-gray-500 border border-gray-200",title:"此消息未触发 agent 推荐,不涉及遵守判定"}};function F({verdict:m}){const l=H[m]??H.not_applicable;return e.jsx("span",{className:E("inline-flex items-center px-2 py-0.5 rounded text-xs whitespace-nowrap",l.className),title:l.title,children:l.label})}function K({events:m,routingTimestamp:l}){const[h,S]=y.useState(new Set),[n,N]=y.useState(!0),u=m.filter(t=>t.hook_type==="PostToolUse"&&t.tool_name),v=new Set(["Read","Grep","Glob"]),a=u.filter(t=>t.tool_name&&v.has(t.tool_name)),r=u.filter(t=>t.tool_name&&!v.has(t.tool_name)),o=t=>v.has(t)?"🔍":["Edit","Write","MultiEdit"].includes(t)?"✏️":t==="Bash"?"⚙️":["Agent","Task"].includes(t)?"🤖":"📦",j=t=>{S(c=>{const x=new Set(c);return x.has(t)?x.delete(t):x.add(t),x})},f=t=>{if(!t)return null;try{return JSON.parse(t)}catch{return null}};return e.jsxs("div",{className:"space-y-3",children:[a.length>0&&e.jsxs("div",{className:"border border-gray-200 rounded-lg p-3",children:[e.jsxs("button",{onClick:()=>N(!n),className:"flex items-center gap-2 text-sm text-gray-700 hover:text-gray-900 w-full",children:[e.jsxs("span",{children:["🔍 侦察 × ",a.length," 次"]}),e.jsx("span",{className:"text-xs text-gray-500",children:n?"(展开)":"(收起)"})]}),!n&&e.jsx("div",{className:"mt-2 space-y-2 pl-4 border-l-2 border-gray-200",children:a.map(t=>{const c=((new Date(t.timestamp).getTime()-l)/1e3).toFixed(1),x=f(t.tool_input),d=f(t.tool_output),g=h.has(t.event_id),_=d==null?void 0:d.error;return e.jsxs("div",{className:"text-xs",children:[e.jsxs("button",{onClick:()=>j(t.event_id),className:"flex items-center gap-2 hover:bg-gray-50 p-1 rounded w-full text-left",children:[e.jsxs("span",{className:"text-gray-400 font-mono",children:[c,"s"]}),e.jsx("span",{children:o(t.tool_name)}),e.jsx("span",{className:"font-medium",children:t.tool_name}),_?e.jsx("span",{className:"text-red-600",children:"✗"}):e.jsx("span",{className:"text-green-600",children:"•"})]}),g&&e.jsxs("div",{className:"mt-1 ml-4 space-y-1",children:[x&&e.jsxs("div",{children:[e.jsx("div",{className:"text-gray-500 mb-0.5",children:"Input:"}),e.jsx(b,{data:x,language:"json",maxHeight:"150px"})]}),d&&e.jsxs("div",{children:[e.jsx("div",{className:"text-gray-500 mb-0.5",children:"Output:"}),e.jsx(b,{data:d,language:"json",maxHeight:"150px"})]})]})]},t.event_id)})})]}),e.jsx("div",{className:"space-y-2 pl-4 border-l-2 border-indigo-200",children:r.map(t=>{const c=((new Date(t.timestamp).getTime()-l)/1e3).toFixed(1),x=f(t.tool_input),d=f(t.tool_output),g=h.has(t.event_id),_=d==null?void 0:d.error;return e.jsxs("div",{className:"text-sm",children:[e.jsxs("button",{onClick:()=>j(t.event_id),className:"flex items-center gap-2 hover:bg-gray-50 p-2 rounded w-full text-left",children:[e.jsxs("span",{className:"text-gray-400 font-mono text-xs",children:[c,"s"]}),e.jsx("span",{children:o(t.tool_name)}),e.jsx("span",{className:"font-medium",children:t.tool_name}),_?e.jsx("span",{className:"text-red-600",children:"✗"}):e.jsx("span",{className:"text-green-600",children:"•"})]}),g&&e.jsxs("div",{className:"mt-2 ml-8 space-y-2",children:[x&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"Input:"}),e.jsx(b,{data:x,language:"json",maxHeight:"200px"})]}),d&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"Output:"}),e.jsx(b,{data:d,language:"json",maxHeight:"200px"})]})]})]},t.event_id)})}),u.length===0&&e.jsx("div",{className:"text-center text-gray-500 text-sm py-8",children:"此次执行未产生工具调用记录"})]})}function P({events:m}){const[l,h]=y.useState(new Set),S=new Set(["Edit","Write","MultiEdit","Bash"]),n=m.filter(a=>a.hook_type==="PostToolUse"&&a.tool_name&&S.has(a.tool_name)),N=a=>{h(r=>{const o=new Set(r);return o.has(a)?o.delete(a):o.add(a),o})},u=a=>{if(!a)return null;try{return JSON.parse(a)}catch{return null}},v=a=>a?a.split(`
|
|
2
|
-
`).length:0;return e.jsxs("div",{className:"space-y-3",children:[n.map(a=>{const r=u(a.tool_input),o=u(a.tool_output),j=l.has(a.event_id);if(a.tool_name==="Bash"){const f=(r==null?void 0:r.command)||"",t=(o==null?void 0:o.stdout)||"",c=(o==null?void 0:o.stderr)||"";return e.jsxs("div",{className:"border border-gray-200 rounded-lg overflow-hidden",children:[e.jsxs("button",{onClick:()=>N(a.event_id),className:"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2",children:[e.jsx("span",{children:"⚙️"}),e.jsxs("span",{className:"font-mono text-sm flex-1 truncate",children:["$ ",f]}),e.jsx("span",{className:"text-xs text-gray-500",children:j?"收起":"展开"})]}),j&&e.jsxs("div",{className:"p-4 space-y-2",children:[t&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"stdout:"}),e.jsx(b,{data:t,language:"bash",maxHeight:"300px"})]}),c&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"stderr:"}),e.jsx(b,{data:c,language:"bash",maxHeight:"300px"})]})]})]},a.event_id)}if(["Edit","Write","MultiEdit"].includes(a.tool_name)){const f=(r==null?void 0:r.file_path)||"(unknown)",t=(r==null?void 0:r.old_string)||"",c=(r==null?void 0:r.new_string)||(r==null?void 0:r.content)||"",x=a.tool_name==="Write"||!t,d=v(c),g=v(t);return e.jsxs("div",{className:"border border-gray-200 rounded-lg overflow-hidden",children:[e.jsxs("button",{onClick:()=>N(a.event_id),className:"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2",children:[e.jsx("span",{children:"📄"}),e.jsx("span",{className:"font-mono text-sm flex-1 truncate",children:f}),e.jsx("span",{className:"text-xs px-2 py-0.5 rounded bg-blue-100 text-blue-700",children:x?"+新增":"~修改"}),!x&&e.jsxs("span",{className:"text-xs text-gray-500",children:["+",d,"/-",g]}),e.jsx("span",{className:"text-xs text-gray-500",children:j?"收起":"展开"})]}),j&&e.jsxs("div",{className:"p-4 space-y-2",children:[t&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"Before:"}),e.jsx(b,{data:t,language:"typescript",maxHeight:"200px"})]}),c&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:x?"Content:":"After:"}),e.jsx(b,{data:c,language:"typescript",maxHeight:"200px"})]})]})]},a.event_id)}return null}),n.length===0&&e.jsx("div",{className:"text-center text-gray-500 text-sm py-8",children:"此次执行未产生文件改动"})]})}async function Q(m){const l=await fetch(`/api/execution-trace/${m}`);if(!l.ok)throw new Error("Failed to fetch execution detail");return l.json()}function re(){const[m,l]=y.useState(""),[h,S]=y.useState(""),[n,N]=y.useState(null),[u,v]=y.useState("basic"),[a,r]=y.useState(!1),[o,j]=y.useState(!1),f=W(),t=D();y.useEffect(()=>{const s=new EventSource("/api/execution-trace/stream");return s.onopen=()=>r(!0),s.onerror=()=>r(!1),s.onmessage=i=>{try{JSON.parse(i.data).type==="execution-status"&&t.invalidateQueries({queryKey:["routing-events"]})}catch{}},()=>{s.close(),r(!1)}},[t]);const{data:c,isLoading:x}=k({queryKey:["routing-events",m],queryFn:()=>G(m),refetchInterval:1e4}),{data:d}=k({queryKey:["execution-detail",n==null?void 0:n.id],queryFn:()=>Q(n.id),enabled:n!==null}),g=y.useMemo(()=>{if(!c)return[];if(!h.trim())return c;const s=h.toLowerCase();return c.filter(i=>{var C,p,w;return((C=i.prompt)==null?void 0:C.toLowerCase().includes(s))||((p=i.routed_to_name)==null?void 0:p.toLowerCase().includes(s))||((w=i.first_tool_name)==null?void 0:w.toLowerCase().includes(s))})},[c,h]),_=s=>{const i=J();if(s==="json")L(`routing-events-${i}.json`,g);else{const C=g.map(p=>{let w={};try{w=JSON.parse(p.intent_json||"{}")}catch{}return{id:p.id,ts:p.ts?T(p.ts,"yyyy-MM-dd HH:mm:ss"):"",prompt:p.prompt,taskType:w.taskType||"",complexity:w.complexity||"",routed_to:p.routed_to_name||"",obeyed:p.obeyed===1?"yes":p.obeyed===0?"no":"",first_tool:p.first_tool_name||"",duration_ms:p.total_execution_ms||"",refusal_reason:p.refusal_reason||""}});q(`routing-events-${i}.csv`,C)}f.success(`已导出 ${g.length} 条追踪记录`),j(!1)};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-4 flex-wrap gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"执行追踪"}),e.jsx("div",{className:"flex items-center gap-2 mt-1",children:a?e.jsxs(e.Fragment,{children:[e.jsx($,{className:"h-3 w-3 text-green-500"}),e.jsx("span",{className:"text-xs text-green-600",children:"实时流已连接"})]}):e.jsxs(e.Fragment,{children:[e.jsx(B,{className:"h-3 w-3 text-gray-400"}),e.jsx("span",{className:"text-xs text-gray-500",children:"实时流未连接"})]})})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx(A,{value:h,onChange:S,placeholder:"搜索 prompt / agent / tool...",className:"w-56"}),e.jsx("div",{className:"flex items-center gap-1",children:V.map(s=>e.jsx("button",{onClick:()=>l(s.value),className:E("px-2.5 py-1.5 text-xs rounded-md",m===s.value?"bg-indigo-100 text-indigo-700":"bg-white text-gray-600 border border-gray-300 hover:bg-gray-50"),children:s.label},s.value))}),e.jsxs("div",{className:"relative",children:[e.jsxs("button",{onClick:()=>j(s=>!s),disabled:g.length===0,className:"inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-white border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50",children:[e.jsx(O,{className:"h-4 w-4"}),"导出"]}),o&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"fixed inset-0 z-10",onClick:()=>j(!1)}),e.jsxs("div",{className:"absolute right-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-20",children:[e.jsx("button",{onClick:()=>_("json"),className:"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50",children:"导出为 JSON"}),e.jsx("button",{onClick:()=>_("csv"),className:"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50",children:"导出为 CSV"})]})]})]})]})]}),e.jsxs("div",{className:"text-sm text-gray-500 mb-3",children:["显示 ",g.length," 条 ",h&&"(已过滤)"]}),e.jsx("div",{className:"bg-white rounded-lg shadow overflow-hidden",children:x?e.jsx("div",{className:"p-6",children:"加载中..."}):e.jsxs("table",{className:"min-w-full divide-y divide-gray-200",children:[e.jsx("thead",{className:"bg-gray-50",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"时间"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"提示"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"路由到"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"遵守"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"首工具"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"耗时"})]})}),e.jsxs("tbody",{className:"bg-white divide-y divide-gray-200",children:[g.map(s=>{let i={};try{i=JSON.parse(s.intent_json||"{}")}catch{}return e.jsxs("tr",{className:"hover:bg-gray-50 cursor-pointer",onClick:()=>N(s),children:[e.jsx("td",{className:"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500",children:T(s.ts,"MM-dd HH:mm:ss")}),e.jsxs("td",{className:"px-4 py-2 max-w-xs",children:[e.jsx("p",{className:"text-xs text-gray-700 truncate",title:s.prompt,children:s.prompt}),e.jsxs("p",{className:"text-xs text-gray-400 mt-0.5",children:[i.taskType," / ",i.complexity]})]}),e.jsx("td",{className:"px-4 py-2 whitespace-nowrap",children:s.routed_to_name?e.jsx("span",{className:"px-2 py-0.5 text-xs font-medium bg-indigo-100 text-indigo-700 rounded",children:s.routed_to_name}):e.jsx("span",{className:"text-xs text-gray-400",children:"未路由"})}),e.jsx("td",{className:"px-4 py-2 whitespace-nowrap",children:e.jsx(F,{verdict:s.verdict})}),e.jsx("td",{className:"px-4 py-2 whitespace-nowrap text-xs text-gray-700",children:s.first_tool_name||"-"}),e.jsx("td",{className:"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500",children:s.total_execution_ms?`${(s.total_execution_ms/1e3).toFixed(1)}s`:"-"})]},s.id)}),g.length===0&&e.jsx("tr",{children:e.jsxs("td",{colSpan:6,className:"px-4 py-12 text-center text-gray-500",children:[e.jsx(R,{className:"h-12 w-12 text-gray-300 mx-auto mb-2"}),h?"无匹配结果":"暂无追踪记录"]})})]})]})}),e.jsx(M,{open:n!==null,onClose:()=>{N(null),v("basic")},title:"Agent 执行详情",children:n&&d&&(()=>{let s={};try{s=JSON.parse(n.intent_json||"{}")}catch{}return e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"flex gap-2 border-b border-gray-200 pb-2",children:["basic","timeline","artifacts"].map(i=>e.jsxs("button",{onClick:()=>v(i),className:E("px-3 py-1.5 text-sm rounded-md transition-colors",u===i?"bg-indigo-100 text-indigo-700 font-medium":"text-gray-600 hover:bg-gray-100"),children:[i==="basic"&&"基本",i==="timeline"&&"过程",i==="artifacts"&&"产物"]},i))}),u==="basic"&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"用户提示"}),e.jsx("div",{className:"bg-purple-50 rounded p-3 text-sm text-gray-800 whitespace-pre-wrap",children:n.prompt})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"路由结果"}),e.jsx("div",{className:"text-sm font-medium",children:n.routed_to_name||"未路由"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"遵守状态"}),e.jsx("div",{children:e.jsx(F,{verdict:n.verdict})})]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"意图分类"}),e.jsx(b,{data:s,language:"json",maxHeight:"200px"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3 text-sm",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"首工具"}),e.jsx("div",{className:"font-mono",children:n.first_tool_name||"-"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"分类耗时"}),e.jsxs("div",{className:"font-mono",children:[n.classification_ms,"ms"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"总执行时间"}),e.jsx("div",{className:"font-mono",children:n.total_execution_ms?`${(n.total_execution_ms/1e3).toFixed(2)}s`:"-"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"完成原因"}),e.jsx("div",{children:n.completion_reason||"-"})]})]}),n.refusal_reason&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"违抗原因"}),e.jsx("div",{className:"bg-red-50 rounded p-3 text-sm text-red-700",children:n.refusal_reason})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"Session"}),e.jsx("div",{className:"text-xs font-mono text-gray-700",children:n.session_id})]})]}),u==="timeline"&&e.jsx(K,{events:d.events,routingTimestamp:n.ts}),u==="artifacts"&&e.jsx(P,{events:d.events})]})})()})]})}export{re as default};
|
|
3
|
-
//# sourceMappingURL=ExecutionTrace-BsWSpu2v.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ExecutionTrace-BsWSpu2v.js","sources":["../../src/pages/ExecutionTrace.tsx"],"sourcesContent":["import { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useState, useEffect, useMemo } from 'react'\nimport { format } from 'date-fns'\nimport { Activity, Wifi, WifiOff, Download } from 'lucide-react'\nimport clsx from 'clsx'\nimport Drawer from '../components/Drawer'\nimport CodeBlock from '../components/CodeBlock'\nimport SearchInput from '../components/SearchInput'\nimport { downloadJSON, downloadCSV, getTimestamp } from '../utils/export'\nimport { useToast } from '../components/Toast'\n\ninterface RoutingEvent {\n id: number\n session_id: string\n project_path: string\n ts: number\n prompt: string\n intent_json: string\n routed_to_type: string\n routed_to_name: string\n is_forced: number\n obeyed: number | null\n classification_ms: number\n fallback_used: number\n refusal_reason: string | null\n first_tool_name: string | null\n first_tool_ts: number | null\n completed_ts: number | null\n total_execution_ms: number | null\n completion_reason: string | null\n verdict: 'obeyed' | 'disobeyed' | 'investigation_only' | 'timeout' | 'no_action' | 'not_applicable'\n}\n\ninterface ExecutionDetail {\n routing: {\n id: number\n sessionId: string\n routeRequestId: string | null\n prompt: string\n timestamp: number\n intent: any\n routedToType: string | null\n routedToName: string | null\n obeyed: number | null\n verdict: RoutingEvent['verdict']\n classificationMs: number | null\n fallbackUsed: boolean\n refusalReason: string | null\n firstTool: string | null\n firstToolTs: number | null\n completedTs: number | null\n totalExecutionMs: number | null\n completionReason: string | null\n taskChain: any[]\n }\n events: Array<{\n event_id: string\n timestamp: string\n hook_type: string\n tool_name: string | null\n user_prompt: string | null\n tool_input: string | null\n tool_output: string | null\n }>\n injections: Array<{\n injection_type: string\n content: string\n timestamp: string\n }>\n agentCalls: Array<{\n toolEventId: number\n tool: string\n subagent: string | null\n startedTs: number\n allowed: boolean\n error: string | null\n completedTs: number | null\n completedEventId: string | null\n status: string\n }>\n}\n\nasync function fetchRoutingEvents(filter?: string): Promise<RoutingEvent[]> {\n let url = '/api/routing/events?limit=200'\n if (filter === 'obeyed') url += '&obeyed=1'\n else if (filter === 'refused') url += '&obeyed=0'\n else if (filter === 'unknown') url += '&obeyed=null'\n const res = await fetch(url)\n if (!res.ok) throw new Error('Failed to fetch')\n return res.json()\n}\n\nconst filters = [\n { value: '', label: '全部' },\n { value: 'obeyed', label: '✓ 遵守' },\n { value: 'refused', label: '✗ 违抗' },\n { value: 'unknown', label: '? 未判定' },\n]\n\ntype Verdict = RoutingEvent['verdict']\n\nconst VERDICT_META: Record<Verdict, { label: string; className: string; title: string }> = {\n obeyed: {\n label: '✓ 遵守',\n className: 'bg-green-100 text-green-800 border border-green-200',\n title: '调用了推荐的 agent',\n },\n disobeyed: {\n label: '✗ 违抗',\n className: 'bg-red-100 text-red-800 border border-red-200',\n title: '使用了其他工具而非推荐 agent',\n },\n investigation_only: {\n label: '◎ 仅侦察',\n className: 'bg-orange-100 text-orange-800 border border-orange-200',\n title: '只做了代码调查(Read/Grep/Glob),未调用推荐 agent',\n },\n timeout: {\n label: '⏱ 超时',\n className: 'bg-gray-100 text-gray-700 border border-gray-200',\n title: '30 秒内未检测到任何工具调用',\n },\n no_action: {\n label: '— 纯对话',\n className: 'bg-gray-100 text-gray-600 border border-gray-200',\n title: '未使用任何工具(纯文字回答)',\n },\n not_applicable: {\n label: '· 未适用',\n className: 'bg-gray-50 text-gray-500 border border-gray-200',\n title: '此消息未触发 agent 推荐,不涉及遵守判定',\n },\n}\n\nfunction VerdictBadge({ verdict }: { verdict: Verdict }) {\n const meta = VERDICT_META[verdict] ?? VERDICT_META.not_applicable\n return (\n <span\n className={clsx('inline-flex items-center px-2 py-0.5 rounded text-xs whitespace-nowrap', meta.className)}\n title={meta.title}\n >\n {meta.label}\n </span>\n )\n}\n\nfunction AgentTimeline({ events, routingTimestamp }: { events: ExecutionDetail['events']; routingTimestamp: number }) {\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set())\n const [collapsedInvestigation, setCollapsedInvestigation] = useState(true)\n\n const postToolUseEvents = events.filter(e => e.hook_type === 'PostToolUse' && e.tool_name)\n\n const investigationTools = new Set(['Read', 'Grep', 'Glob'])\n const investigationEvents = postToolUseEvents.filter(e => e.tool_name && investigationTools.has(e.tool_name))\n const otherEvents = postToolUseEvents.filter(e => e.tool_name && !investigationTools.has(e.tool_name))\n\n const getToolIcon = (toolName: string) => {\n if (investigationTools.has(toolName)) return '🔍'\n if (['Edit', 'Write', 'MultiEdit'].includes(toolName)) return '✏️'\n if (toolName === 'Bash') return '⚙️'\n if (['Agent', 'Task'].includes(toolName)) return '🤖'\n return '📦'\n }\n\n const toggleNode = (eventId: string) => {\n setExpandedNodes(prev => {\n const next = new Set(prev)\n if (next.has(eventId)) next.delete(eventId)\n else next.add(eventId)\n return next\n })\n }\n\n const parseToolData = (jsonStr: string | null) => {\n if (!jsonStr) return null\n try {\n return JSON.parse(jsonStr)\n } catch {\n return null\n }\n }\n\n return (\n <div className=\"space-y-3\">\n {investigationEvents.length > 0 && (\n <div className=\"border border-gray-200 rounded-lg p-3\">\n <button\n onClick={() => setCollapsedInvestigation(!collapsedInvestigation)}\n className=\"flex items-center gap-2 text-sm text-gray-700 hover:text-gray-900 w-full\"\n >\n <span>🔍 侦察 × {investigationEvents.length} 次</span>\n <span className=\"text-xs text-gray-500\">\n {collapsedInvestigation ? '(展开)' : '(收起)'}\n </span>\n </button>\n {!collapsedInvestigation && (\n <div className=\"mt-2 space-y-2 pl-4 border-l-2 border-gray-200\">\n {investigationEvents.map(e => {\n const offsetSec = ((new Date(e.timestamp).getTime() - routingTimestamp) / 1000).toFixed(1)\n const toolInput = parseToolData(e.tool_input)\n const toolOutput = parseToolData(e.tool_output)\n const isExpanded = expandedNodes.has(e.event_id)\n const hasError = toolOutput?.error\n\n return (\n <div key={e.event_id} className=\"text-xs\">\n <button\n onClick={() => toggleNode(e.event_id)}\n className=\"flex items-center gap-2 hover:bg-gray-50 p-1 rounded w-full text-left\"\n >\n <span className=\"text-gray-400 font-mono\">{offsetSec}s</span>\n <span>{getToolIcon(e.tool_name!)}</span>\n <span className=\"font-medium\">{e.tool_name}</span>\n {hasError ? (\n <span className=\"text-red-600\">✗</span>\n ) : (\n <span className=\"text-green-600\">•</span>\n )}\n </button>\n {isExpanded && (\n <div className=\"mt-1 ml-4 space-y-1\">\n {toolInput && (\n <div>\n <div className=\"text-gray-500 mb-0.5\">Input:</div>\n <CodeBlock data={toolInput} language=\"json\" maxHeight=\"150px\" />\n </div>\n )}\n {toolOutput && (\n <div>\n <div className=\"text-gray-500 mb-0.5\">Output:</div>\n <CodeBlock data={toolOutput} language=\"json\" maxHeight=\"150px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )}\n\n <div className=\"space-y-2 pl-4 border-l-2 border-indigo-200\">\n {otherEvents.map(e => {\n const offsetSec = ((new Date(e.timestamp).getTime() - routingTimestamp) / 1000).toFixed(1)\n const toolInput = parseToolData(e.tool_input)\n const toolOutput = parseToolData(e.tool_output)\n const isExpanded = expandedNodes.has(e.event_id)\n const hasError = toolOutput?.error\n\n return (\n <div key={e.event_id} className=\"text-sm\">\n <button\n onClick={() => toggleNode(e.event_id)}\n className=\"flex items-center gap-2 hover:bg-gray-50 p-2 rounded w-full text-left\"\n >\n <span className=\"text-gray-400 font-mono text-xs\">{offsetSec}s</span>\n <span>{getToolIcon(e.tool_name!)}</span>\n <span className=\"font-medium\">{e.tool_name}</span>\n {hasError ? (\n <span className=\"text-red-600\">✗</span>\n ) : (\n <span className=\"text-green-600\">•</span>\n )}\n </button>\n {isExpanded && (\n <div className=\"mt-2 ml-8 space-y-2\">\n {toolInput && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Input:</div>\n <CodeBlock data={toolInput} language=\"json\" maxHeight=\"200px\" />\n </div>\n )}\n {toolOutput && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Output:</div>\n <CodeBlock data={toolOutput} language=\"json\" maxHeight=\"200px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n })}\n </div>\n\n {postToolUseEvents.length === 0 && (\n <div className=\"text-center text-gray-500 text-sm py-8\">\n 此次执行未产生工具调用记录\n </div>\n )}\n </div>\n )\n}\n\nfunction ArtifactCards({ events }: { events: ExecutionDetail['events'] }) {\n const [expandedCards, setExpandedCards] = useState<Set<string>>(new Set())\n\n const artifactTools = new Set(['Edit', 'Write', 'MultiEdit', 'Bash'])\n const artifactEvents = events.filter(e =>\n e.hook_type === 'PostToolUse' && e.tool_name && artifactTools.has(e.tool_name)\n )\n\n const toggleCard = (eventId: string) => {\n setExpandedCards(prev => {\n const next = new Set(prev)\n if (next.has(eventId)) next.delete(eventId)\n else next.add(eventId)\n return next\n })\n }\n\n const parseToolData = (jsonStr: string | null) => {\n if (!jsonStr) return null\n try {\n return JSON.parse(jsonStr)\n } catch {\n return null\n }\n }\n\n const countLines = (str: string | undefined) => {\n if (!str) return 0\n return str.split('\\n').length\n }\n\n return (\n <div className=\"space-y-3\">\n {artifactEvents.map(e => {\n const toolInput = parseToolData(e.tool_input)\n const toolOutput = parseToolData(e.tool_output)\n const isExpanded = expandedCards.has(e.event_id)\n\n if (e.tool_name === 'Bash') {\n const command = toolInput?.command || ''\n const stdout = toolOutput?.stdout || ''\n const stderr = toolOutput?.stderr || ''\n\n return (\n <div key={e.event_id} className=\"border border-gray-200 rounded-lg overflow-hidden\">\n <button\n onClick={() => toggleCard(e.event_id)}\n className=\"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2\"\n >\n <span>⚙️</span>\n <span className=\"font-mono text-sm flex-1 truncate\">$ {command}</span>\n <span className=\"text-xs text-gray-500\">{isExpanded ? '收起' : '展开'}</span>\n </button>\n {isExpanded && (\n <div className=\"p-4 space-y-2\">\n {stdout && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">stdout:</div>\n <CodeBlock data={stdout} language=\"bash\" maxHeight=\"300px\" />\n </div>\n )}\n {stderr && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">stderr:</div>\n <CodeBlock data={stderr} language=\"bash\" maxHeight=\"300px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n }\n\n if (['Edit', 'Write', 'MultiEdit'].includes(e.tool_name!)) {\n const filePath = toolInput?.file_path || '(unknown)'\n const oldString = toolInput?.old_string || ''\n const newString = toolInput?.new_string || toolInput?.content || ''\n const isNew = e.tool_name === 'Write' || !oldString\n const addedLines = countLines(newString)\n const removedLines = countLines(oldString)\n\n return (\n <div key={e.event_id} className=\"border border-gray-200 rounded-lg overflow-hidden\">\n <button\n onClick={() => toggleCard(e.event_id)}\n className=\"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2\"\n >\n <span>📄</span>\n <span className=\"font-mono text-sm flex-1 truncate\">{filePath}</span>\n <span className=\"text-xs px-2 py-0.5 rounded bg-blue-100 text-blue-700\">\n {isNew ? '+新增' : '~修改'}\n </span>\n {!isNew && (\n <span className=\"text-xs text-gray-500\">\n +{addedLines}/-{removedLines}\n </span>\n )}\n <span className=\"text-xs text-gray-500\">{isExpanded ? '收起' : '展开'}</span>\n </button>\n {isExpanded && (\n <div className=\"p-4 space-y-2\">\n {oldString && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Before:</div>\n <CodeBlock data={oldString} language=\"typescript\" maxHeight=\"200px\" />\n </div>\n )}\n {newString && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">{isNew ? 'Content:' : 'After:'}</div>\n <CodeBlock data={newString} language=\"typescript\" maxHeight=\"200px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n }\n\n return null\n })}\n\n {artifactEvents.length === 0 && (\n <div className=\"text-center text-gray-500 text-sm py-8\">\n 此次执行未产生文件改动\n </div>\n )}\n </div>\n )\n}\n\nasync function fetchExecutionDetail(id: number): Promise<ExecutionDetail> {\n const res = await fetch(`/api/execution-trace/${id}`)\n if (!res.ok) throw new Error('Failed to fetch execution detail')\n return res.json()\n}\n\nexport default function ExecutionTrace() {\n const [filter, setFilter] = useState('')\n const [search, setSearch] = useState('')\n const [selectedEvent, setSelectedEvent] = useState<RoutingEvent | null>(null)\n const [activeTab, setActiveTab] = useState<'basic' | 'timeline' | 'artifacts'>('basic')\n const [sseConnected, setSseConnected] = useState(false)\n const [showExportMenu, setShowExportMenu] = useState(false)\n const toast = useToast()\n const queryClient = useQueryClient()\n\n useEffect(() => {\n const eventSource = new EventSource('/api/execution-trace/stream')\n eventSource.onopen = () => setSseConnected(true)\n eventSource.onerror = () => setSseConnected(false)\n eventSource.onmessage = (e) => {\n try {\n const data = JSON.parse(e.data)\n if (data.type === 'execution-status') {\n queryClient.invalidateQueries({ queryKey: ['routing-events'] })\n }\n } catch { /* ignore */ }\n }\n return () => {\n eventSource.close()\n setSseConnected(false)\n }\n }, [queryClient])\n\n const { data: events, isLoading } = useQuery({\n queryKey: ['routing-events', filter],\n queryFn: () => fetchRoutingEvents(filter),\n refetchInterval: 10000,\n })\n\n const { data: executionDetail } = useQuery({\n queryKey: ['execution-detail', selectedEvent?.id],\n queryFn: () => fetchExecutionDetail(selectedEvent!.id),\n enabled: selectedEvent !== null,\n })\n\n const filteredEvents = useMemo(() => {\n if (!events) return []\n if (!search.trim()) return events\n const q = search.toLowerCase()\n return events.filter(e =>\n e.prompt?.toLowerCase().includes(q) ||\n e.routed_to_name?.toLowerCase().includes(q) ||\n e.first_tool_name?.toLowerCase().includes(q)\n )\n }, [events, search])\n\n const handleExport = (exportFormat: 'json' | 'csv') => {\n const ts = getTimestamp()\n if (exportFormat === 'json') {\n downloadJSON(`routing-events-${ts}.json`, filteredEvents)\n } else {\n const flat = filteredEvents.map(e => {\n let intent: { taskType?: string; complexity?: string } = {}\n try { intent = JSON.parse(e.intent_json || '{}') } catch { /* ignore */ }\n return {\n id: e.id,\n ts: e.ts ? format(e.ts, 'yyyy-MM-dd HH:mm:ss') : '',\n prompt: e.prompt,\n taskType: intent.taskType || '',\n complexity: intent.complexity || '',\n routed_to: e.routed_to_name || '',\n obeyed: e.obeyed === 1 ? 'yes' : e.obeyed === 0 ? 'no' : '',\n first_tool: e.first_tool_name || '',\n duration_ms: e.total_execution_ms || '',\n refusal_reason: e.refusal_reason || '',\n }\n })\n downloadCSV(`routing-events-${ts}.csv`, flat)\n }\n toast.success(`已导出 ${filteredEvents.length} 条追踪记录`)\n setShowExportMenu(false)\n }\n\n return (\n <div>\n <div className=\"flex items-center justify-between mb-4 flex-wrap gap-3\">\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900\">执行追踪</h1>\n <div className=\"flex items-center gap-2 mt-1\">\n {sseConnected ? (\n <>\n <Wifi className=\"h-3 w-3 text-green-500\" />\n <span className=\"text-xs text-green-600\">实时流已连接</span>\n </>\n ) : (\n <>\n <WifiOff className=\"h-3 w-3 text-gray-400\" />\n <span className=\"text-xs text-gray-500\">实时流未连接</span>\n </>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <SearchInput\n value={search}\n onChange={setSearch}\n placeholder=\"搜索 prompt / agent / tool...\"\n className=\"w-56\"\n />\n <div className=\"flex items-center gap-1\">\n {filters.map((f) => (\n <button\n key={f.value}\n onClick={() => setFilter(f.value)}\n className={clsx(\n 'px-2.5 py-1.5 text-xs rounded-md',\n filter === f.value\n ? 'bg-indigo-100 text-indigo-700'\n : 'bg-white text-gray-600 border border-gray-300 hover:bg-gray-50'\n )}\n >\n {f.label}\n </button>\n ))}\n </div>\n <div className=\"relative\">\n <button\n onClick={() => setShowExportMenu(v => !v)}\n disabled={filteredEvents.length === 0}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-white border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50\"\n >\n <Download className=\"h-4 w-4\" />\n 导出\n </button>\n {showExportMenu && (\n <>\n <div className=\"fixed inset-0 z-10\" onClick={() => setShowExportMenu(false)} />\n <div className=\"absolute right-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-20\">\n <button\n onClick={() => handleExport('json')}\n className=\"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50\"\n >\n 导出为 JSON\n </button>\n <button\n onClick={() => handleExport('csv')}\n className=\"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50\"\n >\n 导出为 CSV\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n </div>\n\n <div className=\"text-sm text-gray-500 mb-3\">\n 显示 {filteredEvents.length} 条 {search && `(已过滤)`}\n </div>\n\n <div className=\"bg-white rounded-lg shadow overflow-hidden\">\n {isLoading ? (\n <div className=\"p-6\">加载中...</div>\n ) : (\n <table className=\"min-w-full divide-y divide-gray-200\">\n <thead className=\"bg-gray-50\">\n <tr>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">时间</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">提示</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">路由到</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">遵守</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">首工具</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">耗时</th>\n </tr>\n </thead>\n <tbody className=\"bg-white divide-y divide-gray-200\">\n {filteredEvents.map((e) => {\n let intent: any = {}\n try { intent = JSON.parse(e.intent_json || '{}') } catch { /* ignore */ }\n return (\n <tr\n key={e.id}\n className=\"hover:bg-gray-50 cursor-pointer\"\n onClick={() => setSelectedEvent(e)}\n >\n <td className=\"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500\">\n {format(e.ts, 'MM-dd HH:mm:ss')}\n </td>\n <td className=\"px-4 py-2 max-w-xs\">\n <p className=\"text-xs text-gray-700 truncate\" title={e.prompt}>{e.prompt}</p>\n <p className=\"text-xs text-gray-400 mt-0.5\">\n {intent.taskType} / {intent.complexity}\n </p>\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap\">\n {e.routed_to_name ? (\n <span className=\"px-2 py-0.5 text-xs font-medium bg-indigo-100 text-indigo-700 rounded\">\n {e.routed_to_name}\n </span>\n ) : (\n <span className=\"text-xs text-gray-400\">未路由</span>\n )}\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap\">\n <VerdictBadge verdict={e.verdict} />\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap text-xs text-gray-700\">\n {e.first_tool_name || '-'}\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500\">\n {e.total_execution_ms ? `${(e.total_execution_ms / 1000).toFixed(1)}s` : '-'}\n </td>\n </tr>\n )\n })}\n {filteredEvents.length === 0 && (\n <tr>\n <td colSpan={6} className=\"px-4 py-12 text-center text-gray-500\">\n <Activity className=\"h-12 w-12 text-gray-300 mx-auto mb-2\" />\n {search ? '无匹配结果' : '暂无追踪记录'}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n )}\n </div>\n\n <Drawer\n open={selectedEvent !== null}\n onClose={() => {\n setSelectedEvent(null)\n setActiveTab('basic')\n }}\n title=\"Agent 执行详情\"\n >\n {selectedEvent && executionDetail && (() => {\n let intent: any = {}\n try { intent = JSON.parse(selectedEvent.intent_json || '{}') } catch { /* ignore */ }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex gap-2 border-b border-gray-200 pb-2\">\n {(['basic', 'timeline', 'artifacts'] as const).map(tab => (\n <button\n key={tab}\n onClick={() => setActiveTab(tab)}\n className={clsx(\n 'px-3 py-1.5 text-sm rounded-md transition-colors',\n activeTab === tab\n ? 'bg-indigo-100 text-indigo-700 font-medium'\n : 'text-gray-600 hover:bg-gray-100'\n )}\n >\n {tab === 'basic' && '基本'}\n {tab === 'timeline' && '过程'}\n {tab === 'artifacts' && '产物'}\n </button>\n ))}\n </div>\n\n {activeTab === 'basic' && (\n <div className=\"space-y-4\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">用户提示</div>\n <div className=\"bg-purple-50 rounded p-3 text-sm text-gray-800 whitespace-pre-wrap\">\n {selectedEvent.prompt}\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">路由结果</div>\n <div className=\"text-sm font-medium\">\n {selectedEvent.routed_to_name || '未路由'}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">遵守状态</div>\n <div><VerdictBadge verdict={selectedEvent.verdict} /></div>\n </div>\n </div>\n\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">意图分类</div>\n <CodeBlock data={intent} language=\"json\" maxHeight=\"200px\" />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">首工具</div>\n <div className=\"font-mono\">{selectedEvent.first_tool_name || '-'}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">分类耗时</div>\n <div className=\"font-mono\">{selectedEvent.classification_ms}ms</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">总执行时间</div>\n <div className=\"font-mono\">\n {selectedEvent.total_execution_ms\n ? `${(selectedEvent.total_execution_ms / 1000).toFixed(2)}s`\n : '-'}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">完成原因</div>\n <div>{selectedEvent.completion_reason || '-'}</div>\n </div>\n </div>\n\n {selectedEvent.refusal_reason && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">违抗原因</div>\n <div className=\"bg-red-50 rounded p-3 text-sm text-red-700\">\n {selectedEvent.refusal_reason}\n </div>\n </div>\n )}\n\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Session</div>\n <div className=\"text-xs font-mono text-gray-700\">{selectedEvent.session_id}</div>\n </div>\n </div>\n )}\n\n {activeTab === 'timeline' && (\n <AgentTimeline\n events={executionDetail.events}\n routingTimestamp={selectedEvent.ts}\n />\n )}\n\n {activeTab === 'artifacts' && (\n <ArtifactCards events={executionDetail.events} />\n )}\n </div>\n )\n })()}\n </Drawer>\n </div>\n )\n}\n"],"names":["fetchRoutingEvents","filter","url","res","filters","VERDICT_META","VerdictBadge","verdict","meta","jsx","clsx","AgentTimeline","events","routingTimestamp","expandedNodes","setExpandedNodes","useState","collapsedInvestigation","setCollapsedInvestigation","postToolUseEvents","e","investigationTools","investigationEvents","otherEvents","getToolIcon","toolName","toggleNode","eventId","prev","next","parseToolData","jsonStr","jsxs","offsetSec","toolInput","toolOutput","isExpanded","hasError","CodeBlock","ArtifactCards","expandedCards","setExpandedCards","artifactTools","artifactEvents","toggleCard","countLines","str","command","stdout","stderr","filePath","oldString","newString","isNew","addedLines","removedLines","fetchExecutionDetail","id","ExecutionTrace","setFilter","search","setSearch","selectedEvent","setSelectedEvent","activeTab","setActiveTab","sseConnected","setSseConnected","showExportMenu","setShowExportMenu","toast","useToast","queryClient","useQueryClient","useEffect","eventSource","isLoading","useQuery","executionDetail","filteredEvents","useMemo","q","_a","_b","_c","handleExport","exportFormat","ts","getTimestamp","downloadJSON","flat","intent","format","downloadCSV","Fragment","Wifi","WifiOff","SearchInput","f","v","Download","Activity","Drawer","tab"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-2\.5{left:.625rem}.left-4{left:1rem}.right-0{right:0}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-1\/2{top:50%}.top-10{top:2.5rem}.top-4{top:1rem}.-z-10{z-index:-10}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.z-\[9999\]{z-index:9999}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-8{margin-left:2rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.line-clamp-3{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3}.block{display:block}.\!inline{display:inline!important}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-60{height:15rem}.h-8{height:2rem}.h-full{height:100%}.max-h-64{max-height:16rem}.max-h-\[500px\]{max-height:500px}.min-h-screen{min-height:100vh}.w-0\.5{width:.125rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-\[600px\]{width:600px}.w-\[800px\]{width:800px}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-full{min-width:100%}.max-w-2xl{max-width:42rem}.max-w-7xl{max-width:80rem}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-none{max-width:none}.max-w-xl{max-width:36rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x: 100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(229 231 235 / var(--tw-divide-opacity, 1))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l-2{border-left-width:2px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-amber-300{--tw-border-opacity: 1;border-color:rgb(252 211 77 / var(--tw-border-opacity, 1))}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-green-200{--tw-border-opacity: 1;border-color:rgb(187 247 208 / var(--tw-border-opacity, 1))}.border-indigo-200{--tw-border-opacity: 1;border-color:rgb(199 210 254 / var(--tw-border-opacity, 1))}.border-indigo-500{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.border-orange-200{--tw-border-opacity: 1;border-color:rgb(254 215 170 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-yellow-200{--tw-border-opacity: 1;border-color:rgb(254 240 138 / var(--tw-border-opacity, 1))}.border-t-blue-500{--tw-border-opacity: 1;border-top-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\/40{background-color:#0006}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-gray-600{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-green-300{--tw-bg-opacity: 1;background-color:rgb(134 239 172 / var(--tw-bg-opacity, 1))}.bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-indigo-100{--tw-bg-opacity: 1;background-color:rgb(224 231 255 / var(--tw-bg-opacity, 1))}.bg-indigo-50{--tw-bg-opacity: 1;background-color:rgb(238 242 255 / var(--tw-bg-opacity, 1))}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.bg-orange-100{--tw-bg-opacity: 1;background-color:rgb(255 237 213 / var(--tw-bg-opacity, 1))}.bg-purple-100{--tw-bg-opacity: 1;background-color:rgb(243 232 255 / var(--tw-bg-opacity, 1))}.bg-purple-50{--tw-bg-opacity: 1;background-color:rgb(250 245 255 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-sky-100{--tw-bg-opacity: 1;background-color:rgb(224 242 254 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity, 1))}.bg-yellow-600{--tw-bg-opacity: 1;background-color:rgb(202 138 4 / var(--tw-bg-opacity, 1))}.bg-opacity-0{--tw-bg-opacity: 0}.bg-opacity-50{--tw-bg-opacity: .5}.bg-opacity-75{--tw-bg-opacity: .75}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-indigo-500{--tw-gradient-from: #6366f1 var(--tw-gradient-from-position);--tw-gradient-to: rgb(99 102 241 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-purple-600{--tw-gradient-to: #9333ea var(--tw-gradient-to-position)}.p-1{padding:.25rem}.p-12{padding:3rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-2{padding-bottom:.5rem}.pb-4{padding-bottom:1rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-8{padding-left:2rem}.pr-10{padding-right:2.5rem}.pr-8{padding-right:2rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.tracking-wider{letter-spacing:.05em}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-green-800{--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.text-indigo-600{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.text-indigo-700{--tw-text-opacity: 1;color:rgb(67 56 202 / var(--tw-text-opacity, 1))}.text-orange-600{--tw-text-opacity: 1;color:rgb(234 88 12 / var(--tw-text-opacity, 1))}.text-orange-800{--tw-text-opacity: 1;color:rgb(154 52 18 / var(--tw-text-opacity, 1))}.text-purple-600{--tw-text-opacity: 1;color:rgb(147 51 234 / var(--tw-text-opacity, 1))}.text-purple-700{--tw-text-opacity: 1;color:rgb(126 34 206 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.text-sky-600{--tw-text-opacity: 1;color:rgb(2 132 199 / var(--tw-text-opacity, 1))}.text-sky-700{--tw-text-opacity: 1;color:rgb(3 105 161 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.text-yellow-700{--tw-text-opacity: 1;color:rgb(161 98 7 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.opacity-50{opacity:.5}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-amber-200{--tw-ring-opacity: 1;--tw-ring-color: rgb(253 230 138 / var(--tw-ring-opacity, 1))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-500{transition-duration:.5s}:root{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,sans-serif;line-height:1.5;font-weight:400;color-scheme:light;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{margin:0;min-height:100vh}.hover\:border-gray-300:hover{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.hover\:bg-amber-700:hover{--tw-bg-opacity: 1;background-color:rgb(180 83 9 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-indigo-700:hover{--tw-bg-opacity: 1;background-color:rgb(67 56 202 / var(--tw-bg-opacity, 1))}.hover\:bg-orange-50:hover{--tw-bg-opacity: 1;background-color:rgb(255 247 237 / var(--tw-bg-opacity, 1))}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:bg-yellow-700:hover{--tw-bg-opacity: 1;background-color:rgb(161 98 7 / var(--tw-bg-opacity, 1))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-gray-900:hover{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.hover\:text-indigo-700:hover{--tw-text-opacity: 1;color:rgb(67 56 202 / var(--tw-text-opacity, 1))}.hover\:text-red-600:hover{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.hover\:shadow-md:hover{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:border-indigo-500:focus{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-indigo-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-gray-400:disabled{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.disabled\:bg-gray-50:disabled{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.disabled\:text-gray-400:disabled{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width: 640px){.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}}@media (min-width: 768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:fixed{position:fixed}.lg\:inset-y-0{top:0;bottom:0}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:w-64{width:16rem}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:flex-col{flex-direction:column}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:pl-64{padding-left:16rem}}
|