ultracontext 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/entry.mjs +3 -3
- package/dist/cli/sdk-daemon.mjs +11 -314
- package/dist/cli/sdk-daemon.mjs.map +1 -1
- package/dist/{ctl-9dwvaRrC.mjs → ctl-BVPu-D57.mjs} +3 -3
- package/dist/{ctl-9dwvaRrC.mjs.map → ctl-BVPu-D57.mjs.map} +1 -1
- package/dist/{launcher-DXUM0K-z.mjs → launcher-BFPi7_wD.mjs} +3 -3
- package/dist/{launcher-DXUM0K-z.mjs.map → launcher-BFPi7_wD.mjs.map} +1 -1
- package/dist/{lock-Q6z0l6Mr.mjs → lock-CQ3xrIlj.mjs} +3 -26
- package/dist/lock-CQ3xrIlj.mjs.map +1 -0
- package/dist/src-BSCJv6SU.mjs +151 -0
- package/dist/src-BSCJv6SU.mjs.map +1 -0
- package/dist/src-DzUz8GPJ.mjs +921 -0
- package/dist/src-DzUz8GPJ.mjs.map +1 -0
- package/dist/{tui-DNqvslCq.mjs → tui-C3H6iRjz.mjs} +31 -292
- package/dist/tui-C3H6iRjz.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/lock-Q6z0l6Mr.mjs.map +0 -1
- package/dist/src-Xh68VkBy.mjs +0 -83
- package/dist/src-Xh68VkBy.mjs.map +0 -1
- package/dist/tui-DNqvslCq.mjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { f as expandHome } from "./src-BSCJv6SU.mjs";
|
|
1
2
|
import process from "node:process";
|
|
2
3
|
import path from "node:path";
|
|
3
|
-
import os from "node:os";
|
|
4
4
|
import crypto from "node:crypto";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
6
6
|
|
|
@@ -8,12 +8,6 @@ import fs from "node:fs/promises";
|
|
|
8
8
|
function sha256(value) {
|
|
9
9
|
return crypto.createHash("sha256").update(value).digest("hex");
|
|
10
10
|
}
|
|
11
|
-
function expandHome(inputPath) {
|
|
12
|
-
if (!inputPath || !inputPath.startsWith("~")) return inputPath;
|
|
13
|
-
if (inputPath === "~") return os.homedir();
|
|
14
|
-
if (inputPath.startsWith("~/")) return path.join(os.homedir(), inputPath.slice(2));
|
|
15
|
-
return inputPath;
|
|
16
|
-
}
|
|
17
11
|
function toInt(value, fallback) {
|
|
18
12
|
const parsed = Number.parseInt(String(value ?? ""), 10);
|
|
19
13
|
return Number.isFinite(parsed) ? parsed : fallback;
|
|
@@ -35,23 +29,6 @@ function boolFromEnv(value, fallback = false) {
|
|
|
35
29
|
].includes(normalized)) return false;
|
|
36
30
|
return fallback;
|
|
37
31
|
}
|
|
38
|
-
function truncateString(value, maxLen = 4e3) {
|
|
39
|
-
if (typeof value !== "string") return value;
|
|
40
|
-
if (value.length <= maxLen) return value;
|
|
41
|
-
return `${value.slice(0, maxLen)}... [truncated ${value.length - maxLen} chars]`;
|
|
42
|
-
}
|
|
43
|
-
function safeJsonParse(line) {
|
|
44
|
-
try {
|
|
45
|
-
return JSON.parse(line);
|
|
46
|
-
} catch {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
function extractSessionIdFromPath(filePath) {
|
|
51
|
-
const uuidMatch = filePath.match(/([0-9a-f]{8}-[0-9a-f]{4,}-[0-9a-f]{4,}-[0-9a-f]{4,}-[0-9a-f]{8,})/i);
|
|
52
|
-
if (uuidMatch) return uuidMatch[1];
|
|
53
|
-
return path.basename(filePath, ".jsonl") || "unknown-session";
|
|
54
|
-
}
|
|
55
32
|
function extractProjectPathFromFile(filePath) {
|
|
56
33
|
const match = filePath.match(/\.claude\/projects\/([^/]+)/);
|
|
57
34
|
if (!match) return null;
|
|
@@ -133,5 +110,5 @@ async function acquireFileLock({ lockPath = resolveLockPath(process.env), userId
|
|
|
133
110
|
}
|
|
134
111
|
|
|
135
112
|
//#endregion
|
|
136
|
-
export {
|
|
137
|
-
//# sourceMappingURL=lock-
|
|
113
|
+
export { sha256 as a, extractProjectPathFromFile as i, resolveLockPath as n, toInt as o, boolFromEnv as r, acquireFileLock as t };
|
|
114
|
+
//# sourceMappingURL=lock-CQ3xrIlj.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock-CQ3xrIlj.mjs","names":[],"sources":["../../daemon/src/utils.mjs","../../daemon/src/lock.mjs"],"sourcesContent":["import crypto from \"node:crypto\";\n\n// shared utils from harness\nexport { expandHome, truncateString, safeJsonParse, extractSessionIdFromPath } from \"@ultracontext/parsers/utils\";\n\nexport function sha256(value) {\n return crypto.createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nexport function toInt(value, fallback) {\n const parsed = Number.parseInt(String(value ?? \"\"), 10);\n return Number.isFinite(parsed) ? parsed : fallback;\n}\n\nexport function boolFromEnv(value, fallback = false) {\n if (value === undefined) return fallback;\n const normalized = String(value).trim().toLowerCase();\n if ([\"1\", \"true\", \"yes\", \"on\"].includes(normalized)) return true;\n if ([\"0\", \"false\", \"no\", \"off\"].includes(normalized)) return false;\n return fallback;\n}\n\n// extract project path from JSONL file location\n// claude: ~/.claude/projects/-Users-fabio-Code-foo/session.jsonl → /Users/fabio/Code/foo\n// codex: ~/.codex/sessions/<uuid>.jsonl → null (cwd comes from session_meta)\n// openclaw: ~/.openclaw/agents/<name>/sessions/<uuid>.jsonl → null\nexport function extractProjectPathFromFile(filePath) {\n const match = filePath.match(/\\.claude\\/projects\\/([^/]+)/);\n if (!match) return null;\n\n // convert dash-separated path back to real path (leading dash = leading /)\n const encoded = match[1];\n return encoded.replace(/-/g, \"/\");\n}\n","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":";;;;;;;AAKA,SAAgB,OAAO,OAAO;AAC5B,QAAO,OAAO,WAAW,SAAS,CAAC,OAAO,MAAM,CAAC,OAAO,MAAM;;AAGhE,SAAgB,MAAM,OAAO,UAAU;CACrC,MAAM,SAAS,OAAO,SAAS,OAAO,SAAS,GAAG,EAAE,GAAG;AACvD,QAAO,OAAO,SAAS,OAAO,GAAG,SAAS;;AAG5C,SAAgB,YAAY,OAAO,WAAW,OAAO;AACnD,KAAI,UAAU,OAAW,QAAO;CAChC,MAAM,aAAa,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa;AACrD,KAAI;EAAC;EAAK;EAAQ;EAAO;EAAK,CAAC,SAAS,WAAW,CAAE,QAAO;AAC5D,KAAI;EAAC;EAAK;EAAS;EAAM;EAAM,CAAC,SAAS,WAAW,CAAE,QAAO;AAC7D,QAAO;;AAOT,SAAgB,2BAA2B,UAAU;CACnD,MAAM,QAAQ,SAAS,MAAM,8BAA8B;AAC3D,KAAI,CAAC,MAAO,QAAO;AAInB,QADgB,MAAM,GACP,QAAQ,MAAM,IAAI;;;;;AC1BnC,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"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
|
|
4
|
+
//#region ../../packages/parsers/src/utils.mjs
|
|
5
|
+
function expandHome$1(inputPath) {
|
|
6
|
+
if (!inputPath || !inputPath.startsWith("~")) return inputPath;
|
|
7
|
+
if (inputPath === "~") return os.homedir();
|
|
8
|
+
if (inputPath.startsWith("~/")) return path.join(os.homedir(), inputPath.slice(2));
|
|
9
|
+
return inputPath;
|
|
10
|
+
}
|
|
11
|
+
function truncateString(value, maxLen = 4e3) {
|
|
12
|
+
if (typeof value !== "string") return value;
|
|
13
|
+
if (value.length <= maxLen) return value;
|
|
14
|
+
return `${value.slice(0, maxLen)}... [truncated ${value.length - maxLen} chars]`;
|
|
15
|
+
}
|
|
16
|
+
function safeJsonParse(line) {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(line);
|
|
19
|
+
} catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function extractSessionIdFromPath(filePath) {
|
|
24
|
+
const uuidMatch = filePath.match(/([0-9a-f]{8}-[0-9a-f]{4,}-[0-9a-f]{4,}-[0-9a-f]{4,}-[0-9a-f]{8,})/i);
|
|
25
|
+
if (uuidMatch) return uuidMatch[1];
|
|
26
|
+
return path.basename(filePath, ".jsonl") || "unknown-session";
|
|
27
|
+
}
|
|
28
|
+
function normalizeRole(role, fallback = "system") {
|
|
29
|
+
const lowered = String(role ?? "").toLowerCase();
|
|
30
|
+
if (["user", "human"].includes(lowered)) return "user";
|
|
31
|
+
if ([
|
|
32
|
+
"assistant",
|
|
33
|
+
"agent",
|
|
34
|
+
"ai"
|
|
35
|
+
].includes(lowered)) return "assistant";
|
|
36
|
+
return fallback;
|
|
37
|
+
}
|
|
38
|
+
function normalizeWhitespace(value) {
|
|
39
|
+
return String(value ?? "").replace(/\s+/g, " ").trim();
|
|
40
|
+
}
|
|
41
|
+
function preserveText(value) {
|
|
42
|
+
return String(value ?? "").split("\n").map((l) => l.trimEnd()).join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
43
|
+
}
|
|
44
|
+
function toMessage(raw, maxLen = 12e3) {
|
|
45
|
+
if (!raw) return "";
|
|
46
|
+
if (typeof raw === "string") return truncateString(raw, maxLen);
|
|
47
|
+
if (typeof raw === "object") return truncateString(JSON.stringify(raw), maxLen);
|
|
48
|
+
return truncateString(String(raw), maxLen);
|
|
49
|
+
}
|
|
50
|
+
function coerceMessageText(message) {
|
|
51
|
+
const content = message?.content;
|
|
52
|
+
if (typeof content === "string") return content;
|
|
53
|
+
if (content && typeof content === "object") {
|
|
54
|
+
if (typeof content.message === "string") return content.message;
|
|
55
|
+
if (typeof content.text === "string") return content.text;
|
|
56
|
+
if (typeof content.raw === "string") return content.raw;
|
|
57
|
+
}
|
|
58
|
+
if (typeof message?.message === "string") return message.message;
|
|
59
|
+
return "";
|
|
60
|
+
}
|
|
61
|
+
function firstMessageTimestamp(messages) {
|
|
62
|
+
return messages?.[0]?.content?.timestamp ?? messages?.[0]?.metadata?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
63
|
+
}
|
|
64
|
+
function asIso(value) {
|
|
65
|
+
if (!value) return (/* @__PURE__ */ new Date()).toISOString();
|
|
66
|
+
const d = new Date(String(value));
|
|
67
|
+
if (Number.isNaN(d.getTime())) return (/* @__PURE__ */ new Date()).toISOString();
|
|
68
|
+
return d.toISOString();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region ../../packages/protocol/src/index.mjs
|
|
73
|
+
const VERSION = "v1";
|
|
74
|
+
const DEFAULT_DAEMON_WS_HOST = "127.0.0.1";
|
|
75
|
+
const DEFAULT_DAEMON_WS_PORT = 0;
|
|
76
|
+
const DEFAULT_DAEMON_INFO_FILE = "~/.ultracontext/daemon.info";
|
|
77
|
+
const DAEMON_WS_MESSAGE_TYPES = Object.freeze({
|
|
78
|
+
SNAPSHOT: "snapshot",
|
|
79
|
+
STATE: "state",
|
|
80
|
+
LOG: "log",
|
|
81
|
+
CONTEXT_EVENT: "context:event",
|
|
82
|
+
CONFIG_STATE: "config:state",
|
|
83
|
+
REQUEST_ACK: "ack",
|
|
84
|
+
PING: "ping",
|
|
85
|
+
PONG: "pong",
|
|
86
|
+
CONFIG_GET: "config:get",
|
|
87
|
+
CONFIG_SET: "config:set",
|
|
88
|
+
BOOTSTRAP_RESET: "bootstrap:reset"
|
|
89
|
+
});
|
|
90
|
+
function norm(value, fallback = "unknown") {
|
|
91
|
+
return String(value ?? "").trim() || fallback;
|
|
92
|
+
}
|
|
93
|
+
function expandHome(inputPath) {
|
|
94
|
+
const raw = String(inputPath ?? "");
|
|
95
|
+
if (!raw || !raw.startsWith("~")) return raw;
|
|
96
|
+
if (raw === "~") return os.homedir();
|
|
97
|
+
if (raw.startsWith("~/")) return path.join(os.homedir(), raw.slice(2));
|
|
98
|
+
return raw;
|
|
99
|
+
}
|
|
100
|
+
function resolveDaemonWsHost(env = process.env) {
|
|
101
|
+
return String(env.ULTRACONTEXT_DAEMON_WS_HOST ?? env.ULTRACONTEXT_WS_HOST ?? "").trim() || DEFAULT_DAEMON_WS_HOST;
|
|
102
|
+
}
|
|
103
|
+
function resolveDaemonWsPort(env = process.env) {
|
|
104
|
+
const raw = Number.parseInt(String(env.ULTRACONTEXT_DAEMON_WS_PORT ?? env.ULTRACONTEXT_WS_PORT ?? ""), 10);
|
|
105
|
+
if (Number.isInteger(raw) && raw >= 0 && raw <= 65535) return raw;
|
|
106
|
+
return DEFAULT_DAEMON_WS_PORT;
|
|
107
|
+
}
|
|
108
|
+
function resolveDaemonWsInfoFile(env = process.env) {
|
|
109
|
+
return expandHome(env.ULTRACONTEXT_DAEMON_INFO_FILE ?? env.ULTRACONTEXT_DAEMON_WS_PORT_FILE ?? env.ULTRACONTEXT_WS_INFO_FILE ?? DEFAULT_DAEMON_INFO_FILE);
|
|
110
|
+
}
|
|
111
|
+
function createBootstrapStateKey({ host, userId, sourceNames }) {
|
|
112
|
+
const namesKey = (Array.isArray(sourceNames) ? sourceNames.map((name) => String(name ?? "").trim()).filter(Boolean) : []).sort().join(",");
|
|
113
|
+
return `uc:daemon:bootstrap:${VERSION}:${norm(host)}:${norm(userId)}:${namesKey}`;
|
|
114
|
+
}
|
|
115
|
+
function normalizeBootstrapMode(raw, { allowPrompt = false } = {}) {
|
|
116
|
+
const value = String(raw ?? "").trim().toLowerCase();
|
|
117
|
+
if (allowPrompt && value === "prompt") return "prompt";
|
|
118
|
+
if (value === "new" || value === "new_only" || value === "latest") return "new_only";
|
|
119
|
+
if (value === "24h" || value === "last_24h" || value === "last24h") return "last_24h";
|
|
120
|
+
if (value === "all" || value === "full") return "all";
|
|
121
|
+
return "";
|
|
122
|
+
}
|
|
123
|
+
function parseProtocolJson(raw, fallback) {
|
|
124
|
+
if (!raw) return fallback;
|
|
125
|
+
try {
|
|
126
|
+
return JSON.parse(raw);
|
|
127
|
+
} catch {
|
|
128
|
+
return fallback;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function buildDaemonWsMessage(type, data = {}) {
|
|
132
|
+
return {
|
|
133
|
+
type: String(type ?? ""),
|
|
134
|
+
data: data ?? {}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function parseDaemonWsMessage(raw, fallback = null) {
|
|
138
|
+
const parsed = typeof raw === "string" ? parseProtocolJson(raw, fallback) : raw;
|
|
139
|
+
if (!parsed || typeof parsed !== "object") return fallback;
|
|
140
|
+
const type = String(parsed.type ?? "").trim();
|
|
141
|
+
if (!type) return fallback;
|
|
142
|
+
return {
|
|
143
|
+
...parsed,
|
|
144
|
+
type,
|
|
145
|
+
data: parsed.data ?? {}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
//#endregion
|
|
150
|
+
export { preserveText as _, parseDaemonWsMessage as a, truncateString as b, resolveDaemonWsInfoFile as c, coerceMessageText as d, expandHome$1 as f, normalizeWhitespace as g, normalizeRole as h, normalizeBootstrapMode as i, resolveDaemonWsPort as l, firstMessageTimestamp as m, buildDaemonWsMessage as n, parseProtocolJson as o, extractSessionIdFromPath as p, createBootstrapStateKey as r, resolveDaemonWsHost as s, DAEMON_WS_MESSAGE_TYPES as t, asIso as u, safeJsonParse as v, toMessage as y };
|
|
151
|
+
//# sourceMappingURL=src-BSCJv6SU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-BSCJv6SU.mjs","names":["expandHome"],"sources":["../../../packages/parsers/src/utils.mjs","../../../packages/protocol/src/index.mjs"],"sourcesContent":["import os from \"node:os\";\nimport path from \"node:path\";\n\n// resolve ~ to home directory\nexport function expandHome(inputPath) {\n if (!inputPath || !inputPath.startsWith(\"~\")) return inputPath;\n if (inputPath === \"~\") return os.homedir();\n if (inputPath.startsWith(\"~/\")) return path.join(os.homedir(), inputPath.slice(2));\n return inputPath;\n}\n\n// safe truncation with indicator\nexport function truncateString(value, maxLen = 4000) {\n if (typeof value !== \"string\") return value;\n if (value.length <= maxLen) return value;\n return `${value.slice(0, maxLen)}... [truncated ${value.length - maxLen} chars]`;\n}\n\n// swallow malformed JSON\nexport function safeJsonParse(line) {\n try {\n return JSON.parse(line);\n } catch {\n return null;\n }\n}\n\n// pull UUID from file path, fall back to filename\nexport function extractSessionIdFromPath(filePath) {\n const uuidMatch = filePath.match(\n /([0-9a-f]{8}-[0-9a-f]{4,}-[0-9a-f]{4,}-[0-9a-f]{4,}-[0-9a-f]{8,})/i\n );\n if (uuidMatch) return uuidMatch[1];\n\n const fileName = path.basename(filePath, \".jsonl\");\n return fileName || \"unknown-session\";\n}\n\n// normalize role strings across agents\nexport function normalizeRole(role, fallback = \"system\") {\n const lowered = String(role ?? \"\").toLowerCase();\n if ([\"user\", \"human\"].includes(lowered)) return \"user\";\n if ([\"assistant\", \"agent\", \"ai\"].includes(lowered)) return \"assistant\";\n return fallback;\n}\n\n// collapse whitespace to single spaces\nexport function normalizeWhitespace(value) {\n return String(value ?? \"\").replace(/\\s+/g, \" \").trim();\n}\n\n// preserve newlines, trim lines, collapse 3+ blank lines → 2\nexport function preserveText(value) {\n return String(value ?? \"\")\n .split(\"\\n\")\n .map((l) => l.trimEnd())\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n}\n\n// coerce message content to string\nexport function toMessage(raw, maxLen = 12000) {\n if (!raw) return \"\";\n if (typeof raw === \"string\") return truncateString(raw, maxLen);\n if (typeof raw === \"object\") return truncateString(JSON.stringify(raw), maxLen);\n return truncateString(String(raw), maxLen);\n}\n\n// coerce message content to plain text\nexport function coerceMessageText(message) {\n const content = message?.content;\n if (typeof content === \"string\") return content;\n if (content && typeof content === \"object\") {\n if (typeof content.message === \"string\") return content.message;\n if (typeof content.text === \"string\") return content.text;\n if (typeof content.raw === \"string\") return content.raw;\n }\n if (typeof message?.message === \"string\") return message.message;\n return \"\";\n}\n\n// get timestamp from first message\nexport function firstMessageTimestamp(messages) {\n return (\n messages?.[0]?.content?.timestamp ??\n messages?.[0]?.metadata?.timestamp ??\n new Date().toISOString()\n );\n}\n\n// coerce ISO timestamp, fall back to now\nexport function asIso(value) {\n if (!value) return new Date().toISOString();\n const d = new Date(String(value));\n if (Number.isNaN(d.getTime())) return new Date().toISOString();\n return d.toISOString();\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\n\nconst VERSION = \"v1\";\nconst DEFAULT_DAEMON_WS_HOST = \"127.0.0.1\";\nconst DEFAULT_DAEMON_WS_PORT = 0;\nconst DEFAULT_DAEMON_INFO_FILE = \"~/.ultracontext/daemon.info\";\n\nexport const DAEMON_WS_MESSAGE_TYPES = Object.freeze({\n SNAPSHOT: \"snapshot\",\n STATE: \"state\",\n LOG: \"log\",\n CONTEXT_EVENT: \"context:event\",\n CONFIG_STATE: \"config:state\",\n REQUEST_ACK: \"ack\",\n PING: \"ping\",\n PONG: \"pong\",\n CONFIG_GET: \"config:get\",\n CONFIG_SET: \"config:set\",\n BOOTSTRAP_RESET: \"bootstrap:reset\",\n});\n\nfunction norm(value, fallback = \"unknown\") {\n const trimmed = String(value ?? \"\").trim();\n return trimmed || fallback;\n}\n\nfunction expandHome(inputPath) {\n const raw = String(inputPath ?? \"\");\n if (!raw || !raw.startsWith(\"~\")) return raw;\n if (raw === \"~\") return os.homedir();\n if (raw.startsWith(\"~/\")) return path.join(os.homedir(), raw.slice(2));\n return raw;\n}\n\nexport function resolveDaemonWsHost(env = process.env) {\n const raw = String(env.ULTRACONTEXT_DAEMON_WS_HOST ?? env.ULTRACONTEXT_WS_HOST ?? \"\").trim();\n return raw || DEFAULT_DAEMON_WS_HOST;\n}\n\nexport function resolveDaemonWsPort(env = process.env) {\n const raw = Number.parseInt(String(env.ULTRACONTEXT_DAEMON_WS_PORT ?? env.ULTRACONTEXT_WS_PORT ?? \"\"), 10);\n if (Number.isInteger(raw) && raw >= 0 && raw <= 65535) return raw;\n return DEFAULT_DAEMON_WS_PORT;\n}\n\nexport function resolveDaemonWsInfoFile(env = process.env) {\n return expandHome(\n env.ULTRACONTEXT_DAEMON_INFO_FILE ??\n env.ULTRACONTEXT_DAEMON_WS_PORT_FILE ??\n env.ULTRACONTEXT_WS_INFO_FILE ??\n DEFAULT_DAEMON_INFO_FILE\n );\n}\n\nexport function resolveDaemonWsPortFile(env = process.env) {\n return resolveDaemonWsInfoFile(env);\n}\n\nexport function createBootstrapStateKey({ host, userId, sourceNames }) {\n const names = Array.isArray(sourceNames) ? sourceNames.map((name) => String(name ?? \"\").trim()).filter(Boolean) : [];\n const namesKey = names.sort().join(\",\");\n return `uc:daemon:bootstrap:${VERSION}:${norm(host)}:${norm(userId)}:${namesKey}`;\n}\n\nexport function normalizeBootstrapMode(raw, { allowPrompt = false } = {}) {\n const value = String(raw ?? \"\").trim().toLowerCase();\n if (allowPrompt && value === \"prompt\") return \"prompt\";\n if (value === \"new\" || value === \"new_only\" || value === \"latest\") return \"new_only\";\n if (value === \"24h\" || value === \"last_24h\" || value === \"last24h\") return \"last_24h\";\n if (value === \"all\" || value === \"full\") return \"all\";\n return \"\";\n}\n\nexport function parseProtocolJson(raw, fallback) {\n if (!raw) return fallback;\n try {\n return JSON.parse(raw);\n } catch {\n return fallback;\n }\n}\n\nexport function buildDaemonWsMessage(type, data = {}) {\n return { type: String(type ?? \"\"), data: data ?? {} };\n}\n\nexport function parseDaemonWsMessage(raw, fallback = null) {\n const parsed = typeof raw === \"string\" ? parseProtocolJson(raw, fallback) : raw;\n if (!parsed || typeof parsed !== \"object\") return fallback;\n const type = String(parsed.type ?? \"\").trim();\n if (!type) return fallback;\n return {\n ...parsed,\n type,\n data: parsed.data ?? {},\n };\n}\n"],"mappings":"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"}
|