openlimiter 1.3.1 → 1.3.3

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 (52) hide show
  1. package/dist/cli.d.ts +1 -1
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +130 -78
  4. package/dist/cli.js.map +1 -1
  5. package/dist/codex-device-login.d.ts +2 -1
  6. package/dist/codex-device-login.d.ts.map +1 -1
  7. package/dist/codex-device-login.js +6 -4
  8. package/dist/codex-device-login.js.map +1 -1
  9. package/dist/config.d.ts +1 -0
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +3 -2
  12. package/dist/config.js.map +1 -1
  13. package/dist/hub-auth.d.ts +12 -14
  14. package/dist/hub-auth.d.ts.map +1 -1
  15. package/dist/hub-auth.js +232 -47
  16. package/dist/hub-auth.js.map +1 -1
  17. package/dist/hub-sync.d.ts +14 -13
  18. package/dist/hub-sync.d.ts.map +1 -1
  19. package/dist/hub-sync.js +139 -18
  20. package/dist/hub-sync.js.map +1 -1
  21. package/dist/hub.d.ts +6 -3
  22. package/dist/hub.d.ts.map +1 -1
  23. package/dist/hub.js +47 -11
  24. package/dist/hub.js.map +1 -1
  25. package/dist/ingest.d.ts.map +1 -1
  26. package/dist/ingest.js +16 -21
  27. package/dist/ingest.js.map +1 -1
  28. package/dist/session.d.ts +16 -8
  29. package/dist/session.d.ts.map +1 -1
  30. package/dist/session.js +144 -31
  31. package/dist/session.js.map +1 -1
  32. package/dist/statusline.d.ts +1 -1
  33. package/dist/statusline.d.ts.map +1 -1
  34. package/dist/statusline.js +10 -8
  35. package/dist/statusline.js.map +1 -1
  36. package/dist/terminal-backup.d.ts +5 -0
  37. package/dist/terminal-backup.d.ts.map +1 -0
  38. package/dist/terminal-backup.js +88 -0
  39. package/dist/terminal-backup.js.map +1 -0
  40. package/dist/terminal-launcher.d.ts +12 -0
  41. package/dist/terminal-launcher.d.ts.map +1 -0
  42. package/dist/terminal-launcher.js +208 -0
  43. package/dist/terminal-launcher.js.map +1 -0
  44. package/dist/terminal-toml.d.ts +38 -0
  45. package/dist/terminal-toml.d.ts.map +1 -0
  46. package/dist/terminal-toml.js +357 -0
  47. package/dist/terminal-toml.js.map +1 -0
  48. package/dist/terminal.d.ts +10 -37
  49. package/dist/terminal.d.ts.map +1 -1
  50. package/dist/terminal.js +390 -619
  51. package/dist/terminal.js.map +1 -1
  52. package/package.json +4 -4
