codebase-cli 2.0.0-pre.3 → 2.0.0-pre.30
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/agent/agent.js +10 -2
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/config.js +101 -20
- package/dist/agent/config.js.map +1 -1
- package/dist/agent/prompt-suggestion.js +145 -0
- package/dist/agent/prompt-suggestion.js.map +1 -0
- package/dist/agent/system-prompt.js +15 -0
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/app-server/protocol.js +7 -0
- package/dist/app-server/protocol.js.map +1 -0
- package/dist/app-server/server.js +241 -0
- package/dist/app-server/server.js.map +1 -0
- package/dist/auth/credentials.js +10 -0
- package/dist/auth/credentials.js.map +1 -1
- package/dist/auth/flow.js +145 -24
- package/dist/auth/flow.js.map +1 -1
- package/dist/cli.js +58 -6
- package/dist/cli.js.map +1 -1
- package/dist/commands/builtins.js +155 -5
- package/dist/commands/builtins.js.map +1 -1
- package/dist/commands/registry.js +46 -1
- package/dist/commands/registry.js.map +1 -1
- package/dist/glue/client.js +10 -1
- package/dist/glue/client.js.map +1 -1
- package/dist/headless/run.js +1 -1
- package/dist/headless/run.js.map +1 -1
- package/dist/hooks/manager.js +8 -2
- package/dist/hooks/manager.js.map +1 -1
- package/dist/permissions/store.js +4 -0
- package/dist/permissions/store.js.map +1 -1
- package/dist/projects/cli.js +92 -0
- package/dist/projects/cli.js.map +1 -0
- package/dist/projects/client.js +120 -0
- package/dist/projects/client.js.map +1 -0
- package/dist/projects/types.js +2 -0
- package/dist/projects/types.js.map +1 -0
- package/dist/skills/platform-loader.js +133 -38
- package/dist/skills/platform-loader.js.map +1 -1
- package/dist/tools/__test__/mock-tool-context.js +31 -0
- package/dist/tools/__test__/mock-tool-context.js.map +1 -0
- package/dist/tools/read-file.js +8 -2
- package/dist/tools/read-file.js.map +1 -1
- package/dist/ui/App.js +244 -17
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/FirstRunSetup.js +66 -14
- package/dist/ui/FirstRunSetup.js.map +1 -1
- package/dist/ui/Input.js +270 -14
- package/dist/ui/Input.js.map +1 -1
- package/dist/ui/Markdown.js +286 -0
- package/dist/ui/Markdown.js.map +1 -0
- package/dist/ui/Message.js +604 -25
- package/dist/ui/Message.js.map +1 -1
- package/dist/ui/MessageList.js +100 -3
- package/dist/ui/MessageList.js.map +1 -1
- package/dist/ui/Permission.js +43 -20
- package/dist/ui/Permission.js.map +1 -1
- package/dist/ui/PixelC.js +25 -0
- package/dist/ui/PixelC.js.map +1 -0
- package/dist/ui/Status.js +213 -7
- package/dist/ui/Status.js.map +1 -1
- package/dist/ui/Throbber.js +11 -7
- package/dist/ui/Throbber.js.map +1 -1
- package/dist/ui/Welcome.js +59 -0
- package/dist/ui/Welcome.js.map +1 -0
- package/dist/ui/attachments.js +68 -0
- package/dist/ui/attachments.js.map +1 -0
- package/dist/ui/debug-input.js +44 -0
- package/dist/ui/debug-input.js.map +1 -0
- package/dist/ui/highlight.js +324 -0
- package/dist/ui/highlight.js.map +1 -0
- package/dist/ui/history-store.js +60 -0
- package/dist/ui/history-store.js.map +1 -0
- package/dist/ui/path-complete.js +102 -0
- package/dist/ui/path-complete.js.map +1 -0
- package/dist/ui/terminal-restore.js +83 -0
- package/dist/ui/terminal-restore.js.map +1 -0
- package/package.json +5 -1
package/dist/ui/Throbber.js
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Text } from "ink";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
|
-
const FRAMES = ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"];
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* 8-frame pulse cycle — the codebase pixel-C "scanning" through brightness
|
|
6
|
+
* levels. The compact (1-char) variant cycles a single block-glyph: ░▒▓█▓▒░.
|
|
7
|
+
* The full pixel-C variant scans a highlight row across the C shape.
|
|
8
|
+
*
|
|
9
|
+
* Self-throttling: owns its own interval so the parent's reducer state
|
|
10
|
+
* doesn't tick on every frame. A hot message_update stream + a 100ms
|
|
11
|
+
* spinner would otherwise compound into full re-renders 10× a second.
|
|
9
12
|
*/
|
|
10
|
-
|
|
13
|
+
const COMPACT_FRAMES = ["░", "▒", "▓", "█", "█", "▓", "▒", "░"];
|
|
14
|
+
export function Throbber({ color = "cyan", intervalMs = 90 }) {
|
|
11
15
|
const [frame, setFrame] = useState(0);
|
|
12
16
|
useEffect(() => {
|
|
13
17
|
const id = setInterval(() => {
|
|
14
|
-
setFrame((f) => (f + 1) %
|
|
18
|
+
setFrame((f) => (f + 1) % COMPACT_FRAMES.length);
|
|
15
19
|
}, intervalMs);
|
|
16
20
|
return () => clearInterval(id);
|
|
17
21
|
}, [intervalMs]);
|
|
18
|
-
return _jsx(Text, { color: color, children:
|
|
22
|
+
return _jsx(Text, { color: color, children: COMPACT_FRAMES[frame] });
|
|
19
23
|
}
|
|
20
24
|
//# sourceMappingURL=Throbber.js.map
|
package/dist/ui/Throbber.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Throbber.js","sourceRoot":"","sources":["../../src/ui/Throbber.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,MAAM,
|
|
1
|
+
{"version":3,"file":"Throbber.js","sourceRoot":"","sources":["../../src/ui/Throbber.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C;;;;;;;;GAQG;AAEH,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAOhE,MAAM,UAAU,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,UAAU,GAAG,EAAE,EAAiB;IAC1E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEtC,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;YAC3B,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAClD,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,YAAG,cAAc,CAAC,KAAK,CAAC,GAAQ,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
import { Box, Text } from "ink";
|
|
5
|
+
import { PixelC } from "./PixelC.js";
|
|
6
|
+
/**
|
|
7
|
+
* Best-effort git probe for the welcome banner. Returns null if the
|
|
8
|
+
* cwd isn't a git repo (or if `git` isn't on PATH), so non-git
|
|
9
|
+
* projects get a cleaner banner instead of an empty line. We swallow
|
|
10
|
+
* all errors — the banner is decorative; a slow / failing git
|
|
11
|
+
* shouldn't block startup.
|
|
12
|
+
*/
|
|
13
|
+
function readGitInfo(cwd) {
|
|
14
|
+
try {
|
|
15
|
+
const branch = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
16
|
+
cwd,
|
|
17
|
+
encoding: "utf8",
|
|
18
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
19
|
+
}).trim();
|
|
20
|
+
if (!branch)
|
|
21
|
+
return null;
|
|
22
|
+
const status = execSync("git status --porcelain", {
|
|
23
|
+
cwd,
|
|
24
|
+
encoding: "utf8",
|
|
25
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
26
|
+
});
|
|
27
|
+
const dirty = status.split("\n").filter((l) => l.trim().length > 0).length;
|
|
28
|
+
return { branch, dirty };
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Humanize an absolute timestamp into "5m ago" / "3h ago" / "2d ago" — sub-minute reads as "just now". */
|
|
35
|
+
function formatAgo(ts) {
|
|
36
|
+
const sec = Math.max(0, Math.floor((Date.now() - ts) / 1000));
|
|
37
|
+
if (sec < 60)
|
|
38
|
+
return "just now";
|
|
39
|
+
if (sec < 3600)
|
|
40
|
+
return `${Math.floor(sec / 60)}m ago`;
|
|
41
|
+
if (sec < 86400)
|
|
42
|
+
return `${Math.floor(sec / 3600)}h ago`;
|
|
43
|
+
return `${Math.floor(sec / 86400)}d ago`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Empty-state banner shown above the input while the transcript is
|
|
47
|
+
* empty. Pixel-C logo on the left, contextual info + tips on the
|
|
48
|
+
* right. Renders once and gets pushed up by the first user message —
|
|
49
|
+
* not Static-rendered, but only a few rows so it's cheap.
|
|
50
|
+
*/
|
|
51
|
+
export function Welcome({ modelName, source, cwd, resumedFrom }) {
|
|
52
|
+
const cwdLabel = basename(cwd) || cwd;
|
|
53
|
+
const sourceLabel = source === "proxy" ? "signed in via codebase.design" : source === "byok" ? "BYOK" : `${source}`;
|
|
54
|
+
const gitInfo = readGitInfo(cwd);
|
|
55
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { marginRight: 2, children: _jsx(PixelC, {}) }), _jsxs(Box, { flexDirection: "column", justifyContent: "center", children: [_jsx(Text, { bold: true, color: "cyan", children: "codebase" }), _jsx(Text, { dimColor: true, children: modelName }), _jsxs(Text, { dimColor: true, children: [cwdLabel, " \u00B7 ", sourceLabel] }), gitInfo ? (_jsxs(Text, { dimColor: true, children: [gitInfo.branch, gitInfo.dirty > 0
|
|
56
|
+
? ` · ${gitInfo.dirty} uncommitted change${gitInfo.dirty === 1 ? "" : "s"}`
|
|
57
|
+
: " · clean"] })) : null] })] }), resumedFrom ? (_jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: "cyan", children: ["\u21BB Resumed from ", formatAgo(resumedFrom.updatedAt)] }), _jsxs(Text, { dimColor: true, children: [" ", "\u00B7 ", resumedFrom.messageCount, " message", resumedFrom.messageCount === 1 ? "" : "s"] })] })) : null, _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Ask me to read code, edit files, run commands, or anything in between." }), _jsxs(Text, { dimColor: true, children: [_jsx(Text, { color: "cyan", children: "/" }), " commands \u00B7 ", _jsx(Text, { color: "cyan", children: "!" }), "shell \u00B7 ", _jsx(Text, { color: "cyan", children: "\u2191\u2193" }), " ", "history \u00B7 ", _jsx(Text, { color: "cyan", children: "Tab" }), " complete \u00B7 ", _jsx(Text, { color: "cyan", children: "\\" }), "+Enter for newline"] }), _jsx(Text, { dimColor: true, children: "Ctrl-C twice to exit." })] })] }));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=Welcome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Welcome.js","sourceRoot":"","sources":["../../src/ui/Welcome.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join } from "node:path";
|
|
3
|
+
export const MAX_ATTACHMENT_BYTES = 128 * 1024;
|
|
4
|
+
export const MAX_ATTACHMENTS = 8;
|
|
5
|
+
/**
|
|
6
|
+
* Scan the prompt for `@<path>` tokens and resolve each to a readable
|
|
7
|
+
* file under (or adjacent to) the cwd. Returns one entry per resolved
|
|
8
|
+
* file; unresolved `@` mentions don't appear here and stay as literal
|
|
9
|
+
* text — we never silently drop or rewrite user input.
|
|
10
|
+
*
|
|
11
|
+
* Skip rules:
|
|
12
|
+
* - tokens without a slash or dot (email-style @alice mentions)
|
|
13
|
+
* - paths over 256 chars (clearly not a real path)
|
|
14
|
+
* - non-files (directories, sockets, ...)
|
|
15
|
+
* - files larger than MAX_ATTACHMENT_BYTES
|
|
16
|
+
* - past MAX_ATTACHMENTS total attachments per prompt
|
|
17
|
+
*/
|
|
18
|
+
export function collectAttachments(text, cwd) {
|
|
19
|
+
const out = [];
|
|
20
|
+
const seen = new Set();
|
|
21
|
+
const pattern = /@([A-Za-z0-9_./-]+)/g;
|
|
22
|
+
for (const match of text.matchAll(pattern)) {
|
|
23
|
+
if (out.length >= MAX_ATTACHMENTS)
|
|
24
|
+
break;
|
|
25
|
+
const rel = match[1];
|
|
26
|
+
if (!rel || rel.length > 256)
|
|
27
|
+
continue;
|
|
28
|
+
if (!rel.includes("/") && !rel.includes("."))
|
|
29
|
+
continue;
|
|
30
|
+
const abs = isAbsolute(rel) ? rel : join(cwd, rel);
|
|
31
|
+
if (seen.has(abs))
|
|
32
|
+
continue;
|
|
33
|
+
seen.add(abs);
|
|
34
|
+
try {
|
|
35
|
+
const stat = statSync(abs);
|
|
36
|
+
if (!stat.isFile())
|
|
37
|
+
continue;
|
|
38
|
+
if (stat.size > MAX_ATTACHMENT_BYTES)
|
|
39
|
+
continue;
|
|
40
|
+
const content = readFileSync(abs, "utf8");
|
|
41
|
+
out.push({ token: match[0], relPath: rel, absPath: abs, content });
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// File doesn't exist or isn't readable — leave the token in text.
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build the agent-bound prompt with attachments inlined as fenced code
|
|
51
|
+
* blocks above the user's actual ask. The original `@path` tokens stay
|
|
52
|
+
* in the text so the model can correlate the references with the
|
|
53
|
+
* attached content.
|
|
54
|
+
*/
|
|
55
|
+
export function buildAttachmentPrompt(text, attachments) {
|
|
56
|
+
const parts = ["Attached files (auto-inlined from @ mentions):", ""];
|
|
57
|
+
for (const a of attachments) {
|
|
58
|
+
parts.push(`### ${a.relPath}`);
|
|
59
|
+
parts.push("```");
|
|
60
|
+
parts.push(a.content);
|
|
61
|
+
parts.push("```");
|
|
62
|
+
parts.push("");
|
|
63
|
+
}
|
|
64
|
+
parts.push("---");
|
|
65
|
+
parts.push(text);
|
|
66
|
+
return parts.join("\n");
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=attachments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/ui/attachments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAS7C,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,GAAG,IAAI,CAAC;AAC/C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,GAAW;IAC3D,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,OAAO,GAAG,sBAAsB,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5C,IAAI,GAAG,CAAC,MAAM,IAAI,eAAe;YAAE,MAAM;QACzC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG;YAAE,SAAS;QACvC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,SAAS;QACvD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;gBAAE,SAAS;YAC7B,IAAI,IAAI,CAAC,IAAI,GAAG,oBAAoB;gBAAE,SAAS;YAC/C,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC1C,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;QAAC,MAAM,CAAC;YACR,kEAAkE;QACnE,CAAC;IACF,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,WAAkC;IACrF,MAAM,KAAK,GAAa,CAAC,gDAAgD,EAAE,EAAE,CAAC,CAAC;IAC/E,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { appendFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
let logPath = null;
|
|
5
|
+
let warned = false;
|
|
6
|
+
export function isDebugInputEnabled() {
|
|
7
|
+
return process.env.CODEBASE_DEBUG_INPUT === "1";
|
|
8
|
+
}
|
|
9
|
+
function resolveLogPath() {
|
|
10
|
+
if (logPath)
|
|
11
|
+
return logPath;
|
|
12
|
+
const dir = join(homedir(), ".codebase", "logs");
|
|
13
|
+
try {
|
|
14
|
+
mkdirSync(dir, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// The fs error is non-fatal; the appendFileSync below will throw
|
|
18
|
+
// the same problem and we'll surface it once via the `warned`
|
|
19
|
+
// guard, not on every keystroke.
|
|
20
|
+
}
|
|
21
|
+
logPath = join(dir, "input.log");
|
|
22
|
+
return logPath;
|
|
23
|
+
}
|
|
24
|
+
export function logInputEvent(input, key) {
|
|
25
|
+
if (!isDebugInputEnabled())
|
|
26
|
+
return;
|
|
27
|
+
try {
|
|
28
|
+
const entry = {
|
|
29
|
+
t: new Date().toISOString(),
|
|
30
|
+
// Show the actual code points so a stray \x7f or \x1b is visible.
|
|
31
|
+
input,
|
|
32
|
+
codes: Array.from(input).map((ch) => ch.charCodeAt(0)),
|
|
33
|
+
key,
|
|
34
|
+
};
|
|
35
|
+
appendFileSync(resolveLogPath(), `${JSON.stringify(entry)}\n`);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (warned)
|
|
39
|
+
return;
|
|
40
|
+
warned = true;
|
|
41
|
+
process.stderr.write(`\n[debug-input] failed to write log: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=debug-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-input.js","sourceRoot":"","sources":["../../src/ui/debug-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AA8BjC,IAAI,OAAO,GAAkB,IAAI,CAAC;AAClC,IAAI,MAAM,GAAG,KAAK,CAAC;AAEnB,MAAM,UAAU,mBAAmB;IAClC,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,GAAG,CAAC;AACjD,CAAC;AAED,SAAS,cAAc;IACtB,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC;QACJ,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACR,iEAAiE;QACjE,8DAA8D;QAC9D,iCAAiC;IAClC,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACjC,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,GAAgB;IAC5D,IAAI,CAAC,mBAAmB,EAAE;QAAE,OAAO;IACnC,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG;YACb,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC3B,kEAAkE;YAClE,KAAK;YACL,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACtD,GAAG;SACH,CAAC;QACF,cAAc,CAAC,cAAc,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,IAAI,MAAM;YAAE,OAAO;QACnB,MAAM,GAAG,IAAI,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB,wCAAwC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAC5F,CAAC;IACH,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny regex-based syntax highlighter for code blocks inside markdown.
|
|
3
|
+
* Each language is a flat list of `(regex, kind)` rules tried in order;
|
|
4
|
+
* the first match wins, the matched span is emitted as a typed token,
|
|
5
|
+
* and the scan resumes after it. Anything not matched falls through as
|
|
6
|
+
* plain text.
|
|
7
|
+
*
|
|
8
|
+
* We deliberately do *not* take a 6 MB dep (highlight.js, prismjs) just
|
|
9
|
+
* to colorize terminal code blocks — these rules handle 95% of what an
|
|
10
|
+
* LLM emits and stay easy to read. If a language isn't in `LANGS`, the
|
|
11
|
+
* caller renders the code block as plain text.
|
|
12
|
+
*/
|
|
13
|
+
const TS_KEYWORDS = [
|
|
14
|
+
"abstract",
|
|
15
|
+
"as",
|
|
16
|
+
"async",
|
|
17
|
+
"await",
|
|
18
|
+
"break",
|
|
19
|
+
"case",
|
|
20
|
+
"catch",
|
|
21
|
+
"class",
|
|
22
|
+
"const",
|
|
23
|
+
"continue",
|
|
24
|
+
"debugger",
|
|
25
|
+
"declare",
|
|
26
|
+
"default",
|
|
27
|
+
"delete",
|
|
28
|
+
"do",
|
|
29
|
+
"else",
|
|
30
|
+
"enum",
|
|
31
|
+
"export",
|
|
32
|
+
"extends",
|
|
33
|
+
"finally",
|
|
34
|
+
"for",
|
|
35
|
+
"from",
|
|
36
|
+
"function",
|
|
37
|
+
"get",
|
|
38
|
+
"if",
|
|
39
|
+
"implements",
|
|
40
|
+
"import",
|
|
41
|
+
"in",
|
|
42
|
+
"infer",
|
|
43
|
+
"instanceof",
|
|
44
|
+
"interface",
|
|
45
|
+
"is",
|
|
46
|
+
"keyof",
|
|
47
|
+
"let",
|
|
48
|
+
"namespace",
|
|
49
|
+
"new",
|
|
50
|
+
"null",
|
|
51
|
+
"of",
|
|
52
|
+
"package",
|
|
53
|
+
"private",
|
|
54
|
+
"protected",
|
|
55
|
+
"public",
|
|
56
|
+
"readonly",
|
|
57
|
+
"return",
|
|
58
|
+
"set",
|
|
59
|
+
"static",
|
|
60
|
+
"super",
|
|
61
|
+
"switch",
|
|
62
|
+
"this",
|
|
63
|
+
"throw",
|
|
64
|
+
"true",
|
|
65
|
+
"false",
|
|
66
|
+
"try",
|
|
67
|
+
"type",
|
|
68
|
+
"typeof",
|
|
69
|
+
"undefined",
|
|
70
|
+
"var",
|
|
71
|
+
"void",
|
|
72
|
+
"while",
|
|
73
|
+
"with",
|
|
74
|
+
"yield",
|
|
75
|
+
];
|
|
76
|
+
const PY_KEYWORDS = [
|
|
77
|
+
"and",
|
|
78
|
+
"as",
|
|
79
|
+
"assert",
|
|
80
|
+
"async",
|
|
81
|
+
"await",
|
|
82
|
+
"break",
|
|
83
|
+
"class",
|
|
84
|
+
"continue",
|
|
85
|
+
"def",
|
|
86
|
+
"del",
|
|
87
|
+
"elif",
|
|
88
|
+
"else",
|
|
89
|
+
"except",
|
|
90
|
+
"False",
|
|
91
|
+
"finally",
|
|
92
|
+
"for",
|
|
93
|
+
"from",
|
|
94
|
+
"global",
|
|
95
|
+
"if",
|
|
96
|
+
"import",
|
|
97
|
+
"in",
|
|
98
|
+
"is",
|
|
99
|
+
"lambda",
|
|
100
|
+
"None",
|
|
101
|
+
"nonlocal",
|
|
102
|
+
"not",
|
|
103
|
+
"or",
|
|
104
|
+
"pass",
|
|
105
|
+
"raise",
|
|
106
|
+
"return",
|
|
107
|
+
"True",
|
|
108
|
+
"try",
|
|
109
|
+
"while",
|
|
110
|
+
"with",
|
|
111
|
+
"yield",
|
|
112
|
+
];
|
|
113
|
+
const GO_KEYWORDS = [
|
|
114
|
+
"break",
|
|
115
|
+
"case",
|
|
116
|
+
"chan",
|
|
117
|
+
"const",
|
|
118
|
+
"continue",
|
|
119
|
+
"default",
|
|
120
|
+
"defer",
|
|
121
|
+
"else",
|
|
122
|
+
"fallthrough",
|
|
123
|
+
"for",
|
|
124
|
+
"func",
|
|
125
|
+
"go",
|
|
126
|
+
"goto",
|
|
127
|
+
"if",
|
|
128
|
+
"import",
|
|
129
|
+
"interface",
|
|
130
|
+
"map",
|
|
131
|
+
"package",
|
|
132
|
+
"range",
|
|
133
|
+
"return",
|
|
134
|
+
"select",
|
|
135
|
+
"struct",
|
|
136
|
+
"switch",
|
|
137
|
+
"type",
|
|
138
|
+
"var",
|
|
139
|
+
"nil",
|
|
140
|
+
"true",
|
|
141
|
+
"false",
|
|
142
|
+
];
|
|
143
|
+
const SH_KEYWORDS = [
|
|
144
|
+
"if",
|
|
145
|
+
"then",
|
|
146
|
+
"else",
|
|
147
|
+
"elif",
|
|
148
|
+
"fi",
|
|
149
|
+
"for",
|
|
150
|
+
"in",
|
|
151
|
+
"do",
|
|
152
|
+
"done",
|
|
153
|
+
"while",
|
|
154
|
+
"until",
|
|
155
|
+
"case",
|
|
156
|
+
"esac",
|
|
157
|
+
"function",
|
|
158
|
+
"return",
|
|
159
|
+
"exit",
|
|
160
|
+
"break",
|
|
161
|
+
"continue",
|
|
162
|
+
"local",
|
|
163
|
+
"export",
|
|
164
|
+
"readonly",
|
|
165
|
+
"declare",
|
|
166
|
+
"set",
|
|
167
|
+
"unset",
|
|
168
|
+
"shift",
|
|
169
|
+
];
|
|
170
|
+
const TS_RULES = [
|
|
171
|
+
{ pattern: /^\/\/[^\n]*/, kind: "comment" },
|
|
172
|
+
{ pattern: /^\/\*[\s\S]*?\*\//, kind: "comment" },
|
|
173
|
+
{ pattern: /^`(?:[^`\\]|\\.)*`/, kind: "string" },
|
|
174
|
+
{ pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
|
|
175
|
+
{ pattern: /^'(?:[^'\\\n]|\\.)*'/, kind: "string" },
|
|
176
|
+
{ pattern: /^\b(?:0x[0-9a-fA-F]+|0b[01]+|\d+\.?\d*(?:[eE][+-]?\d+)?)\b/, kind: "number" },
|
|
177
|
+
{ pattern: new RegExp(`^\\b(?:${TS_KEYWORDS.join("|")})\\b`), kind: "keyword" },
|
|
178
|
+
{ pattern: /^\b[A-Z][A-Za-z0-9_]*\b/, kind: "type" },
|
|
179
|
+
{ pattern: /^[A-Za-z_$][\w$]*(?=\s*\()/, kind: "function" },
|
|
180
|
+
{ pattern: /^[A-Za-z_$][\w$]*(?=\s*:)/, kind: "property" },
|
|
181
|
+
{ pattern: /^[+\-*/%=<>!&|^~?:]+/, kind: "operator" },
|
|
182
|
+
{ pattern: /^[{}[\]().,;]/, kind: "punctuation" },
|
|
183
|
+
];
|
|
184
|
+
const PY_RULES = [
|
|
185
|
+
{ pattern: /^#[^\n]*/, kind: "comment" },
|
|
186
|
+
{ pattern: /^"""[\s\S]*?"""/, kind: "string" },
|
|
187
|
+
{ pattern: /^'''[\s\S]*?'''/, kind: "string" },
|
|
188
|
+
{ pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
|
|
189
|
+
{ pattern: /^'(?:[^'\\\n]|\\.)*'/, kind: "string" },
|
|
190
|
+
{ pattern: /^\b\d+\.?\d*(?:[eE][+-]?\d+)?\b/, kind: "number" },
|
|
191
|
+
{ pattern: new RegExp(`^\\b(?:${PY_KEYWORDS.join("|")})\\b`), kind: "keyword" },
|
|
192
|
+
{ pattern: /^\b[A-Z][A-Za-z0-9_]*\b/, kind: "type" },
|
|
193
|
+
{ pattern: /^[A-Za-z_][\w]*(?=\s*\()/, kind: "function" },
|
|
194
|
+
{ pattern: /^[+\-*/%=<>!&|^~]+/, kind: "operator" },
|
|
195
|
+
{ pattern: /^[{}[\]().,:;]/, kind: "punctuation" },
|
|
196
|
+
];
|
|
197
|
+
const GO_RULES = [
|
|
198
|
+
{ pattern: /^\/\/[^\n]*/, kind: "comment" },
|
|
199
|
+
{ pattern: /^\/\*[\s\S]*?\*\//, kind: "comment" },
|
|
200
|
+
{ pattern: /^`[\s\S]*?`/, kind: "string" },
|
|
201
|
+
{ pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
|
|
202
|
+
{ pattern: /^'(?:[^'\\]|\\.)*'/, kind: "string" },
|
|
203
|
+
{ pattern: /^\b\d+\.?\d*\b/, kind: "number" },
|
|
204
|
+
{ pattern: new RegExp(`^\\b(?:${GO_KEYWORDS.join("|")})\\b`), kind: "keyword" },
|
|
205
|
+
{ pattern: /^\b[A-Z][A-Za-z0-9_]*\b/, kind: "type" },
|
|
206
|
+
{ pattern: /^[A-Za-z_][\w]*(?=\s*\()/, kind: "function" },
|
|
207
|
+
{ pattern: /^[+\-*/%=<>!&|^~]+/, kind: "operator" },
|
|
208
|
+
{ pattern: /^[{}[\]().,;:]/, kind: "punctuation" },
|
|
209
|
+
];
|
|
210
|
+
const SH_RULES = [
|
|
211
|
+
{ pattern: /^#[^\n]*/, kind: "comment" },
|
|
212
|
+
{ pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
|
|
213
|
+
{ pattern: /^'[^'\n]*'/, kind: "string" },
|
|
214
|
+
{ pattern: /^\$[A-Za-z_][\w]*/, kind: "property" },
|
|
215
|
+
{ pattern: /^\$\{[^}]*\}/, kind: "property" },
|
|
216
|
+
{ pattern: /^\b\d+\b/, kind: "number" },
|
|
217
|
+
{ pattern: new RegExp(`^\\b(?:${SH_KEYWORDS.join("|")})\\b`), kind: "keyword" },
|
|
218
|
+
{ pattern: /^-{1,2}[A-Za-z][\w-]*/, kind: "operator" },
|
|
219
|
+
{ pattern: /^[|&;<>(){}]+/, kind: "punctuation" },
|
|
220
|
+
];
|
|
221
|
+
const JSON_RULES = [
|
|
222
|
+
{ pattern: /^"(?:[^"\\\n]|\\.)*"(?=\s*:)/, kind: "property" },
|
|
223
|
+
{ pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
|
|
224
|
+
{ pattern: /^\b(?:true|false|null)\b/, kind: "keyword" },
|
|
225
|
+
{ pattern: /^-?\b\d+\.?\d*(?:[eE][+-]?\d+)?\b/, kind: "number" },
|
|
226
|
+
{ pattern: /^[{}[\],]/, kind: "punctuation" },
|
|
227
|
+
{ pattern: /^:/, kind: "operator" },
|
|
228
|
+
];
|
|
229
|
+
const LANGS = {
|
|
230
|
+
ts: TS_RULES,
|
|
231
|
+
tsx: TS_RULES,
|
|
232
|
+
js: TS_RULES,
|
|
233
|
+
jsx: TS_RULES,
|
|
234
|
+
javascript: TS_RULES,
|
|
235
|
+
typescript: TS_RULES,
|
|
236
|
+
py: PY_RULES,
|
|
237
|
+
python: PY_RULES,
|
|
238
|
+
go: GO_RULES,
|
|
239
|
+
golang: GO_RULES,
|
|
240
|
+
sh: SH_RULES,
|
|
241
|
+
bash: SH_RULES,
|
|
242
|
+
zsh: SH_RULES,
|
|
243
|
+
shell: SH_RULES,
|
|
244
|
+
json: JSON_RULES,
|
|
245
|
+
};
|
|
246
|
+
/** Get the rule set for a language slug, or null if unsupported. */
|
|
247
|
+
export function rulesFor(lang) {
|
|
248
|
+
if (!lang)
|
|
249
|
+
return null;
|
|
250
|
+
return LANGS[lang.toLowerCase()] ?? null;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Tokenize `code` according to `lang`. Returns one big flat token list
|
|
254
|
+
* with whitespace and unmatched content emitted as `text`. The caller
|
|
255
|
+
* is responsible for rendering each token in its kind's color.
|
|
256
|
+
*/
|
|
257
|
+
export function highlight(code, lang) {
|
|
258
|
+
const rules = rulesFor(lang);
|
|
259
|
+
if (!rules)
|
|
260
|
+
return [{ kind: "text", text: code }];
|
|
261
|
+
const out = [];
|
|
262
|
+
let buffer = "";
|
|
263
|
+
let i = 0;
|
|
264
|
+
while (i < code.length) {
|
|
265
|
+
// Eat whitespace into the rolling text buffer — saves work and keeps
|
|
266
|
+
// indentation intact in the output.
|
|
267
|
+
const ch = code[i];
|
|
268
|
+
if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") {
|
|
269
|
+
buffer += ch;
|
|
270
|
+
i++;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const slice = code.slice(i);
|
|
274
|
+
let matched = null;
|
|
275
|
+
for (const rule of rules) {
|
|
276
|
+
const m = slice.match(rule.pattern);
|
|
277
|
+
if (m && m.index === 0) {
|
|
278
|
+
matched = { kind: rule.kind, len: m[0].length };
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (matched) {
|
|
283
|
+
if (buffer) {
|
|
284
|
+
out.push({ kind: "text", text: buffer });
|
|
285
|
+
buffer = "";
|
|
286
|
+
}
|
|
287
|
+
out.push({ kind: matched.kind, text: slice.slice(0, matched.len) });
|
|
288
|
+
i += matched.len;
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
// No match — accumulate one char into the plain-text buffer.
|
|
292
|
+
buffer += ch;
|
|
293
|
+
i++;
|
|
294
|
+
}
|
|
295
|
+
if (buffer)
|
|
296
|
+
out.push({ kind: "text", text: buffer });
|
|
297
|
+
return out;
|
|
298
|
+
}
|
|
299
|
+
/** Map a token kind to an Ink color. Returns undefined for plain text. */
|
|
300
|
+
export function colorForKind(kind) {
|
|
301
|
+
switch (kind) {
|
|
302
|
+
case "keyword":
|
|
303
|
+
return "magenta";
|
|
304
|
+
case "string":
|
|
305
|
+
return "green";
|
|
306
|
+
case "number":
|
|
307
|
+
return "yellow";
|
|
308
|
+
case "comment":
|
|
309
|
+
return "gray";
|
|
310
|
+
case "type":
|
|
311
|
+
return "cyan";
|
|
312
|
+
case "function":
|
|
313
|
+
return "blue";
|
|
314
|
+
case "property":
|
|
315
|
+
return "cyan";
|
|
316
|
+
case "regex":
|
|
317
|
+
return "yellow";
|
|
318
|
+
case "operator":
|
|
319
|
+
case "punctuation":
|
|
320
|
+
case "text":
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=highlight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight.js","sourceRoot":"","sources":["../../src/ui/highlight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
const MAX_HISTORY = 200;
|
|
6
|
+
/**
|
|
7
|
+
* Per-cwd prompt history persisted to ~/.codebase/projects/<hash>/history.json.
|
|
8
|
+
* Keeps the most recent MAX_HISTORY entries, oldest first; identical to
|
|
9
|
+
* SessionStore's hashing so we share the project directory layout.
|
|
10
|
+
*
|
|
11
|
+
* Stored as a JSON array of strings. No metadata, no timestamps — the
|
|
12
|
+
* Input component just needs the chronological list for ↑/↓ recall.
|
|
13
|
+
*/
|
|
14
|
+
export class HistoryStore {
|
|
15
|
+
path;
|
|
16
|
+
max;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
const dataRoot = options.dataRoot ?? join(homedir(), ".codebase");
|
|
19
|
+
const hash = createHash("sha256").update(options.cwd).digest("hex").slice(0, 8);
|
|
20
|
+
this.path = join(dataRoot, "projects", hash, "history.json");
|
|
21
|
+
this.max = options.max ?? MAX_HISTORY;
|
|
22
|
+
}
|
|
23
|
+
get filePath() {
|
|
24
|
+
return this.path;
|
|
25
|
+
}
|
|
26
|
+
load() {
|
|
27
|
+
if (!existsSync(this.path))
|
|
28
|
+
return [];
|
|
29
|
+
try {
|
|
30
|
+
const raw = readFileSync(this.path, "utf8");
|
|
31
|
+
const parsed = JSON.parse(raw);
|
|
32
|
+
if (!Array.isArray(parsed))
|
|
33
|
+
return [];
|
|
34
|
+
return parsed.filter((s) => typeof s === "string");
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Append `entry`. Collapses adjacent dupes so ↑↑↑ doesn't dwell. */
|
|
41
|
+
append(entry) {
|
|
42
|
+
const trimmed = entry.trim();
|
|
43
|
+
if (!trimmed)
|
|
44
|
+
return;
|
|
45
|
+
const current = this.load();
|
|
46
|
+
if (current[current.length - 1] === trimmed)
|
|
47
|
+
return;
|
|
48
|
+
const next = [...current, trimmed];
|
|
49
|
+
const sliced = next.length > this.max ? next.slice(next.length - this.max) : next;
|
|
50
|
+
const dir = join(this.path, "..");
|
|
51
|
+
try {
|
|
52
|
+
mkdirSync(dir, { recursive: true });
|
|
53
|
+
writeFileSync(this.path, JSON.stringify(sliced), { mode: 0o600 });
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// best-effort — losing one history write isn't worth surfacing an error.
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=history-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-store.js","sourceRoot":"","sources":["../../src/ui/history-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,GAAG,GAAG,CAAC;AAQxB;;;;;;;GAOG;AACH,MAAM,OAAO,YAAY;IACP,IAAI,CAAS;IACb,GAAG,CAAS;IAE7B,YAAY,OAA4B;QACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAChF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC;IACvC,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,IAAI;QACH,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC;QACtC,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,CAAC;YACtC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC;IAED,qEAAqE;IACrE,MAAM,CAAC,KAAa;QACnB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,OAAO;YAAE,OAAO;QACpD,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC;YACJ,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACpC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACR,yEAAyE;QAC1E,CAAC;IACF,CAAC;CACD"}
|