@creative-dswork/dscode 0.2.3 → 0.2.4
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/dscode.mjs
CHANGED
|
@@ -214348,7 +214348,7 @@ function generateRecoveryTimelineHTML(recoveryArcs) {
|
|
|
214348
214348
|
<span style="background:${COLORS.warn};color:#000;padding:4px 10px;border-radius:4px;font-size:12px;font-weight:600;white-space:nowrap;">\u{1F50D} Step ${arc.detectionStep}</span>
|
|
214349
214349
|
<span style="color:${COLORS.textMuted};font-size:14px;">\u2192</span>
|
|
214350
214350
|
<span style="background:${effectiveColor};color:#000;padding:4px 10px;border-radius:4px;font-size:12px;font-weight:600;white-space:nowrap;">${effectiveIcon} Step ${arc.correctionStep}</span>
|
|
214351
|
-
<span style="background:rgba(
|
|
214351
|
+
<span style="background:rgba(212,151,8,0.15);padding:2px 8px;border-radius:4px;font-size:11px;color:${COLORS.accent};">${detLabel}</span>
|
|
214352
214352
|
<span style="font-size:11px;color:${COLORS.textMuted};">${arc.stepsToRecover} steps</span>
|
|
214353
214353
|
${arc.misdiagnosisCount > 0 ? `<span style="background:rgba(210,153,29,0.15);padding:2px 8px;border-radius:4px;font-size:11px;color:${COLORS.warn};">${arc.misdiagnosisCount} \u6B21\u8BEF\u5224</span>` : ""}
|
|
214354
214354
|
</div>
|
|
@@ -214356,7 +214356,7 @@ function generateRecoveryTimelineHTML(recoveryArcs) {
|
|
|
214356
214356
|
<span style="color:${COLORS.danger};">${escapeHtml(arc.errorAgent)}</span>: ${escapeHtml(arc.errorSummary)}
|
|
214357
214357
|
\u2192 <span style="color:${effectiveColor};">${escapeHtml(arc.correctionAgent)}</span>: ${escapeHtml(arc.correctionSummary)}
|
|
214358
214358
|
</div>
|
|
214359
|
-
<div style="font-size:12px;color:${COLORS.accent};font-style:italic;padding:8px 12px;background:rgba(
|
|
214359
|
+
<div style="font-size:12px;color:${COLORS.accent};font-style:italic;padding:8px 12px;background:rgba(212,151,8,0.08);border-radius:4px;border-left:3px solid ${COLORS.accent};margin-top:8px;">
|
|
214360
214360
|
\u{1F4A1} \u6839\u56E0\u5047\u8BF4: ${escapeHtml(arc.rootCauseHypothesis)}
|
|
214361
214361
|
</div>
|
|
214362
214362
|
</div>`;
|
|
@@ -214444,7 +214444,7 @@ function generateRuleChainHTML(attribution, rulesApplied) {
|
|
|
214444
214444
|
"Rule3": "Irrecoverable Point \u2014 identifies the FIRST step that made the correct path unrecoverable (not necessarily the first error)"
|
|
214445
214445
|
};
|
|
214446
214446
|
const ruleItems = rulesApplied.map((r) => `
|
|
214447
|
-
<div style="padding:8px 12px;margin:4px 0;background:${r === "Rule3" ? "rgba(
|
|
214447
|
+
<div style="padding:8px 12px;margin:4px 0;background:${r === "Rule3" ? "rgba(224,85,83,0.15)" : "rgba(212,151,8,0.1)"};border-left:3px solid ${r === "Rule3" ? COLORS.danger : COLORS.accent};border-radius:4px;">
|
|
214448
214448
|
<strong style="color:${COLORS.accent};font-size:13px;">${escapeHtml(r)}</strong>
|
|
214449
214449
|
<div style="font-size:12px;color:${COLORS.textMuted};margin-top:2px;">${escapeHtml(ruleDescriptions[r] ?? "")}</div>
|
|
214450
214450
|
</div>`).join("");
|
|
@@ -214471,7 +214471,7 @@ function generateCascadePathHTML(cascadePath) {
|
|
|
214471
214471
|
<span style="font-family:monospace;font-size:13px;color:${COLORS.accent};">${escapeHtml(e.fromZoneId)}:${e.fromStepId}</span>
|
|
214472
214472
|
<span style="color:${COLORS.textMuted};font-size:18px;">\u2192</span>
|
|
214473
214473
|
<span style="font-family:monospace;font-size:13px;">${escapeHtml(e.toZoneId)}:${e.toStepId}</span>
|
|
214474
|
-
<span style="background:rgba(
|
|
214474
|
+
<span style="background:rgba(212,151,8,0.15);padding:2px 8px;border-radius:4px;font-size:11px;color:${COLORS.accent};">${mechanismLabel}</span>
|
|
214475
214475
|
<span style="font-size:11px;color:${COLORS.textMuted};">\u6570\u636E: ${escapeHtml(e.dataItem)}</span>
|
|
214476
214476
|
</div>`;
|
|
214477
214477
|
}).join("");
|
|
@@ -214503,9 +214503,9 @@ body {
|
|
|
214503
214503
|
max-width: 1200px;
|
|
214504
214504
|
margin: 0 auto;
|
|
214505
214505
|
}
|
|
214506
|
-
h1 { font-size: 28px; font-weight: 600; margin-bottom: 4px; color: #
|
|
214507
|
-
h2 { font-size: 20px; font-weight: 600; margin: 32px 0 16px; color: #
|
|
214508
|
-
h3 { font-size: 16px; font-weight: 600; margin-bottom: 8px; color: #
|
|
214506
|
+
h1 { font-size: 28px; font-weight: 600; margin-bottom: 4px; color: #e8e4dd; }
|
|
214507
|
+
h2 { font-size: 20px; font-weight: 600; margin: 32px 0 16px; color: #e8e4dd; border-bottom: 1px solid ${COLORS.border}; padding-bottom: 8px; }
|
|
214508
|
+
h3 { font-size: 16px; font-weight: 600; margin-bottom: 8px; color: #e8e4dd; }
|
|
214509
214509
|
.header { background: ${COLORS.card}; border: 1px solid ${COLORS.border}; border-radius: 8px; padding: 24px; margin-bottom: 24px; }
|
|
214510
214510
|
.header-meta { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; margin-top: 16px; }
|
|
214511
214511
|
.meta-item { }
|
|
@@ -214686,7 +214686,7 @@ ${(() => {
|
|
|
214686
214686
|
grouped[cat].push(r);
|
|
214687
214687
|
}
|
|
214688
214688
|
return Object.entries(grouped).map(([cat, catRules]) => `
|
|
214689
|
-
<h3 style="font-size:15px;font-weight:600;margin:24px 0 12px;color:#
|
|
214689
|
+
<h3 style="font-size:15px;font-weight:600;margin:24px 0 12px;color:#e8e4dd;">${escapeHtml(catLabels[cat] ?? cat)}</h3>
|
|
214690
214690
|
${catRules.map((r) => {
|
|
214691
214691
|
const sevLabel = r.severity >= 1 ? "ERROR" : r.severity >= 0.6 ? "WARN" : "INFO";
|
|
214692
214692
|
const sevColor = r.severity >= 1 ? COLORS.danger : r.severity >= 0.6 ? COLORS.warn : COLORS.accent;
|
|
@@ -214707,7 +214707,7 @@ ${catRules.map((r) => {
|
|
|
214707
214707
|
${r.rawDescription ? `
|
|
214708
214708
|
<details style="margin-bottom:8px;">
|
|
214709
214709
|
<summary style="font-size:11px;color:${COLORS.accent};cursor:pointer;">\u{1F4DD} \u8BE6\u7EC6\u63CF\u8FF0</summary>
|
|
214710
|
-
<p style="font-size:12px;color:${COLORS.textMuted};margin:4px 0;padding:8px;background:rgba(
|
|
214710
|
+
<p style="font-size:12px;color:${COLORS.textMuted};margin:4px 0;padding:8px;background:rgba(212,151,8,0.05);border-radius:4px;white-space:pre-wrap;">${escapeHtml(r.rawDescription)}</p>
|
|
214711
214711
|
</details>` : ""}
|
|
214712
214712
|
${r.severity >= 1 ? `<div style="font-size:11px;color:${COLORS.danger};margin-bottom:6px;">\u26A0 \u5EFA\u8BAE\u6301\u4E45\u5316\u5230 Agent \u914D\u7F6E (${escapeHtml(r.targetLayer)})</div>` : ""}
|
|
214713
214713
|
<div style="background:${COLORS.card};border-radius:4px;padding:10px 12px;">
|
|
@@ -214771,15 +214771,15 @@ var init_dashboard = __esm({
|
|
|
214771
214771
|
"src/eval/dashboard.ts"() {
|
|
214772
214772
|
"use strict";
|
|
214773
214773
|
COLORS = {
|
|
214774
|
-
ok: "#
|
|
214775
|
-
warn: "#
|
|
214776
|
-
danger: "#
|
|
214777
|
-
bg: "#
|
|
214778
|
-
card: "#
|
|
214779
|
-
border: "#
|
|
214780
|
-
text: "#
|
|
214781
|
-
textMuted: "#
|
|
214782
|
-
accent: "#
|
|
214774
|
+
ok: "#5ca860",
|
|
214775
|
+
warn: "#d4a017",
|
|
214776
|
+
danger: "#e05553",
|
|
214777
|
+
bg: "#1e1c19",
|
|
214778
|
+
card: "#282622",
|
|
214779
|
+
border: "#3a3732",
|
|
214780
|
+
text: "#e8e4dd",
|
|
214781
|
+
textMuted: "#8a8580",
|
|
214782
|
+
accent: "#d49708"
|
|
214783
214783
|
};
|
|
214784
214784
|
CASCADE_MECHANISM_LABELS = {
|
|
214785
214785
|
data_contamination: "\u6570\u636E\u6C61\u67D3",
|
|
@@ -220764,6 +220764,7 @@ import { createServer, request as httpRequest2 } from "node:http";
|
|
|
220764
220764
|
import { readFileSync as readFileSync23, existsSync as existsSync25 } from "node:fs";
|
|
220765
220765
|
import { join as join28, extname as extname2, resolve as resolve10 } from "node:path";
|
|
220766
220766
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
220767
|
+
import { streamSimple as streamSimple3 } from "@mariozechner/pi-ai";
|
|
220767
220768
|
function extractImagesFromToolResult(result) {
|
|
220768
220769
|
if (!result || typeof result !== "object") return void 0;
|
|
220769
220770
|
const r = result;
|
|
@@ -220816,6 +220817,7 @@ var init_web_backend = __esm({
|
|
|
220816
220817
|
// Context window broadcast throttling
|
|
220817
220818
|
contextWindowThrottleTimer = null;
|
|
220818
220819
|
contextWindowThrottlePending = false;
|
|
220820
|
+
lastArtifactHtml = "";
|
|
220819
220821
|
isAssistantTurn = false;
|
|
220820
220822
|
constructor(options) {
|
|
220821
220823
|
this.port = options.port;
|
|
@@ -221034,6 +221036,7 @@ var init_web_backend = __esm({
|
|
|
221034
221036
|
projectPath: s.projectPath || "",
|
|
221035
221037
|
preview: s.preview || "",
|
|
221036
221038
|
totalActiveMs: s.id === currentId2 ? sm2.getTotalActiveMs() : s.totalActiveMs ?? 0,
|
|
221039
|
+
contentHash: s.contentHash ?? "",
|
|
221037
221040
|
pendingPermission: s.pendingPermission || void 0
|
|
221038
221041
|
}))
|
|
221039
221042
|
});
|
|
@@ -221355,6 +221358,10 @@ var init_web_backend = __esm({
|
|
|
221355
221358
|
client.send({ type: "file_list_result", prefix: cmd.prefix, items });
|
|
221356
221359
|
break;
|
|
221357
221360
|
}
|
|
221361
|
+
case "artifact": {
|
|
221362
|
+
await this.handleArtifact(client, cmd);
|
|
221363
|
+
break;
|
|
221364
|
+
}
|
|
221358
221365
|
case "mcp": {
|
|
221359
221366
|
this.handleMcp(client, cmd);
|
|
221360
221367
|
break;
|
|
@@ -221412,6 +221419,7 @@ var init_web_backend = __esm({
|
|
|
221412
221419
|
projectPath: s.projectPath || "",
|
|
221413
221420
|
preview: s.preview || "",
|
|
221414
221421
|
totalActiveMs: s.id === currentId ? sessionManager.getTotalActiveMs() : s.totalActiveMs ?? 0,
|
|
221422
|
+
contentHash: s.contentHash ?? "",
|
|
221415
221423
|
pendingPermission: s.pendingPermission || void 0
|
|
221416
221424
|
}))
|
|
221417
221425
|
});
|
|
@@ -221442,6 +221450,7 @@ var init_web_backend = __esm({
|
|
|
221442
221450
|
projectPath: s.projectPath || "",
|
|
221443
221451
|
preview: s.preview || "",
|
|
221444
221452
|
totalActiveMs: s.id === currentId ? sm.getTotalActiveMs() : s.totalActiveMs ?? 0,
|
|
221453
|
+
contentHash: s.contentHash ?? "",
|
|
221445
221454
|
pendingPermission: s.pendingPermission || void 0
|
|
221446
221455
|
}))
|
|
221447
221456
|
});
|
|
@@ -221549,7 +221558,8 @@ var init_web_backend = __esm({
|
|
|
221549
221558
|
modelId: s.modelId,
|
|
221550
221559
|
projectPath: s.projectPath || "",
|
|
221551
221560
|
preview: s.preview || "",
|
|
221552
|
-
totalActiveMs: s.totalActiveMs ?? 0
|
|
221561
|
+
totalActiveMs: s.totalActiveMs ?? 0,
|
|
221562
|
+
contentHash: s.contentHash ?? ""
|
|
221553
221563
|
}))
|
|
221554
221564
|
});
|
|
221555
221565
|
}
|
|
@@ -221583,7 +221593,8 @@ var init_web_backend = __esm({
|
|
|
221583
221593
|
modelId: s.modelId,
|
|
221584
221594
|
projectPath: s.projectPath || "",
|
|
221585
221595
|
preview: s.preview || "",
|
|
221586
|
-
totalActiveMs: s.totalActiveMs ?? 0
|
|
221596
|
+
totalActiveMs: s.totalActiveMs ?? 0,
|
|
221597
|
+
contentHash: s.contentHash ?? ""
|
|
221587
221598
|
}));
|
|
221588
221599
|
client.send({ type: "sessions", data });
|
|
221589
221600
|
break;
|
|
@@ -221609,7 +221620,8 @@ var init_web_backend = __esm({
|
|
|
221609
221620
|
modelId: s.modelId,
|
|
221610
221621
|
projectPath: s.projectPath || "",
|
|
221611
221622
|
preview: s.preview || "",
|
|
221612
|
-
totalActiveMs: s.totalActiveMs ?? 0
|
|
221623
|
+
totalActiveMs: s.totalActiveMs ?? 0,
|
|
221624
|
+
contentHash: s.contentHash ?? ""
|
|
221613
221625
|
}))
|
|
221614
221626
|
});
|
|
221615
221627
|
break;
|
|
@@ -221738,7 +221750,8 @@ ${matchList}` });
|
|
|
221738
221750
|
modelId: s.modelId,
|
|
221739
221751
|
projectPath: s.projectPath || "",
|
|
221740
221752
|
preview: s.preview || "",
|
|
221741
|
-
totalActiveMs: s.totalActiveMs ?? 0
|
|
221753
|
+
totalActiveMs: s.totalActiveMs ?? 0,
|
|
221754
|
+
contentHash: s.contentHash ?? ""
|
|
221742
221755
|
}))
|
|
221743
221756
|
});
|
|
221744
221757
|
break;
|
|
@@ -221939,6 +221952,224 @@ ${matchList}` });
|
|
|
221939
221952
|
res.end("Not Found");
|
|
221940
221953
|
}
|
|
221941
221954
|
}
|
|
221955
|
+
async handleArtifact(client, cmd) {
|
|
221956
|
+
try {
|
|
221957
|
+
let styleConstraints = "";
|
|
221958
|
+
try {
|
|
221959
|
+
const skillPath = join28(this.config.projectPath, ".dscode", "html_output_skill");
|
|
221960
|
+
if (existsSync25(skillPath)) {
|
|
221961
|
+
styleConstraints = readFileSync23(skillPath, "utf-8");
|
|
221962
|
+
}
|
|
221963
|
+
} catch {
|
|
221964
|
+
}
|
|
221965
|
+
const designColors = `DESIGN SYSTEM COLORS (MUST use these exact hex values for EVERY color in your HTML):
|
|
221966
|
+
- Background: #f8f7f5
|
|
221967
|
+
- Surface: #f3f2ef
|
|
221968
|
+
- Border: #e6e4e0
|
|
221969
|
+
- Text: #2d2a26
|
|
221970
|
+
- Muted Text: #8a8580
|
|
221971
|
+
- Accent: #ca8a04 (warm amber/gold \u2014 use for highlights, progress bars, headings)
|
|
221972
|
+
- Success: #347539 text on #edf4ed background
|
|
221973
|
+
- Error: #9f2f2d text on #fdebec background
|
|
221974
|
+
- Warning: #956400 text on #fbf3db background
|
|
221975
|
+
- User Bubble: #ca8a04 background, #ffffff text`;
|
|
221976
|
+
const defaultStyleConstraints = `CRITICAL STYLE RULES:
|
|
221977
|
+
- Use the exact hex colors from DESIGN SYSTEM COLORS above \u2014 do NOT substitute with other greens, reds, or blues
|
|
221978
|
+
- Flat design: 1px solid var(--border) borders, no box-shadow, no gradients
|
|
221979
|
+
- Border-radius: 8px for cards/panels, 6px for buttons, 12px for large containers
|
|
221980
|
+
- Typography: system-ui, -apple-system, sans-serif for labels; monospace for data values
|
|
221981
|
+
- Emoji for visual markers, CSS conic-gradient or inline SVG for chart-like elements
|
|
221982
|
+
- Background MUST be #f8f7f5, never white (#fff) or transparent
|
|
221983
|
+
- Text MUST be #2d2a26, never pure black (#000) or cold gray
|
|
221984
|
+
- The accent color MUST be #ca8a04 (warm amber), never blue`;
|
|
221985
|
+
const systemPrompt = `You are an expert HTML dashboard designer. Generate a single, self-contained HTML file.
|
|
221986
|
+
|
|
221987
|
+
CRITICAL RULES:
|
|
221988
|
+
- Output ONLY valid HTML starting with <!DOCTYPE html>
|
|
221989
|
+
- All CSS MUST be inlined in <style> tags within <head>
|
|
221990
|
+
- NO external resources (fonts, images, scripts, CDN links)
|
|
221991
|
+
- Use system-ui, -apple-system, sans-serif for labels and monospace for data values
|
|
221992
|
+
- Use emoji icons for visual markers
|
|
221993
|
+
- Use CSS conic-gradient or inline SVG for chart-like elements
|
|
221994
|
+
- Make it visually rich and data-dense
|
|
221995
|
+
- Self-contained, single HTML document
|
|
221996
|
+
|
|
221997
|
+
${designColors}
|
|
221998
|
+
|
|
221999
|
+
${styleConstraints ? `ARTIFACT STYLE RULES (from .dscode/html_output_skill):
|
|
222000
|
+
${styleConstraints}
|
|
222001
|
+
` : defaultStyleConstraints}
|
|
222002
|
+
|
|
222003
|
+
Respond ONLY with the raw HTML starting with <!DOCTYPE html>. DO NOT wrap the output in markdown code fences (no \`\`\`html). DO NOT add any explanatory text before or after the HTML. Just output the HTML directly.`;
|
|
222004
|
+
let sessionSummary = "";
|
|
222005
|
+
if (cmd.context === "session_dashboard" || cmd.action === "generate") {
|
|
222006
|
+
sessionSummary = this.buildSessionSummary();
|
|
222007
|
+
}
|
|
222008
|
+
let userPrompt;
|
|
222009
|
+
if (cmd.action === "generate") {
|
|
222010
|
+
userPrompt = `Create a rich visual dashboard for this coding session. Use the data below to build a comprehensive, beautiful dashboard:
|
|
222011
|
+
|
|
222012
|
+
${sessionSummary}
|
|
222013
|
+
|
|
222014
|
+
Make it visually stunning with emojis, progress bars, color-coded metrics, and CSS charts.`;
|
|
222015
|
+
} else {
|
|
222016
|
+
const existingHtml = this.lastArtifactHtml || "";
|
|
222017
|
+
userPrompt = `Here is the current dashboard HTML:
|
|
222018
|
+
|
|
222019
|
+
${existingHtml.slice(0, 5e3)}
|
|
222020
|
+
|
|
222021
|
+
User instruction: ${cmd.instruction || "update the dashboard"}
|
|
222022
|
+
|
|
222023
|
+
Modify the HTML to fulfill the user's request. Output the complete modified HTML.`;
|
|
222024
|
+
}
|
|
222025
|
+
const model = resolveModel(this.config.provider, this.config.modelId);
|
|
222026
|
+
client.send({ type: "artifact_start" });
|
|
222027
|
+
let fullHtml = "";
|
|
222028
|
+
const stream = streamSimple3(model, {
|
|
222029
|
+
systemPrompt,
|
|
222030
|
+
messages: [{ role: "user", content: userPrompt, timestamp: Date.now() }]
|
|
222031
|
+
}, {
|
|
222032
|
+
apiKey: this.config.apiKey,
|
|
222033
|
+
maxTokens: this.config.maxTokens,
|
|
222034
|
+
timeoutMs: 12e4,
|
|
222035
|
+
maxRetries: 1
|
|
222036
|
+
});
|
|
222037
|
+
for await (const event of stream) {
|
|
222038
|
+
if (event.type === "text_delta") {
|
|
222039
|
+
fullHtml += event.delta;
|
|
222040
|
+
client.send({ type: "artifact_delta", delta: event.delta });
|
|
222041
|
+
} else if (event.type === "error") {
|
|
222042
|
+
client.send({ type: "error", text: `Artifact generation error: ${event.errorMessage || "Unknown error"}` });
|
|
222043
|
+
}
|
|
222044
|
+
}
|
|
222045
|
+
fullHtml = this.stripArtifactFences(fullHtml);
|
|
222046
|
+
this.lastArtifactHtml = fullHtml;
|
|
222047
|
+
client.send({ type: "artifact_end" });
|
|
222048
|
+
} catch (err) {
|
|
222049
|
+
client.send({ type: "artifact_end" });
|
|
222050
|
+
client.send({
|
|
222051
|
+
type: "error",
|
|
222052
|
+
text: `Artifact generation failed: ${err instanceof Error ? err.message : String(err)}`
|
|
222053
|
+
});
|
|
222054
|
+
}
|
|
222055
|
+
}
|
|
222056
|
+
stripArtifactFences(html) {
|
|
222057
|
+
let result = html.trim();
|
|
222058
|
+
const fencePattern = /^```(?:html)?\s*\n/;
|
|
222059
|
+
result = result.replace(fencePattern, "");
|
|
222060
|
+
const endFence = /\n```\s*$/;
|
|
222061
|
+
result = result.replace(endFence, "");
|
|
222062
|
+
if (!result.trimStart().startsWith("<")) {
|
|
222063
|
+
return html;
|
|
222064
|
+
}
|
|
222065
|
+
return result;
|
|
222066
|
+
}
|
|
222067
|
+
buildSessionSummary() {
|
|
222068
|
+
const sm = this.harness.sessionManager;
|
|
222069
|
+
const agent = this.harness.agent;
|
|
222070
|
+
const cm = this.harness.contextManager;
|
|
222071
|
+
const messages = agent.state.messages;
|
|
222072
|
+
const tools = this.currentAssistant?.tools ?? [];
|
|
222073
|
+
const breakdown = cm.getCategoryBreakdown(messages, tools, this.getSkillToolNames());
|
|
222074
|
+
const totalTokens = breakdown.total;
|
|
222075
|
+
const usedTokens = breakdown.used;
|
|
222076
|
+
const freeTokens = breakdown.free;
|
|
222077
|
+
const usagePercent = totalTokens > 0 ? Math.round(usedTokens / totalTokens * 100) : 0;
|
|
222078
|
+
const categories = breakdown.categories;
|
|
222079
|
+
const toolStats = /* @__PURE__ */ new Map();
|
|
222080
|
+
for (const msg of messages) {
|
|
222081
|
+
const m = msg;
|
|
222082
|
+
if (m.role === "assistant" && Array.isArray(m.content)) {
|
|
222083
|
+
for (const block of m.content) {
|
|
222084
|
+
if (block.type === "toolCall") {
|
|
222085
|
+
const name = block.name || "unknown";
|
|
222086
|
+
const existing = toolStats.get(name) || { calls: 0, errors: 0 };
|
|
222087
|
+
existing.calls++;
|
|
222088
|
+
toolStats.set(name, existing);
|
|
222089
|
+
}
|
|
222090
|
+
}
|
|
222091
|
+
}
|
|
222092
|
+
if (m.role === "toolResult" && m.isError) {
|
|
222093
|
+
const name = m.toolName || "unknown";
|
|
222094
|
+
const existing = toolStats.get(name);
|
|
222095
|
+
if (existing) {
|
|
222096
|
+
existing.errors++;
|
|
222097
|
+
} else {
|
|
222098
|
+
toolStats.set(name, { calls: 0, errors: 1 });
|
|
222099
|
+
}
|
|
222100
|
+
}
|
|
222101
|
+
}
|
|
222102
|
+
const toolEntries = Array.from(toolStats.entries()).map(([name, stats]) => ({
|
|
222103
|
+
name,
|
|
222104
|
+
callCount: stats.calls,
|
|
222105
|
+
errorCount: stats.errors,
|
|
222106
|
+
successCount: stats.calls - stats.errors,
|
|
222107
|
+
successRate: stats.calls > 0 ? Math.round((stats.calls - stats.errors) / stats.calls * 100) : 100
|
|
222108
|
+
})).sort((a, b) => b.callCount - a.callCount);
|
|
222109
|
+
const totalToolCalls = toolEntries.reduce((sum, t) => sum + t.callCount, 0);
|
|
222110
|
+
const totalToolErrors = toolEntries.reduce((sum, t) => sum + t.errorCount, 0);
|
|
222111
|
+
const sessionActiveMs = sm?.getTotalActiveMs?.() ?? 0;
|
|
222112
|
+
const turnCount = messages.filter((m) => m.role === "user").length;
|
|
222113
|
+
const avgTurnMs = turnCount > 0 ? Math.round(sessionActiveMs / turnCount) : 0;
|
|
222114
|
+
const pressureScore = totalTokens > 0 ? Math.round(usedTokens / totalTokens * 100) : 0;
|
|
222115
|
+
let pressureLabel = "low";
|
|
222116
|
+
if (pressureScore > 95) pressureLabel = "critical";
|
|
222117
|
+
else if (pressureScore > 80) pressureLabel = "high";
|
|
222118
|
+
else if (pressureScore > 50) pressureLabel = "moderate";
|
|
222119
|
+
const topTools = toolEntries.slice(0, 3).map((t) => ({
|
|
222120
|
+
name: t.name,
|
|
222121
|
+
successRate: t.successRate,
|
|
222122
|
+
warning: t.errorCount > 0 && t.errorCount / t.callCount > 0.2 ? "\u26A0\uFE0F" : ""
|
|
222123
|
+
}));
|
|
222124
|
+
function formatMs(ms) {
|
|
222125
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
222126
|
+
const sec = Math.floor(ms / 1e3);
|
|
222127
|
+
if (sec < 60) return `${sec}s`;
|
|
222128
|
+
const min = Math.floor(sec / 60);
|
|
222129
|
+
const remainSec = sec % 60;
|
|
222130
|
+
if (min < 60) return `${min}m ${remainSec}s`;
|
|
222131
|
+
const hrs = Math.floor(min / 60);
|
|
222132
|
+
const remainMin = min % 60;
|
|
222133
|
+
return `${hrs}h ${remainMin}m`;
|
|
222134
|
+
}
|
|
222135
|
+
return JSON.stringify({
|
|
222136
|
+
tokenUsage: {
|
|
222137
|
+
total: totalTokens,
|
|
222138
|
+
used: usedTokens,
|
|
222139
|
+
free: freeTokens,
|
|
222140
|
+
usagePercent,
|
|
222141
|
+
categories: {
|
|
222142
|
+
system: categories.system ?? null,
|
|
222143
|
+
rules: categories.rules ?? null,
|
|
222144
|
+
user: categories.user ?? null,
|
|
222145
|
+
thinking: categories.thinking ?? null,
|
|
222146
|
+
readwrite: categories.readwrite ?? null,
|
|
222147
|
+
edit: categories.edit ?? null,
|
|
222148
|
+
shell: categories.shell ?? null,
|
|
222149
|
+
skill: categories.skill ?? null,
|
|
222150
|
+
mcp: categories.mcp ?? null,
|
|
222151
|
+
other: categories.other ?? null
|
|
222152
|
+
}
|
|
222153
|
+
},
|
|
222154
|
+
toolStatistics: {
|
|
222155
|
+
tools: toolEntries,
|
|
222156
|
+
totalToolsCalled: totalToolCalls,
|
|
222157
|
+
totalErrors: totalToolErrors
|
|
222158
|
+
},
|
|
222159
|
+
timing: {
|
|
222160
|
+
sessionActiveMs,
|
|
222161
|
+
sessionActiveFormatted: formatMs(sessionActiveMs),
|
|
222162
|
+
turnCount,
|
|
222163
|
+
avgTurnMs,
|
|
222164
|
+
avgTurnFormatted: formatMs(avgTurnMs)
|
|
222165
|
+
},
|
|
222166
|
+
contextHealth: {
|
|
222167
|
+
pressureScore,
|
|
222168
|
+
pressureLabel
|
|
222169
|
+
},
|
|
222170
|
+
topTools
|
|
222171
|
+
}, null, 2);
|
|
222172
|
+
}
|
|
221942
222173
|
};
|
|
221943
222174
|
}
|
|
221944
222175
|
});
|
|
@@ -222181,6 +222412,7 @@ var SessionStore = class {
|
|
|
222181
222412
|
|
|
222182
222413
|
// src/session/manager.ts
|
|
222183
222414
|
import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync2 } from "node:fs";
|
|
222415
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
222184
222416
|
import { join as join5 } from "node:path";
|
|
222185
222417
|
function ulid() {
|
|
222186
222418
|
const t = Date.now().toString(36).padStart(10, "0");
|
|
@@ -222274,6 +222506,7 @@ var SessionManager = class {
|
|
|
222274
222506
|
preview: "",
|
|
222275
222507
|
hasImages: false,
|
|
222276
222508
|
imageCount: 0,
|
|
222509
|
+
contentHash: "",
|
|
222277
222510
|
totalActiveMs: 0
|
|
222278
222511
|
};
|
|
222279
222512
|
this.accumulatedMs = 0;
|
|
@@ -222330,6 +222563,8 @@ var SessionManager = class {
|
|
|
222330
222563
|
if (!this.current.preview) {
|
|
222331
222564
|
this.current.preview = extractFirstUserMessage(messages);
|
|
222332
222565
|
}
|
|
222566
|
+
const contentHash2 = createHash3("sha256").update(messages.map((m) => `${m.role}:${String(m.content ?? "").slice(0, 200)}`).join("|")).digest("hex").slice(0, 12);
|
|
222567
|
+
this.current.contentHash = contentHash2;
|
|
222333
222568
|
this.current.projectPath = this.projectPath;
|
|
222334
222569
|
let totalImages = 0;
|
|
222335
222570
|
let hasImages = false;
|
|
@@ -222651,14 +222886,14 @@ var ContextManager = class {
|
|
|
222651
222886
|
|
|
222652
222887
|
// src/memory/store.ts
|
|
222653
222888
|
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
222654
|
-
import { createHash as
|
|
222889
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
222655
222890
|
import { join as join6 } from "node:path";
|
|
222656
222891
|
var MemoryStore = class {
|
|
222657
222892
|
dataDir;
|
|
222658
222893
|
projectHash;
|
|
222659
222894
|
constructor(dataDir, projectPath) {
|
|
222660
222895
|
this.dataDir = join6(dataDir, "memory");
|
|
222661
|
-
this.projectHash =
|
|
222896
|
+
this.projectHash = createHash4("sha256").update(projectPath).digest("hex").slice(0, 12);
|
|
222662
222897
|
if (!existsSync6(this.dataDir)) {
|
|
222663
222898
|
mkdirSync5(this.dataDir, { recursive: true });
|
|
222664
222899
|
}
|
|
@@ -222773,16 +223008,16 @@ import { join as join9, resolve as resolve2, dirname as dirname2 } from "node:pa
|
|
|
222773
223008
|
import { Type as Type2 } from "@mariozechner/pi-ai";
|
|
222774
223009
|
|
|
222775
223010
|
// src/drivers/edit/hash.ts
|
|
222776
|
-
import { createHash as
|
|
223011
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
222777
223012
|
import { Type } from "@mariozechner/pi-ai";
|
|
222778
223013
|
function computeLineHash(line) {
|
|
222779
|
-
return
|
|
223014
|
+
return createHash5("md5").update(line.trim()).digest("hex").slice(0, 6);
|
|
222780
223015
|
}
|
|
222781
223016
|
function computeResolutionHash(line) {
|
|
222782
|
-
return
|
|
223017
|
+
return createHash5("md5").update(line.trim()).digest("hex").slice(0, 8);
|
|
222783
223018
|
}
|
|
222784
223019
|
function computeFileVersion(content) {
|
|
222785
|
-
return "fv_" +
|
|
223020
|
+
return "fv_" + createHash5("sha256").update(content).digest("hex").slice(0, 8);
|
|
222786
223021
|
}
|
|
222787
223022
|
function hashLines(lines) {
|
|
222788
223023
|
const resolutionMap = /* @__PURE__ */ new Map();
|
|
@@ -222835,7 +223070,7 @@ function computeContextHash(lines, lineIdx) {
|
|
|
222835
223070
|
const prev = findNonEmptyBefore(lines, lineIdx);
|
|
222836
223071
|
const curr = lines[lineIdx].trim();
|
|
222837
223072
|
const next = findNonEmptyAfter(lines, lineIdx);
|
|
222838
|
-
return
|
|
223073
|
+
return createHash5("md5").update(`${prev}
|
|
222839
223074
|
${curr}
|
|
222840
223075
|
${next}`).digest("hex").slice(0, 8);
|
|
222841
223076
|
}
|
|
@@ -223434,7 +223669,7 @@ function generateLocalDiff(oldLines, newLines, ops, ctx) {
|
|
|
223434
223669
|
// src/checkpoint/index.ts
|
|
223435
223670
|
import { homedir as homedir4 } from "node:os";
|
|
223436
223671
|
import { join as join8 } from "node:path";
|
|
223437
|
-
import { createHash as
|
|
223672
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
223438
223673
|
|
|
223439
223674
|
// src/checkpoint/checkpoint-manager.ts
|
|
223440
223675
|
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, unlinkSync as unlinkSync2 } from "node:fs";
|
|
@@ -223740,7 +223975,7 @@ var _snapshotStore = null;
|
|
|
223740
223975
|
var _checkpointManager = null;
|
|
223741
223976
|
var _fileWriteTracker = null;
|
|
223742
223977
|
function initCheckpointSystem(projectPath, sessionId) {
|
|
223743
|
-
const projectHash =
|
|
223978
|
+
const projectHash = createHash6("sha256").update(projectPath).digest("hex").slice(0, 12);
|
|
223744
223979
|
const baseDir = join8(homedir4(), ".dscode", "checkpoints", "per-project", projectHash, sessionId);
|
|
223745
223980
|
_snapshotStore = new SnapshotStore();
|
|
223746
223981
|
const store = new FileSystemCheckpointStore(baseDir);
|
|
@@ -224343,7 +224578,7 @@ import { resolve as resolve4 } from "node:path";
|
|
|
224343
224578
|
import { Type as Type5 } from "@mariozechner/pi-ai";
|
|
224344
224579
|
|
|
224345
224580
|
// src/drivers/edit/recovery.ts
|
|
224346
|
-
import { createHash as
|
|
224581
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
224347
224582
|
function recoverBySnapshot(snapshotLines, currentLines, operations, snapshotCtx) {
|
|
224348
224583
|
let expectedLines;
|
|
224349
224584
|
try {
|
|
@@ -224523,7 +224758,7 @@ function computeContextHash2(lines, lineIdx) {
|
|
|
224523
224758
|
const prev = findNonEmptyBefore2(lines, lineIdx);
|
|
224524
224759
|
const curr = lines[lineIdx].trim();
|
|
224525
224760
|
const next = findNonEmptyAfter2(lines, lineIdx);
|
|
224526
|
-
return
|
|
224761
|
+
return createHash7("md5").update(`${prev}
|
|
224527
224762
|
${curr}
|
|
224528
224763
|
${next}`).digest("hex").slice(0, 8);
|
|
224529
224764
|
}
|
|
@@ -228442,6 +228677,7 @@ var ConversationView = class {
|
|
|
228442
228677
|
this.thinkingBuffer = "";
|
|
228443
228678
|
this.toolEntries = [];
|
|
228444
228679
|
this.renderedToolCount = 0;
|
|
228680
|
+
this.tui.requestRender(true);
|
|
228445
228681
|
}
|
|
228446
228682
|
thinkingDelta(delta) {
|
|
228447
228683
|
this.thinkingBuffer += delta;
|
|
@@ -228793,7 +229029,7 @@ var ConversationView = class {
|
|
|
228793
229029
|
this.box.addChild(permText);
|
|
228794
229030
|
this.liveComponents.push(permText);
|
|
228795
229031
|
}
|
|
228796
|
-
this.tui.requestRender(
|
|
229032
|
+
this.tui.requestRender(false);
|
|
228797
229033
|
}
|
|
228798
229034
|
};
|
|
228799
229035
|
|
|
@@ -228991,6 +229227,23 @@ var HybridAutocompleteProvider = class {
|
|
|
228991
229227
|
return true;
|
|
228992
229228
|
}
|
|
228993
229229
|
};
|
|
229230
|
+
function formatTokens(n) {
|
|
229231
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
229232
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
|
|
229233
|
+
return String(n);
|
|
229234
|
+
}
|
|
229235
|
+
function formatContextPercent(estimated, contextWindow) {
|
|
229236
|
+
if (contextWindow <= 0 || !isFinite(estimated) || Number.isNaN(estimated)) return null;
|
|
229237
|
+
const pct = Math.round(estimated / contextWindow * 100);
|
|
229238
|
+
const text = `\u2593\u2593 ${pct}%`;
|
|
229239
|
+
if (pct > 95) return c.red(text);
|
|
229240
|
+
if (pct > 80) return c.yellow(text);
|
|
229241
|
+
return c.dim(text);
|
|
229242
|
+
}
|
|
229243
|
+
function formatCost(total) {
|
|
229244
|
+
if (total >= 0.01) return `$${total.toFixed(4)}`;
|
|
229245
|
+
return `\xA2${(total * 100).toFixed(2)}`;
|
|
229246
|
+
}
|
|
228994
229247
|
var TuiApp = class {
|
|
228995
229248
|
deps;
|
|
228996
229249
|
terminal;
|
|
@@ -229660,13 +229913,27 @@ var TuiApp = class {
|
|
|
229660
229913
|
this.markActivity();
|
|
229661
229914
|
this.conversation.toolEnd(name, result, isError);
|
|
229662
229915
|
}
|
|
229663
|
-
finishAssistantMessage() {
|
|
229916
|
+
finishAssistantMessage(usage) {
|
|
229664
229917
|
this.finalizeIdleSegment();
|
|
229665
229918
|
this.conversation.finishAssistantMessage();
|
|
229919
|
+
const parts = [];
|
|
229666
229920
|
if (this.totalWaitMs >= 1e3) {
|
|
229667
|
-
this.
|
|
229668
|
-
|
|
229669
|
-
|
|
229921
|
+
parts.push(`\u23F1 ${this.formatElapsed(this.totalWaitMs)}`);
|
|
229922
|
+
}
|
|
229923
|
+
if (usage && usage.input > 0 && usage.output > 0) {
|
|
229924
|
+
parts.push(`\u{1F4CA} ${formatTokens(usage.input)}\u2193 ${formatTokens(usage.output)}\u2191`);
|
|
229925
|
+
}
|
|
229926
|
+
{
|
|
229927
|
+
const estimatedTokens = this.deps.contextManager.getEstimatedTokens(this.deps.agent.state.messages);
|
|
229928
|
+
const contextWindow = this.deps.contextManager.getContextWindow();
|
|
229929
|
+
const ctxStr = formatContextPercent(estimatedTokens, contextWindow);
|
|
229930
|
+
if (ctxStr) parts.push(ctxStr);
|
|
229931
|
+
}
|
|
229932
|
+
if (usage && usage.cost.total > 0) {
|
|
229933
|
+
parts.push(`\u{1F4B0} ${formatCost(usage.cost.total)}`);
|
|
229934
|
+
}
|
|
229935
|
+
if (parts.length > 0) {
|
|
229936
|
+
this.conversation.addInfo(c.dim(parts.join(" \xB7 ")));
|
|
229670
229937
|
}
|
|
229671
229938
|
}
|
|
229672
229939
|
addInfo(text, _display) {
|
|
@@ -229950,8 +230217,8 @@ var TuiBackend = class {
|
|
|
229950
230217
|
deps.events.on("turn:streaming:start", () => {
|
|
229951
230218
|
this.tui.startAssistantMessage();
|
|
229952
230219
|
});
|
|
229953
|
-
deps.events.on("turn:end", () => {
|
|
229954
|
-
this.tui.finishAssistantMessage();
|
|
230220
|
+
deps.events.on("turn:end", (e) => {
|
|
230221
|
+
this.tui.finishAssistantMessage(e.usage);
|
|
229955
230222
|
});
|
|
229956
230223
|
deps.events.on("message:user", (e) => {
|
|
229957
230224
|
this.tui.addUserMessage(e.text);
|
|
@@ -231199,7 +231466,8 @@ You have a \`skill\` tool available. When you decide to use a skill from the lis
|
|
|
231199
231466
|
if (event.type === "turn_end") {
|
|
231200
231467
|
this.sessionManager.trySaveSession(this.agent);
|
|
231201
231468
|
const turnEndMsg = event.message;
|
|
231202
|
-
|
|
231469
|
+
const rawUsage = turnEndMsg?.usage;
|
|
231470
|
+
this.events.emit({ type: "turn:end", stopReason: turnEndMsg?.stopReason, usage: rawUsage ? { input: rawUsage.input, output: rawUsage.output, cacheRead: rawUsage.cacheRead, cacheWrite: rawUsage.cacheWrite, total: rawUsage.totalTokens, cost: { total: rawUsage.cost.total } } : void 0 });
|
|
231203
231471
|
const msg = turnEndMsg;
|
|
231204
231472
|
if (msg?.stopReason === "length") {
|
|
231205
231473
|
this.events.emit({ type: "ui:info", text: "Output truncated (hit max_tokens). Continue from where you left off." });
|
|
@@ -0,0 +1 @@
|
|
|
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:Geist Sans,system-ui,sans-serif;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:Geist Mono,JetBrains Mono,Fira Code,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}*{scrollbar-width:thin;scrollbar-color:var(--color-border) transparent;transition:background-color .3s ease,border-color .3s ease,color .3s ease}*::-webkit-scrollbar{width:6px}*::-webkit-scrollbar-track{background:transparent}*::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:3px}body{font-family:Geist Sans,system-ui,sans-serif;background-color:var(--color-bg);color:var(--color-text)}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.btn{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn:focus{outline:2px solid transparent;outline-offset:2px}.btn:focus-visible{--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(2px + 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);--tw-ring-offset-width: 1px}.btn:disabled{cursor:not-allowed;opacity:.5}.btn{border-radius:6px;border:1px solid transparent}.btn-primary{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn-primary:focus{outline:2px solid transparent;outline-offset:2px}.btn-primary:focus-visible{--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(2px + 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);--tw-ring-offset-width: 1px}.btn-primary:disabled{cursor:not-allowed;opacity:.5}.btn-primary{border-radius:6px;border:1px solid transparent;background-color:var(--color-accent);color:#fff;border-color:var(--color-accent)}.btn-primary:hover{background-color:var(--color-accent-hover);border-color:var(--color-accent-hover)}.btn-secondary{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn-secondary:focus{outline:2px solid transparent;outline-offset:2px}.btn-secondary:focus-visible{--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(2px + 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);--tw-ring-offset-width: 1px}.btn-secondary:disabled{cursor:not-allowed;opacity:.5}.btn-secondary{border-radius:6px;border:1px solid transparent;background-color:var(--color-surface);color:var(--color-text);border-color:var(--color-border)}.btn-secondary:hover{background-color:var(--color-surface-hover)}.btn-danger{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn-danger:focus{outline:2px solid transparent;outline-offset:2px}.btn-danger:focus-visible{--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(2px + 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);--tw-ring-offset-width: 1px}.btn-danger:disabled{cursor:not-allowed;opacity:.5}.btn-danger{border-radius:6px;border:1px solid transparent;background-color:var(--color-error);color:var(--color-error-text);border-color:var(--color-error-text)}.btn-danger:hover{filter:brightness(.95)}.input{width:100%;padding:.625rem 1rem;font-size:.875rem;line-height:1.25rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.input::-moz-placeholder{color:var(--color-text-muted)}.input::placeholder{color:var(--color-text-muted)}.input:focus{outline:2px solid transparent;outline-offset:2px}.input{border-radius:12px;border:1px solid var(--color-border);background-color:var(--color-surface);color:var(--color-text)}.input:focus{border-color:var(--color-accent)}.card{border-radius:8px;border:1px solid var(--color-border);background-color:var(--color-surface);padding:1rem}.tool-card{border-radius:8px;border:1px solid var(--color-border);background-color:var(--color-surface);padding:1rem;margin-bottom:.5rem}.resize-handle{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;z-index:10;transition:background-color .15s ease}.resize-handle:hover{background-color:var(--color-border)}.resize-handle:active{background-color:var(--color-accent)}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.inset-y-0{top:0;bottom:0}.-right-1\.5{right:-.375rem}.-top-1\.5{top:-.375rem}.bottom-full{bottom:100%}.left-0{left:0}.left-1\/2{left:50%}.left-4{left:1rem}.right-4{right:1rem}.top-4{top:1rem}.top-full{top:100%}.z-40{z-index:40}.z-50{z-index:50}.z-\[100\]{z-index:100}.mx-auto{margin-left:auto;margin-right:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.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-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.table-cell{display:table-cell}.hidden{display:none}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-screen{height:100vh}.max-h-24{max-height:6rem}.max-h-32{max-height:8rem}.max-h-40{max-height:10rem}.max-h-48{max-height:12rem}.max-h-60{max-height:15rem}.max-h-\[200px\]{max-height:200px}.max-h-\[300px\]{max-height:300px}.max-h-\[400px\]{max-height:400px}.max-h-\[70vh\]{max-height:70vh}.min-h-0{min-height:0px}.min-h-\[40px\]{min-height:40px}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-5{width:1.25rem}.w-72{width:18rem}.w-80{width:20rem}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-full{min-width:100%}.max-w-4xl{max-width:56rem}.max-w-\[200px\]{max-width:200px}.max-w-\[300px\]{max-width:300px}.max-w-\[85\%\]{max-width:85%}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-none{max-width:none}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x: -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-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))}.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))}.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 bounce{0%,to{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}.animate-bounce{animation:bounce 1s infinite}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.animate-slide-in{animation:slide-in .3s ease-out forwards}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.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-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))}.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-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-btn{border-radius:6px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-sm{border-radius:.125rem}.border{border-width:1px}.border-0{border-width:0px}.border-b{border-bottom-width:1px}.bg-black\/30{background-color:#0000004d}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.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}.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-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pl-3{padding-left:.75rem}.pt-16{padding-top:4rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:Geist Mono,JetBrains Mono,Fira Code,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.capitalize{text-transform:capitalize}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.underline{text-decoration-line:underline}.\!opacity-0{opacity:0!important}.opacity-0{opacity:0}.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)}.outline{outline-style:solid}.ring{--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(3px + 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)}.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{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[filter\]{transition-property:filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.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-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}:root{--color-bg: #f8f7f5;--color-surface: #f3f2ef;--color-surface-hover: #ebe9e5;--color-border: #e6e4e0;--color-text: #2d2a26;--color-text-muted: #8a8580;--color-accent: #ca8a04;--color-accent-hover: #a07004;--color-accent-bg: rgba(202, 138, 4, .12);--color-success: #edf4ed;--color-success-text: #347539;--color-error: #fdebec;--color-error-text: #9f2f2d;--color-warning: #fbf3db;--color-warning-text: #956400;--color-user-bubble: #ca8a04;--color-user-bubble-text: #ffffff;--cw-system: #8a8580;--cw-rules: #a0908b;--cw-user: #ca8a04;--cw-thinking: #a78bfa;--cw-readwrite: #eab308;--cw-edit: #3b82f6;--cw-shell: #ef4444;--cw-skill: #059669;--cw-mcp: #8b5cf6;--cw-other: #6b7280}.dark{--color-bg: #1e1c19;--color-surface: #282622;--color-surface-hover: #322e2a;--color-border: #3a3732;--color-text: #e8e4dd;--color-text-muted: #8a8580;--cw-system: #8a8580;--cw-rules: #b0a09b;--cw-user: #d49708;--cw-thinking: #7c6bb0;--cw-readwrite: #ca8a04;--cw-edit: #60a5fa;--cw-shell: #f87171;--cw-skill: #10b981;--cw-mcp: #a78bfa;--cw-other: #9ca3af;--color-accent: #d49708;--color-accent-bg: rgba(212, 151, 8, .15);--color-accent-hover: #e5a50a;--color-success: #1a2e1a;--color-success-text: #5ca860;--color-error: #3a1a1a;--color-error-text: #e05553;--color-warning: #3a2e10;--color-warning-text: #d4a017;--color-user-bubble: #d49708;--color-user-bubble-text: #1e1c19}@media (max-width: 767px){.resize-handle{display:none}}@keyframes fade-up{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes slide-in{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}@keyframes spin{to{transform:rotate(360deg)}}.animate-fade-up{animation:fade-up .6s cubic-bezier(.16,1,.3,1) forwards}.animate-slide-in{@keyframes view-fade-in{0%{opacity:0}to{opacity:1}}animation:slide-in .3s ease-out forwards}.animate-slide-in .view-fade-enter{animation:view-fade-in .3s ease-out forwards}@media (prefers-reduced-motion: reduce){.animate-fade-up,.animate-slide-in{animation:none}*{transition:none!important}}.hover\:opacity-70:hover{opacity:.7}.hover\:opacity-90:hover{opacity:.9}.hover\:brightness-95:hover{--tw-brightness: brightness(.95);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)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width: 640px){.sm\:inline{display:inline}}@media (min-width: 768px){.md\:static{position:static}.md\:block{display:block}.md\:flex{display:flex}.md\:hidden{display:none}.md\:max-w-\[75\%\]{max-width:75%}.md\: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))}}
|