@flanksource/clicky-ui 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.cjs +15 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +15 -0
- package/dist/ai.js.map +1 -1
- package/dist/data/ProgressBars.cjs +194 -0
- package/dist/data/ProgressBars.cjs.map +1 -0
- package/dist/data/ProgressBars.d.ts +85 -0
- package/dist/data/ProgressBars.d.ts.map +1 -0
- package/dist/data/ProgressBars.js +194 -0
- package/dist/data/ProgressBars.js.map +1 -0
- package/dist/data/ProgressBars.model.cjs +27 -0
- package/dist/data/ProgressBars.model.cjs.map +1 -0
- package/dist/data/ProgressBars.model.d.ts +20 -0
- package/dist/data/ProgressBars.model.d.ts.map +1 -0
- package/dist/data/ProgressBars.model.js +27 -0
- package/dist/data/ProgressBars.model.js.map +1 -0
- package/dist/data/TimeseriesCoreBars.cjs +19 -173
- package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts +9 -26
- package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.js +20 -174
- package/dist/data/TimeseriesCoreBars.js.map +1 -1
- package/dist/data/WorkloadCard.model.cjs.map +1 -1
- package/dist/data/WorkloadCard.model.d.ts +2 -2
- package/dist/data/WorkloadCard.model.d.ts.map +1 -1
- package/dist/data/WorkloadCard.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.cjs +275 -0
- package/dist/data/ai/SessionViewer.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.d.ts +33 -0
- package/dist/data/ai/SessionViewer.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.fixtures.d.ts +4 -0
- package/dist/data/ai/SessionViewer.fixtures.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.js +275 -0
- package/dist/data/ai/SessionViewer.js.map +1 -0
- package/dist/data/ai/SessionViewer.model.cjs +275 -0
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.model.d.ts +87 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.model.js +275 -0
- package/dist/data/ai/SessionViewer.model.js.map +1 -0
- package/dist/data/ai/SessionViewerMenu.cjs +190 -0
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -0
- package/dist/data/ai/SessionViewerMenu.d.ts +24 -0
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -0
- package/dist/data/ai/SessionViewerMenu.js +190 -0
- package/dist/data/ai/SessionViewerMenu.js.map +1 -0
- package/dist/data/ai/index.d.ts +3 -0
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/session-categories.cjs +219 -0
- package/dist/data/ai/session-categories.cjs.map +1 -0
- package/dist/data/ai/session-categories.d.ts +36 -0
- package/dist/data/ai/session-categories.d.ts.map +1 -0
- package/dist/data/ai/session-categories.js +219 -0
- package/dist/data/ai/session-categories.js.map +1 -0
- package/dist/data/test-runner/TestRunner.fixtures.d.ts.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.cjs.map +1 -1
- package/dist/data/version-info.js +3 -3
- package/dist/data/version-info.js.map +1 -1
- package/dist/data.cjs +4 -2
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +3 -2
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +4 -2
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +4 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/data/TimeseriesCoreBars.model.cjs +0 -27
- package/dist/data/TimeseriesCoreBars.model.cjs.map +0 -1
- package/dist/data/TimeseriesCoreBars.model.d.ts +0 -20
- package/dist/data/TimeseriesCoreBars.model.d.ts.map +0 -1
- package/dist/data/TimeseriesCoreBars.model.js +0 -27
- package/dist/data/TimeseriesCoreBars.model.js.map +0 -1
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const UiClose = require("../../icons/components/UiClose.cjs");
|
|
4
|
+
const UiHourglass = require("../../icons/components/UiHourglass.cjs");
|
|
5
|
+
const UiNetwork = require("../../icons/components/UiNetwork.cjs");
|
|
6
|
+
const UiCode2 = require("../../icons/components/UiCode2.cjs");
|
|
7
|
+
const UiCamera = require("../../icons/components/UiCamera.cjs");
|
|
8
|
+
const UiEye = require("../../icons/components/UiEye.cjs");
|
|
9
|
+
const UiCommand = require("../../icons/components/UiCommand.cjs");
|
|
10
|
+
const UiTerminal = require("../../icons/components/UiTerminal.cjs");
|
|
11
|
+
const UiSelect = require("../../icons/components/UiSelect.cjs");
|
|
12
|
+
const UiGlobe = require("../../icons/components/UiGlobe.cjs");
|
|
13
|
+
const UiCloudDownload = require("../../icons/components/UiCloudDownload.cjs");
|
|
14
|
+
const UiKanban = require("../../icons/components/UiKanban.cjs");
|
|
15
|
+
const UiQuestion = require("../../icons/components/UiQuestion.cjs");
|
|
16
|
+
const UiSearch = require("../../icons/components/UiSearch.cjs");
|
|
17
|
+
const UiStop = require("../../icons/components/UiStop.cjs");
|
|
18
|
+
const UiMagicWand = require("../../icons/components/UiMagicWand.cjs");
|
|
19
|
+
const UiRobotAi = require("../../icons/components/UiRobotAi.cjs");
|
|
20
|
+
const UiFileSearch = require("../../icons/components/UiFileSearch.cjs");
|
|
21
|
+
const UiEdit = require("../../icons/components/UiEdit.cjs");
|
|
22
|
+
const UiLayers = require("../../icons/components/UiLayers.cjs");
|
|
23
|
+
const UiSave = require("../../icons/components/UiSave.cjs");
|
|
24
|
+
const UiFileText = require("../../icons/components/UiFileText.cjs");
|
|
25
|
+
const UiImage = require("../../icons/components/UiImage.cjs");
|
|
26
|
+
const UiSparkles = require("../../icons/components/UiSparkles.cjs");
|
|
27
|
+
const UiPuzzle = require("../../icons/components/UiPuzzle.cjs");
|
|
28
|
+
const UiWrench = require("../../icons/components/UiWrench.cjs");
|
|
29
|
+
function truncate(text, max) {
|
|
30
|
+
return text.length <= max ? text : `${text.slice(0, max)}…`;
|
|
31
|
+
}
|
|
32
|
+
function parseEntries(input) {
|
|
33
|
+
if (Array.isArray(input)) return input;
|
|
34
|
+
const text = input.trim();
|
|
35
|
+
if (!text) return [];
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(text);
|
|
38
|
+
return Array.isArray(parsed) ? parsed : [parsed];
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
return text.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(line);
|
|
44
|
+
} catch {
|
|
45
|
+
throw new Error(`SessionViewer: invalid session JSON line: ${truncate(line, 80)}`);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function roleFromType(type) {
|
|
50
|
+
return type === "user" || type === "assistant" ? type : "assistant";
|
|
51
|
+
}
|
|
52
|
+
function toolEvent(id, tool, input, response, timestamp, meta = {}) {
|
|
53
|
+
return {
|
|
54
|
+
id,
|
|
55
|
+
kind: "tool",
|
|
56
|
+
tool,
|
|
57
|
+
...input ? { toolInput: input } : {},
|
|
58
|
+
...response ? { toolResponse: response } : {},
|
|
59
|
+
...timestamp ? { timestamp } : {},
|
|
60
|
+
...meta.model ? { model: meta.model } : {},
|
|
61
|
+
...meta.reasoningEffort ? { reasoningEffort: meta.reasoningEffort } : {},
|
|
62
|
+
...meta.source ? { source: meta.source } : {}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function blockEvent(block, role, id, timestamp) {
|
|
66
|
+
if (block.type === "tool_use" || block.name && block.input) {
|
|
67
|
+
if (!block.name) return null;
|
|
68
|
+
return toolEvent(id, block.name, block.input, void 0, timestamp);
|
|
69
|
+
}
|
|
70
|
+
if (block.type === "thinking" || block.thinking) {
|
|
71
|
+
const text = block.thinking ?? block.text;
|
|
72
|
+
return text ? { id, kind: "thinking", text, ...timestamp ? { timestamp } : {} } : null;
|
|
73
|
+
}
|
|
74
|
+
if (block.text) {
|
|
75
|
+
return {
|
|
76
|
+
id,
|
|
77
|
+
kind: role === "user" ? "user" : "assistant",
|
|
78
|
+
text: block.text,
|
|
79
|
+
...timestamp ? { timestamp } : {}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
function normalizeSession(input) {
|
|
85
|
+
const entries = parseEntries(input);
|
|
86
|
+
const events = [];
|
|
87
|
+
entries.forEach((entry, seq) => {
|
|
88
|
+
var _a, _b;
|
|
89
|
+
const baseId = entry.uuid ?? `e${seq}`;
|
|
90
|
+
if (entry.isApiErrorMessage) {
|
|
91
|
+
events.push({
|
|
92
|
+
id: `${baseId}-err`,
|
|
93
|
+
kind: "error",
|
|
94
|
+
text: errorMessage(entry),
|
|
95
|
+
...entry.error ? { errorType: entry.error } : {},
|
|
96
|
+
...entry.apiErrorStatus ? { errorStatus: entry.apiErrorStatus } : {},
|
|
97
|
+
...entry.timestamp ? { timestamp: entry.timestamp } : {}
|
|
98
|
+
});
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const tu = entry.tool_use;
|
|
102
|
+
if (tu == null ? void 0 : tu.tool) {
|
|
103
|
+
events.push(
|
|
104
|
+
toolEvent(`${baseId}-tool`, tu.tool, tu.input, tu.response, tu.timestamp ?? entry.timestamp, {
|
|
105
|
+
...tu.model ? { model: tu.model } : {},
|
|
106
|
+
...tu.reasoning_effort ? { reasoningEffort: tu.reasoning_effort } : {},
|
|
107
|
+
...tu.source ? { source: tu.source } : {}
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const role = roleFromType(((_a = entry.message) == null ? void 0 : _a.role) ?? entry.type);
|
|
113
|
+
for (const [i, block] of (((_b = entry.message) == null ? void 0 : _b.content) ?? []).entries()) {
|
|
114
|
+
const ev = blockEvent(block, role, `${baseId}-${i}`, entry.timestamp);
|
|
115
|
+
if (ev) events.push(ev);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
return events;
|
|
119
|
+
}
|
|
120
|
+
function errorMessage(entry) {
|
|
121
|
+
const status = entry.apiErrorStatus ? ` (HTTP ${entry.apiErrorStatus})` : "";
|
|
122
|
+
return `${entry.error ?? "API error"}${status}`;
|
|
123
|
+
}
|
|
124
|
+
const ACTIONS = {
|
|
125
|
+
// File operations
|
|
126
|
+
Read: { icon: UiFileText.UiFileText, tone: "sky", label: "Read file" },
|
|
127
|
+
Write: { icon: UiSave.UiSave, tone: "amber", label: "Write file" },
|
|
128
|
+
Edit: { icon: UiEdit.UiEdit, tone: "violet", label: "Edit file" },
|
|
129
|
+
MultiEdit: { icon: UiLayers.UiLayers, tone: "violet", label: "Multi-edit" },
|
|
130
|
+
NotebookEdit: { icon: UiEdit.UiEdit, tone: "violet", label: "Edit notebook" },
|
|
131
|
+
// Search & navigation
|
|
132
|
+
Grep: { icon: UiSearch.UiSearch, tone: "amber", label: "Grep" },
|
|
133
|
+
Glob: { icon: UiFileSearch.UiFileSearch, tone: "sky", label: "Glob" },
|
|
134
|
+
// Execution & shell
|
|
135
|
+
Bash: { icon: UiTerminal.UiTerminal, tone: "emerald", label: "Run command" },
|
|
136
|
+
BashOutput: { icon: UiCode2.UiCode2, tone: "emerald", label: "Shell output" },
|
|
137
|
+
KillShell: { icon: UiStop.UiStop, tone: "rose", label: "Kill shell" },
|
|
138
|
+
KillBash: { icon: UiStop.UiStop, tone: "rose", label: "Kill shell" },
|
|
139
|
+
// Agents & planning
|
|
140
|
+
Task: { icon: UiRobotAi.UiRobotAi, tone: "indigo", label: "Sub-agent task" },
|
|
141
|
+
Agent: { icon: UiRobotAi.UiRobotAi, tone: "indigo", label: "Sub-agent task" },
|
|
142
|
+
Skill: { icon: UiMagicWand.UiMagicWand, tone: "fuchsia", label: "Invoke skill" },
|
|
143
|
+
TodoWrite: { icon: UiKanban.UiKanban, tone: "sky", label: "Update todos" },
|
|
144
|
+
TaskCreate: { icon: UiKanban.UiKanban, tone: "sky", label: "Create task" },
|
|
145
|
+
TaskUpdate: { icon: UiKanban.UiKanban, tone: "sky", label: "Update task" },
|
|
146
|
+
TaskList: { icon: UiKanban.UiKanban, tone: "sky", label: "List tasks" },
|
|
147
|
+
TaskGet: { icon: UiKanban.UiKanban, tone: "sky", label: "Get task" },
|
|
148
|
+
TaskOutput: { icon: UiKanban.UiKanban, tone: "sky", label: "Task output" },
|
|
149
|
+
TaskStop: { icon: UiStop.UiStop, tone: "rose", label: "Stop task" },
|
|
150
|
+
ToolSearch: { icon: UiSearch.UiSearch, tone: "amber", label: "Search tools" },
|
|
151
|
+
AskUserQuestion: { icon: UiQuestion.UiQuestion, tone: "sky", label: "Ask user" },
|
|
152
|
+
EnterPlanMode: { icon: UiKanban.UiKanban, tone: "sky", label: "Enter plan mode" },
|
|
153
|
+
ExitPlanMode: { icon: UiKanban.UiKanban, tone: "sky", label: "Exit plan mode" },
|
|
154
|
+
// Web & browser automation
|
|
155
|
+
WebFetch: { icon: UiCloudDownload.UiCloudDownload, tone: "sky", label: "Fetch URL" },
|
|
156
|
+
WebSearch: { icon: UiGlobe.UiGlobe, tone: "sky", label: "Web search" },
|
|
157
|
+
browser_navigate: { icon: UiGlobe.UiGlobe, tone: "sky", label: "Navigate" },
|
|
158
|
+
browser_navigate_back: { icon: UiGlobe.UiGlobe, tone: "sky", label: "Navigate back" },
|
|
159
|
+
browser_click: { icon: UiSelect.UiSelect, tone: "sky", label: "Click" },
|
|
160
|
+
browser_triple_click: { icon: UiSelect.UiSelect, tone: "sky", label: "Triple click" },
|
|
161
|
+
browser_type: { icon: UiTerminal.UiTerminal, tone: "emerald", label: "Type text" },
|
|
162
|
+
browser_press_key: { icon: UiCommand.UiCommand, tone: "amber", label: "Press key" },
|
|
163
|
+
browser_snapshot: { icon: UiEye.UiEye, tone: "violet", label: "Snapshot" },
|
|
164
|
+
browser_take_screenshot: { icon: UiCamera.UiCamera, tone: "violet", label: "Screenshot" },
|
|
165
|
+
browser_evaluate: { icon: UiCode2.UiCode2, tone: "violet", label: "Evaluate JS" },
|
|
166
|
+
browser_network_requests: { icon: UiNetwork.UiNetwork, tone: "emerald", label: "Network" },
|
|
167
|
+
browser_wait_for: { icon: UiHourglass.UiHourglass, tone: "amber", label: "Wait" },
|
|
168
|
+
browser_close: { icon: UiClose.UiClose, tone: "rose", label: "Close browser" }
|
|
169
|
+
};
|
|
170
|
+
const MCP_ICON_SERVERS = /* @__PURE__ */ new Set(["iconify", "icons8", "lucide", "react-icons"]);
|
|
171
|
+
const MCP_GEN_SERVERS = /* @__PURE__ */ new Set(["gemini", "openai", "anthropic"]);
|
|
172
|
+
function splitMcpTool(tool) {
|
|
173
|
+
const rest = tool.startsWith("mcp__") ? tool.slice("mcp__".length) : tool;
|
|
174
|
+
const idx = rest.indexOf("__");
|
|
175
|
+
if (idx < 0) return null;
|
|
176
|
+
return { server: rest.slice(0, idx), name: rest.slice(idx + 2) };
|
|
177
|
+
}
|
|
178
|
+
function getSessionAction(tool) {
|
|
179
|
+
const exact = ACTIONS[tool];
|
|
180
|
+
if (exact) return exact;
|
|
181
|
+
const mcp = splitMcpTool(tool);
|
|
182
|
+
if (mcp) {
|
|
183
|
+
const label = `${mcp.server}: ${mcp.name.replace(/_/g, " ")}`;
|
|
184
|
+
if (MCP_ICON_SERVERS.has(mcp.server)) return { icon: UiImage.UiImage, tone: "pink", label };
|
|
185
|
+
if (MCP_GEN_SERVERS.has(mcp.server)) return { icon: UiSparkles.UiSparkles, tone: "violet", label };
|
|
186
|
+
return { icon: UiPuzzle.UiPuzzle, tone: "violet", label };
|
|
187
|
+
}
|
|
188
|
+
return { icon: UiWrench.UiWrench, tone: "slate", label: tool };
|
|
189
|
+
}
|
|
190
|
+
function summarizeToolInput(tool, input) {
|
|
191
|
+
if (!input) return "";
|
|
192
|
+
const str = (key) => typeof input[key] === "string" ? input[key] : "";
|
|
193
|
+
const first = (...keys) => {
|
|
194
|
+
for (const key of keys) {
|
|
195
|
+
const value = str(key);
|
|
196
|
+
if (value) return value;
|
|
197
|
+
}
|
|
198
|
+
return "";
|
|
199
|
+
};
|
|
200
|
+
const mcp = splitMcpTool(tool);
|
|
201
|
+
if (mcp) {
|
|
202
|
+
const arg = first("url", "sql", "query", "element", "method");
|
|
203
|
+
return arg ? truncate(arg, 80) : "";
|
|
204
|
+
}
|
|
205
|
+
switch (tool) {
|
|
206
|
+
case "Bash":
|
|
207
|
+
case "browser_type":
|
|
208
|
+
return truncate(str("command") || str("text"), 80);
|
|
209
|
+
case "Read":
|
|
210
|
+
case "Write":
|
|
211
|
+
case "Edit":
|
|
212
|
+
case "MultiEdit":
|
|
213
|
+
case "NotebookEdit":
|
|
214
|
+
return first("file_path", "notebook_path", "path");
|
|
215
|
+
case "Grep":
|
|
216
|
+
return [str("pattern"), str("path")].filter(Boolean).join(" ");
|
|
217
|
+
case "Glob":
|
|
218
|
+
return str("pattern");
|
|
219
|
+
case "Task":
|
|
220
|
+
case "Agent":
|
|
221
|
+
return truncate(first("description", "prompt"), 80);
|
|
222
|
+
case "Skill":
|
|
223
|
+
return first("skill", "command", "name");
|
|
224
|
+
case "TaskCreate":
|
|
225
|
+
return truncate(first("subject", "description"), 80);
|
|
226
|
+
case "TaskUpdate": {
|
|
227
|
+
const id = first("taskId", "task_id", "id");
|
|
228
|
+
const status = str("status");
|
|
229
|
+
return status ? `${id} ${status}`.trim() : id;
|
|
230
|
+
}
|
|
231
|
+
case "TaskGet":
|
|
232
|
+
case "TaskOutput":
|
|
233
|
+
case "TaskStop":
|
|
234
|
+
return first("task_id", "taskId", "id");
|
|
235
|
+
case "ToolSearch":
|
|
236
|
+
case "WebSearch":
|
|
237
|
+
return truncate(str("query"), 80);
|
|
238
|
+
case "WebFetch":
|
|
239
|
+
case "browser_navigate":
|
|
240
|
+
return str("url");
|
|
241
|
+
case "AskUserQuestion": {
|
|
242
|
+
const questions = input["questions"];
|
|
243
|
+
return Array.isArray(questions) ? `${questions.length} questions` : "";
|
|
244
|
+
}
|
|
245
|
+
case "ExitPlanMode":
|
|
246
|
+
return str("planFilePath");
|
|
247
|
+
default:
|
|
248
|
+
return "";
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function summarizeSession(events) {
|
|
252
|
+
let toolCount = 0;
|
|
253
|
+
let messageCount = 0;
|
|
254
|
+
const modelCounts = /* @__PURE__ */ new Map();
|
|
255
|
+
for (const event of events) {
|
|
256
|
+
if (event.kind === "tool") toolCount += 1;
|
|
257
|
+
if (event.kind === "user" || event.kind === "assistant") messageCount += 1;
|
|
258
|
+
if (event.model) modelCounts.set(event.model, (modelCounts.get(event.model) ?? 0) + 1);
|
|
259
|
+
}
|
|
260
|
+
let model;
|
|
261
|
+
let best = 0;
|
|
262
|
+
for (const [name, count] of modelCounts) {
|
|
263
|
+
if (count > best) {
|
|
264
|
+
best = count;
|
|
265
|
+
model = name;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return { toolCount, messageCount, ...model ? { model } : {} };
|
|
269
|
+
}
|
|
270
|
+
exports.getSessionAction = getSessionAction;
|
|
271
|
+
exports.normalizeSession = normalizeSession;
|
|
272
|
+
exports.splitMcpTool = splitMcpTool;
|
|
273
|
+
exports.summarizeSession = summarizeSession;
|
|
274
|
+
exports.summarizeToolInput = summarizeToolInput;
|
|
275
|
+
//# sourceMappingURL=SessionViewer.model.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionViewer.model.cjs","sources":["../../../src/data/ai/SessionViewer.model.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\nimport {\n UiCamera,\n UiClose,\n UiCloudDownload,\n UiCode2,\n UiCommand,\n UiEdit,\n UiEye,\n UiFileSearch,\n UiFileText,\n UiGlobe,\n UiHourglass,\n UiImage,\n UiKanban,\n UiLayers,\n UiMagicWand,\n UiNetwork,\n UiPuzzle,\n UiQuestion,\n UiRobotAi,\n UiSave,\n UiSearch,\n UiSelect,\n UiSparkles,\n UiStop,\n UiTerminal,\n UiWrench,\n} from \"../../icons\";\n\n// ── Captain session schema ──────────────────────────────────────────────────\n// Mirrors github.com/flanksource/captain pkg/ai/history types. A session is a\n// list of SessionEntry records (the rows of a Claude Code / Codex JSONL log).\n\nexport interface SessionToolUse {\n tool?: string;\n input?: Record<string, unknown>;\n timestamp?: string;\n cwd?: string;\n session_id?: string;\n tool_use_id?: string;\n /** \"claude\" or \"codex\". */\n source?: string;\n model?: string;\n reasoning_effort?: string;\n response?: string;\n}\n\nexport interface SessionContent {\n /** Block kind: \"text\", \"thinking\", \"tool_use\", \"tool_result\", … */\n type?: string;\n text?: string;\n thinking?: string;\n name?: string;\n input?: Record<string, unknown>;\n id?: string;\n}\n\nexport interface SessionMessage {\n role?: string;\n stop_reason?: string;\n content?: SessionContent[];\n}\n\nexport interface SessionEntry {\n /** Top-level entry kind: assistant, user, system, … */\n type?: string;\n tool_use?: SessionToolUse;\n message?: SessionMessage;\n timestamp?: string;\n cwd?: string;\n sessionId?: string;\n uuid?: string;\n /** Synthetic assistant entry Claude Code writes when an API request fails. */\n isApiErrorMessage?: boolean;\n apiErrorStatus?: number;\n /** Claude Code's error classification (e.g. \"rate_limit\"). */\n error?: string;\n}\n\n/** Either a parsed list of entries or the raw log text (JSON array or JSONL). */\nexport type SessionInput = string | SessionEntry[];\n\n// ── Normalized events ───────────────────────────────────────────────────────\n// The raw schema interleaves consolidated `tool_use` rows with `message`\n// content blocks. normalizeSession flattens both shapes into a single ordered\n// list the viewer can render row-by-row.\n\nexport type SessionEventKind = \"user\" | \"assistant\" | \"thinking\" | \"tool\" | \"error\";\n\nexport interface SessionEvent {\n id: string;\n kind: SessionEventKind;\n /** Tool name (kind === \"tool\"). */\n tool?: string;\n toolInput?: Record<string, unknown>;\n toolResponse?: string;\n /** Prose for user/assistant/thinking, or the error message for errors. */\n text?: string;\n timestamp?: string;\n model?: string;\n reasoningEffort?: string;\n source?: string;\n errorType?: string;\n errorStatus?: number;\n}\n\nfunction truncate(text: string, max: number): string {\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n\n// parseEntries accepts a parsed array as-is, or parses a string as a whole-\n// document JSON (array or single object, possibly pretty-printed) first, then\n// falls back to JSONL (one object per line). The whole-document parse error is\n// caught only to attempt the JSONL fallback — a genuinely malformed JSONL line\n// throws loudly rather than being silently dropped.\nfunction parseEntries(input: SessionInput): SessionEntry[] {\n if (Array.isArray(input)) return input;\n const text = input.trim();\n if (!text) return [];\n try {\n const parsed: unknown = JSON.parse(text);\n return Array.isArray(parsed) ? (parsed as SessionEntry[]) : [parsed as SessionEntry];\n } catch {\n // not a single JSON document — treat as JSONL below\n }\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n try {\n return JSON.parse(line) as SessionEntry;\n } catch {\n throw new Error(`SessionViewer: invalid session JSON line: ${truncate(line, 80)}`);\n }\n });\n}\n\nfunction roleFromType(type: string | undefined): string {\n return type === \"user\" || type === \"assistant\" ? type : \"assistant\";\n}\n\nfunction toolEvent(\n id: string,\n tool: string,\n input: Record<string, unknown> | undefined,\n response: string | undefined,\n timestamp: string | undefined,\n meta: { model?: string; reasoningEffort?: string; source?: string } = {},\n): SessionEvent {\n return {\n id,\n kind: \"tool\",\n tool,\n ...(input ? { toolInput: input } : {}),\n ...(response ? { toolResponse: response } : {}),\n ...(timestamp ? { timestamp } : {}),\n ...(meta.model ? { model: meta.model } : {}),\n ...(meta.reasoningEffort ? { reasoningEffort: meta.reasoningEffort } : {}),\n ...(meta.source ? { source: meta.source } : {}),\n };\n}\n\nfunction blockEvent(\n block: SessionContent,\n role: string,\n id: string,\n timestamp: string | undefined,\n): SessionEvent | null {\n if (block.type === \"tool_use\" || (block.name && block.input)) {\n if (!block.name) return null;\n return toolEvent(id, block.name, block.input, undefined, timestamp);\n }\n if (block.type === \"thinking\" || block.thinking) {\n const text = block.thinking ?? block.text;\n return text ? { id, kind: \"thinking\", text, ...(timestamp ? { timestamp } : {}) } : null;\n }\n if (block.text) {\n return {\n id,\n kind: role === \"user\" ? \"user\" : \"assistant\",\n text: block.text,\n ...(timestamp ? { timestamp } : {}),\n };\n }\n return null;\n}\n\n/** Flatten a captain session (entries or raw log text) into ordered events. */\nexport function normalizeSession(input: SessionInput): SessionEvent[] {\n const entries = parseEntries(input);\n const events: SessionEvent[] = [];\n entries.forEach((entry, seq) => {\n const baseId = entry.uuid ?? `e${seq}`;\n\n if (entry.isApiErrorMessage) {\n events.push({\n id: `${baseId}-err`,\n kind: \"error\",\n text: errorMessage(entry),\n ...(entry.error ? { errorType: entry.error } : {}),\n ...(entry.apiErrorStatus ? { errorStatus: entry.apiErrorStatus } : {}),\n ...(entry.timestamp ? { timestamp: entry.timestamp } : {}),\n });\n return;\n }\n\n const tu = entry.tool_use;\n if (tu?.tool) {\n events.push(\n toolEvent(`${baseId}-tool`, tu.tool, tu.input, tu.response, tu.timestamp ?? entry.timestamp, {\n ...(tu.model ? { model: tu.model } : {}),\n ...(tu.reasoning_effort ? { reasoningEffort: tu.reasoning_effort } : {}),\n ...(tu.source ? { source: tu.source } : {}),\n }),\n );\n return;\n }\n\n const role = roleFromType(entry.message?.role ?? entry.type);\n for (const [i, block] of (entry.message?.content ?? []).entries()) {\n const ev = blockEvent(block, role, `${baseId}-${i}`, entry.timestamp);\n if (ev) events.push(ev);\n }\n });\n return events;\n}\n\nfunction errorMessage(entry: SessionEntry): string {\n const status = entry.apiErrorStatus ? ` (HTTP ${entry.apiErrorStatus})` : \"\";\n return `${entry.error ?? \"API error\"}${status}`;\n}\n\n// ── Action icon registry ────────────────────────────────────────────────────\n// Implements the Flanksource \"Coding agent action icons\" design: every agent\n// tool maps to a Phosphor-derived generated icon (Ui*) and a semantic tone so a\n// scan of the log reads at a glance. Tones group by surface — file reads (sky),\n// writes (amber), edits (violet), execution (emerald), agents (indigo),\n// destructive (rose), assets (pink/fuchsia).\n\nexport type SessionTone =\n | \"sky\"\n | \"amber\"\n | \"violet\"\n | \"emerald\"\n | \"rose\"\n | \"indigo\"\n | \"fuchsia\"\n | \"pink\"\n | \"slate\";\n\nexport interface SessionActionMeta {\n icon: StaticIconComponent;\n tone: SessionTone;\n /** Human-readable verb shown as the row heading. */\n label: string;\n}\n\nconst ACTIONS: Record<string, SessionActionMeta> = {\n // File operations\n Read: { icon: UiFileText, tone: \"sky\", label: \"Read file\" },\n Write: { icon: UiSave, tone: \"amber\", label: \"Write file\" },\n Edit: { icon: UiEdit, tone: \"violet\", label: \"Edit file\" },\n MultiEdit: { icon: UiLayers, tone: \"violet\", label: \"Multi-edit\" },\n NotebookEdit: { icon: UiEdit, tone: \"violet\", label: \"Edit notebook\" },\n // Search & navigation\n Grep: { icon: UiSearch, tone: \"amber\", label: \"Grep\" },\n Glob: { icon: UiFileSearch, tone: \"sky\", label: \"Glob\" },\n // Execution & shell\n Bash: { icon: UiTerminal, tone: \"emerald\", label: \"Run command\" },\n BashOutput: { icon: UiCode2, tone: \"emerald\", label: \"Shell output\" },\n KillShell: { icon: UiStop, tone: \"rose\", label: \"Kill shell\" },\n KillBash: { icon: UiStop, tone: \"rose\", label: \"Kill shell\" },\n // Agents & planning\n Task: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Agent: { icon: UiRobotAi, tone: \"indigo\", label: \"Sub-agent task\" },\n Skill: { icon: UiMagicWand, tone: \"fuchsia\", label: \"Invoke skill\" },\n TodoWrite: { icon: UiKanban, tone: \"sky\", label: \"Update todos\" },\n TaskCreate: { icon: UiKanban, tone: \"sky\", label: \"Create task\" },\n TaskUpdate: { icon: UiKanban, tone: \"sky\", label: \"Update task\" },\n TaskList: { icon: UiKanban, tone: \"sky\", label: \"List tasks\" },\n TaskGet: { icon: UiKanban, tone: \"sky\", label: \"Get task\" },\n TaskOutput: { icon: UiKanban, tone: \"sky\", label: \"Task output\" },\n TaskStop: { icon: UiStop, tone: \"rose\", label: \"Stop task\" },\n ToolSearch: { icon: UiSearch, tone: \"amber\", label: \"Search tools\" },\n AskUserQuestion: { icon: UiQuestion, tone: \"sky\", label: \"Ask user\" },\n EnterPlanMode: { icon: UiKanban, tone: \"sky\", label: \"Enter plan mode\" },\n ExitPlanMode: { icon: UiKanban, tone: \"sky\", label: \"Exit plan mode\" },\n // Web & browser automation\n WebFetch: { icon: UiCloudDownload, tone: \"sky\", label: \"Fetch URL\" },\n WebSearch: { icon: UiGlobe, tone: \"sky\", label: \"Web search\" },\n browser_navigate: { icon: UiGlobe, tone: \"sky\", label: \"Navigate\" },\n browser_navigate_back: { icon: UiGlobe, tone: \"sky\", label: \"Navigate back\" },\n browser_click: { icon: UiSelect, tone: \"sky\", label: \"Click\" },\n browser_triple_click: { icon: UiSelect, tone: \"sky\", label: \"Triple click\" },\n browser_type: { icon: UiTerminal, tone: \"emerald\", label: \"Type text\" },\n browser_press_key: { icon: UiCommand, tone: \"amber\", label: \"Press key\" },\n browser_snapshot: { icon: UiEye, tone: \"violet\", label: \"Snapshot\" },\n browser_take_screenshot: { icon: UiCamera, tone: \"violet\", label: \"Screenshot\" },\n browser_evaluate: { icon: UiCode2, tone: \"violet\", label: \"Evaluate JS\" },\n browser_network_requests: { icon: UiNetwork, tone: \"emerald\", label: \"Network\" },\n browser_wait_for: { icon: UiHourglass, tone: \"amber\", label: \"Wait\" },\n browser_close: { icon: UiClose, tone: \"rose\", label: \"Close browser\" },\n};\n\n// MCP tools surface as `mcp__<server>__<name>` or `<server>__<name>`. Icon\n// servers get a distinct accent; generative servers reuse the sparkle; the rest\n// fall back to the puzzle piece.\nconst MCP_ICON_SERVERS = new Set([\"iconify\", \"icons8\", \"lucide\", \"react-icons\"]);\nconst MCP_GEN_SERVERS = new Set([\"gemini\", \"openai\", \"anthropic\"]);\n\ninterface McpTool {\n server: string;\n name: string;\n}\n\nexport function splitMcpTool(tool: string): McpTool | null {\n const rest = tool.startsWith(\"mcp__\") ? tool.slice(\"mcp__\".length) : tool;\n const idx = rest.indexOf(\"__\");\n if (idx < 0) return null;\n return { server: rest.slice(0, idx), name: rest.slice(idx + 2) };\n}\n\n/** Resolve the icon, tone, and label for a tool name. */\nexport function getSessionAction(tool: string): SessionActionMeta {\n const exact = ACTIONS[tool];\n if (exact) return exact;\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const label = `${mcp.server}: ${mcp.name.replace(/_/g, \" \")}`;\n if (MCP_ICON_SERVERS.has(mcp.server)) return { icon: UiImage, tone: \"pink\", label };\n if (MCP_GEN_SERVERS.has(mcp.server)) return { icon: UiSparkles, tone: \"violet\", label };\n return { icon: UiPuzzle, tone: \"violet\", label };\n }\n\n return { icon: UiWrench, tone: \"slate\", label: tool };\n}\n\n// summarizeToolInput condenses a tool's input into a one-line preview, ported\n// from captain's history.FormatToolUseSummary so the viewer reads like the CLI.\nexport function summarizeToolInput(tool: string, input?: Record<string, unknown>): string {\n if (!input) return \"\";\n const str = (key: string): string => (typeof input[key] === \"string\" ? (input[key] as string) : \"\");\n const first = (...keys: string[]): string => {\n for (const key of keys) {\n const value = str(key);\n if (value) return value;\n }\n return \"\";\n };\n\n const mcp = splitMcpTool(tool);\n if (mcp) {\n const arg = first(\"url\", \"sql\", \"query\", \"element\", \"method\");\n return arg ? truncate(arg, 80) : \"\";\n }\n\n switch (tool) {\n case \"Bash\":\n case \"browser_type\":\n return truncate(str(\"command\") || str(\"text\"), 80);\n case \"Read\":\n case \"Write\":\n case \"Edit\":\n case \"MultiEdit\":\n case \"NotebookEdit\":\n return first(\"file_path\", \"notebook_path\", \"path\");\n case \"Grep\":\n return [str(\"pattern\"), str(\"path\")].filter(Boolean).join(\" \");\n case \"Glob\":\n return str(\"pattern\");\n case \"Task\":\n case \"Agent\":\n return truncate(first(\"description\", \"prompt\"), 80);\n case \"Skill\":\n return first(\"skill\", \"command\", \"name\");\n case \"TaskCreate\":\n return truncate(first(\"subject\", \"description\"), 80);\n case \"TaskUpdate\": {\n const id = first(\"taskId\", \"task_id\", \"id\");\n const status = str(\"status\");\n return status ? `${id} ${status}`.trim() : id;\n }\n case \"TaskGet\":\n case \"TaskOutput\":\n case \"TaskStop\":\n return first(\"task_id\", \"taskId\", \"id\");\n case \"ToolSearch\":\n case \"WebSearch\":\n return truncate(str(\"query\"), 80);\n case \"WebFetch\":\n case \"browser_navigate\":\n return str(\"url\");\n case \"AskUserQuestion\": {\n const questions = input[\"questions\"];\n return Array.isArray(questions) ? `${questions.length} questions` : \"\";\n }\n case \"ExitPlanMode\":\n return str(\"planFilePath\");\n default:\n return \"\";\n }\n}\n\n/** Count tool-call events, the dominant model, and totals for the header. */\nexport function summarizeSession(events: SessionEvent[]): {\n toolCount: number;\n messageCount: number;\n model?: string;\n} {\n let toolCount = 0;\n let messageCount = 0;\n const modelCounts = new Map<string, number>();\n for (const event of events) {\n if (event.kind === \"tool\") toolCount += 1;\n if (event.kind === \"user\" || event.kind === \"assistant\") messageCount += 1;\n if (event.model) modelCounts.set(event.model, (modelCounts.get(event.model) ?? 0) + 1);\n }\n let model: string | undefined;\n let best = 0;\n for (const [name, count] of modelCounts) {\n if (count > best) {\n best = count;\n model = name;\n }\n }\n return { toolCount, messageCount, ...(model ? { model } : {}) };\n}\n"],"names":["UiFileText","UiSave","UiEdit","UiLayers","UiSearch","UiFileSearch","UiTerminal","UiCode2","UiStop","UiRobotAi","UiMagicWand","UiKanban","UiQuestion","UiCloudDownload","UiGlobe","UiSelect","UiCommand","UiEye","UiCamera","UiNetwork","UiHourglass","UiClose","UiImage","UiSparkles","UiPuzzle","UiWrench"],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { StaticIconComponent } from '../Icon';
|
|
2
|
+
export interface SessionToolUse {
|
|
3
|
+
tool?: string;
|
|
4
|
+
input?: Record<string, unknown>;
|
|
5
|
+
timestamp?: string;
|
|
6
|
+
cwd?: string;
|
|
7
|
+
session_id?: string;
|
|
8
|
+
tool_use_id?: string;
|
|
9
|
+
/** "claude" or "codex". */
|
|
10
|
+
source?: string;
|
|
11
|
+
model?: string;
|
|
12
|
+
reasoning_effort?: string;
|
|
13
|
+
response?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface SessionContent {
|
|
16
|
+
/** Block kind: "text", "thinking", "tool_use", "tool_result", … */
|
|
17
|
+
type?: string;
|
|
18
|
+
text?: string;
|
|
19
|
+
thinking?: string;
|
|
20
|
+
name?: string;
|
|
21
|
+
input?: Record<string, unknown>;
|
|
22
|
+
id?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface SessionMessage {
|
|
25
|
+
role?: string;
|
|
26
|
+
stop_reason?: string;
|
|
27
|
+
content?: SessionContent[];
|
|
28
|
+
}
|
|
29
|
+
export interface SessionEntry {
|
|
30
|
+
/** Top-level entry kind: assistant, user, system, … */
|
|
31
|
+
type?: string;
|
|
32
|
+
tool_use?: SessionToolUse;
|
|
33
|
+
message?: SessionMessage;
|
|
34
|
+
timestamp?: string;
|
|
35
|
+
cwd?: string;
|
|
36
|
+
sessionId?: string;
|
|
37
|
+
uuid?: string;
|
|
38
|
+
/** Synthetic assistant entry Claude Code writes when an API request fails. */
|
|
39
|
+
isApiErrorMessage?: boolean;
|
|
40
|
+
apiErrorStatus?: number;
|
|
41
|
+
/** Claude Code's error classification (e.g. "rate_limit"). */
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
/** Either a parsed list of entries or the raw log text (JSON array or JSONL). */
|
|
45
|
+
export type SessionInput = string | SessionEntry[];
|
|
46
|
+
export type SessionEventKind = "user" | "assistant" | "thinking" | "tool" | "error";
|
|
47
|
+
export interface SessionEvent {
|
|
48
|
+
id: string;
|
|
49
|
+
kind: SessionEventKind;
|
|
50
|
+
/** Tool name (kind === "tool"). */
|
|
51
|
+
tool?: string;
|
|
52
|
+
toolInput?: Record<string, unknown>;
|
|
53
|
+
toolResponse?: string;
|
|
54
|
+
/** Prose for user/assistant/thinking, or the error message for errors. */
|
|
55
|
+
text?: string;
|
|
56
|
+
timestamp?: string;
|
|
57
|
+
model?: string;
|
|
58
|
+
reasoningEffort?: string;
|
|
59
|
+
source?: string;
|
|
60
|
+
errorType?: string;
|
|
61
|
+
errorStatus?: number;
|
|
62
|
+
}
|
|
63
|
+
/** Flatten a captain session (entries or raw log text) into ordered events. */
|
|
64
|
+
export declare function normalizeSession(input: SessionInput): SessionEvent[];
|
|
65
|
+
export type SessionTone = "sky" | "amber" | "violet" | "emerald" | "rose" | "indigo" | "fuchsia" | "pink" | "slate";
|
|
66
|
+
export interface SessionActionMeta {
|
|
67
|
+
icon: StaticIconComponent;
|
|
68
|
+
tone: SessionTone;
|
|
69
|
+
/** Human-readable verb shown as the row heading. */
|
|
70
|
+
label: string;
|
|
71
|
+
}
|
|
72
|
+
interface McpTool {
|
|
73
|
+
server: string;
|
|
74
|
+
name: string;
|
|
75
|
+
}
|
|
76
|
+
export declare function splitMcpTool(tool: string): McpTool | null;
|
|
77
|
+
/** Resolve the icon, tone, and label for a tool name. */
|
|
78
|
+
export declare function getSessionAction(tool: string): SessionActionMeta;
|
|
79
|
+
export declare function summarizeToolInput(tool: string, input?: Record<string, unknown>): string;
|
|
80
|
+
/** Count tool-call events, the dominant model, and totals for the header. */
|
|
81
|
+
export declare function summarizeSession(events: SessionEvent[]): {
|
|
82
|
+
toolCount: number;
|
|
83
|
+
messageCount: number;
|
|
84
|
+
model?: string;
|
|
85
|
+
};
|
|
86
|
+
export {};
|
|
87
|
+
//# sourceMappingURL=SessionViewer.model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionViewer.model.d.ts","sourceRoot":"","sources":["../../../src/data/ai/SessionViewer.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAkCnD,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,YAAY,EAAE,CAAC;AAOnD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpF,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAoFD,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,EAAE,CAqCpE;AAcD,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,OAAO,GACP,QAAQ,GACR,SAAS,GACT,MAAM,GACN,QAAQ,GACR,SAAS,GACT,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;CACf;AAuDD,UAAU,OAAO;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAKzD;AAED,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAahE;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA8DxF;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAkBA"}
|