@@ -0,0 +1,12 @@
1
+ export interface Launcher {
2
+ node: string;
3
+ entry: string;
4
+ version: string;
5
+ }
6
+ export declare const RUNTIME_STAMP_FILE_NAME = ".openlimiter-runtime.json";
7
+ export declare function verifyLauncher(launcher: Launcher): Promise<void>;
8
+ /** Copy the shipped runtime, its production dependency closure and Node itself.
9
+ * Never retain a reference to an npm cache directory that may be removed. */
10
+ export declare function installLauncher(directory: string, source?: string): Promise<Launcher>;
11
+ export declare function launcherCommand(launcher: Launcher, shell: "posix" | "cmd" | "powershell"): string;
12
+ //# sourceMappingURL=terminal-launcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-launcher.d.ts","sourceRoot":"","sources":["../src/terminal-launcher.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,QAAQ;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAG1E,eAAO,MAAM,uBAAuB,8BAA8B,CAAC;AAmGnE,wBAAsB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED;6EAC6E;AAC7E,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,SAAmE,GAAG,OAAO,CAAC,QAAQ,CAAC,CA+DrJ;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,GAAG,YAAY,GAAG,MAAM,CAKjG"}
@@ -0,0 +1,208 @@
1
+ import { createHash } from "node:crypto";
2
+ import { randomUUID } from "node:crypto";
3
+ import { cp, link, lstat, mkdir, mkdtemp, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
4
+ import { createRequire } from "node:module";
5
+ import { fileURLToPath } from "node:url";
6
+ import path from "node:path";
7
+ const LAUNCHER_ENTRY_CONTENT = 'import("./node_modules/openlimiter/dist/bin.js");\n';
8
+ export const RUNTIME_STAMP_FILE_NAME = ".openlimiter-runtime.json";
9
+ function ownerIsCurrentUser(uid) {
10
+ if (process.platform === "win32" || typeof process.getuid !== "function")
11
+ return true;
12
+ return uid === process.getuid();
13
+ }
14
+ async function assertSafeTree(root) {
15
+ const pending = [root];
16
+ while (pending.length > 0) {
17
+ const current = pending.pop();
18
+ const info = await lstat(current);
19
+ if (info.isSymbolicLink() || !ownerIsCurrentUser(info.uid))
20
+ throw new Error("Invalid launcher");
21
+ if (!info.isDirectory())
22
+ continue;
23
+ for (const entry of await readdir(current))
24
+ pending.push(path.join(current, entry));
25
+ }
26
+ }
27
+ async function runtimeFiles(root) {
28
+ const files = [];
29
+ const pending = [root];
30
+ while (pending.length > 0) {
31
+ const current = pending.pop();
32
+ for (const entry of await readdir(current)) {
33
+ const file = path.join(current, entry);
34
+ const info = await lstat(file);
35
+ if (info.isSymbolicLink() || !ownerIsCurrentUser(info.uid))
36
+ throw new Error("Invalid launcher");
37
+ if (info.isDirectory())
38
+ pending.push(file);
39
+ else
40
+ files.push(file);
41
+ }
42
+ }
43
+ return files
44
+ .filter(file => path.relative(root, file).split(path.sep).join("/") !== RUNTIME_STAMP_FILE_NAME)
45
+ .sort((a, b) => a.localeCompare(b));
46
+ }
47
+ async function runtimeFileHashes(root) {
48
+ const hashes = {};
49
+ for (const file of await runtimeFiles(root)) {
50
+ const relative = path.relative(root, file).split(path.sep).join("/");
51
+ hashes[relative] = createHash("sha256").update(await readFile(file)).digest("hex");
52
+ }
53
+ return hashes;
54
+ }
55
+ async function runtimeStampIsValid(root, expectedVersion) {
56
+ let stamp;
57
+ try {
58
+ const stampFile = path.join(root, RUNTIME_STAMP_FILE_NAME);
59
+ const info = await lstat(stampFile);
60
+ if (!info.isFile() || info.isSymbolicLink() || info.size > 1_048_576)
61
+ return false;
62
+ const parsed = JSON.parse(await readFile(stampFile, "utf8"));
63
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
64
+ return false;
65
+ const candidate = parsed;
66
+ if (typeof candidate.version !== "string" || candidate.version.length === 0 ||
67
+ typeof candidate.files !== "object" || candidate.files === null || Array.isArray(candidate.files))
68
+ return false;
69
+ const files = candidate.files;
70
+ if (Object.keys(files).some(file => !file || path.posix.isAbsolute(file) || file.includes("..") ||
71
+ typeof files[file] !== "string" || !/^[a-f0-9]{64}$/u.test(files[file])))
72
+ return false;
73
+ stamp = { version: candidate.version, files: files };
74
+ }
75
+ catch {
76
+ return false;
77
+ }
78
+ if (expectedVersion !== undefined && stamp.version !== expectedVersion)
79
+ return false;
80
+ const actual = await runtimeFileHashes(root);
81
+ const actualNames = Object.keys(actual).sort();
82
+ const stampedNames = Object.keys(stamp.files).sort();
83
+ if (actualNames.length !== stampedNames.length || actualNames.some((file, index) => file !== stampedNames[index]))
84
+ return false;
85
+ return actualNames.every(file => actual[file] === stamp.files[file]);
86
+ }
87
+ /** Check only bytes and filesystem metadata. Never execute an existing file. */
88
+ async function existingLauncherIsTrusted(launcher) {
89
+ const root = path.dirname(launcher.entry);
90
+ try {
91
+ await lstat(root);
92
+ }
93
+ catch (error) {
94
+ if (error.code === "ENOENT")
95
+ return false;
96
+ throw error;
97
+ }
98
+ await assertSafeTree(root);
99
+ let entry;
100
+ try {
101
+ entry = await readFile(launcher.entry, "utf8");
102
+ const node = await lstat(launcher.node);
103
+ if (!node.isFile())
104
+ return false;
105
+ }
106
+ catch (error) {
107
+ if (error.code === "ENOENT")
108
+ return false;
109
+ throw error;
110
+ }
111
+ if (entry !== LAUNCHER_ENTRY_CONTENT)
112
+ return false;
113
+ return await runtimeStampIsValid(root, launcher.version);
114
+ }
115
+ export async function verifyLauncher(launcher) {
116
+ if (!(await existingLauncherIsTrusted(launcher)))
117
+ throw new Error("Invalid launcher");
118
+ }
119
+ /** Copy the shipped runtime, its production dependency closure and Node itself.
120
+ * Never retain a reference to an npm cache directory that may be removed. */
121
+ export async function installLauncher(directory, source = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")) {
122
+ await mkdir(directory, { recursive: true });
123
+ const target = path.join(directory, "terminal-runtime");
124
+ const sourceManifest = JSON.parse(await readFile(path.join(source, "package.json"), "utf8"));
125
+ if (typeof sourceManifest.version !== "string" || sourceManifest.version.length === 0)
126
+ throw new Error("Invalid launcher");
127
+ const version = sourceManifest.version;
128
+ const result = { node: path.join(target, process.platform === "win32" ? "node.exe" : "node"), entry: path.join(target, "openlimiter.cjs"), version };
129
+ try {
130
+ if (await existingLauncherIsTrusted(result))
131
+ return result;
132
+ }
133
+ catch {
134
+ /* A present runtime with unsafe metadata must never be adopted or followed. */
135
+ throw new Error("Invalid launcher");
136
+ }
137
+ const staging = await mkdtemp(path.join(directory, "terminal-runtime-"));
138
+ try {
139
+ const copied = new Set();
140
+ async function copyPackage(root) {
141
+ const manifest = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"));
142
+ if (copied.has(manifest.name))
143
+ return;
144
+ copied.add(manifest.name);
145
+ const destination = path.join(staging, "node_modules", manifest.name);
146
+ await mkdir(destination, { recursive: true });
147
+ await cp(path.join(root, "dist"), path.join(destination, "dist"), {
148
+ recursive: true, dereference: true,
149
+ filter: file => !file.endsWith(".map") && !file.endsWith(".d.ts") && !file.endsWith(".tsbuildinfo")
150
+ });
151
+ await cp(path.join(root, "package.json"), path.join(destination, "package.json"));
152
+ const resolve = createRequire(path.join(root, "package.json"));
153
+ for (const name of Object.keys(manifest.dependencies ?? {})) {
154
+ // OpenLimiter's shipped packages expose dist/index.js and contain only
155
+ // first party runtime dependencies. Refuse an unexpected package layout.
156
+ const entry = resolve.resolve(name);
157
+ if (path.basename(path.dirname(entry)) !== "dist")
158
+ throw new Error("Invalid launcher");
159
+ await copyPackage(path.dirname(path.dirname(entry)));
160
+ }
161
+ }
162
+ await copyPackage(source);
163
+ const node = path.join(staging, path.basename(result.node));
164
+ try {
165
+ await link(process.execPath, node);
166
+ }
167
+ catch {
168
+ await cp(process.execPath, node);
169
+ }
170
+ await writeFile(path.join(staging, "openlimiter.cjs"), LAUNCHER_ENTRY_CONTENT, { mode: 0o600 });
171
+ const stamp = { version, files: await runtimeFileHashes(staging) };
172
+ await writeFile(path.join(staging, RUNTIME_STAMP_FILE_NAME), JSON.stringify(stamp) + "\n", { mode: 0o600 });
173
+ await verifyLauncher({ node, entry: path.join(staging, "openlimiter.cjs"), version });
174
+ const displaced = `${target}.${process.pid}.${randomUUID()}.old`;
175
+ let hadExisting = false;
176
+ try {
177
+ await rename(target, displaced);
178
+ hadExisting = true;
179
+ }
180
+ catch (error) {
181
+ if (error.code !== "ENOENT")
182
+ throw error;
183
+ }
184
+ try {
185
+ await rename(staging, target);
186
+ }
187
+ catch (error) {
188
+ if (hadExisting)
189
+ await rename(displaced, target).catch(() => undefined);
190
+ throw error;
191
+ }
192
+ if (hadExisting)
193
+ await rm(displaced, { recursive: true, force: true });
194
+ await verifyLauncher(result);
195
+ return result;
196
+ }
197
+ finally {
198
+ await rm(staging, { recursive: true, force: true });
199
+ }
200
+ }
201
+ export function launcherCommand(launcher, shell) {
202
+ const quote = shell === "cmd"
203
+ ? (value) => { if (/["%\r\n]/.test(value))
204
+ throw new Error("Invalid launcher"); return `"${value}"`; }
205
+ : (value) => `'${value.replaceAll("'", shell === "powershell" ? "''" : "'\\''")}'`;
206
+ return `${shell === "powershell" ? "& " : ""}${quote(launcher.node)} ${quote(launcher.entry)}`;
207
+ }
208
+ //# sourceMappingURL=terminal-launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-launcher.js","sourceRoot":"","sources":["../src/terminal-launcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /** A lossless TOML syntax tree. Unchanged values and comments retain their bytes.
2
+ * Values are parsed recursively, so strings, arrays and inline tables cannot
3
+ * masquerade as assignments or table headers during an edit. */
4
+ type Value = string | number | boolean | null | Value[] | {
5
+ [key: string]: Value;
6
+ };
7
+ interface Entry {
8
+ keys: string[];
9
+ start: number;
10
+ end: number;
11
+ value: Value;
12
+ }
13
+ interface Table {
14
+ keys: string[];
15
+ insert: number;
16
+ array: boolean;
17
+ }
18
+ declare class Parser {
19
+ readonly text: string;
20
+ i: number;
21
+ entries: Entry[];
22
+ tables: Table[];
23
+ constructor(text: string);
24
+ fail(): never;
25
+ peek(): string;
26
+ spaces(multiline?: boolean): void;
27
+ comment(): void;
28
+ string(key?: boolean): string;
29
+ keys(): string[];
30
+ value(depth?: number): Value;
31
+ parse(): this;
32
+ }
33
+ export declare function parseToml(text: string): Parser;
34
+ export declare function tomlValue(text: string, keys: string[]): Value | undefined;
35
+ /** Serialize only changed scalar values, then parse the entire candidate. */
36
+ export declare function editToml(text: string, table: string[], settings: Record<string, Value>): string;
37
+ export {};
38
+ //# sourceMappingURL=terminal-toml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-toml.d.ts","sourceRoot":"","sources":["../src/terminal-toml.ts"],"names":[],"mappings":"AAAA;;gEAEgE;AAChE,KAAK,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAA;CAAE,CAAC;AACnF,UAAU,KAAK;IAAG,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE;AAC5E,UAAU,KAAK;IAAG,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AAGlE,cAAM,MAAM;IAIE,QAAQ,CAAC,IAAI,EAAE,MAAM;IAHjC,CAAC,SAAK;IACN,OAAO,EAAE,KAAK,EAAE,CAAM;IACtB,MAAM,EAAE,KAAK,EAAE,CAAM;gBACA,IAAI,EAAE,MAAM;IACjC,IAAI,IAAI,KAAK;IACb,IAAI,IAAI,MAAM;IACd,MAAM,CAAC,SAAS,UAAQ,GAAG,IAAI;IAO/B,OAAO,IAAI,IAAI;IAGf,MAAM,CAAC,GAAG,UAAQ,GAAG,MAAM;IAwC3B,IAAI,IAAI,MAAM,EAAE;IAiBhB,KAAK,CAAC,KAAK,SAAI,GAAG,KAAK;IA6DvB,KAAK,IAAI,IAAI;CAmDd;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAqC;AACpF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,GAAG,SAAS,CAezE;AA+BD,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,CAuC/F"}
@@ -0,0 +1,357 @@
1
+ const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
2
+ class Parser {
3
+ text;
4
+ i = 0;
5
+ entries = [];
6
+ tables = [];
7
+ constructor(text) {
8
+ this.text = text;
9
+ }
10
+ fail() { throw new Error("Invalid TOML"); }
11
+ peek() { return this.text[this.i] ?? ""; }
12
+ spaces(multiline = false) {
13
+ while (this.i < this.text.length) {
14
+ if (/[ \t]/.test(this.peek()) || (multiline && /[\r\n]/.test(this.peek())))
15
+ this.i++;
16
+ else if (multiline && this.peek() === "#")
17
+ this.comment();
18
+ else
19
+ break;
20
+ }
21
+ }
22
+ comment() {
23
+ while (this.i < this.text.length && this.peek() !== "\n")
24
+ this.i++;
25
+ }
26
+ string(key = false) {
27
+ const quote = this.peek();
28
+ const triple = !key && this.text.slice(this.i, this.i + 3) === quote.repeat(3);
29
+ this.i += triple ? 3 : 1;
30
+ if (triple && this.text.slice(this.i, this.i + 2) === "\r\n")
31
+ this.i += 2;
32
+ else if (triple && this.peek() === "\n")
33
+ this.i++;
34
+ let result = "";
35
+ while (this.i < this.text.length) {
36
+ if (this.peek() === quote) {
37
+ if (!triple) {
38
+ this.i++;
39
+ return result;
40
+ }
41
+ if (this.text.slice(this.i, this.i + 3) === quote.repeat(3)) {
42
+ this.i += 3;
43
+ for (let n = 0; n < 2 && this.peek() === quote; n++, this.i++)
44
+ result += quote;
45
+ return result;
46
+ }
47
+ }
48
+ const c = this.text[this.i++];
49
+ if ((!triple && /[\r\n]/.test(c)) || /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/.test(c))
50
+ this.fail();
51
+ if (c !== "\\" || quote === "'") {
52
+ result += c;
53
+ continue;
54
+ }
55
+ if (triple && /[ \t\r\n]/.test(this.peek())) {
56
+ const start = this.i;
57
+ while (this.i < this.text.length && /\s/.test(this.peek()))
58
+ this.i++;
59
+ if (!this.text.slice(start, this.i).includes("\n"))
60
+ this.fail();
61
+ continue;
62
+ }
63
+ const escape = this.text[this.i++] ?? "";
64
+ const escapes = { b: "\b", t: "\t", n: "\n", f: "\f", r: "\r", '"': '"', "\\": "\\" };
65
+ if (escape in escapes)
66
+ result += escapes[escape];
67
+ else if (escape === "u" || escape === "U") {
68
+ const size = escape === "u" ? 4 : 8;
69
+ const hex = this.text.slice(this.i, this.i + size);
70
+ if (hex.length !== size || !/^[0-9a-f]+$/i.test(hex))
71
+ this.fail();
72
+ const point = Number.parseInt(hex, 16);
73
+ if (point > 0x10ffff || (point >= 0xd800 && point <= 0xdfff))
74
+ this.fail();
75
+ result += String.fromCodePoint(point);
76
+ this.i += size;
77
+ }
78
+ else
79
+ this.fail();
80
+ }
81
+ return this.fail();
82
+ }
83
+ keys() {
84
+ const keys = [];
85
+ do {
86
+ this.spaces();
87
+ if (this.peek() === '"' || this.peek() === "'")
88
+ keys.push(this.string(true));
89
+ else {
90
+ const start = this.i;
91
+ while (this.i < this.text.length && /[A-Za-z0-9_-]/.test(this.peek()))
92
+ this.i++;
93
+ if (this.i === start)
94
+ this.fail();
95
+ keys.push(this.text.slice(start, this.i));
96
+ }
97
+ this.spaces();
98
+ if (this.peek() !== ".")
99
+ return keys;
100
+ this.i++;
101
+ } while (this.i < this.text.length);
102
+ return this.fail();
103
+ }
104
+ value(depth = 0) {
105
+ if (depth > 100)
106
+ this.fail();
107
+ this.spaces();
108
+ if (this.peek() === '"' || this.peek() === "'")
109
+ return this.string();
110
+ if (this.peek() === "[") {
111
+ this.i++;
112
+ const values = [];
113
+ this.spaces(true);
114
+ while (this.peek() !== "]") {
115
+ values.push(this.value(depth + 1));
116
+ this.spaces(true);
117
+ if (this.peek() !== ",")
118
+ break;
119
+ this.i++;
120
+ this.spaces(true);
121
+ }
122
+ if (this.peek() !== "]")
123
+ this.fail();
124
+ this.i++;
125
+ return values;
126
+ }
127
+ if (this.peek() === "{") {
128
+ this.i++;
129
+ const result = Object.create(null);
130
+ const assigned = [];
131
+ this.spaces();
132
+ while (this.peek() !== "}") {
133
+ const keys = this.keys();
134
+ if (assigned.some(k => same(k.slice(0, keys.length), keys) || same(keys.slice(0, k.length), k)))
135
+ this.fail();
136
+ assigned.push(keys);
137
+ if (this.peek() !== "=")
138
+ this.fail();
139
+ this.i++;
140
+ result[JSON.stringify(keys)] = this.value(depth + 1);
141
+ this.spaces();
142
+ if (this.peek() !== ",")
143
+ break;
144
+ this.i++;
145
+ this.spaces();
146
+ if (this.peek() === "}")
147
+ this.fail();
148
+ }
149
+ if (this.peek() !== "}")
150
+ this.fail();
151
+ this.i++;
152
+ return result;
153
+ }
154
+ const start = this.i;
155
+ while (this.i < this.text.length && !/[\r\n,#\]}]/.test(this.peek()))
156
+ this.i++;
157
+ const raw = this.text.slice(start, this.i).trim();
158
+ if (raw === "true" || raw === "false")
159
+ return raw === "true";
160
+ if (/^[+-]?(inf|nan)$/.test(raw))
161
+ return null;
162
+ if (/^[+-]?(0|[1-9](?:_?[0-9])*)(\.[0-9](?:_?[0-9])*)?([eE][+-]?[0-9](?:_?[0-9])*)?$/.test(raw) ||
163
+ /^0(x[0-9a-fA-F](?:_?[0-9a-fA-F])*|o[0-7](?:_?[0-7])*|b[01](?:_?[01])*)$/.test(raw))
164
+ return Number(raw.replaceAll("_", ""));
165
+ if (/^(\d{4}-\d{2}-\d{2}([Tt ]\d{2}:\d{2}:\d{2}(\.\d+)?([Zz]|[+-]\d{2}:\d{2})?)?|\d{2}:\d{2}:\d{2}(\.\d+)?)$/.test(raw)) {
166
+ const date = /^(\d{4})-(\d{2})-(\d{2})/.exec(raw);
167
+ if (date) {
168
+ const year = Number(date[1]), month = Number(date[2]), day = Number(date[3]);
169
+ const days = [31, year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
170
+ if (month < 1 || month > 12 || day < 1 || day > days[month - 1])
171
+ this.fail();
172
+ }
173
+ const time = /(\d{2}):(\d{2}):(\d{2})/.exec(raw);
174
+ if (time && (Number(time[1]) > 23 || Number(time[2]) > 59 || Number(time[3]) > 60))
175
+ this.fail();
176
+ const offset = /[+-](\d{2}):(\d{2})$/.exec(raw);
177
+ if (offset && (Number(offset[1]) > 23 || Number(offset[2]) > 59))
178
+ this.fail();
179
+ return raw;
180
+ }
181
+ return this.fail();
182
+ }
183
+ parse() {
184
+ if (/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/.test(this.text) || /\r(?!\n)/.test(this.text))
185
+ this.fail();
186
+ if (this.text.charCodeAt(0) === 0xfeff)
187
+ this.i = 1;
188
+ let section = [], scope = [];
189
+ const values = [], tables = new Set(), dotted = new Set(), arrays = new Map();
190
+ while (this.i < this.text.length) {
191
+ this.spaces(true);
192
+ if (this.i === this.text.length)
193
+ break;
194
+ if (this.peek() === "[") {
195
+ this.i++;
196
+ const array = this.peek() === "[";
197
+ if (array)
198
+ this.i++;
199
+ section = this.keys();
200
+ if (this.peek() !== "]")
201
+ this.fail();
202
+ this.i++;
203
+ if (array) {
204
+ if (this.peek() !== "]")
205
+ this.fail();
206
+ this.i++;
207
+ }
208
+ scope = [...section];
209
+ for (let n = 1; n <= section.length; n++) {
210
+ const id = JSON.stringify(section.slice(0, n));
211
+ if (n === section.length && array) {
212
+ if (!arrays.has(id) && (dotted.has(JSON.stringify(scope)) || tables.has(JSON.stringify(scope)) || values.some(k => same(scope.slice(0, k.length), k))))
213
+ this.fail();
214
+ arrays.set(id, (arrays.get(id) ?? 0) + 1);
215
+ }
216
+ if (arrays.has(id))
217
+ scope[n - 1] += `\u0000${arrays.get(id)}`;
218
+ }
219
+ const id = JSON.stringify(scope);
220
+ if (tables.has(id) || dotted.has(id) || values.some(k => same(scope.slice(0, k.length), k)))
221
+ this.fail();
222
+ tables.add(id);
223
+ this.tables.push({ keys: section, insert: this.i, array: array || scope.some(k => k.includes("\u0000")) });
224
+ }
225
+ else {
226
+ const keys = this.keys();
227
+ const full = [...scope, ...keys];
228
+ if (values.some(k => same(k.slice(0, full.length), full) || same(full.slice(0, k.length), k)) || tables.has(JSON.stringify(full)))
229
+ this.fail();
230
+ values.push(full);
231
+ for (let n = scope.length + 1; n < full.length; n++)
232
+ dotted.add(JSON.stringify(full.slice(0, n)));
233
+ if (this.peek() !== "=")
234
+ this.fail();
235
+ this.i++;
236
+ this.spaces();
237
+ const start = this.i;
238
+ const value = this.value();
239
+ this.entries.push({ keys: [...section, ...keys], start, end: this.i, value });
240
+ }
241
+ this.spaces();
242
+ if (this.peek() === "#")
243
+ this.comment();
244
+ if (this.peek() === "\r")
245
+ this.i++;
246
+ if (this.i < this.text.length && this.peek() !== "\n")
247
+ this.fail();
248
+ if (this.peek() === "\n")
249
+ this.i++;
250
+ const last = this.tables.at(-1);
251
+ if (last)
252
+ last.insert = this.i;
253
+ }
254
+ return this;
255
+ }
256
+ }
257
+ export function parseToml(text) { return new Parser(text).parse(); }
258
+ export function tomlValue(text, keys) {
259
+ const parsed = parseToml(text);
260
+ const direct = parsed.entries.find(e => same(e.keys, keys));
261
+ if (direct !== undefined)
262
+ return direct.value;
263
+ for (const entry of parsed.entries) {
264
+ if (entry.keys.length >= keys.length || !same(entry.keys, keys.slice(0, entry.keys.length)))
265
+ continue;
266
+ let value = entry.value;
267
+ for (const key of keys.slice(entry.keys.length)) {
268
+ const table = inlineTable(value);
269
+ value = table?.[JSON.stringify([key])];
270
+ if (value === undefined)
271
+ break;
272
+ }
273
+ if (value !== undefined)
274
+ return value;
275
+ }
276
+ return undefined;
277
+ }
278
+ function inlineTable(value) {
279
+ if (typeof value !== "object" || value === null || Array.isArray(value))
280
+ return null;
281
+ return Object.keys(value).every(key => {
282
+ try {
283
+ const decoded = JSON.parse(key);
284
+ return Array.isArray(decoded) && decoded.every(part => typeof part === "string");
285
+ }
286
+ catch {
287
+ return false;
288
+ }
289
+ }) ? value : null;
290
+ }
291
+ function tomlKey(key) {
292
+ return /^[A-Za-z0-9_-]+$/u.test(key) ? key : JSON.stringify(key);
293
+ }
294
+ function serializeTomlValue(value) {
295
+ if (typeof value === "string")
296
+ return JSON.stringify(value);
297
+ if (typeof value === "number")
298
+ return Number.isFinite(value) ? String(value) : "nan";
299
+ if (typeof value === "boolean")
300
+ return String(value);
301
+ if (value === null)
302
+ return "nan";
303
+ if (Array.isArray(value))
304
+ return `[${value.map(serializeTomlValue).join(", ")}]`;
305
+ const entries = Object.entries(value).map(([encoded, child]) => {
306
+ const decoded = JSON.parse(encoded);
307
+ return `${decoded.map(tomlKey).join(".")} = ${serializeTomlValue(child)}`;
308
+ });
309
+ return `{${entries.join(", ")}}`;
310
+ }
311
+ /** Serialize only changed scalar values, then parse the entire candidate. */
312
+ export function editToml(text, table, settings) {
313
+ const parsed = parseToml(text);
314
+ if (parsed.tables.some(t => t.array && same(t.keys.slice(0, table.length), table)))
315
+ throw new Error("Invalid TOML");
316
+ const edits = [];
317
+ const added = [];
318
+ const inlineParent = parsed.entries.find(e => same(e.keys, table) && inlineTable(e.value) !== null);
319
+ if (inlineParent !== undefined) {
320
+ const updated = { ...(inlineTable(inlineParent.value) ?? {}) };
321
+ for (const [key, value] of Object.entries(settings))
322
+ updated[JSON.stringify([key])] = value;
323
+ edits.push({ start: inlineParent.start, end: inlineParent.end, text: serializeTomlValue(updated) });
324
+ if (!text.split(/\r?\n/).some(line => line.trim() === "# openlimiter managed")) {
325
+ edits.push({ start: text.length, end: text.length, text: `${text.endsWith("\n") ? "" : "\n"}# openlimiter managed\n` });
326
+ }
327
+ let result = text;
328
+ for (const edit of edits.sort((a, b) => b.start - a.start))
329
+ result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
330
+ parseToml(result);
331
+ return result;
332
+ }
333
+ for (const [key, value] of Object.entries(settings)) {
334
+ const entry = parsed.entries.find(e => same(e.keys, [...table, key]));
335
+ const serialized = serializeTomlValue(value);
336
+ if (entry)
337
+ edits.push({ start: entry.start, end: entry.end, text: serialized });
338
+ else
339
+ added.push(`${key} = ${serialized}`);
340
+ }
341
+ const existingTable = parsed.tables.find(t => same(t.keys, table));
342
+ const dottedRepresentation = existingTable === undefined && parsed.entries.some(entry => entry.keys.length > table.length && same(entry.keys.slice(0, table.length), table));
343
+ const addedContent = dottedRepresentation
344
+ ? added.map(line => `${table.join(".")}.${line}`)
345
+ : added;
346
+ const insertion = existingTable?.insert ?? text.length;
347
+ const content = existingTable ? added : dottedRepresentation ? addedContent : [`[${table.join(".")}]`, ...added];
348
+ const hasManagedMarker = text.split(/\r?\n/).some(line => line.trim() === "# openlimiter managed");
349
+ if (!hasManagedMarker)
350
+ edits.push({ start: insertion, end: insertion, text: `\n# openlimiter managed\n${content.join("\n")}\n` });
351
+ let result = text;
352
+ for (const edit of edits.sort((a, b) => b.start - a.start))
353
+ result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
354
+ parseToml(result);
355
+ return result;
356
+ }
357
+ //# sourceMappingURL=terminal-toml.js.map