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.
Files changed (41) hide show
  1. package/dist/cli/entry.mjs +9 -3
  2. package/dist/cli/entry.mjs.map +1 -1
  3. package/dist/cli/onboarding.mjs +268 -111
  4. package/dist/cli/onboarding.mjs.map +1 -1
  5. package/dist/cli/sdk-sync.mjs +199 -939
  6. package/dist/cli/sdk-sync.mjs.map +1 -1
  7. package/dist/cli/switch.mjs +168 -0
  8. package/dist/cli/switch.mjs.map +1 -0
  9. package/dist/{ctl-CXfNEPN8.mjs → ctl-DTQZxn3N.mjs} +2 -2
  10. package/dist/{ctl-CXfNEPN8.mjs.map → ctl-DTQZxn3N.mjs.map} +1 -1
  11. package/dist/hero-art-C03HmDXN.mjs +46 -0
  12. package/dist/hero-art-C03HmDXN.mjs.map +1 -0
  13. package/dist/index.d.mts +21 -1
  14. package/dist/index.d.mts.map +1 -1
  15. package/dist/index.mjs +25 -3
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/{launcher-BMMjzr5k.mjs → launcher-ZylswrpR.mjs} +3 -3
  18. package/dist/{launcher-BMMjzr5k.mjs.map → launcher-ZylswrpR.mjs.map} +1 -1
  19. package/dist/{lock-5aJnda81.mjs → lock-BhZX2aF3.mjs} +2 -2
  20. package/dist/{lock-5aJnda81.mjs.map → lock-BhZX2aF3.mjs.map} +1 -1
  21. package/dist/onboarding-preferences-Alhblobi.mjs +76 -0
  22. package/dist/onboarding-preferences-Alhblobi.mjs.map +1 -0
  23. package/dist/src-Bovo1ukU.mjs +1200 -0
  24. package/dist/src-Bovo1ukU.mjs.map +1 -0
  25. package/dist/{tui-DZ1SDOH2.mjs → tui-DLEjew3K.mjs} +334 -115
  26. package/dist/tui-DLEjew3K.mjs.map +1 -0
  27. package/dist/utils-BTfShW0g.mjs +36 -0
  28. package/dist/utils-BTfShW0g.mjs.map +1 -0
  29. package/dist/{utils-CmuIYHtm.mjs → utils-D9CKnbke.mjs} +26 -34
  30. package/dist/utils-D9CKnbke.mjs.map +1 -0
  31. package/lib/register-skills.mjs +96 -0
  32. package/package.json +8 -3
  33. package/plugin/.claude-plugin/plugin.json +6 -0
  34. package/plugin/README.md +112 -0
  35. package/plugin/marketplace.json +17 -0
  36. package/plugin/skills/switch/SKILL.md +27 -0
  37. package/postinstall.mjs +35 -2
  38. package/dist/Spinner-CwBjkXHv.mjs +0 -153
  39. package/dist/Spinner-CwBjkXHv.mjs.map +0 -1
  40. package/dist/tui-DZ1SDOH2.mjs.map +0 -1
  41. 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-5aJnda81.mjs";
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-CXfNEPN8.mjs.map
121
+ //# sourceMappingURL=ctl-DTQZxn3N.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ctl-CXfNEPN8.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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"}
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
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, ids, options) {
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
- if (!res.ok) {
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,
@@ -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 { s as expandHome } from "./utils-CmuIYHtm.mjs";
2
- import { n as resolveLockPath } from "./lock-5aJnda81.mjs";
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-BMMjzr5k.mjs.map
140
+ //# sourceMappingURL=launcher-ZylswrpR.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"launcher-BMMjzr5k.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
+ {"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 { s as expandHome } from "./utils-CmuIYHtm.mjs";
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-5aJnda81.mjs.map
81
+ //# sourceMappingURL=lock-BhZX2aF3.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"lock-5aJnda81.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"}
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"}