ultracontext 1.1.1 → 1.1.5

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/README.md CHANGED
@@ -4,13 +4,11 @@
4
4
  </a>
5
5
  </p>
6
6
 
7
- <h3 align="center">The Context Hub for AI agents.</h3>
7
+ <h3 align="center">Context infrastructure for AI agents.</h3>
8
8
 
9
9
  <p align="center">
10
- <a href="https://ultracontext.ai/docs">Documentation</a>
11
- ·
12
- <a href="https://ultracontext.ai/docs/api-reference/introduction">API Reference</a>
13
- ·
10
+ <a href="https://ultracontext.ai/docs">Documentation</a> ·
11
+ <a href="https://ultracontext.ai/docs/api-reference/introduction">API Reference</a> ·
14
12
  <a href="https://ultracontext.ai/docs/changelog">Changelog</a>
15
13
  </p>
16
14
 
@@ -24,8 +22,8 @@
24
22
  <a href="https://github.com/ultracontext/ultracontext/blob/main/LICENSE">
25
23
  <img src="https://img.shields.io/github/license/ultracontext/ultracontext" alt="license" />
26
24
  </a>
27
- <a href="https://github.com/ultracontext/ultracontext">
28
- <img src="https://img.shields.io/github/stars/ultracontext/ultracontext.svg?style=social&label=Star" alt="GitHub stars" />
25
+ <a href="https://ultracontext.ai">
26
+ <img src="https://img.shields.io/badge/Visit-ultracontext.ai-4B6EF5" alt="Visit ultracontext.ai" />
29
27
  </a>
30
28
  </p>
31
29
 
@@ -33,95 +31,92 @@
33
31
  <a href="https://twitter.com/ultracontext">
34
32
  <img src="https://img.shields.io/badge/Follow%20on%20X-000000?style=for-the-badge&logo=x&logoColor=white" alt="Follow on X" />
35
33
  </a>
34
+ <a href="https://discord.com/invite/4HjcS6KwhW">
35
+ <img src="https://img.shields.io/badge/Join%20our%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Join our Discord" />
36
+ </a>
36
37
  </div>
37
38
 
38
- <div align="center">
39
-
40
- ## All agents. All machines. One Hub.
39
+ ---
41
40
 
42
- </div>
43
- <img src="https://ultracontext.ai/ultracontext-hub.gif" alt="How it works" />
41
+ <h2 align="center">All agents. One context.</h2>
44
42
 
45
- ## Introduction
43
+ Auto-capture and share your agents' context everywhere. Realtime. Open source.
46
44
 
