ultracontext 1.4.13 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/entry.mjs +9 -3
- package/dist/cli/entry.mjs.map +1 -1
- package/dist/cli/onboarding.mjs +268 -111
- package/dist/cli/onboarding.mjs.map +1 -1
- package/dist/cli/sdk-sync.mjs +199 -939
- package/dist/cli/sdk-sync.mjs.map +1 -1
- package/dist/cli/switch.mjs +168 -0
- package/dist/cli/switch.mjs.map +1 -0
- package/dist/{ctl-CXfNEPN8.mjs → ctl-DTQZxn3N.mjs} +2 -2
- package/dist/{ctl-CXfNEPN8.mjs.map → ctl-DTQZxn3N.mjs.map} +1 -1
- package/dist/hero-art-C03HmDXN.mjs +46 -0
- package/dist/hero-art-C03HmDXN.mjs.map +1 -0
- package/dist/index.d.mts +21 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +25 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{launcher-BMMjzr5k.mjs → launcher-ZylswrpR.mjs} +3 -3
- package/dist/{launcher-BMMjzr5k.mjs.map → launcher-ZylswrpR.mjs.map} +1 -1
- package/dist/{lock-5aJnda81.mjs → lock-BhZX2aF3.mjs} +2 -2
- package/dist/{lock-5aJnda81.mjs.map → lock-BhZX2aF3.mjs.map} +1 -1
- package/dist/onboarding-preferences-Alhblobi.mjs +76 -0
- package/dist/onboarding-preferences-Alhblobi.mjs.map +1 -0
- package/dist/src-Bovo1ukU.mjs +1200 -0
- package/dist/src-Bovo1ukU.mjs.map +1 -0
- package/dist/{tui-DZ1SDOH2.mjs → tui-DLEjew3K.mjs} +334 -115
- package/dist/tui-DLEjew3K.mjs.map +1 -0
- package/dist/utils-BTfShW0g.mjs +36 -0
- package/dist/utils-BTfShW0g.mjs.map +1 -0
- package/dist/{utils-CmuIYHtm.mjs → utils-D9CKnbke.mjs} +26 -34
- package/dist/utils-D9CKnbke.mjs.map +1 -0
- package/lib/register-skills.mjs +96 -0
- package/package.json +8 -3
- package/plugin/.claude-plugin/plugin.json +6 -0
- package/plugin/README.md +112 -0
- package/plugin/marketplace.json +17 -0
- package/plugin/skills/switch/SKILL.md +27 -0
- package/postinstall.mjs +35 -2
- package/dist/Spinner-CwBjkXHv.mjs +0 -153
- package/dist/Spinner-CwBjkXHv.mjs.map +0 -1
- package/dist/tui-DZ1SDOH2.mjs.map +0 -1
- package/dist/utils-CmuIYHtm.mjs.map +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
|
|
5
|
+
//#region src/cli/switch.mjs
|
|
6
|
+
const isTTY = process.stdout.isTTY;
|
|
7
|
+
const esc = (code) => isTTY ? `\x1b[${code}m` : "";
|
|
8
|
+
const r = esc(0);
|
|
9
|
+
const b = esc(1);
|
|
10
|
+
const d = esc(2);
|
|
11
|
+
const green = esc("38;2;80;200;120");
|
|
12
|
+
const red = esc("38;2;220;80;80");
|
|
13
|
+
const gray = esc("38;5;245");
|
|
14
|
+
const VALID_TARGETS = ["codex", "claude"];
|
|
15
|
+
const TERM_GHOSTTY = "ghostty";
|
|
16
|
+
const TERM_ITERM2 = "iTerm.app";
|
|
17
|
+
const TERM_TERMINAL_APP = "Apple_Terminal";
|
|
18
|
+
const GHOSTTY_FOCUS_DELAY_MS = 150;
|
|
19
|
+
const GHOSTTY_TAB_OPEN_DELAY_MS = 300;
|
|
20
|
+
function parseArgs() {
|
|
21
|
+
const args = process.argv.slice(3);
|
|
22
|
+
const opts = {
|
|
23
|
+
target: null,
|
|
24
|
+
last: null,
|
|
25
|
+
session: null,
|
|
26
|
+
noLaunch: false
|
|
27
|
+
};
|
|
28
|
+
for (let i = 0; i < args.length; i++) {
|
|
29
|
+
const arg = args[i];
|
|
30
|
+
if (arg === "--last") {
|
|
31
|
+
const val = Number(args[++i]);
|
|
32
|
+
if (!val || val <= 0) throw new Error("--last requires a positive number");
|
|
33
|
+
opts.last = val;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (arg === "--session") {
|
|
37
|
+
opts.session = args[++i];
|
|
38
|
+
if (!opts.session) throw new Error("--session requires a path");
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (arg === "--no-launch") {
|
|
42
|
+
opts.noLaunch = true;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (!arg.startsWith("-") && !opts.target) {
|
|
46
|
+
opts.target = arg.toLowerCase();
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
throw new Error(`Unknown argument: ${arg}`);
|
|
50
|
+
}
|
|
51
|
+
if (!opts.target) throw new Error("Missing target. Usage: ultracontext switch <codex|claude>");
|
|
52
|
+
if (!VALID_TARGETS.includes(opts.target)) throw new Error(`Invalid target: ${opts.target}. Must be: ${VALID_TARGETS.join(", ")}`);
|
|
53
|
+
return opts;
|
|
54
|
+
}
|
|
55
|
+
function shellQuote(value) {
|
|
56
|
+
return `'${String(value).replace(/'/g, "'\\''")}'`;
|
|
57
|
+
}
|
|
58
|
+
function appleScriptEscape(value) {
|
|
59
|
+
return String(value).replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
60
|
+
}
|
|
61
|
+
function runAppleScript(script) {
|
|
62
|
+
return spawnSync("osascript", ["-e", script]).status === 0;
|
|
63
|
+
}
|
|
64
|
+
function writePasteboard(value) {
|
|
65
|
+
return spawnSync("pbcopy", [], { input: value }).status === 0;
|
|
66
|
+
}
|
|
67
|
+
function launchGhostty(cmd) {
|
|
68
|
+
if (!writePasteboard(cmd)) return false;
|
|
69
|
+
const focusSec = GHOSTTY_FOCUS_DELAY_MS / 1e3;
|
|
70
|
+
const tabSec = GHOSTTY_TAB_OPEN_DELAY_MS / 1e3;
|
|
71
|
+
return runAppleScript([
|
|
72
|
+
"tell application \"Ghostty\" to activate",
|
|
73
|
+
`delay ${focusSec}`,
|
|
74
|
+
"tell application \"System Events\"",
|
|
75
|
+
" tell process \"ghostty\"",
|
|
76
|
+
" keystroke \"t\" using command down",
|
|
77
|
+
` delay ${tabSec}`,
|
|
78
|
+
" keystroke \"v\" using command down",
|
|
79
|
+
" key code 36",
|
|
80
|
+
" end tell",
|
|
81
|
+
"end tell"
|
|
82
|
+
].join("\n"));
|
|
83
|
+
}
|
|
84
|
+
function launchITerm2(cmd) {
|
|
85
|
+
return runAppleScript(`tell application "iTerm2" to tell current window to create tab with default profile command "${appleScriptEscape(cmd)}"`);
|
|
86
|
+
}
|
|
87
|
+
function launchTerminalApp(cmd) {
|
|
88
|
+
return runAppleScript(`tell application "Terminal" to do script "${appleScriptEscape(cmd)}"`);
|
|
89
|
+
}
|
|
90
|
+
const TERMINALS = [
|
|
91
|
+
{
|
|
92
|
+
match: (term) => term.toLowerCase().includes(TERM_GHOSTTY),
|
|
93
|
+
launch: launchGhostty
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
match: (term) => term === TERM_ITERM2,
|
|
97
|
+
launch: launchITerm2
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
match: (term) => term === TERM_TERMINAL_APP,
|
|
101
|
+
launch: launchTerminalApp
|
|
102
|
+
}
|
|
103
|
+
];
|
|
104
|
+
function openInNewTab(cmd) {
|
|
105
|
+
if (os.platform() !== "darwin") return false;
|
|
106
|
+
const term = process.env.TERM_PROGRAM ?? "";
|
|
107
|
+
const entry = TERMINALS.find((t) => t.match(term));
|
|
108
|
+
if (!entry) return false;
|
|
109
|
+
try {
|
|
110
|
+
return entry.launch(cmd);
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function doSwitch(opts) {
|
|
116
|
+
const source = opts.target === "codex" ? "claude" : "codex";
|
|
117
|
+
const { switchSession } = await import("../src-Bovo1ukU.mjs").then((n) => n.t);
|
|
118
|
+
const result = await switchSession({
|
|
119
|
+
source,
|
|
120
|
+
target: opts.target,
|
|
121
|
+
sessionPath: opts.session,
|
|
122
|
+
cwd: process.cwd(),
|
|
123
|
+
last: opts.last
|
|
124
|
+
});
|
|
125
|
+
if (!result.written) {
|
|
126
|
+
console.error(`${red}x${r} Switch failed: ${result.reason}`);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
if (opts.noLaunch) {
|
|
130
|
+
console.log(JSON.stringify({
|
|
131
|
+
sessionId: result.sessionId,
|
|
132
|
+
filePath: result.filePath,
|
|
133
|
+
messageCount: result.messageCount
|
|
134
|
+
}));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
console.log(`${green}✓${r} Switched to ${b}${opts.target}${r}`);
|
|
138
|
+
console.log(` ${d}Session:${r} ${gray}${result.sessionId}${r}`);
|
|
139
|
+
console.log(` ${d}File:${r} ${gray}${result.filePath}${r}`);
|
|
140
|
+
console.log(` ${d}Messages:${r} ${gray}${result.messageCount}${r}`);
|
|
141
|
+
if (opts.target === "codex") {
|
|
142
|
+
const cmd = `codex fork ${result.sessionId} -C ${shellQuote(result.cwd)}`;
|
|
143
|
+
if (!openInNewTab(cmd)) {
|
|
144
|
+
console.log(`\n ${d}Run in your terminal:${r}`);
|
|
145
|
+
console.log(` ${cmd}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (opts.target === "claude") console.log(`\n Open a new Claude Code session to load this context.`);
|
|
149
|
+
}
|
|
150
|
+
async function runSwitch() {
|
|
151
|
+
let opts;
|
|
152
|
+
try {
|
|
153
|
+
opts = parseArgs();
|
|
154
|
+
} catch (err) {
|
|
155
|
+
console.error(`${red}x${r} ${err.message}`);
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
await doSwitch(opts);
|
|
160
|
+
} catch (err) {
|
|
161
|
+
console.error(`${red}x${r} ${err.message}`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
//#endregion
|
|
167
|
+
export { appleScriptEscape, openInNewTab, parseArgs, runSwitch, shellQuote, writePasteboard };
|
|
168
|
+
//# sourceMappingURL=switch.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch.mjs","names":[],"sources":["../../src/cli/switch.mjs"],"sourcesContent":["// CLI handler for `ultracontext switch <target>`\nimport { spawnSync } from \"node:child_process\";\nimport process from \"node:process\";\nimport os from \"node:os\";\n\n// ANSI helpers (match entry.mjs style)\nconst isTTY = process.stdout.isTTY;\nconst esc = (code) => (isTTY ? `\\x1b[${code}m` : \"\");\nconst r = esc(0);\nconst b = esc(1);\nconst d = esc(2);\nconst green = esc(\"38;2;80;200;120\");\nconst red = esc(\"38;2;220;80;80\");\nconst gray = esc(\"38;5;245\");\n\nconst VALID_TARGETS = [\"codex\", \"claude\"];\n\n// known terminal program identifiers from TERM_PROGRAM\nconst TERM_GHOSTTY = \"ghostty\";\nconst TERM_ITERM2 = \"iTerm.app\";\nconst TERM_TERMINAL_APP = \"Apple_Terminal\";\n\n// ms to wait after activate / Cmd+T for Ghostty to be ready to receive paste\nconst GHOSTTY_FOCUS_DELAY_MS = 150;\nconst GHOSTTY_TAB_OPEN_DELAY_MS = 300;\n\n// parse switch-specific args from process.argv\nfunction parseArgs() {\n const args = process.argv.slice(3);\n const opts = { target: null, last: null, session: null, noLaunch: false };\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n\n if (arg === \"--last\") {\n const val = Number(args[++i]);\n if (!val || val <= 0) throw new Error(\"--last requires a positive number\");\n opts.last = val;\n continue;\n }\n\n if (arg === \"--session\") {\n opts.session = args[++i];\n if (!opts.session) throw new Error(\"--session requires a path\");\n continue;\n }\n\n if (arg === \"--no-launch\") {\n opts.noLaunch = true;\n continue;\n }\n\n // positional: target\n if (!arg.startsWith(\"-\") && !opts.target) {\n opts.target = arg.toLowerCase();\n continue;\n }\n\n throw new Error(`Unknown argument: ${arg}`);\n }\n\n if (!opts.target) throw new Error(\"Missing target. Usage: ultracontext switch <codex|claude>\");\n if (!VALID_TARGETS.includes(opts.target)) {\n throw new Error(`Invalid target: ${opts.target}. Must be: ${VALID_TARGETS.join(\", \")}`);\n }\n\n return opts;\n}\n\n// single-quote wrap + escape any embedded single quotes — safe for POSIX shells\nfunction shellQuote(value) {\n return `'${String(value).replace(/'/g, \"'\\\\''\")}'`;\n}\n\n// escape \\ and \" for AppleScript double-quoted string literals\nfunction appleScriptEscape(value) {\n return String(value).replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\n// run AppleScript via spawnSync — argv form avoids shell-layer interpolation\nfunction runAppleScript(script) {\n const r = spawnSync(\"osascript\", [\"-e\", script]);\n return r.status === 0;\n}\n\n// write a string to the macOS pasteboard via pbcopy (stdin avoids all quoting)\nfunction writePasteboard(value) {\n const r = spawnSync(\"pbcopy\", [], { input: value });\n return r.status === 0;\n}\n\n// Ghostty: pasteboard the command, activate Ghostty, open tab, paste, return.\n// Pasteboard + Cmd+V avoids the focus-race window where typed keystrokes could\n// land in the frontmost app if it's not Ghostty. Activate re-anchors focus\n// explicitly before any keystroke is sent, and we tell process \"ghostty\" for\n// every keystroke so System Events routes them to the right process.\nfunction launchGhostty(cmd) {\n if (!writePasteboard(cmd)) return false;\n const focusSec = GHOSTTY_FOCUS_DELAY_MS / 1000;\n const tabSec = GHOSTTY_TAB_OPEN_DELAY_MS / 1000;\n const script = [\n 'tell application \"Ghostty\" to activate',\n `delay ${focusSec}`,\n 'tell application \"System Events\"',\n ' tell process \"ghostty\"',\n ' keystroke \"t\" using command down',\n ` delay ${tabSec}`,\n ' keystroke \"v\" using command down',\n ' key code 36',\n ' end tell',\n 'end tell',\n ].join(\"\\n\");\n return runAppleScript(script);\n}\n\n// iTerm2: create new tab with command\nfunction launchITerm2(cmd) {\n const script = `tell application \"iTerm2\" to tell current window to create tab with default profile command \"${appleScriptEscape(cmd)}\"`;\n return runAppleScript(script);\n}\n\n// Terminal.app: do script in new tab\nfunction launchTerminalApp(cmd) {\n const script = `tell application \"Terminal\" to do script \"${appleScriptEscape(cmd)}\"`;\n return runAppleScript(script);\n}\n\n// dispatch table for supported terminals\nconst TERMINALS = [\n { match: (term) => term.toLowerCase().includes(TERM_GHOSTTY), launch: launchGhostty },\n { match: (term) => term === TERM_ITERM2, launch: launchITerm2 },\n { match: (term) => term === TERM_TERMINAL_APP, launch: launchTerminalApp },\n];\n\n// open a command in a new terminal tab (macOS)\nfunction openInNewTab(cmd) {\n if (os.platform() !== \"darwin\") return false;\n const term = process.env.TERM_PROGRAM ?? \"\";\n const entry = TERMINALS.find((t) => t.match(term));\n if (!entry) return false;\n try { return entry.launch(cmd); } catch { return false; }\n}\n\nasync function doSwitch(opts) {\n // auto-detect source (opposite of target)\n const source = opts.target === \"codex\" ? \"claude\" : \"codex\";\n\n // dynamic import — parsers is a workspace dep\n const { switchSession } = await import(\"@ultracontext/parsers\");\n\n const result = await switchSession({\n source,\n target: opts.target,\n sessionPath: opts.session,\n cwd: process.cwd(),\n last: opts.last,\n });\n\n if (!result.written) {\n console.error(`${red}x${r} Switch failed: ${result.reason}`);\n process.exit(1);\n }\n\n // --no-launch: print JSON for scripting\n if (opts.noLaunch) {\n console.log(JSON.stringify({\n sessionId: result.sessionId,\n filePath: result.filePath,\n messageCount: result.messageCount,\n }));\n return;\n }\n\n // success output\n console.log(`${green}✓${r} Switched to ${b}${opts.target}${r}`);\n console.log(` ${d}Session:${r} ${gray}${result.sessionId}${r}`);\n console.log(` ${d}File:${r} ${gray}${result.filePath}${r}`);\n console.log(` ${d}Messages:${r} ${gray}${result.messageCount}${r}`);\n\n // launch target agent in a new terminal tab — shell-quote cwd so spaces/metachars can't break it\n if (opts.target === \"codex\") {\n const cmd = `codex fork ${result.sessionId} -C ${shellQuote(result.cwd)}`;\n const launched = openInNewTab(cmd);\n if (!launched) {\n // print on its own line with no ANSI wrapping so copy-paste yields a clean command\n console.log(`\\n ${d}Run in your terminal:${r}`);\n console.log(` ${cmd}`);\n }\n }\n\n if (opts.target === \"claude\") {\n console.log(`\\n Open a new Claude Code session to load this context.`);\n }\n}\n\nexport async function runSwitch() {\n let opts;\n try {\n opts = parseArgs();\n } catch (err) {\n console.error(`${red}x${r} ${err.message}`);\n process.exit(1);\n }\n\n try {\n await doSwitch(opts);\n } catch (err) {\n console.error(`${red}x${r} ${err.message}`);\n process.exit(1);\n }\n}\n\n// exported for tests\nexport { parseArgs, shellQuote, appleScriptEscape, openInNewTab, writePasteboard };\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as resolveDaemonInfoFile } from "./protocol-BI9ficcl.mjs";
|
|
2
|
-
import { n as resolveLockPath } from "./lock-
|
|
2
|
+
import { n as resolveLockPath } from "./lock-BhZX2aF3.mjs";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
@@ -118,4 +118,4 @@ if (process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/.*\//,
|
|
|
118
118
|
|
|
119
119
|
//#endregion
|
|
120
120
|
export { runCtl };
|
|
121
|
-
//# sourceMappingURL=ctl-
|
|
121
|
+
//# sourceMappingURL=ctl-DTQZxn3N.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ctl-
|
|
1
|
+
{"version":3,"file":"ctl-DTQZxn3N.mjs","names":[],"sources":["../../sync/src/ctl.mjs"],"sourcesContent":["// daemon ctl — status/stop commands, exported as runCtl()\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport process from \"node:process\";\n\nimport { resolveDaemonInfoFile } from \"./protocol.mjs\";\n\nimport { resolveLockPath } from \"./lock.mjs\";\n\nfunction isPidAlive(pid) {\n if (!Number.isInteger(pid) || pid <= 1) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n if (error?.code === \"EPERM\") return true;\n if (error?.code === \"ESRCH\") return false;\n return false;\n }\n}\n\nasync function readJsonFile(filePath) {\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === \"object\" ? parsed : null;\n } catch {\n return null;\n }\n}\n\nasync function removeFileIfExists(filePath) {\n try { await fs.unlink(filePath); } catch { /* ignore */ }\n}\n\nfunction pickPid(lock, info) {\n const lockPid = Number.parseInt(String(lock?.pid ?? \"\"), 10);\n if (Number.isInteger(lockPid) && lockPid > 1) return lockPid;\n const infoPid = Number.parseInt(String(info?.pid ?? \"\"), 10);\n if (Number.isInteger(infoPid) && infoPid > 1) return infoPid;\n return 0;\n}\n\n// ── ANSI helpers ────────────────────────────────────────────────\n\nconst isTTY = process.stdout.isTTY;\nconst esc = (code) => (isTTY ? `\\x1b[${code}m` : \"\");\nconst r = esc(0);\nconst b = esc(1);\nconst d = esc(2);\nconst blue = esc(\"38;2;47;111;179\");\nconst green = esc(\"38;2;80;200;120\");\nconst red = esc(\"38;2;220;80;80\");\nconst gray = esc(\"38;5;245\");\n\n// ── commands ────────────────────────────────────────────────────\n\nasync function status({ lockPath, infoPath }) {\n const lock = await readJsonFile(lockPath);\n const info = await readJsonFile(infoPath);\n const pid = pickPid(lock, info);\n\n console.log(\"\");\n console.log(` ${blue}${b}UltraContext${r} ${d}Daemon${r}`);\n console.log(\"\");\n\n if (!isPidAlive(pid)) {\n console.log(` ${gray}○${r} ${d}Offline${r}`);\n console.log(\"\");\n return 0;\n }\n\n const port = Number.parseInt(String(info?.port ?? \"\"), 10);\n const portStr = Number.isInteger(port) && port > 0 ? ` ${gray}Port ${port}${r}` : \"\";\n const sinceStr = info?.startedAt ? ` ${gray}Since ${info.startedAt}${r}` : \"\";\n console.log(` ${green}●${r} ${b}Online${r} ${gray}PID ${pid}${r}${portStr}`);\n if (sinceStr) console.log(` ${sinceStr}`);\n console.log(\"\");\n return 0;\n}\n\nasync function stop({ lockPath, infoPath }) {\n const lock = await readJsonFile(lockPath);\n const info = await readJsonFile(infoPath);\n const pid = pickPid(lock, info);\n\n console.log(\"\");\n console.log(` ${blue}${b}UltraContext${r} ${d}Daemon${r}`);\n console.log(\"\");\n\n if (!isPidAlive(pid)) {\n await removeFileIfExists(lockPath);\n await removeFileIfExists(infoPath);\n console.log(` ${gray}○${r} ${d}Already stopped${r}`);\n console.log(\"\");\n return 0;\n }\n\n process.kill(pid, \"SIGTERM\");\n\n const deadline = Date.now() + 5000;\n while (Date.now() < deadline) {\n if (!isPidAlive(pid)) break;\n await new Promise((resolve) => setTimeout(resolve, 120));\n }\n\n if (isPidAlive(pid)) {\n console.error(` ${red}✕${r} ${b}Timed out${r} ${gray}PID ${pid} still running${r}`);\n console.error(\"\");\n return 1;\n }\n\n await removeFileIfExists(lockPath);\n await removeFileIfExists(infoPath);\n console.log(` ${green}✓${r} ${b}Stopped${r} ${gray}PID ${pid}${r}`);\n console.log(\"\");\n return 0;\n}\n\n// ── exported entry point ────────────────────────────────────────\n\nexport async function runCtl() {\n const cmd = String(process.argv[2] ?? \"status\").trim().toLowerCase();\n const lockPath = path.resolve(resolveLockPath(process.env));\n const infoPath = path.resolve(resolveDaemonInfoFile(process.env));\n\n if (cmd === \"status\") return status({ lockPath, infoPath });\n if (cmd === \"stop\") return stop({ lockPath, infoPath });\n\n console.error(`Invalid command: ${cmd}`);\n console.error(\"Use: ultracontext [status|stop]\");\n return 1;\n}\n\n// auto-exec when run directly\nconst isDirectRun = process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/.*\\//, \"\"));\nif (isDirectRun) {\n runCtl().then((code) => process.exit(code)).catch((error) => {\n console.error(`Daemon control failed: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import figlet from "figlet";
|
|
2
|
+
|
|
3
|
+
//#region ../sync/src/ui/hero-art.mjs
|
|
4
|
+
const HERO_TEXT = "UltraContext";
|
|
5
|
+
const HERO_FONT_ORDER = [
|
|
6
|
+
"ANSI Shadow",
|
|
7
|
+
"Standard",
|
|
8
|
+
"Small",
|
|
9
|
+
"Mini"
|
|
10
|
+
];
|
|
11
|
+
const HERO_ART_CACHE = /* @__PURE__ */ new Map();
|
|
12
|
+
function trimBlankEdgeLines(lines) {
|
|
13
|
+
let start = 0;
|
|
14
|
+
let end = lines.length;
|
|
15
|
+
while (start < end && !String(lines[start] ?? "").trim()) start += 1;
|
|
16
|
+
while (end > start && !String(lines[end - 1] ?? "").trim()) end -= 1;
|
|
17
|
+
return lines.slice(start, end);
|
|
18
|
+
}
|
|
19
|
+
const HERO_FONT_ART = HERO_FONT_ORDER.map((font) => {
|
|
20
|
+
try {
|
|
21
|
+
const lines = trimBlankEdgeLines(figlet.textSync(HERO_TEXT, {
|
|
22
|
+
font,
|
|
23
|
+
horizontalLayout: "default",
|
|
24
|
+
verticalLayout: "default"
|
|
25
|
+
}).replace(/\n+$/g, "").split("\n").map((line) => line.replace(/\s+$/g, "")));
|
|
26
|
+
return {
|
|
27
|
+
lines,
|
|
28
|
+
width: Math.max(...lines.map((line) => line.length), 0)
|
|
29
|
+
};
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}).filter(Boolean);
|
|
34
|
+
function heroArtForWidth(columns) {
|
|
35
|
+
const available = Math.max(columns ?? 8, 8);
|
|
36
|
+
const cacheKey = String(available);
|
|
37
|
+
if (HERO_ART_CACHE.has(cacheKey)) return HERO_ART_CACHE.get(cacheKey);
|
|
38
|
+
const candidate = HERO_FONT_ART.find((entry) => entry.width <= available);
|
|
39
|
+
const art = candidate ? candidate.lines.map((line) => line.padEnd(candidate.width, " ")) : available >= 12 ? [HERO_TEXT] : ["UC"];
|
|
40
|
+
HERO_ART_CACHE.set(cacheKey, art);
|
|
41
|
+
return art;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
export { heroArtForWidth as t };
|
|
46
|
+
//# sourceMappingURL=hero-art-C03HmDXN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hero-art-C03HmDXN.mjs","names":[],"sources":["../../sync/src/ui/hero-art.mjs"],"sourcesContent":["import figlet from \"figlet\";\n\nconst HERO_TEXT = \"UltraContext\";\nconst HERO_FONT_ORDER = [\"ANSI Shadow\", \"Standard\", \"Small\", \"Mini\"];\nconst HERO_ART_CACHE = new Map();\n\nfunction trimBlankEdgeLines(lines) {\n let start = 0;\n let end = lines.length;\n while (start < end && !String(lines[start] ?? \"\").trim()) start += 1;\n while (end > start && !String(lines[end - 1] ?? \"\").trim()) end -= 1;\n return lines.slice(start, end);\n}\n\nconst HERO_FONT_ART = HERO_FONT_ORDER.map((font) => {\n try {\n const raw = figlet.textSync(HERO_TEXT, {\n font,\n horizontalLayout: \"default\",\n verticalLayout: \"default\",\n });\n const lines = trimBlankEdgeLines(\n raw\n .replace(/\\n+$/g, \"\")\n .split(\"\\n\")\n .map((line) => line.replace(/\\s+$/g, \"\"))\n );\n const width = Math.max(...lines.map((line) => line.length), 0);\n return { lines, width };\n } catch {\n return null;\n }\n}).filter(Boolean);\n\nexport function heroArtForWidth(columns) {\n const available = Math.max(columns ?? 8, 8);\n const cacheKey = String(available);\n if (HERO_ART_CACHE.has(cacheKey)) return HERO_ART_CACHE.get(cacheKey);\n\n const candidate = HERO_FONT_ART.find((entry) => entry.width <= available);\n const art = candidate\n ? candidate.lines.map((line) => line.padEnd(candidate.width, \" \"))\n : available >= 12\n ? [HERO_TEXT]\n : [\"UC\"];\n\n HERO_ART_CACHE.set(cacheKey, art);\n return art;\n}\n"],"mappings":";;;AAEA,MAAM,YAAY;AAClB,MAAM,kBAAkB;CAAC;CAAe;CAAY;CAAS;CAAO;AACpE,MAAM,iCAAiB,IAAI,KAAK;AAEhC,SAAS,mBAAmB,OAAO;CACjC,IAAI,QAAQ;CACZ,IAAI,MAAM,MAAM;AAChB,QAAO,QAAQ,OAAO,CAAC,OAAO,MAAM,UAAU,GAAG,CAAC,MAAM,CAAE,UAAS;AACnE,QAAO,MAAM,SAAS,CAAC,OAAO,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,CAAE,QAAO;AACnE,QAAO,MAAM,MAAM,OAAO,IAAI;;AAGhC,MAAM,gBAAgB,gBAAgB,KAAK,SAAS;AAClD,KAAI;EAMF,MAAM,QAAQ,mBALF,OAAO,SAAS,WAAW;GACrC;GACA,kBAAkB;GAClB,gBAAgB;GACjB,CAAC,CAGG,QAAQ,SAAS,GAAG,CACpB,MAAM,KAAK,CACX,KAAK,SAAS,KAAK,QAAQ,SAAS,GAAG,CAAC,CAC5C;AAED,SAAO;GAAE;GAAO,OADF,KAAK,IAAI,GAAG,MAAM,KAAK,SAAS,KAAK,OAAO,EAAE,EAAE;GACvC;SACjB;AACN,SAAO;;EAET,CAAC,OAAO,QAAQ;AAElB,SAAgB,gBAAgB,SAAS;CACvC,MAAM,YAAY,KAAK,IAAI,WAAW,GAAG,EAAE;CAC3C,MAAM,WAAW,OAAO,UAAU;AAClC,KAAI,eAAe,IAAI,SAAS,CAAE,QAAO,eAAe,IAAI,SAAS;CAErE,MAAM,YAAY,cAAc,MAAM,UAAU,MAAM,SAAS,UAAU;CACzE,MAAM,MAAM,YACR,UAAU,MAAM,KAAK,SAAS,KAAK,OAAO,UAAU,OAAO,IAAI,CAAC,GAChE,aAAa,KACX,CAAC,UAAU,GACX,CAAC,KAAK;AAEZ,gBAAe,IAAI,UAAU,IAAI;AACjC,QAAO"}
|
package/dist/index.d.mts
CHANGED
|
@@ -89,6 +89,10 @@ type UpdateResponse<T = unknown> = {
|
|
|
89
89
|
version: number;
|
|
90
90
|
};
|
|
91
91
|
type DeleteInput = (string | number) | (string | number)[];
|
|
92
|
+
type DeletePermanentInput = {
|
|
93
|
+
permanent: true;
|
|
94
|
+
metadata?: Record<string, unknown>;
|
|
95
|
+
};
|
|
92
96
|
type DeleteResponse<T = unknown> = {
|
|
93
97
|
data: Array<{
|
|
94
98
|
id: string;
|
|
@@ -97,6 +101,20 @@ type DeleteResponse<T = unknown> = {
|
|
|
97
101
|
} & T>;
|
|
98
102
|
version: number;
|
|
99
103
|
};
|
|
104
|
+
type PermanentDeleteResponse = {
|
|
105
|
+
deleted: boolean;
|
|
106
|
+
id: string;
|
|
107
|
+
metadata?: Record<string, unknown>;
|
|
108
|
+
};
|
|
109
|
+
type DeleteManyResult = {
|
|
110
|
+
id: string;
|
|
111
|
+
deleted: boolean;
|
|
112
|
+
error?: string;
|
|
113
|
+
};
|
|
114
|
+
type DeleteManyResponse = {
|
|
115
|
+
results: DeleteManyResult[];
|
|
116
|
+
deleted_count: number;
|
|
117
|
+
};
|
|
100
118
|
declare class UltraContextHttpError extends Error {
|
|
101
119
|
readonly status: number;
|
|
102
120
|
readonly url: string;
|
|
@@ -120,8 +138,10 @@ declare class UltraContext {
|
|
|
120
138
|
get<T = unknown>(id: string, options?: GetContextInput): Promise<GetContextResponse<T>>;
|
|
121
139
|
update<T = unknown>(contextId: string, input: UpdateInput, options?: MutationOptions): Promise<UpdateResponse<T>>;
|
|
122
140
|
delete<T = unknown>(contextId: string, ids: DeleteInput, options?: MutationOptions): Promise<DeleteResponse<T>>;
|
|
141
|
+
delete(contextId: string, input: DeletePermanentInput): Promise<PermanentDeleteResponse>;
|
|
142
|
+
deleteMany(ids: string[]): Promise<DeleteManyResponse>;
|
|
123
143
|
private request;
|
|
124
144
|
}
|
|
125
145
|
//#endregion
|
|
126
|
-
export { AppendInput, AppendMessage, AppendResponse, CreateContextInput, CreateContextResponse, DeleteInput, DeleteResponse, GetContextInput, GetContextResponse, ListContextsInput, ListContextsResponse, MutationOptions, UltraContext, UltraContextConfig, UltraContextHttpError, UpdateInput, UpdateMessageInput, UpdateResponse, Version };
|
|
146
|
+
export { AppendInput, AppendMessage, AppendResponse, CreateContextInput, CreateContextResponse, DeleteInput, DeleteManyResponse, DeleteManyResult, DeletePermanentInput, DeleteResponse, GetContextInput, GetContextResponse, ListContextsInput, ListContextsResponse, MutationOptions, PermanentDeleteResponse, UltraContext, UltraContextConfig, UltraContextHttpError, UpdateInput, UpdateMessageInput, UpdateResponse, Version };
|
|
127
147
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";KAAY,kBAAA;EACR,MAAA;EACA,OAAA;EACA,KAAA,UAAe,KAAA;EACf,OAAA,GAAU,MAAA;EACV,SAAA;AAAA;AAAA,KAGQ,OAAA;EACR,OAAA;EACA,UAAA;EACA,SAAA;EACA,QAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,KAGH,kBAAA;EACR,IAAA;EACA,OAAA;EACA,EAAA;EACA,MAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,KAGH,qBAAA;EACR,EAAA;EACA,QAAA,EAAU,MAAA;EACV,UAAA;AAAA;AAAA,KAGQ,aAAA,GAAgB,IAAA,CAAK,MAAA;EAAyC,QAAA,GAAW,MAAA;AAAA;AAAA,KACzE,WAAA,GAAc,aAAA,GAAgB,aAAA;AAAA,KAE9B,cAAA;EACR,IAAA,EAAM,KAAA;IAAQ,EAAA;IAAY,KAAA;IAAe,QAAA,EAAU,MAAA;EAAA,IAA4B,CAAA;EAC/E,OAAA;AAAA;AAAA,KAGQ,eAAA;EACR,OAAA;EACA,EAAA;EACA,MAAA;EACA,OAAA;AAAA;AAAA,KAGQ,kBAAA;EACR,IAAA,EAAM,KAAA;IAAQ,EAAA;IAAY,KAAA;IAAe,QAAA,EAAU,MAAA;EAAA,IAA4B,CAAA;EAC/E,OAAA;EACA,QAAA,GAAW,OAAA;AAAA;AAAA,KAGH,iBAAA;EACR,KAAA;EACA,MAAA;EACA,OAAA;EACA,IAAA;EACA,YAAA;EACA,UAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,KAGQ,oBAAA;EACR,IAAA,EAAM,KAAA;IACF,EAAA;IACA,QAAA,EAAU,MAAA;IACV,UAAA;EAAA;AAAA;AAAA,KAII,eAAA;EACR,QAAA,GAAW,MAAA;AAAA;AAAA,KAGH,kBAAA;EACH,EAAA;EAAY,KAAA;AAAA,IAAkB,MAAA;EAC9B,KAAA;EAAe,EAAA;AAAA,IAAe,MAAA;AAAA,KAC3B,WAAA,GAAc,kBAAA,GAAqB,kBAAA;AAAA,KAEnC,cAAA;EACR,IAAA,EAAM,KAAA;IAAQ,EAAA;IAAY,KAAA;IAAe,QAAA,EAAU,MAAA;EAAA,IAA4B,CAAA;EAC/E,OAAA;AAAA;AAAA,KAGQ,WAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -62,15 +62,36 @@ var UltraContext = class {
|
|
|
62
62
|
body
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
|
-
async delete(contextId,
|
|
65
|
+
async delete(contextId, input, options) {
|
|
66
|
+
if (typeof input === "object" && !Array.isArray(input) && input !== null && input.permanent === true) {
|
|
67
|
+
const meta = input.metadata;
|
|
68
|
+
return this.request(`/contexts/${encodeURIComponent(contextId)}`, {
|
|
69
|
+
method: "DELETE",
|
|
70
|
+
body: meta ? {
|
|
71
|
+
permanent: true,
|
|
72
|
+
metadata: meta
|
|
73
|
+
} : { permanent: true }
|
|
74
|
+
});
|
|
75
|
+
}
|
|
66
76
|
return this.request(`/contexts/${encodeURIComponent(contextId)}`, {
|
|
67
77
|
method: "DELETE",
|
|
68
78
|
body: {
|
|
69
|
-
ids,
|
|
79
|
+
ids: input,
|
|
70
80
|
metadata: options?.metadata
|
|
71
81
|
}
|
|
72
82
|
});
|
|
73
83
|
}
|
|
84
|
+
async deleteMany(ids) {
|
|
85
|
+
return this.request("/contexts/delete-many", {
|
|
86
|
+
method: "POST",
|
|
87
|
+
body: { ids },
|
|
88
|
+
acceptStatuses: [
|
|
89
|
+
200,
|
|
90
|
+
207,
|
|
91
|
+
500
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
}
|
|
74
95
|
async request(path, init) {
|
|
75
96
|
const url = `${this.baseUrl}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
76
97
|
const headers = {
|
|
@@ -92,7 +113,8 @@ var UltraContext = class {
|
|
|
92
113
|
body,
|
|
93
114
|
signal: ac?.signal
|
|
94
115
|
});
|
|
95
|
-
|
|
116
|
+
const accepted = init.acceptStatuses?.includes(res.status) ?? false;
|
|
117
|
+
if (!res.ok && !accepted) {
|
|
96
118
|
const bodyText = await safeReadText(res);
|
|
97
119
|
throw new UltraContextHttpError({
|
|
98
120
|
status: res.status,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["export type UltraContextConfig = {\n apiKey: string;\n baseUrl?: string;\n fetch?: typeof fetch;\n headers?: Record<string, string>;\n timeoutMs?: number;\n};\n\nexport type Version = {\n version: number;\n created_at: string;\n operation: 'create' | 'update' | 'delete';\n affected: string[] | null;\n metadata?: Record<string, unknown>;\n};\n\nexport type CreateContextInput = {\n from?: string;\n version?: number;\n at?: number;\n before?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type CreateContextResponse = {\n id: string;\n metadata: Record<string, unknown>;\n created_at: string;\n};\n\nexport type AppendMessage = Omit<Record<string, unknown>, 'metadata'> & { metadata?: Record<string, unknown> };\nexport type AppendInput = AppendMessage | AppendMessage[];\n\nexport type AppendResponse<T = unknown> = {\n data: Array<{ id: string; index: number; metadata: Record<string, unknown> } & T>;\n version: number;\n};\n\nexport type GetContextInput = {\n version?: number;\n at?: number;\n before?: string;\n history?: boolean;\n};\n\nexport type GetContextResponse<T = unknown> = {\n data: Array<{ id: string; index: number; metadata: Record<string, unknown> } & T>;\n version: number;\n versions?: Version[];\n};\n\nexport type ListContextsInput = {\n limit?: number;\n source?: string;\n user_id?: string;\n host?: string;\n project_path?: string;\n session_id?: string;\n after?: string;\n before?: string;\n};\n\nexport type ListContextsResponse = {\n data: Array<{\n id: string;\n metadata: Record<string, unknown>;\n created_at: string;\n }>;\n};\n\nexport type MutationOptions = {\n metadata?: Record<string, unknown>;\n};\n\nexport type UpdateMessageInput =\n | ({ id: string; index?: never } & Record<string, unknown>)\n | ({ index: number; id?: never } & Record<string, unknown>);\nexport type UpdateInput = UpdateMessageInput | UpdateMessageInput[];\n\nexport type UpdateResponse<T = unknown> = {\n data: Array<{ id: string; index: number; metadata: Record<string, unknown> } & T>;\n version: number;\n};\n\nexport type DeleteInput = (string | number) | (string | number)[];\n\nexport type DeleteResponse<T = unknown> = {\n data: Array<{ id: string; index: number; metadata: Record<string, unknown> } & T>;\n version: number;\n};\n\nexport class UltraContextHttpError extends Error {\n readonly status: number;\n readonly url: string;\n readonly bodyText?: string;\n\n constructor(args: { status: number; url: string; bodyText?: string }) {\n super(`UltraContext request failed: ${args.status} ${args.url}`);\n this.name = 'UltraContextHttpError';\n this.status = args.status;\n this.url = args.url;\n this.bodyText = args.bodyText;\n }\n}\n\nexport class UltraContext {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly fetchFn: typeof fetch;\n private readonly headers?: Record<string, string>;\n private readonly timeoutMs?: number;\n\n constructor(cfg: UltraContextConfig) {\n this.baseUrl = (cfg.baseUrl ?? 'https://api.ultracontext.ai').replace(/\\/+$/, '');\n this.apiKey = cfg.apiKey;\n this.fetchFn = cfg.fetch ?? fetch;\n this.headers = cfg.headers;\n this.timeoutMs = cfg.timeoutMs;\n }\n\n async create(input: CreateContextInput = {}): Promise<CreateContextResponse> {\n return this.request<CreateContextResponse>('/contexts', {\n method: 'POST',\n body: input,\n });\n }\n\n async append<T = unknown>(contextId: string, input: AppendInput): Promise<AppendResponse<T>> {\n return this.request<AppendResponse<T>>(`/contexts/${encodeURIComponent(contextId)}`, {\n method: 'POST',\n body: input,\n });\n }\n\n async get(options?: ListContextsInput): Promise<ListContextsResponse>;\n async get<T = unknown>(id: string, options?: GetContextInput): Promise<GetContextResponse<T>>;\n async get<T = unknown>(\n idOrOptions?: string | ListContextsInput,\n options?: GetContextInput\n ): Promise<GetContextResponse<T> | ListContextsResponse> {\n if (!idOrOptions || typeof idOrOptions === 'object') {\n const params = new URLSearchParams();\n if (typeof idOrOptions === 'object') {\n if (idOrOptions.limit) params.set('limit', String(idOrOptions.limit));\n if (idOrOptions.source) params.set('source', idOrOptions.source);\n if (idOrOptions.user_id) params.set('user_id', idOrOptions.user_id);\n if (idOrOptions.host) params.set('host', idOrOptions.host);\n if (idOrOptions.project_path) params.set('project_path', idOrOptions.project_path);\n if (idOrOptions.session_id) params.set('session_id', idOrOptions.session_id);\n if (idOrOptions.after) params.set('after', idOrOptions.after);\n if (idOrOptions.before) params.set('before', idOrOptions.before);\n }\n const query = params.toString();\n return this.request<ListContextsResponse>(`/contexts${query ? `?${query}` : ''}`, { method: 'GET' });\n }\n\n const params = new URLSearchParams();\n if (options?.version !== undefined) params.set('version', String(options.version));\n if (options?.at !== undefined) params.set('at', String(options.at));\n if (options?.before) params.set('before', options.before);\n if (options?.history) params.set('history', 'true');\n const query = params.toString();\n return this.request<GetContextResponse<T>>(`/contexts/${encodeURIComponent(idOrOptions)}${query ? `?${query}` : ''}`, { method: 'GET' });\n }\n\n async update<T = unknown>(contextId: string, input: UpdateInput, options?: MutationOptions): Promise<UpdateResponse<T>> {\n const body = options?.metadata\n ? { updates: Array.isArray(input) ? input : [input], metadata: options.metadata }\n : input;\n\n return this.request<UpdateResponse<T>>(`/contexts/${encodeURIComponent(contextId)}`, {\n method: 'PATCH',\n body,\n });\n }\n\n async delete<T = unknown>(contextId: string, ids: DeleteInput, options?: MutationOptions): Promise<DeleteResponse<T>> {\n return this.request<DeleteResponse<T>>(`/contexts/${encodeURIComponent(contextId)}`, {\n method: 'DELETE',\n body: { ids, metadata: options?.metadata },\n });\n }\n\n private async request<T>(path: string, init: { method: string; body?: unknown; headers?: Record<string, string> }): Promise<T> {\n const url = `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n ...(this.headers ?? {}),\n ...(init.headers ?? {}),\n };\n\n let body: BodyInit | undefined;\n if (init.body !== undefined) {\n headers['Content-Type'] = headers['Content-Type'] ?? 'application/json';\n body = JSON.stringify(init.body);\n }\n\n const ac = this.timeoutMs ? new AbortController() : undefined;\n const timeout = this.timeoutMs ? setTimeout(() => ac?.abort(), this.timeoutMs) : undefined;\n\n try {\n const res = await this.fetchFn(url, {\n method: init.method,\n headers,\n body,\n signal: ac?.signal,\n });\n\n if (!res.ok) {\n const bodyText = await safeReadText(res);\n throw new UltraContextHttpError({ status: res.status, url, bodyText });\n }\n\n if (res.status === 204) return undefined as unknown as T;\n\n const contentType = res.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) return (await res.json()) as T;\n return (await res.text()) as unknown as T;\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n }\n}\n\nasync function safeReadText(res: Response) {\n try {\n return await res.text();\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["export type UltraContextConfig = {\n apiKey: string;\n baseUrl?: string;\n fetch?: typeof fetch;\n headers?: Record<string, string>;\n timeoutMs?: number;\n};\n\nexport type Version = {\n version: number;\n created_at: string;\n operation: 'create' | 'update' | 'delete';\n affected: string[] | null;\n metadata?: Record<string, unknown>;\n};\n\nexport type CreateContextInput = {\n from?: string;\n version?: number;\n at?: number;\n before?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type CreateContextResponse = {\n id: string;\n metadata: Record<string, unknown>;\n created_at: string;\n};\n\nexport type AppendMessage = Omit<Record<string, unknown>, 'metadata'> & { metadata?: Record<string, unknown> };\nexport type AppendInput = AppendMessage | AppendMessage[];\n\nexport type AppendResponse<T = unknown> = {\n data: Array<{ id: string; index: number; metadata: Record<string, unknown> } & T>;\n version: number;\n};\n\nexport type GetContextInput = {\n version?: number;\n at?: number;\n before?: string;\n history?: boolean;\n};\n\nexport type GetContextResponse<T = unknown> = {\n data: Array<{ id: string; index: number; metadata: Record<string, unknown> } & T>;\n version: number;\n versions?: Version[];\n};\n\nexport type ListContextsInput = {\n limit?: number;\n source?: string;\n user_id?: string;\n host?: string;\n project_path?: string;\n session_id?: string;\n after?: string;\n before?: string;\n};\n\nexport type ListContextsResponse = {\n data: Array<{\n id: string;\n metadata: Record<string, unknown>;\n created_at: string;\n }>;\n};\n\nexport type MutationOptions = {\n metadata?: Record<string, unknown>;\n};\n\nexport type UpdateMessageInput =\n | ({ id: string; index?: never } & Record<string, unknown>)\n | ({ index: number; id?: never } & Record<string, unknown>);\nexport type UpdateInput = UpdateMessageInput | UpdateMessageInput[];\n\nexport type UpdateResponse<T = unknown> = {\n data: Array<{ id: string; index: number; metadata: Record<string, unknown> } & T>;\n version: number;\n};\n\nexport type DeleteInput = (string | number) | (string | number)[];\n\n// Unified delete input — either message ids (soft, versioned) OR {permanent: true} (hard, irreversible)\nexport type DeletePermanentInput = { permanent: true; metadata?: Record<string, unknown> };\n\nexport type DeleteResponse<T = unknown> = {\n data: Array<{ id: string; index: number; metadata: Record<string, unknown> } & T>;\n version: number;\n};\n\nexport type PermanentDeleteResponse = {\n deleted: boolean;\n id: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type DeleteManyResult = {\n id: string;\n deleted: boolean;\n error?: string;\n};\n\nexport type DeleteManyResponse = {\n results: DeleteManyResult[];\n deleted_count: number;\n};\n\nexport class UltraContextHttpError extends Error {\n readonly status: number;\n readonly url: string;\n readonly bodyText?: string;\n\n constructor(args: { status: number; url: string; bodyText?: string }) {\n super(`UltraContext request failed: ${args.status} ${args.url}`);\n this.name = 'UltraContextHttpError';\n this.status = args.status;\n this.url = args.url;\n this.bodyText = args.bodyText;\n }\n}\n\nexport class UltraContext {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly fetchFn: typeof fetch;\n private readonly headers?: Record<string, string>;\n private readonly timeoutMs?: number;\n\n constructor(cfg: UltraContextConfig) {\n this.baseUrl = (cfg.baseUrl ?? 'https://api.ultracontext.ai').replace(/\\/+$/, '');\n this.apiKey = cfg.apiKey;\n this.fetchFn = cfg.fetch ?? fetch;\n this.headers = cfg.headers;\n this.timeoutMs = cfg.timeoutMs;\n }\n\n async create(input: CreateContextInput = {}): Promise<CreateContextResponse> {\n return this.request<CreateContextResponse>('/contexts', {\n method: 'POST',\n body: input,\n });\n }\n\n async append<T = unknown>(contextId: string, input: AppendInput): Promise<AppendResponse<T>> {\n return this.request<AppendResponse<T>>(`/contexts/${encodeURIComponent(contextId)}`, {\n method: 'POST',\n body: input,\n });\n }\n\n async get(options?: ListContextsInput): Promise<ListContextsResponse>;\n async get<T = unknown>(id: string, options?: GetContextInput): Promise<GetContextResponse<T>>;\n async get<T = unknown>(\n idOrOptions?: string | ListContextsInput,\n options?: GetContextInput\n ): Promise<GetContextResponse<T> | ListContextsResponse> {\n if (!idOrOptions || typeof idOrOptions === 'object') {\n const params = new URLSearchParams();\n if (typeof idOrOptions === 'object') {\n if (idOrOptions.limit) params.set('limit', String(idOrOptions.limit));\n if (idOrOptions.source) params.set('source', idOrOptions.source);\n if (idOrOptions.user_id) params.set('user_id', idOrOptions.user_id);\n if (idOrOptions.host) params.set('host', idOrOptions.host);\n if (idOrOptions.project_path) params.set('project_path', idOrOptions.project_path);\n if (idOrOptions.session_id) params.set('session_id', idOrOptions.session_id);\n if (idOrOptions.after) params.set('after', idOrOptions.after);\n if (idOrOptions.before) params.set('before', idOrOptions.before);\n }\n const query = params.toString();\n return this.request<ListContextsResponse>(`/contexts${query ? `?${query}` : ''}`, { method: 'GET' });\n }\n\n const params = new URLSearchParams();\n if (options?.version !== undefined) params.set('version', String(options.version));\n if (options?.at !== undefined) params.set('at', String(options.at));\n if (options?.before) params.set('before', options.before);\n if (options?.history) params.set('history', 'true');\n const query = params.toString();\n return this.request<GetContextResponse<T>>(`/contexts/${encodeURIComponent(idOrOptions)}${query ? `?${query}` : ''}`, { method: 'GET' });\n }\n\n async update<T = unknown>(contextId: string, input: UpdateInput, options?: MutationOptions): Promise<UpdateResponse<T>> {\n const body = options?.metadata\n ? { updates: Array.isArray(input) ? input : [input], metadata: options.metadata }\n : input;\n\n return this.request<UpdateResponse<T>>(`/contexts/${encodeURIComponent(contextId)}`, {\n method: 'PATCH',\n body,\n });\n }\n\n async delete<T = unknown>(contextId: string, ids: DeleteInput, options?: MutationOptions): Promise<DeleteResponse<T>>;\n async delete(contextId: string, input: DeletePermanentInput): Promise<PermanentDeleteResponse>;\n async delete<T = unknown>(\n contextId: string,\n input: DeleteInput | DeletePermanentInput,\n options?: MutationOptions,\n ): Promise<DeleteResponse<T> | PermanentDeleteResponse> {\n const isPermanent =\n typeof input === 'object' &&\n !Array.isArray(input) &&\n input !== null &&\n (input as DeletePermanentInput).permanent === true;\n\n if (isPermanent) {\n const meta = (input as DeletePermanentInput).metadata;\n return this.request<PermanentDeleteResponse>(`/contexts/${encodeURIComponent(contextId)}`, {\n method: 'DELETE',\n body: meta ? { permanent: true, metadata: meta } : { permanent: true },\n });\n }\n\n return this.request<DeleteResponse<T>>(`/contexts/${encodeURIComponent(contextId)}`, {\n method: 'DELETE',\n body: { ids: input as DeleteInput, metadata: options?.metadata },\n });\n }\n\n async deleteMany(ids: string[]): Promise<DeleteManyResponse> {\n // 200 (all ok), 207 (partial), 500 (all failed) all carry a results body — surface directly.\n return this.request<DeleteManyResponse>('/contexts/delete-many', {\n method: 'POST',\n body: { ids },\n acceptStatuses: [200, 207, 500],\n });\n }\n\n private async request<T>(path: string, init: { method: string; body?: unknown; headers?: Record<string, string>; acceptStatuses?: number[] }): Promise<T> {\n const url = `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n ...(this.headers ?? {}),\n ...(init.headers ?? {}),\n };\n\n let body: BodyInit | undefined;\n if (init.body !== undefined) {\n headers['Content-Type'] = headers['Content-Type'] ?? 'application/json';\n body = JSON.stringify(init.body);\n }\n\n const ac = this.timeoutMs ? new AbortController() : undefined;\n const timeout = this.timeoutMs ? setTimeout(() => ac?.abort(), this.timeoutMs) : undefined;\n\n try {\n const res = await this.fetchFn(url, {\n method: init.method,\n headers,\n body,\n signal: ac?.signal,\n });\n\n const accepted = init.acceptStatuses?.includes(res.status) ?? false;\n if (!res.ok && !accepted) {\n const bodyText = await safeReadText(res);\n throw new UltraContextHttpError({ status: res.status, url, bodyText });\n }\n\n if (res.status === 204) return undefined as unknown as T;\n\n const contentType = res.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) return (await res.json()) as T;\n return (await res.text()) as unknown as T;\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n }\n}\n\nasync function safeReadText(res: Response) {\n try {\n return await res.text();\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as resolveLockPath } from "./lock-
|
|
1
|
+
import { i as expandHome } from "./utils-D9CKnbke.mjs";
|
|
2
|
+
import { n as resolveLockPath } from "./lock-BhZX2aF3.mjs";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import path from "node:path";
|
|
@@ -137,4 +137,4 @@ if (process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/.*\//,
|
|
|
137
137
|
|
|
138
138
|
//#endregion
|
|
139
139
|
export { launchDaemon };
|
|
140
|
-
//# sourceMappingURL=launcher-
|
|
140
|
+
//# sourceMappingURL=launcher-ZylswrpR.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launcher-
|
|
1
|
+
{"version":3,"file":"launcher-ZylswrpR.mjs","names":["fs","fsSync"],"sources":["../../sync/src/launcher.mjs"],"sourcesContent":["// daemon launcher — spawns daemon in background, exported as launchDaemon()\nimport fs from \"node:fs/promises\";\nimport fsSync from \"node:fs\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\n\n\nimport { resolveLockPath } from \"./lock.mjs\";\nimport { expandHome } from \"./utils.mjs\";\n\nconst DEFAULT_LOG_FILE = \"~/.ultracontext/daemon.log\";\n\n// ── ANSI helpers ────────────────────────────────────────────────\n\nconst isTTY = process.stdout.isTTY;\nconst esc = (code) => (isTTY ? `\\x1b[${code}m` : \"\");\nconst reset = esc(0);\nconst bold = esc(1);\nconst dim = esc(2);\nconst blue = esc(\"38;2;47;111;179\");\nconst cyan = esc(\"38;2;126;195;255\");\nconst green = esc(\"38;2;80;200;120\");\nconst red = esc(\"38;2;220;80;80\");\nconst gray = esc(\"38;5;245\");\n\n// ── process helpers ─────────────────────────────────────────────\n\nfunction isPidAlive(pid) {\n if (!Number.isInteger(pid) || pid <= 1) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n if (error?.code === \"EPERM\") return true;\n if (error?.code === \"ESRCH\") return false;\n return false;\n }\n}\n\nasync function readJsonFile(filePath) {\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === \"object\" ? parsed : null;\n } catch {\n return null;\n }\n}\n\nasync function readLogTail(logPath, lines = 12) {\n try {\n const raw = await fs.readFile(logPath, \"utf8\");\n const allLines = raw.split(\"\\n\").map((l) => l.trimEnd()).filter(Boolean);\n return allLines.length === 0 ? [] : allLines.slice(-Math.max(lines, 1));\n } catch {\n return [];\n }\n}\n\nfunction resolveDaemonLogFile(env = process.env) {\n return expandHome(env.ULTRACONTEXT_DAEMON_LOG_FILE ?? DEFAULT_LOG_FILE);\n}\n\nasync function resolveRunningProcess(lockPath) {\n const lock = await readJsonFile(lockPath);\n const lockPid = Number.parseInt(String(lock?.pid ?? \"\"), 10);\n if (isPidAlive(lockPid)) {\n return { pid: lockPid, startedAt: String(lock?.startedAt ?? \"\"), userId: String(lock?.userId ?? \"\"), host: String(lock?.host ?? \"\") };\n }\n return null;\n}\n\nasync function resolveWritableLogPath(preferredPath) {\n const primary = path.resolve(preferredPath);\n try {\n await fs.mkdir(path.dirname(primary), { recursive: true });\n fsSync.accessSync(path.dirname(primary), fsSync.constants.W_OK);\n return primary;\n } catch {\n const fallback = path.resolve(process.cwd(), \".ultracontext-daemon.log\");\n await fs.mkdir(path.dirname(fallback), { recursive: true });\n return fallback;\n }\n}\n\n// ── exported entry point ────────────────────────────────────────\n\nexport async function launchDaemon({ entryPath, diagnosticsHint } = {}) {\n const resolvedEntry = entryPath ?? fileURLToPath(new URL(\"./index.mjs\", import.meta.url));\n const hint = diagnosticsHint ?? \"pnpm --filter @ultracontext/sync run start\";\n\n const lockPath = path.resolve(resolveLockPath(process.env));\n const preferredLogPath = resolveDaemonLogFile(process.env);\n\n console.log(\"\");\n console.log(` ${blue}${bold}UltraContext${reset} ${dim}Daemon${reset}`);\n console.log(\"\");\n\n // already running\n const running = await resolveRunningProcess(lockPath);\n if (running) {\n console.log(` ${cyan}●${reset} ${bold}Already running${reset} ${gray}PID ${running.pid}${reset}`);\n console.log(\"\");\n process.exit(2);\n return;\n }\n\n // spawn daemon\n const logPath = await resolveWritableLogPath(preferredLogPath);\n const outFd = fsSync.openSync(logPath, \"a\");\n const errFd = fsSync.openSync(logPath, \"a\");\n\n let child;\n try {\n child = spawn(process.execPath, [resolvedEntry, \"--daemon\"], {\n env: process.env,\n detached: false,\n stdio: [\"ignore\", outFd, errFd],\n });\n child.unref();\n } finally {\n try { fsSync.closeSync(outFd); } catch { /* ignore */ }\n try { fsSync.closeSync(errFd); } catch { /* ignore */ }\n }\n\n await new Promise((resolve) => setTimeout(resolve, 350));\n\n // failed\n if (!isPidAlive(child.pid)) {\n console.log(` ${red}✕${reset} ${bold}Failed to start${reset}`);\n const tail = await readLogTail(logPath);\n if (tail.length > 0) {\n console.log(\"\");\n for (const line of tail) console.error(` ${gray}${line}${reset}`);\n }\n console.log(\"\");\n console.log(` ${dim}Try: ${hint}${reset}`);\n console.log(\"\");\n process.exit(1);\n return;\n }\n\n // success\n console.log(` ${green}✓${reset} ${bold}Started${reset} ${gray}PID ${child.pid}${reset}`);\n console.log(` ${gray}${logPath}${reset}`);\n console.log(\"\");\n}\n\n// auto-exec when run directly\nconst isDirectRun = process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/.*\\//, \"\"));\nif (isDirectRun) {\n launchDaemon().catch((error) => {\n console.error(` ${red}✕${reset} ${error instanceof Error ? error.message : String(error)}`);\n console.error(\"\");\n process.exit(1);\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as expandHome } from "./utils-D9CKnbke.mjs";
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
@@ -78,4 +78,4 @@ async function acquireFileLock({ lockPath = resolveLockPath(process.env), userId
|
|
|
78
78
|
|
|
79
79
|
//#endregion
|
|
80
80
|
export { resolveLockPath as n, acquireFileLock as t };
|
|
81
|
-
//# sourceMappingURL=lock-
|
|
81
|
+
//# sourceMappingURL=lock-BhZX2aF3.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock-
|
|
1
|
+
{"version":3,"file":"lock-BhZX2aF3.mjs","names":[],"sources":["../../sync/src/lock.mjs"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport process from \"node:process\";\n\nimport { expandHome } from \"./utils.mjs\";\n\nconst DEFAULT_LOCK_PATH = \"~/.ultracontext/daemon.lock\";\n\nfunction isPidAlive(pid) {\n if (!Number.isInteger(pid) || pid <= 1) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n if (error?.code === \"EPERM\") return true;\n if (error?.code === \"ESRCH\") return false;\n return false;\n }\n}\n\nasync function readExistingLock(lockPath) {\n try {\n const raw = await fs.readFile(lockPath, \"utf8\");\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === \"object\" ? parsed : null;\n } catch {\n return null;\n }\n}\n\nexport function resolveLockPath(env = process.env) {\n return expandHome(env.ULTRACONTEXT_LOCK_FILE ?? DEFAULT_LOCK_PATH);\n}\n\nexport async function acquireFileLock({\n lockPath = resolveLockPath(process.env),\n userId = \"\",\n host = \"\",\n} = {}) {\n const resolved = path.resolve(lockPath);\n await fs.mkdir(path.dirname(resolved), { recursive: true });\n\n let handle;\n try {\n handle = await fs.open(resolved, \"wx\");\n } catch (error) {\n if (error?.code !== \"EEXIST\") throw error;\n\n const existing = await readExistingLock(resolved);\n const existingPid = Number.parseInt(String(existing?.pid ?? \"\"), 10);\n if (!isPidAlive(existingPid)) {\n try {\n await fs.unlink(resolved);\n } catch {\n // ignore\n }\n handle = await fs.open(resolved, \"wx\");\n } else {\n const reason = existingPid\n ? `UltraContext daemon already running (PID: ${existingPid})`\n : \"UltraContext daemon already running\";\n const lockError = new Error(reason);\n lockError.code = \"ELOCKED\";\n lockError.pid = existingPid;\n throw lockError;\n }\n }\n\n const payload = {\n pid: process.pid,\n host: String(host ?? \"\"),\n userId: String(userId ?? \"\"),\n startedAt: new Date().toISOString(),\n };\n await handle.writeFile(`${JSON.stringify(payload, null, 2)}\\n`, \"utf8\");\n\n let released = false;\n const release = async () => {\n if (released) return;\n released = true;\n try {\n await handle.close();\n } catch {\n // ignore\n }\n try {\n await fs.unlink(resolved);\n } catch {\n // ignore\n }\n };\n\n return {\n lockPath: resolved,\n payload,\n release,\n };\n}\n"],"mappings":";;;;;;AAMA,MAAM,oBAAoB;AAE1B,SAAS,WAAW,KAAK;AACvB,KAAI,CAAC,OAAO,UAAU,IAAI,IAAI,OAAO,EAAG,QAAO;AAC/C,KAAI;AACF,UAAQ,KAAK,KAAK,EAAE;AACpB,SAAO;UACA,OAAO;AACd,MAAI,OAAO,SAAS,QAAS,QAAO;AACpC,MAAI,OAAO,SAAS,QAAS,QAAO;AACpC,SAAO;;;AAIX,eAAe,iBAAiB,UAAU;AACxC,KAAI;EACF,MAAM,MAAM,MAAM,GAAG,SAAS,UAAU,OAAO;EAC/C,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,SAAO,UAAU,OAAO,WAAW,WAAW,SAAS;SACjD;AACN,SAAO;;;AAIX,SAAgB,gBAAgB,MAAM,QAAQ,KAAK;AACjD,QAAO,WAAW,IAAI,0BAA0B,kBAAkB;;AAGpE,eAAsB,gBAAgB,EACpC,WAAW,gBAAgB,QAAQ,IAAI,EACvC,SAAS,IACT,OAAO,OACL,EAAE,EAAE;CACN,MAAM,WAAW,KAAK,QAAQ,SAAS;AACvC,OAAM,GAAG,MAAM,KAAK,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;CAE3D,IAAI;AACJ,KAAI;AACF,WAAS,MAAM,GAAG,KAAK,UAAU,KAAK;UAC/B,OAAO;AACd,MAAI,OAAO,SAAS,SAAU,OAAM;EAEpC,MAAM,WAAW,MAAM,iBAAiB,SAAS;EACjD,MAAM,cAAc,OAAO,SAAS,OAAO,UAAU,OAAO,GAAG,EAAE,GAAG;AACpE,MAAI,CAAC,WAAW,YAAY,EAAE;AAC5B,OAAI;AACF,UAAM,GAAG,OAAO,SAAS;WACnB;AAGR,YAAS,MAAM,GAAG,KAAK,UAAU,KAAK;SACjC;GACL,MAAM,SAAS,cACX,6CAA6C,YAAY,KACzD;GACJ,MAAM,YAAY,IAAI,MAAM,OAAO;AACnC,aAAU,OAAO;AACjB,aAAU,MAAM;AAChB,SAAM;;;CAIV,MAAM,UAAU;EACd,KAAK,QAAQ;EACb,MAAM,OAAO,QAAQ,GAAG;EACxB,QAAQ,OAAO,UAAU,GAAG;EAC5B,4BAAW,IAAI,MAAM,EAAC,aAAa;EACpC;AACD,OAAM,OAAO,UAAU,GAAG,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC,KAAK,OAAO;CAEvE,IAAI,WAAW;CACf,MAAM,UAAU,YAAY;AAC1B,MAAI,SAAU;AACd,aAAW;AACX,MAAI;AACF,SAAM,OAAO,OAAO;UACd;AAGR,MAAI;AACF,SAAM,GAAG,OAAO,SAAS;UACnB;;AAKV,QAAO;EACL,UAAU;EACV;EACA;EACD"}
|