47
- Agents now do our work. Today, most of our knowledge and key decisions live inside context windows. But they are spread across many agents, computers, and teams.
45
+ ![ultracontext-gif](https://github.com/user-attachments/assets/be73afe5-161d-4fa3-8f4d-c4987fe63cb4)
48
46
 
49
- Not anymore.
47
+ Everyone is shipping with agents. Few are shipping with agents together.
50
48
 
51
- ## UltraContext Features
49
+ Multiple people, multiple agents, multiple machines. Our contexts are spread everywhere. There's no standard for context engineering. No infrastructure to build on. No fundamental building blocks to agree on. So we decided to make it.
52
50
 
53
- - **Auto-ingest** Captures contexts from your agents in realtime.
54
- - **Realtime access** — Immediately see contexts created on any machine, by any agent, whenever you want.
55
- - **Collaborate** — Share contexts across your team. See what everyone sees, instantly and without any friction.
56
- - **Switch between agents** — Pick up where one agent left off with another.
57
- - **Open source** — Own your data. Self-host when you need to.
58
- - **Plug and play** — Install and run with a single line of code.
59
- - **Fork & clone** — Continue contexts while preserving the full history.
60
- - **Customizable** — Add your own agents and extend behavior with the context API ([Docs here](https://ultracontext.ai/docs/api-reference/introduction)).
51
+ UltraContext is the context infrastructure. The API gives you git-like primitives for context engineering. The Hub lets you auto-capture, share, and collaborate across agents in realtime.
61
52
 
62
53
  ## Install
63
54
 
64
- Requires **Node >= 22**.
55
+ Requires Node >= 22.
65
56
 
66
57
  ```bash
67
58
  npm install -g ultracontext
68
59
  ```
69
60
 
70
- That's it. The setup wizard runs automatically — walks you through API key, sync preferences, and launches the dashboard.
61
+ ## The Hub
71
62
 
72
- Already installed? Run `ultracontext config` to reconfigure.
63
+ **All agents. One context.**
73
64
 
74
- ## Quick Start
65
+ The Hub lets you auto-capture, share, and collaborate across agents in realtime.
75
66
 
76
- ```bash
77
- ultracontext # start daemon + open dashboard
78
- ultracontext config # run setup wizard
79
- ultracontext start # start daemon only
80
- ultracontext stop # stop daemon
81
- ultracontext status # check if daemon is running
82
- ultracontext tui # open dashboard only
83
- ultracontext update # update CLI globally (npm/pnpm/bun)
84
- ```
67
+ ### Features
85
68
 
86
- The default ultracontext command does everything: checks the daemon, starts it if needed, and opens the TUI dashboard.
69
+ - **Auto-capture** Ingests your agents' context in realtime. Zero config.
70
+ - **Switch between agents** — Pick up where one agent left off with another.
71
+ - **Collaborate** — Share contexts across your team. See what everyone sees. Realtime.
72
+ - **Fork & clone** — Continue contexts while preserving the full history.
73
+ - **Own your data** — Open source. Your contexts. Your rules.
87
74
 
88
- ## How it works
75
+ ### How it works
89
76
 
90
77
  1. A daemon runs in the background, watching your agents.
91
- 2. Contexts are ingested in realtime with the Context API.
92
- 3. Your Context Hub gets updated.
78
+ 2. Contexts are ingested in realtime.
79
+ 3. Your dashboard gets updated.
93
80
 
94
- We use a git-like context engineering API under the hood to interact with the agent's contexts. You can use it to add your own custom agents, tweak behavior and more. ([Docs here](https://ultracontext.ai/docs/))
81
+ ### Quick Start
95
82
 
96
- When you open an existing session from the hub, it forks the context, so the original context is always preserved by default and automatically versioned so you can keep track of it later using metadata.
83
+ ```bash
84
+ ultracontext # start daemon + open dashboard
85
+ ultracontext config # run setup wizard
86
+ ultracontext start # start daemon only
87
+ ultracontext stop # stop daemon
88
+ ultracontext status # check if daemon is running
89
+ ultracontext tui # open dashboard only
90
+ ```
97
91
 
98
- There is a local caching layer that prevents duplicate context creations and appends.
92
+ The default `ultracontext` command does everything: checks the daemon, starts it if needed, and opens the dashboard.
99
93
 
100
- ## Star History
94
+ When you open an existing session, it forks the context — the original is always preserved and automatically versioned. A local caching layer prevents duplicate context creations and appends.
101
95
 
102
- [![Star History Chart](https://api.star-history.com/svg?repos=ultracontext/ultracontext&type=date&legend=top-left)](https://www.star-history.com/#ultracontext/ultracontext&type=date&legend=top-left)
96
+ Add your own agents and extend behavior with the Context API. ([Docs here](https://ultracontext.ai/docs/))
103
97
 
104
- ## Everything we built so far
98
+ ## The API
105
99
 
106
- - Daemon - Runs in the background, watching your agents.
107
- - TUI - Terminal UI for the daemon.
108
- - [Context API](https://ultracontext.ai/docs/) - Git-like context engineering API.
109
- - [Context API SDKs](https://ultracontext.ai/docs/quickstart/nodejs) - Node and Python SDKs.
100
+ **Context engineering built like Git.**
110
101
 
111
- <div align="center">
102
+ The API gives you git-like primitives for context engineering, without the complexity.
112
103
 
113
- # The Context API
104
+ ### Features
114
105
 
115
- </div>
106
+ - **Five methods** — Create, get, append, update, delete. That's it.
107
+ - **Automatic versioning** — Every change creates a new version. Full history out of the box.
108
+ - **Time-travel** — Jump to any point in your context history.
109
+ - **Framework-agnostic** — Works with any LLM framework. No vendor lock-in.
110
+
111
+ The simplest way to control what your agents see. Replace messages, compact long context, replay decisions and roll back mistakes — all with a single API call.
116
112
 
117
- The Context API is the simplest way to control what your agents see. Replace messages, compact/offload long context, replay decisions and roll back mistakes with a single API call. Versioned context out of the box. Full history. Zero complexity. You can use the API standalone to build your own agents or to tweak behavior of existing ones in ultracontext. ([Docs here](https://ultracontext.ai/docs/api-reference/introduction))
113
+ Use the API standalone to build your own agents, or to extend existing ones in UltraContext.
118
114
 
119
- ## Context API SDKs
120
115
 
121
- | SDK | Install | Source |
122
- |-----|---------|--------|
123
- | JavaScript/TypeScript | `npm install ultracontext` | [apps/js-sdk](./apps/js-sdk) |
124
- | Python | `pip install ultracontext` | [apps/python-sdk](./apps/python-sdk) |
116
+ | SDK | Install | Source |
117
+ | --------------------- | -------------------------- | ------------------------------------ |
118
+ | JavaScript/TypeScript | `npm install ultracontext` | [apps/js-sdk](./apps/js-sdk) |
119
+ | Python | `pip install ultracontext` | [apps/python-sdk](./apps/python-sdk) |
125
120
 
126
121
 
127
122
  ### JavaScript/TypeScript
@@ -130,7 +125,7 @@ The Context API is the simplest way to control what your agents see. Replace mes
130
125
  npm install ultracontext
131
126
  ```
132
127
 
133
- ```js
128
+ ```typescript
134
129
  import { UltraContext } from 'ultracontext';
135
130
 
136
131
  const uc = new UltraContext({ apiKey: 'uc_live_...' });
@@ -160,12 +155,24 @@ uc.append(ctx["id"], {"role": "user", "content": "Hello!"})
160
155
  response = generate_text(model=model, messages=uc.get(ctx["id"])["data"])
161
156
  ```
162
157
 
163
- Get an API key from the [UltraContext Dashboard](https://ultracontext.ai/dashboard).
158
+ <p align="center">📚 Context API Guides</p>
159
+ <p align="center">
160
+ <a href="https://ultracontext.ai/docs/guides/store-retrieve-contexts">Store & Retrieve</a>
161
+ ·
162
+ <a href="https://ultracontext.ai/docs/guides/edit-contexts">Edit Contexts</a>
163
+ ·
164
+ <a href="https://ultracontext.ai/docs/guides/fork-clone-contexts">Fork & Clone</a>
165
+ ·
166
+ <a href="https://ultracontext.ai/docs/guides/view-context-history">View History</a>
167
+ </p>
168
+
169
+ ## Star History
170
+
171
+ [![Star History Chart](https://api.star-history.com/svg?repos=ultracontext/ultracontext-node&type=date&legend=top-left)](https://www.star-history.com/#ultracontext/ultracontext-node&type=date&legend=top-left)
172
+
164
173
 
165
174
  ## Documentation
166
175
 
167
176
  - [Quickstart](https://ultracontext.ai/docs/quickstart/nodejs) — Get running in 2 minutes
168
177
  - [Guides](https://ultracontext.ai/docs/guides/store-retrieve-contexts) — Practical patterns for common use cases
169
- - [API Reference](https://ultracontext.ai/docs/api-reference/introduction) — Full endpoint documentation
170
-
171
- ---
178
+ - [API Reference](https://ultracontext.ai/docs/api-reference/introduction) — Full endpoint documentation
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
2
2
  import { Box, Text } from "ink";
3
3
  import figlet from "figlet";
4
4
 
5
- //#region src/cli/tui/ui/hero-art.mjs
5
+ //#region ../tui/src/ui/hero-art.mjs
6
6
  const HERO_TEXT = "UltraContext";
7
7
  const HERO_FONT_ORDER = [
8
8
  "Standard",
@@ -44,7 +44,7 @@ function heroArtForWidth(columns) {
44
44
  }
45
45
 
46
46
  //#endregion
47
- //#region src/cli/tui/ui/constants.mjs
47
+ //#region ../tui/src/ui/constants.mjs
48
48
  const UC_BRAND_BLUE = "#2f6fb3";
49
49
  const UC_BLUE_LIGHT = "#7ec3ff";
50
50
  const UC_CLAUDE_ORANGE = "#f4a261";
@@ -66,7 +66,7 @@ const MENU_TABS = [
66
66
  ];
67
67
 
68
68
  //#endregion
69
- //#region src/cli/tui/Spinner.mjs
69
+ //#region ../tui/src/Spinner.mjs
70
70
  const WIDTH = 28;
71
71
  const HEIGHT = 10;
72
72
  const SCALE = 40;
@@ -150,4 +150,4 @@ const Spinner = ({ color = "green", prefix = "", suffix = "", prefixColor = "whi
150
150
 
151
151
  //#endregion
152
152
  export { UC_CLAUDE_ORANGE as a, heroArtForWidth as c, UC_BRAND_BLUE as i, MENU_TABS as n, UC_CODEX_BLUE as o, UC_BLUE_LIGHT as r, UC_OPENCLAW_RED as s, Spinner as t };
153
- //# sourceMappingURL=Spinner-C7LzYron.mjs.map
153
+ //# sourceMappingURL=Spinner-C_38udz8.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Spinner-C_38udz8.mjs","names":[],"sources":["../../tui/src/ui/hero-art.mjs","../../tui/src/ui/constants.mjs","../../tui/src/Spinner.mjs"],"sourcesContent":["import figlet from \"figlet\";\n\nconst HERO_TEXT = \"UltraContext\";\nconst HERO_FONT_ORDER = [\"Standard\", \"Small\", \"Mini\", \"Slant\"];\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","export const UC_BRAND_BLUE = \"#2f6fb3\";\nexport const UC_BLUE_LIGHT = \"#7ec3ff\";\nexport const UC_CLAUDE_ORANGE = \"#f4a261\";\nexport const UC_CODEX_BLUE = \"#5fb2ff\";\nexport const UC_OPENCLAW_RED = \"#e76f51\";\n\nexport const MENU_TABS = [\n { id: \"logs\", label: \"Live View\" },\n { id: \"contexts\", label: \"Contexts\" },\n { id: \"configs\", label: \"Configs\" },\n];\n","import React, { useState, useEffect } from \"react\";\nimport { Box, Text } from \"ink\";\n\nconst WIDTH = 28;\nconst HEIGHT = 10;\nconst SCALE = 40.0;\nconst CAMERA_Z = 20.0;\nconst CHARS = \"··..,,--::;;==!!**##$$@@\";\n\nconst zBuffer = new Float32Array(WIDTH * HEIGHT);\nconst screenBuffer = new Uint8Array(WIDTH * HEIGHT);\n\nconst pointsData = [];\nfunction addPoint(x, y, z, type) {\n pointsData.push(x, y, z, type);\n}\n\nfunction addLine(x1, y1, z1, x2, y2, z2) {\n const density = 15;\n for (let i = 0; i <= density; i++) {\n const t = i / density;\n addPoint(\n x1 + (x2 - x1) * t,\n y1 + (y2 - y1) * t,\n z1 + (z2 - z1) * t,\n 0\n );\n }\n}\n\naddLine(-1.8, -1.2, 0, -1.8, 1.2, 0);\naddLine(-1.8, 1.2, 0, -1.0, 1.2, 0);\naddLine(-1.8, -1.2, 0, -1.0, -1.2, 0);\n\naddLine(1.8, -1.2, 0, 1.8, 1.2, 0);\naddLine(1.8, 1.2, 0, 1.0, 1.2, 0);\naddLine(1.8, -1.2, 0, 1.0, -1.2, 0);\n\naddPoint(0, 0, 0, 1);\n\nconst points = new Float32Array(pointsData);\nconst pointCount = points.length / 4;\n\nfunction renderFrame(angle) {\n zBuffer.fill(-Infinity);\n screenBuffer.fill(32);\n\n const cosA = Math.cos(angle);\n const sinA = Math.sin(angle);\n\n for (let i = 0; i < pointCount; i++) {\n const idx = i * 4;\n const px = points[idx];\n const py = points[idx + 1];\n const pz = points[idx + 2];\n const ptype = points[idx + 3];\n\n const xRot = px * cosA - pz * sinA;\n const yRot = py;\n const zRot = px * sinA + pz * cosA;\n\n const zFinal = zRot - CAMERA_Z;\n const ooz = -1.0 / zFinal;\n\n const screenX = Math.floor(WIDTH / 2 + xRot * ooz * SCALE * 2.0);\n const screenY = Math.floor(HEIGHT / 2 - yRot * ooz * SCALE);\n\n if (screenX >= 0 && screenX < WIDTH && screenY >= 0 && screenY < HEIGHT) {\n const bufIdx = screenX + screenY * WIDTH;\n if (ooz > zBuffer[bufIdx]) {\n zBuffer[bufIdx] = ooz;\n if (ptype === 1) {\n screenBuffer[bufIdx] = 79;\n } else {\n let charIdx = Math.floor((zRot + 2.0) * 4.5);\n if (charIdx < 0) charIdx = 0;\n if (charIdx >= CHARS.length) charIdx = CHARS.length - 1;\n screenBuffer[bufIdx] = CHARS.charCodeAt(charIdx);\n }\n }\n }\n }\n\n const lines = [];\n for (let y = 0; y < HEIGHT; y++) {\n let row = \"\";\n const offset = y * WIDTH;\n for (let x = 0; x < WIDTH; x++) {\n row += String.fromCharCode(screenBuffer[offset + x]);\n }\n lines.push(row);\n }\n return lines;\n}\n\nconst Spinner = ({\n color = \"green\",\n prefix = \"\",\n suffix = \"\",\n prefixColor = \"white\",\n suffixColor = \"white\",\n sideLines = [],\n sideGap = 0,\n sideColor = \"white\",\n}) => {\n const [frameRows, setFrameRows] = useState(() => renderFrame(0));\n\n useEffect(() => {\n let angle = 0;\n const timer = setInterval(() => {\n angle += 0.05;\n setFrameRows(renderFrame(angle));\n }, 33);\n timer.unref?.();\n return () => clearInterval(timer);\n }, []);\n\n return React.createElement(\n Box,\n { flexDirection: \"column\" },\n ...frameRows.map((row, index) =>\n React.createElement(\n Text,\n { key: `spinner-row-${index}` },\n prefix ? React.createElement(Text, { color: prefixColor }, prefix) : \"\",\n React.createElement(Text, { color }, row),\n sideLines.length > 0\n ? React.createElement(Text, { color: sideColor }, `${\" \".repeat(Math.max(sideGap, 0))}${sideLines[index] ?? \"\"}`)\n : \"\",\n suffix ? React.createElement(Text, { color: suffixColor }, suffix) : \"\"\n )\n )\n );\n};\n\nexport default Spinner;\n"],"mappings":"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"}
@@ -205,6 +205,16 @@ function runGlobalUpdate(manager, tag) {
205
205
  stdio: "inherit"
206
206
  }).status !== 0) throw new Error(`Update failed while running: ${bin} ${args.join(" ")}`);
207
207
  }
208
+ const isTTY = process.stdout.isTTY;
209
+ const esc = (code) => isTTY ? `\x1b[${code}m` : "";
210
+ const r = esc(0);
211
+ const b = esc(1);
212
+ const d = esc(2);
213
+ const blue = esc("38;2;47;111;179");
214
+ const green = esc("38;2;80;200;120");
215
+ esc("38;2;220;80;80");
216
+ const cyan = esc("36");
217
+ const gray = esc("38;5;245");
208
218
  function runUpdate(rawArgs) {
209
219
  const opts = parseUpdateOptions(rawArgs);
210
220
  if (opts.help) {
@@ -213,22 +223,115 @@ function runUpdate(rawArgs) {
213
223
  }
214
224
  const manager = opts.manager ?? detectGlobalInstallManager();
215
225
  if (!manager) throw new Error("Could not detect install manager for this CLI. Re-run with --manager <npm|pnpm|bun>.");
226
+ const previousVersion = readVersion();
227
+ console.log("");
228
+ console.log(` ${blue}${b}UltraContext${r} ${d}Update${r}`);
229
+ console.log("");
216
230
  const wasRunning = isDaemonRunning();
217
231
  if (wasRunning && opts.restart) {
218
- console.log("Stopping daemon before update...");
232
+ console.log(` ${gray}○${r} ${d}Stopping daemon...${r}`);
219
233
  const stopCode = runCliSubcommand("stop");
220
234
  if (stopCode !== 0) throw new Error(`Failed to stop daemon before update (exit ${stopCode}).`);
221
235
  }
222
- console.log(`Updating ${PACKAGE_NAME} via ${manager} (${PACKAGE_NAME}@${opts.tag})...`);
236
+ console.log(` ${gray}↓${r} ${d}Updating via ${manager}${r} ${gray}(${PACKAGE_NAME}@${opts.tag})${r}`);
223
237
  runGlobalUpdate(manager, opts.tag);
224
- console.log("Update completed.");
238
+ const newVersion = readVersion();
239
+ console.log("");
240
+ console.log(` ${green}✓${r} ${b}Updated${r} ${gray}${previousVersion} → ${newVersion}${r}`);
225
241
  if (wasRunning && opts.restart) {
226
- console.log("Restarting daemon...");
242
+ console.log(` ${green}●${r} ${d}Restarting daemon...${r}`);
227
243
  const startCode = runCliSubcommand("start");
228
244
  if (startCode !== 0) throw new Error(`Update succeeded but daemon restart failed (exit ${startCode}).`);
229
- } else if (wasRunning) console.log("Daemon was running before update. Restart manually with: ultracontext start");
245
+ } else if (wasRunning) console.log(` ${gray}○${r} ${d}Daemon was stopped. Run:${r} ${cyan}ultracontext start${r}`);
246
+ console.log("");
247
+ }
248
+ const UPDATE_CHECK_INTERVAL = 10800 * 1e3;
249
+ const SKIP_UPDATE_CHECK = new Set([
250
+ "version",
251
+ "v",
252
+ "update",
253
+ "upgrade",
254
+ "help",
255
+ "h",
256
+ "stop",
257
+ "status"
258
+ ]);
259
+ function getUpdateCheckPath() {
260
+ const home = process.env.HOME || process.env.USERPROFILE || "~";
261
+ return path.join(home, ".ultracontext", "update-check.json");
262
+ }
263
+ function readUpdateCache() {
264
+ try {
265
+ return JSON.parse(fs.readFileSync(getUpdateCheckPath(), "utf8"));
266
+ } catch {
267
+ return null;
268
+ }
269
+ }
270
+ function writeUpdateCache(data) {
271
+ try {
272
+ fs.writeFileSync(getUpdateCheckPath(), JSON.stringify(data));
273
+ } catch {}
274
+ }
275
+ async function fetchLatestVersion() {
276
+ const controller = new AbortController();
277
+ const timeout = setTimeout(() => controller.abort(), 3e3);
278
+ try {
279
+ return (await (await fetch("https://registry.npmjs.org/ultracontext/latest", { signal: controller.signal })).json()).version ?? null;
280
+ } catch {
281
+ return null;
282
+ } finally {
283
+ clearTimeout(timeout);
284
+ }
285
+ }
286
+ function isNewer(latest, current) {
287
+ const l = latest.split(".").map(Number);
288
+ const c = current.split(".").map(Number);
289
+ for (let i = 0; i < 3; i++) {
290
+ if ((l[i] ?? 0) > (c[i] ?? 0)) return true;
291
+ if ((l[i] ?? 0) < (c[i] ?? 0)) return false;
292
+ }
293
+ return false;
294
+ }
295
+ function printUpdateNotice(current, latest) {
296
+ console.log(`\n ${blue}${b}UltraContext${r} ${d}Update available${r}`);
297
+ console.log(` ${gray}${current}${r} → ${green}${b}${latest}${r}`);
298
+ console.log(` Run ${cyan}ultracontext update${r} to upgrade.\n`);
299
+ }
300
+ async function checkForUpdate() {
301
+ const current = readVersion();
302
+ if (current === "unknown") return;
303
+ const cache = readUpdateCache();
304
+ if (cache?.lastCheck && Date.now() - cache.lastCheck < UPDATE_CHECK_INTERVAL) {
305
+ if (cache.latestVersion && isNewer(cache.latestVersion, current)) printUpdateNotice(current, cache.latestVersion);
306
+ return;
307
+ }
308
+ const latest = await fetchLatestVersion();
309
+ writeUpdateCache({
310
+ lastCheck: Date.now(),
311
+ latestVersion: latest
312
+ });
313
+ if (latest && isNewer(latest, current)) printUpdateNotice(current, latest);
314
+ }
315
+ async function launchDaemonSDK() {
316
+ const { launchDaemon } = await import("../launcher-VTbHuuaQ.mjs");
317
+ await launchDaemon({
318
+ entryPath: fileURLToPath(new URL("./sdk-daemon.mjs", import.meta.url)),
319
+ diagnosticsHint: "DAEMON_VERBOSE=1 ultracontext start"
320
+ });
321
+ }
322
+ async function runCtlSDK() {
323
+ const { runCtl } = await import("../ctl-DaIi3tUU.mjs");
324
+ await runCtl();
325
+ }
326
+ async function launchTuiSDK() {
327
+ const { tuiBoot } = await import("../tui-DVtkwVMl.mjs");
328
+ await tuiBoot({
329
+ assetsRoot: path.resolve(__dirname, "..", ".."),
330
+ offlineNotice: "Daemon offline. Run: ultracontext start"
331
+ });
230
332
  }
231
333
  async function run() {
334
+ if (!SKIP_UPDATE_CHECK.has(command)) await checkForUpdate();
232
335
  let onboardResult = null;
233
336
  if (NEEDS_KEY.has(command)) {
234
337
  loadApiKeyFromConfig();
@@ -236,25 +339,25 @@ async function run() {
236
339
  }
237
340
  switch (command) {
238
341
  case "start":
239
- await import("./daemon/launcher.mjs");
240
- if (onboardResult?.launchTui) await import("./tui/index.mjs");
342
+ await launchDaemonSDK();
343
+ if (onboardResult?.launchTui) await launchTuiSDK();
241
344
  break;
242
345
  case "stop":
243
346
  process.argv[2] = "stop";
244
- await import("./daemon/ctl.mjs");
347
+ await runCtlSDK();
245
348
  break;
246
349
  case "status":
247
350
  process.argv[2] = "status";
248
- await import("./daemon/ctl.mjs");
351
+ await runCtlSDK();
249
352
  break;
250
353
  case "config":
251
354
  if ((await runOnboarding())?.launchTui) {
252
- if (!isDaemonRunning()) await import("./daemon/launcher.mjs");
253
- await import("./tui/index.mjs");
355
+ if (!isDaemonRunning()) await launchDaemonSDK();
356
+ await launchTuiSDK();
254
357
  }
255
358
  break;
256
359
  case "tui":
257
- await import("./tui/index.mjs");
360
+ await launchTuiSDK();
258
361
  break;
259
362
  case "version":
260
363
  case "v":
@@ -265,8 +368,8 @@ async function run() {
265
368
  runUpdate(process.argv.slice(3));
266
369
  break;
267
370
  case "":
268
- if (!isDaemonRunning()) await import("./daemon/launcher.mjs");
269
- await import("./tui/index.mjs");
371
+ if (!isDaemonRunning()) await launchDaemonSDK();
372
+ await launchTuiSDK();
270
373
  break;
271
374
  case "help":
272
375
  case "h":
@@ -1 +1 @@
1
- {"version":3,"file":"entry.mjs","names":[],"sources":["../../src/cli/entry.mjs"],"sourcesContent":["#!/usr/bin/env node\n\n// CLI router — dispatches subcommands to daemon/tui entry points\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport { spawnSync } from \"node:child_process\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst command = (process.argv[2] ?? \"\").trim().toLowerCase().replace(/^--?/, \"\");\nconst PACKAGE_NAME = \"ultracontext\";\nconst packageRoot = path.resolve(__dirname, \"..\", \"..\");\nconst cliWrapperPath = path.join(packageRoot, \"ultracontext.mjs\");\n\n// resolve package version\nfunction readVersion() {\n try {\n const pkgPath = path.resolve(__dirname, \"..\", \"..\", \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n return pkg.version ?? \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nfunction printHelp() {\n const version = readVersion();\n console.log(`ultracontext v${version}\n\nUsage: ultracontext [command] [options]\n\nCommands:\n (none) Start daemon if needed, then open TUI\n config Run the setup wizard\n start Start the daemon in the background\n stop Stop a running daemon\n status Show daemon status\n tui Launch the interactive terminal UI\n update Update CLI globally via npm/pnpm/bun\n version Print version\n help Show this help message\n\nEnvironment:\n ULTRACONTEXT_API_KEY Required. Your UltraContext API key.\n ULTRACONTEXT_BASE_URL API base URL (default: https://api.ultracontext.ai)\n`);\n}\n\nfunction printUpdateHelp() {\n console.log(`Usage: ultracontext update [options]\n\nOptions:\n --tag <dist-tag|version> Package tag/version (default: latest)\n --manager <npm|pnpm|bun> Force package manager (auto-detected by default)\n --no-restart Do not restart daemon after update\n -h, --help Show this help message\n`);\n}\n\n// commands that need an API key\nconst NEEDS_KEY = new Set([\"\", \"start\", \"tui\"]);\n\n// interactive onboarding wizard (Ink-based), returns { launchTui }\nasync function runOnboarding() {\n const { onboard } = await import(\"./onboarding.mjs\");\n return onboard();\n}\n\n// check if daemon is already running via lock file\nfunction isDaemonRunning() {\n try {\n const lockPath = path.join(process.env.HOME || process.env.USERPROFILE || \"~\", \".ultracontext\", \"daemon.lock\");\n const lock = JSON.parse(fs.readFileSync(lockPath, \"utf8\"));\n const pid = Number.parseInt(String(lock?.pid ?? \"\"), 10);\n if (!Number.isInteger(pid) || pid <= 1) return false;\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n// try loading key from config file if env is empty\nfunction loadApiKeyFromConfig() {\n if (process.env.ULTRACONTEXT_API_KEY) return;\n try {\n const configPath = path.join(process.env.HOME || process.env.USERPROFILE || \"~\", \".ultracontext\", \"config.json\");\n const cfg = JSON.parse(fs.readFileSync(configPath, \"utf8\"));\n if (cfg.apiKey) process.env.ULTRACONTEXT_API_KEY = String(cfg.apiKey);\n } catch { /* no config */ }\n}\n\nfunction normalizeTag(value) {\n const trimmed = String(value ?? \"\").trim();\n if (!trimmed) return \"latest\";\n if (trimmed.startsWith(`${PACKAGE_NAME}@`)) return trimmed.slice(`${PACKAGE_NAME}@`.length);\n return trimmed;\n}\n\nfunction safeRealpath(targetPath) {\n try {\n return fs.realpathSync(targetPath);\n } catch {\n return path.resolve(targetPath);\n }\n}\n\nfunction pathsEqual(left, right) {\n return path.resolve(left) === path.resolve(right);\n}\n\nfunction runCapture(commandName, args) {\n const result = spawnSync(commandName, args, {\n env: process.env,\n encoding: \"utf8\",\n });\n return {\n ok: result.status === 0,\n stdout: String(result.stdout ?? \"\"),\n stderr: String(result.stderr ?? \"\"),\n };\n}\n\nfunction resolveBunGlobalRoot() {\n const home = process.env.HOME || process.env.USERPROFILE || os.homedir();\n const bunInstall = String(process.env.BUN_INSTALL ?? \"\").trim() || path.join(home, \".bun\");\n return path.join(bunInstall, \"install\", \"global\", \"node_modules\");\n}\n\nfunction detectGlobalInstallManager() {\n const packageRootReal = safeRealpath(packageRoot);\n const npmGlobalRoot = runCapture(\"npm\", [\"root\", \"-g\"]);\n if (npmGlobalRoot.ok) {\n const npmRoot = npmGlobalRoot.stdout.trim();\n if (npmRoot) {\n const npmExpected = safeRealpath(path.join(npmRoot, PACKAGE_NAME));\n if (pathsEqual(npmExpected, packageRootReal)) return \"npm\";\n }\n }\n\n const pnpmGlobalRoot = runCapture(\"pnpm\", [\"root\", \"-g\"]);\n if (pnpmGlobalRoot.ok) {\n const pnpmRoot = pnpmGlobalRoot.stdout.trim();\n if (pnpmRoot) {\n const pnpmExpected = safeRealpath(path.join(pnpmRoot, PACKAGE_NAME));\n if (pathsEqual(pnpmExpected, packageRootReal)) return \"pnpm\";\n }\n }\n\n const bunExpected = safeRealpath(path.join(resolveBunGlobalRoot(), PACKAGE_NAME));\n if (pathsEqual(bunExpected, packageRootReal)) return \"bun\";\n\n return null;\n}\n\nfunction parseUpdateOptions(args) {\n const opts = {\n tag: \"latest\",\n manager: null,\n restart: true,\n help: false,\n };\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = String(args[i] ?? \"\").trim();\n if (!arg) continue;\n\n if (arg === \"-h\" || arg === \"--help\") {\n opts.help = true;\n continue;\n }\n\n if (arg === \"--no-restart\") {\n opts.restart = false;\n continue;\n }\n\n if (arg === \"--tag\") {\n const next = args[i + 1];\n if (!next || String(next).startsWith(\"-\")) {\n throw new Error(\"Missing value for --tag\");\n }\n opts.tag = normalizeTag(next);\n i += 1;\n continue;\n }\n\n if (arg === \"--manager\") {\n const next = String(args[i + 1] ?? \"\").trim().toLowerCase();\n if (!next || next.startsWith(\"-\")) {\n throw new Error(\"Missing value for --manager\");\n }\n if (![\"npm\", \"pnpm\", \"bun\"].includes(next)) {\n throw new Error(`Invalid --manager value: ${next}`);\n }\n opts.manager = next;\n i += 1;\n continue;\n }\n\n throw new Error(`Unknown update option: ${arg}`);\n }\n\n return opts;\n}\n\nfunction runCliSubcommand(subcommand) {\n const result = spawnSync(process.execPath, [cliWrapperPath, subcommand], {\n env: process.env,\n stdio: \"inherit\",\n });\n return result.status ?? 1;\n}\n\nfunction runGlobalUpdate(manager, tag) {\n const spec = `${PACKAGE_NAME}@${normalizeTag(tag)}`;\n const argvByManager = {\n npm: [\"npm\", [\"i\", \"-g\", spec]],\n pnpm: [\"pnpm\", [\"add\", \"-g\", spec]],\n bun: [\"bun\", [\"add\", \"-g\", spec]],\n };\n\n const tuple = argvByManager[manager];\n if (!tuple) {\n throw new Error(`Unsupported package manager: ${manager}`);\n }\n\n const [bin, args] = tuple;\n const result = spawnSync(bin, args, {\n env: process.env,\n stdio: \"inherit\",\n });\n if (result.status !== 0) {\n throw new Error(`Update failed while running: ${bin} ${args.join(\" \")}`);\n }\n}\n\nfunction runUpdate(rawArgs) {\n const opts = parseUpdateOptions(rawArgs);\n if (opts.help) {\n printUpdateHelp();\n return;\n }\n\n const manager = opts.manager ?? detectGlobalInstallManager();\n if (!manager) {\n throw new Error(\n \"Could not detect install manager for this CLI. Re-run with --manager <npm|pnpm|bun>.\",\n );\n }\n\n const wasRunning = isDaemonRunning();\n if (wasRunning && opts.restart) {\n console.log(\"Stopping daemon before update...\");\n const stopCode = runCliSubcommand(\"stop\");\n if (stopCode !== 0) {\n throw new Error(`Failed to stop daemon before update (exit ${stopCode}).`);\n }\n }\n\n console.log(`Updating ${PACKAGE_NAME} via ${manager} (${PACKAGE_NAME}@${opts.tag})...`);\n runGlobalUpdate(manager, opts.tag);\n console.log(\"Update completed.\");\n\n if (wasRunning && opts.restart) {\n console.log(\"Restarting daemon...\");\n const startCode = runCliSubcommand(\"start\");\n if (startCode !== 0) {\n throw new Error(`Update succeeded but daemon restart failed (exit ${startCode}).`);\n }\n } else if (wasRunning) {\n console.log(\"Daemon was running before update. Restart manually with: ultracontext start\");\n }\n}\n\nasync function run() {\n // load saved key, then onboard if still missing\n let onboardResult = null;\n if (NEEDS_KEY.has(command)) {\n loadApiKeyFromConfig();\n if (!process.env.ULTRACONTEXT_API_KEY) onboardResult = await runOnboarding();\n }\n\n switch (command) {\n case \"start\":\n await import(\"./daemon/launcher.mjs\");\n if (onboardResult?.launchTui) await import(\"./tui/index.mjs\");\n break;\n\n case \"stop\":\n process.argv[2] = \"stop\";\n await import(\"./daemon/ctl.mjs\");\n break;\n\n case \"status\":\n process.argv[2] = \"status\";\n await import(\"./daemon/ctl.mjs\");\n break;\n\n case \"config\": {\n const configResult = await runOnboarding();\n if (configResult?.launchTui) {\n if (!isDaemonRunning()) await import(\"./daemon/launcher.mjs\");\n await import(\"./tui/index.mjs\");\n }\n break;\n }\n\n case \"tui\":\n await import(\"./tui/index.mjs\");\n break;\n\n case \"version\":\n case \"v\":\n console.log(readVersion());\n break;\n\n case \"update\":\n case \"upgrade\":\n runUpdate(process.argv.slice(3));\n break;\n\n // default: ensure daemon running, then open TUI\n case \"\": {\n if (!isDaemonRunning()) await import(\"./daemon/launcher.mjs\");\n await import(\"./tui/index.mjs\");\n break;\n }\n\n case \"help\":\n case \"h\":\n printHelp();\n break;\n\n default:\n console.error(`Unknown command: ${process.argv[2]}`);\n printHelp();\n process.exit(1);\n }\n}\n\nrun().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"entry.mjs","names":[],"sources":["../../src/cli/entry.mjs"],"sourcesContent":["#!/usr/bin/env node\n\n// CLI router — dispatches subcommands to daemon/tui entry points\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport { spawnSync } from \"node:child_process\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst command = (process.argv[2] ?? \"\").trim().toLowerCase().replace(/^--?/, \"\");\nconst PACKAGE_NAME = \"ultracontext\";\nconst packageRoot = path.resolve(__dirname, \"..\", \"..\");\nconst cliWrapperPath = path.join(packageRoot, \"ultracontext.mjs\");\n\n// resolve package version\nfunction readVersion() {\n try {\n const pkgPath = path.resolve(__dirname, \"..\", \"..\", \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n return pkg.version ?? \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nfunction printHelp() {\n const version = readVersion();\n console.log(`ultracontext v${version}\n\nUsage: ultracontext [command] [options]\n\nCommands:\n (none) Start daemon if needed, then open TUI\n config Run the setup wizard\n start Start the daemon in the background\n stop Stop a running daemon\n status Show daemon status\n tui Launch the interactive terminal UI\n update Update CLI globally via npm/pnpm/bun\n version Print version\n help Show this help message\n\nEnvironment:\n ULTRACONTEXT_API_KEY Required. Your UltraContext API key.\n ULTRACONTEXT_BASE_URL API base URL (default: https://api.ultracontext.ai)\n`);\n}\n\nfunction printUpdateHelp() {\n console.log(`Usage: ultracontext update [options]\n\nOptions:\n --tag <dist-tag|version> Package tag/version (default: latest)\n --manager <npm|pnpm|bun> Force package manager (auto-detected by default)\n --no-restart Do not restart daemon after update\n -h, --help Show this help message\n`);\n}\n\n// commands that need an API key\nconst NEEDS_KEY = new Set([\"\", \"start\", \"tui\"]);\n\n// interactive onboarding wizard (Ink-based), returns { launchTui }\nasync function runOnboarding() {\n const { onboard } = await import(\"./onboarding.mjs\");\n return onboard();\n}\n\n// check if daemon is already running via lock file\nfunction isDaemonRunning() {\n try {\n const lockPath = path.join(process.env.HOME || process.env.USERPROFILE || \"~\", \".ultracontext\", \"daemon.lock\");\n const lock = JSON.parse(fs.readFileSync(lockPath, \"utf8\"));\n const pid = Number.parseInt(String(lock?.pid ?? \"\"), 10);\n if (!Number.isInteger(pid) || pid <= 1) return false;\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n// try loading key from config file if env is empty\nfunction loadApiKeyFromConfig() {\n if (process.env.ULTRACONTEXT_API_KEY) return;\n try {\n const configPath = path.join(process.env.HOME || process.env.USERPROFILE || \"~\", \".ultracontext\", \"config.json\");\n const cfg = JSON.parse(fs.readFileSync(configPath, \"utf8\"));\n if (cfg.apiKey) process.env.ULTRACONTEXT_API_KEY = String(cfg.apiKey);\n } catch { /* no config */ }\n}\n\nfunction normalizeTag(value) {\n const trimmed = String(value ?? \"\").trim();\n if (!trimmed) return \"latest\";\n if (trimmed.startsWith(`${PACKAGE_NAME}@`)) return trimmed.slice(`${PACKAGE_NAME}@`.length);\n return trimmed;\n}\n\nfunction safeRealpath(targetPath) {\n try {\n return fs.realpathSync(targetPath);\n } catch {\n return path.resolve(targetPath);\n }\n}\n\nfunction pathsEqual(left, right) {\n return path.resolve(left) === path.resolve(right);\n}\n\nfunction runCapture(commandName, args) {\n const result = spawnSync(commandName, args, {\n env: process.env,\n encoding: \"utf8\",\n });\n return {\n ok: result.status === 0,\n stdout: String(result.stdout ?? \"\"),\n stderr: String(result.stderr ?? \"\"),\n };\n}\n\nfunction resolveBunGlobalRoot() {\n const home = process.env.HOME || process.env.USERPROFILE || os.homedir();\n const bunInstall = String(process.env.BUN_INSTALL ?? \"\").trim() || path.join(home, \".bun\");\n return path.join(bunInstall, \"install\", \"global\", \"node_modules\");\n}\n\nfunction detectGlobalInstallManager() {\n const packageRootReal = safeRealpath(packageRoot);\n const npmGlobalRoot = runCapture(\"npm\", [\"root\", \"-g\"]);\n if (npmGlobalRoot.ok) {\n const npmRoot = npmGlobalRoot.stdout.trim();\n if (npmRoot) {\n const npmExpected = safeRealpath(path.join(npmRoot, PACKAGE_NAME));\n if (pathsEqual(npmExpected, packageRootReal)) return \"npm\";\n }\n }\n\n const pnpmGlobalRoot = runCapture(\"pnpm\", [\"root\", \"-g\"]);\n if (pnpmGlobalRoot.ok) {\n const pnpmRoot = pnpmGlobalRoot.stdout.trim();\n if (pnpmRoot) {\n const pnpmExpected = safeRealpath(path.join(pnpmRoot, PACKAGE_NAME));\n if (pathsEqual(pnpmExpected, packageRootReal)) return \"pnpm\";\n }\n }\n\n const bunExpected = safeRealpath(path.join(resolveBunGlobalRoot(), PACKAGE_NAME));\n if (pathsEqual(bunExpected, packageRootReal)) return \"bun\";\n\n return null;\n}\n\nfunction parseUpdateOptions(args) {\n const opts = {\n tag: \"latest\",\n manager: null,\n restart: true,\n help: false,\n };\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = String(args[i] ?? \"\").trim();\n if (!arg) continue;\n\n if (arg === \"-h\" || arg === \"--help\") {\n opts.help = true;\n continue;\n }\n\n if (arg === \"--no-restart\") {\n opts.restart = false;\n continue;\n }\n\n if (arg === \"--tag\") {\n const next = args[i + 1];\n if (!next || String(next).startsWith(\"-\")) {\n throw new Error(\"Missing value for --tag\");\n }\n opts.tag = normalizeTag(next);\n i += 1;\n continue;\n }\n\n if (arg === \"--manager\") {\n const next = String(args[i + 1] ?? \"\").trim().toLowerCase();\n if (!next || next.startsWith(\"-\")) {\n throw new Error(\"Missing value for --manager\");\n }\n if (![\"npm\", \"pnpm\", \"bun\"].includes(next)) {\n throw new Error(`Invalid --manager value: ${next}`);\n }\n opts.manager = next;\n i += 1;\n continue;\n }\n\n throw new Error(`Unknown update option: ${arg}`);\n }\n\n return opts;\n}\n\nfunction runCliSubcommand(subcommand) {\n const result = spawnSync(process.execPath, [cliWrapperPath, subcommand], {\n env: process.env,\n stdio: \"inherit\",\n });\n return result.status ?? 1;\n}\n\nfunction runGlobalUpdate(manager, tag) {\n const spec = `${PACKAGE_NAME}@${normalizeTag(tag)}`;\n const argvByManager = {\n npm: [\"npm\", [\"i\", \"-g\", spec]],\n pnpm: [\"pnpm\", [\"add\", \"-g\", spec]],\n bun: [\"bun\", [\"add\", \"-g\", spec]],\n };\n\n const tuple = argvByManager[manager];\n if (!tuple) {\n throw new Error(`Unsupported package manager: ${manager}`);\n }\n\n const [bin, args] = tuple;\n const result = spawnSync(bin, args, {\n env: process.env,\n stdio: \"inherit\",\n });\n if (result.status !== 0) {\n throw new Error(`Update failed while running: ${bin} ${args.join(\" \")}`);\n }\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 cyan = esc(\"36\");\nconst gray = esc(\"38;5;245\");\n\nfunction runUpdate(rawArgs) {\n const opts = parseUpdateOptions(rawArgs);\n if (opts.help) {\n printUpdateHelp();\n return;\n }\n\n const manager = opts.manager ?? detectGlobalInstallManager();\n if (!manager) {\n throw new Error(\n \"Could not detect install manager for this CLI. Re-run with --manager <npm|pnpm|bun>.\",\n );\n }\n\n const previousVersion = readVersion();\n\n console.log(\"\");\n console.log(` ${blue}${b}UltraContext${r} ${d}Update${r}`);\n console.log(\"\");\n\n // stop daemon before update\n const wasRunning = isDaemonRunning();\n if (wasRunning && opts.restart) {\n console.log(` ${gray}○${r} ${d}Stopping daemon...${r}`);\n const stopCode = runCliSubcommand(\"stop\");\n if (stopCode !== 0) {\n throw new Error(`Failed to stop daemon before update (exit ${stopCode}).`);\n }\n }\n\n // run update\n console.log(` ${gray}↓${r} ${d}Updating via ${manager}${r} ${gray}(${PACKAGE_NAME}@${opts.tag})${r}`);\n runGlobalUpdate(manager, opts.tag);\n\n // read new version after update\n const newVersion = readVersion();\n console.log(\"\");\n console.log(` ${green}✓${r} ${b}Updated${r} ${gray}${previousVersion} → ${newVersion}${r}`);\n\n // restart daemon\n if (wasRunning && opts.restart) {\n console.log(` ${green}●${r} ${d}Restarting daemon...${r}`);\n const startCode = runCliSubcommand(\"start\");\n if (startCode !== 0) {\n throw new Error(`Update succeeded but daemon restart failed (exit ${startCode}).`);\n }\n } else if (wasRunning) {\n console.log(` ${gray}○${r} ${d}Daemon was stopped. Run:${r} ${cyan}ultracontext start${r}`);\n }\n\n console.log(\"\");\n}\n\n// ── update check ────────────────────────────────────────────────\n\nconst UPDATE_CHECK_INTERVAL = 3 * 60 * 60 * 1000; // 3h\nconst SKIP_UPDATE_CHECK = new Set([\"version\", \"v\", \"update\", \"upgrade\", \"help\", \"h\", \"stop\", \"status\"]);\n\nfunction getUpdateCheckPath() {\n const home = process.env.HOME || process.env.USERPROFILE || \"~\";\n return path.join(home, \".ultracontext\", \"update-check.json\");\n}\n\nfunction readUpdateCache() {\n try { return JSON.parse(fs.readFileSync(getUpdateCheckPath(), \"utf8\")); }\n catch { return null; }\n}\n\nfunction writeUpdateCache(data) {\n try { fs.writeFileSync(getUpdateCheckPath(), JSON.stringify(data)); }\n catch { /* best effort */ }\n}\n\nasync function fetchLatestVersion() {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 3000);\n try {\n const res = await fetch(\"https://registry.npmjs.org/ultracontext/latest\", { signal: controller.signal });\n const data = await res.json();\n return data.version ?? null;\n } catch { return null; }\n finally { clearTimeout(timeout); }\n}\n\nfunction isNewer(latest, current) {\n const l = latest.split(\".\").map(Number);\n const c = current.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) {\n if ((l[i] ?? 0) > (c[i] ?? 0)) return true;\n if ((l[i] ?? 0) < (c[i] ?? 0)) return false;\n }\n return false;\n}\n\nfunction printUpdateNotice(current, latest) {\n console.log(`\\n ${blue}${b}UltraContext${r} ${d}Update available${r}`);\n console.log(` ${gray}${current}${r} → ${green}${b}${latest}${r}`);\n console.log(` Run ${cyan}ultracontext update${r} to upgrade.\\n`);\n}\n\nasync function checkForUpdate() {\n const current = readVersion();\n if (current === \"unknown\") return;\n\n // use cache if fresh\n const cache = readUpdateCache();\n if (cache?.lastCheck && Date.now() - cache.lastCheck < UPDATE_CHECK_INTERVAL) {\n if (cache.latestVersion && isNewer(cache.latestVersion, current)) {\n printUpdateNotice(current, cache.latestVersion);\n }\n return;\n }\n\n // fetch from registry\n const latest = await fetchLatestVersion();\n writeUpdateCache({ lastCheck: Date.now(), latestVersion: latest });\n if (latest && isNewer(latest, current)) {\n printUpdateNotice(current, latest);\n }\n}\n\n// ── launch helpers ──────────────────────────────────────────────\n\nasync function launchDaemonSDK() {\n const { launchDaemon } = await import(\"@ultracontext/daemon/launcher\");\n await launchDaemon({\n entryPath: fileURLToPath(new URL(\"./sdk-daemon.mjs\", import.meta.url)),\n diagnosticsHint: \"DAEMON_VERBOSE=1 ultracontext start\",\n });\n}\n\nasync function runCtlSDK() {\n const { runCtl } = await import(\"@ultracontext/daemon/ctl\");\n await runCtl();\n}\n\nasync function launchTuiSDK() {\n const { tuiBoot } = await import(\"@ultracontext/tui/tui\");\n await tuiBoot({\n assetsRoot: path.resolve(__dirname, \"..\", \"..\"),\n offlineNotice: \"Daemon offline. Run: ultracontext start\",\n });\n}\n\n// ── main ────────────────────────────────────────────────────────\n\nasync function run() {\n // check for updates (silent on error, cached 24h)\n if (!SKIP_UPDATE_CHECK.has(command)) await checkForUpdate();\n\n // load saved key, then onboard if still missing\n let onboardResult = null;\n if (NEEDS_KEY.has(command)) {\n loadApiKeyFromConfig();\n if (!process.env.ULTRACONTEXT_API_KEY) onboardResult = await runOnboarding();\n }\n\n switch (command) {\n case \"start\":\n await launchDaemonSDK();\n if (onboardResult?.launchTui) await launchTuiSDK();\n break;\n\n case \"stop\":\n process.argv[2] = \"stop\";\n await runCtlSDK();\n break;\n\n case \"status\":\n process.argv[2] = \"status\";\n await runCtlSDK();\n break;\n\n case \"config\": {\n const configResult = await runOnboarding();\n if (configResult?.launchTui) {\n if (!isDaemonRunning()) await launchDaemonSDK();\n await launchTuiSDK();\n }\n break;\n }\n\n case \"tui\":\n await launchTuiSDK();\n break;\n\n case \"version\":\n case \"v\":\n console.log(readVersion());\n break;\n\n case \"update\":\n case \"upgrade\":\n runUpdate(process.argv.slice(3));\n break;\n\n // default: ensure daemon running, then open TUI\n case \"\": {\n if (!isDaemonRunning()) await launchDaemonSDK();\n await launchTuiSDK();\n break;\n }\n\n case \"help\":\n case \"h\":\n printHelp();\n break;\n\n default:\n console.error(`Unknown command: ${process.argv[2]}`);\n printHelp();\n process.exit(1);\n }\n}\n\nrun().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n});\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { c as heroArtForWidth, i as UC_BRAND_BLUE, r as UC_BLUE_LIGHT, t as Spinner } from "../Spinner-C7LzYron.mjs";
1
+ import { c as heroArtForWidth, i as UC_BRAND_BLUE, r as UC_BLUE_LIGHT, t as Spinner } from "../Spinner-C_38udz8.mjs";
2
2
  import process from "node:process";
3
3
  import path from "node:path";
4
4
  import fs from "node:fs";