@warlock.js/ai-cli 0.0.0-stage → 5.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/LICENSE +21 -0
- package/README.md +69 -2
- package/cjs/index.cjs +4576 -0
- package/cjs/index.cjs.map +1 -0
- package/esm/adapters/aider.d.mts +41 -0
- package/esm/adapters/aider.d.mts.map +1 -0
- package/esm/adapters/aider.mjs +294 -0
- package/esm/adapters/aider.mjs.map +1 -0
- package/esm/adapters/amp.d.mts +33 -0
- package/esm/adapters/amp.d.mts.map +1 -0
- package/esm/adapters/amp.mjs +119 -0
- package/esm/adapters/amp.mjs.map +1 -0
- package/esm/adapters/antigravity.d.mts +37 -0
- package/esm/adapters/antigravity.d.mts.map +1 -0
- package/esm/adapters/antigravity.mjs +235 -0
- package/esm/adapters/antigravity.mjs.map +1 -0
- package/esm/adapters/claude-code.d.mts +30 -0
- package/esm/adapters/claude-code.d.mts.map +1 -0
- package/esm/adapters/claude-code.mjs +121 -0
- package/esm/adapters/claude-code.mjs.map +1 -0
- package/esm/adapters/claude-stream.d.mts +32 -0
- package/esm/adapters/claude-stream.d.mts.map +1 -0
- package/esm/adapters/claude-stream.mjs +140 -0
- package/esm/adapters/claude-stream.mjs.map +1 -0
- package/esm/adapters/codex.d.mts +37 -0
- package/esm/adapters/codex.d.mts.map +1 -0
- package/esm/adapters/codex.mjs +320 -0
- package/esm/adapters/codex.mjs.map +1 -0
- package/esm/adapters/copilot.d.mts +35 -0
- package/esm/adapters/copilot.d.mts.map +1 -0
- package/esm/adapters/copilot.mjs +244 -0
- package/esm/adapters/copilot.mjs.map +1 -0
- package/esm/adapters/cursor.d.mts +35 -0
- package/esm/adapters/cursor.d.mts.map +1 -0
- package/esm/adapters/cursor.mjs +203 -0
- package/esm/adapters/cursor.mjs.map +1 -0
- package/esm/adapters/droid.d.mts +32 -0
- package/esm/adapters/droid.d.mts.map +1 -0
- package/esm/adapters/droid.mjs +183 -0
- package/esm/adapters/droid.mjs.map +1 -0
- package/esm/adapters/grok.d.mts +32 -0
- package/esm/adapters/grok.d.mts.map +1 -0
- package/esm/adapters/grok.mjs +199 -0
- package/esm/adapters/grok.mjs.map +1 -0
- package/esm/adapters/index.d.mts +16 -0
- package/esm/adapters/index.mjs +18 -0
- package/esm/adapters/kimi.d.mts +34 -0
- package/esm/adapters/kimi.d.mts.map +1 -0
- package/esm/adapters/kimi.mjs +162 -0
- package/esm/adapters/kimi.mjs.map +1 -0
- package/esm/adapters/mistral-vibe.d.mts +32 -0
- package/esm/adapters/mistral-vibe.d.mts.map +1 -0
- package/esm/adapters/mistral-vibe.mjs +252 -0
- package/esm/adapters/mistral-vibe.mjs.map +1 -0
- package/esm/adapters/opencode.d.mts +36 -0
- package/esm/adapters/opencode.d.mts.map +1 -0
- package/esm/adapters/opencode.mjs +219 -0
- package/esm/adapters/opencode.mjs.map +1 -0
- package/esm/adapters/qwen-code.d.mts +30 -0
- package/esm/adapters/qwen-code.d.mts.map +1 -0
- package/esm/adapters/qwen-code.mjs +94 -0
- package/esm/adapters/qwen-code.mjs.map +1 -0
- package/esm/adapters/reasonix.d.mts +31 -0
- package/esm/adapters/reasonix.d.mts.map +1 -0
- package/esm/adapters/reasonix.mjs +250 -0
- package/esm/adapters/reasonix.mjs.map +1 -0
- package/esm/adapters/shared.d.mts +78 -0
- package/esm/adapters/shared.d.mts.map +1 -0
- package/esm/adapters/shared.mjs +161 -0
- package/esm/adapters/shared.mjs.map +1 -0
- package/esm/cli-agent.d.mts +40 -0
- package/esm/cli-agent.d.mts.map +1 -0
- package/esm/cli-agent.mjs +207 -0
- package/esm/cli-agent.mjs.map +1 -0
- package/esm/cli.d.mts +53 -0
- package/esm/cli.d.mts.map +1 -0
- package/esm/cli.mjs +61 -0
- package/esm/cli.mjs.map +1 -0
- package/esm/contracts/adapter.contract.d.mts +154 -0
- package/esm/contracts/adapter.contract.d.mts.map +1 -0
- package/esm/contracts/events.type.d.mts +111 -0
- package/esm/contracts/events.type.d.mts.map +1 -0
- package/esm/contracts/index.d.mts +4 -0
- package/esm/contracts/mcp.type.d.mts +29 -0
- package/esm/contracts/mcp.type.d.mts.map +1 -0
- package/esm/contracts/options.type.d.mts +87 -0
- package/esm/contracts/options.type.d.mts.map +1 -0
- package/esm/errors.d.mts +46 -0
- package/esm/errors.d.mts.map +1 -0
- package/esm/errors.mjs +32 -0
- package/esm/errors.mjs.map +1 -0
- package/esm/index.d.mts +31 -0
- package/esm/index.mjs +28 -0
- package/esm/model/cli-model.d.mts +48 -0
- package/esm/model/cli-model.d.mts.map +1 -0
- package/esm/model/cli-model.mjs +133 -0
- package/esm/model/cli-model.mjs.map +1 -0
- package/esm/probe/probe.d.mts +18 -0
- package/esm/probe/probe.d.mts.map +1 -0
- package/esm/probe/probe.mjs +148 -0
- package/esm/probe/probe.mjs.map +1 -0
- package/esm/session/aggregate.mjs +86 -0
- package/esm/session/aggregate.mjs.map +1 -0
- package/esm/session/environment.mjs +71 -0
- package/esm/session/environment.mjs.map +1 -0
- package/esm/session/run-directory.mjs +74 -0
- package/esm/session/run-directory.mjs.map +1 -0
- package/esm/session/session.mjs +188 -0
- package/esm/session/session.mjs.map +1 -0
- package/esm/spawn/invocation.d.mts +35 -0
- package/esm/spawn/invocation.d.mts.map +1 -0
- package/esm/spawn/invocation.mjs +76 -0
- package/esm/spawn/invocation.mjs.map +1 -0
- package/esm/spawn/process-tree.mjs +57 -0
- package/esm/spawn/process-tree.mjs.map +1 -0
- package/esm/spawn/resolve-command.d.mts +73 -0
- package/esm/spawn/resolve-command.d.mts.map +1 -0
- package/esm/spawn/resolve-command.mjs +109 -0
- package/esm/spawn/resolve-command.mjs.map +1 -0
- package/esm/stream/event-log.mjs +52 -0
- package/esm/stream/event-log.mjs.map +1 -0
- package/esm/stream/json-lines.d.mts +33 -0
- package/esm/stream/json-lines.d.mts.map +1 -0
- package/esm/stream/json-lines.mjs +65 -0
- package/esm/stream/json-lines.mjs.map +1 -0
- package/esm/stream/line-splitter.mjs +53 -0
- package/esm/stream/line-splitter.mjs.map +1 -0
- package/esm/utils/toml.d.mts +22 -0
- package/esm/utils/toml.d.mts.map +1 -0
- package/esm/utils/toml.mjs +53 -0
- package/esm/utils/toml.mjs.map +1 -0
- package/llms-full.txt +373 -0
- package/llms.txt +10 -0
- package/package.json +39 -4
- package/skills/README.md +13 -0
- package/skills/index.md +22 -0
- package/skills/run-cli-agents/SKILL.md +186 -0
- package/skills/write-a-cli-adapter/SKILL.md +173 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region ../../packages/ai-cli/src/stream/event-log.ts
|
|
2
|
+
/**
|
|
3
|
+
* An append-only event log that any number of async iterators can read.
|
|
4
|
+
* Each iterator starts at the first event and ends once the log is closed
|
|
5
|
+
* and drained, so a late consumer still sees the whole session.
|
|
6
|
+
*/
|
|
7
|
+
var EventLog = class {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.items = [];
|
|
10
|
+
this.closed = false;
|
|
11
|
+
this.waiters = [];
|
|
12
|
+
}
|
|
13
|
+
push(item) {
|
|
14
|
+
if (this.closed) return;
|
|
15
|
+
this.items.push(item);
|
|
16
|
+
this.wake();
|
|
17
|
+
}
|
|
18
|
+
close() {
|
|
19
|
+
this.closed = true;
|
|
20
|
+
this.wake();
|
|
21
|
+
}
|
|
22
|
+
get size() {
|
|
23
|
+
return this.items.length;
|
|
24
|
+
}
|
|
25
|
+
[Symbol.asyncIterator]() {
|
|
26
|
+
let index = 0;
|
|
27
|
+
return { next: async () => {
|
|
28
|
+
while (index >= this.items.length && !this.closed) await new Promise((resolve) => this.waiters.push(resolve));
|
|
29
|
+
if (index < this.items.length) {
|
|
30
|
+
const value = this.items[index];
|
|
31
|
+
index += 1;
|
|
32
|
+
return {
|
|
33
|
+
value,
|
|
34
|
+
done: false
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
value: void 0,
|
|
39
|
+
done: true
|
|
40
|
+
};
|
|
41
|
+
} };
|
|
42
|
+
}
|
|
43
|
+
wake() {
|
|
44
|
+
const waiters = this.waiters;
|
|
45
|
+
this.waiters = [];
|
|
46
|
+
for (const waiter of waiters) waiter();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
export { EventLog };
|
|
52
|
+
//# sourceMappingURL=event-log.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-log.mjs","names":[],"sources":["../../../../../../../../packages/ai-cli/src/stream/event-log.ts"],"sourcesContent":["/**\n * An append-only event log that any number of async iterators can read.\n * Each iterator starts at the first event and ends once the log is closed\n * and drained, so a late consumer still sees the whole session.\n */\nexport class EventLog<T> implements AsyncIterable<T> {\n private readonly items: T[] = [];\n private closed = false;\n private waiters: Array<() => void> = [];\n\n public push(item: T): void {\n if (this.closed) {\n return;\n }\n\n this.items.push(item);\n this.wake();\n }\n\n public close(): void {\n this.closed = true;\n this.wake();\n }\n\n public get size(): number {\n return this.items.length;\n }\n\n public [Symbol.asyncIterator](): AsyncIterator<T> {\n let index = 0;\n\n return {\n next: async (): Promise<IteratorResult<T>> => {\n while (index >= this.items.length && !this.closed) {\n await new Promise<void>((resolve) => this.waiters.push(resolve));\n }\n\n if (index < this.items.length) {\n const value = this.items[index] as T;\n\n index += 1;\n\n return { value, done: false };\n }\n\n return { value: undefined, done: true };\n },\n };\n }\n\n private wake(): void {\n const waiters = this.waiters;\n\n this.waiters = [];\n\n for (const waiter of waiters) {\n waiter();\n }\n }\n}\n"],"mappings":";;;;;;AAKA,IAAa,WAAb,MAAqD;;eACrB,CAAC;gBACd;iBACoB,CAAC;;CAEtC,AAAO,KAAK,MAAe;EACzB,IAAI,KAAK,QACP;EAGF,KAAK,MAAM,KAAK,IAAI;EACpB,KAAK,KAAK;CACZ;CAEA,AAAO,QAAc;EACnB,KAAK,SAAS;EACd,KAAK,KAAK;CACZ;CAEA,IAAW,OAAe;EACxB,OAAO,KAAK,MAAM;CACpB;CAEA,CAAQ,OAAO,iBAAmC;EAChD,IAAI,QAAQ;EAEZ,OAAO,EACL,MAAM,YAAwC;GAC5C,OAAO,SAAS,KAAK,MAAM,UAAU,CAAC,KAAK,QACzC,MAAM,IAAI,SAAe,YAAY,KAAK,QAAQ,KAAK,OAAO,CAAC;GAGjE,IAAI,QAAQ,KAAK,MAAM,QAAQ;IAC7B,MAAM,QAAQ,KAAK,MAAM;IAEzB,SAAS;IAET,OAAO;KAAE;KAAO,MAAM;IAAM;GAC9B;GAEA,OAAO;IAAE,OAAO;IAAW,MAAM;GAAK;EACxC,EACF;CACF;CAEA,AAAQ,OAAa;EACnB,MAAM,UAAU,KAAK;EAErB,KAAK,UAAU,CAAC;EAEhB,KAAK,MAAM,UAAU,SACnB,OAAO;CAEX;AACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { CliParsedEvent } from "../contracts/events.type.mjs";
|
|
2
|
+
import { CliStreamParser } from "../contracts/adapter.contract.mjs";
|
|
3
|
+
//#region ../../packages/ai-cli/src/stream/json-lines.d.ts
|
|
4
|
+
/** A plain JSON object. */
|
|
5
|
+
type JsonRecord = Record<string, unknown>;
|
|
6
|
+
/** `value` as a JSON object, or `undefined`. */
|
|
7
|
+
declare function asRecord(value: unknown): JsonRecord | undefined;
|
|
8
|
+
/** `value` as an array, or an empty array. */
|
|
9
|
+
declare function asArray(value: unknown): unknown[];
|
|
10
|
+
/** A string field, or `undefined`. */
|
|
11
|
+
declare function stringField(record: JsonRecord | undefined, key: string): string | undefined;
|
|
12
|
+
/** A finite number field, or `undefined`. */
|
|
13
|
+
declare function numberField(record: JsonRecord | undefined, key: string): number | undefined;
|
|
14
|
+
/** A nested object field, or `undefined`. */
|
|
15
|
+
declare function recordField(record: JsonRecord | undefined, key: string): JsonRecord | undefined;
|
|
16
|
+
/** Tool output as text: strings verbatim, text-block arrays joined, anything else as JSON. */
|
|
17
|
+
declare function outputText(value: unknown): string;
|
|
18
|
+
/** Parse one line as a JSON object; anything else (banners, blank lines) is `undefined`. */
|
|
19
|
+
declare function parseJsonLine(line: string): JsonRecord | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Build a parser for a JSONL/NDJSON stream. Non-JSON lines (progress
|
|
22
|
+
* banners, warnings) are skipped; each JSON object goes to `onRecord`.
|
|
23
|
+
* `onEnd` may flush buffered state when stdout closes.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const parser = jsonLinesParser((record) =>
|
|
27
|
+
* record.type === "text" ? [{ type: "message", text: String(record.text), delta: false }] : [],
|
|
28
|
+
* );
|
|
29
|
+
*/
|
|
30
|
+
declare function jsonLinesParser(onRecord: (record: JsonRecord) => CliParsedEvent[], onEnd?: () => CliParsedEvent[]): CliStreamParser;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { JsonRecord, asArray, asRecord, jsonLinesParser, numberField, outputText, parseJsonLine, recordField, stringField };
|
|
33
|
+
//# sourceMappingURL=json-lines.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-lines.d.mts","names":[],"sources":["../../../../../../../../packages/ai-cli/src/stream/json-lines.ts"],"mappings":";;;;KAGY,UAAA,GAAa,MAAM;;iBAGf,QAAA,CAAS,KAAA,YAAiB,UAAU;AAHpD;AAAA,iBAUgB,OAAA,CAAQ,KAAc;;iBAKtB,WAAA,CAAY,MAAA,EAAQ,UAAU,cAAc,GAAA;AAf7B;AAAA,iBAsBf,WAAA,CAAY,MAAA,EAAQ,UAAU,cAAc,GAAA;;iBAO5C,WAAA,CAAY,MAAA,EAAQ,UAAA,cAAwB,GAAA,WAAc,UAAU;;iBAKpE,UAAA,CAAW,KAAc;AAxBzC;AAAA,iBAgDgB,aAAA,CAAc,IAAA,WAAe,UAAU;;;AAhDjB;AAKtC;;;;;;;iBAmEgB,eAAA,CACd,QAAA,GAAW,MAAA,EAAQ,UAAA,KAAe,cAAA,IAClC,KAAA,SAAa,cAAA,KACZ,eAAA"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
//#region ../../packages/ai-cli/src/stream/json-lines.ts
|
|
2
|
+
/** `value` as a JSON object, or `undefined`. */
|
|
3
|
+
function asRecord(value) {
|
|
4
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
5
|
+
}
|
|
6
|
+
/** `value` as an array, or an empty array. */
|
|
7
|
+
function asArray(value) {
|
|
8
|
+
return Array.isArray(value) ? value : [];
|
|
9
|
+
}
|
|
10
|
+
/** A string field, or `undefined`. */
|
|
11
|
+
function stringField(record, key) {
|
|
12
|
+
const value = record?.[key];
|
|
13
|
+
return typeof value === "string" ? value : void 0;
|
|
14
|
+
}
|
|
15
|
+
/** A finite number field, or `undefined`. */
|
|
16
|
+
function numberField(record, key) {
|
|
17
|
+
const value = record?.[key];
|
|
18
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
19
|
+
}
|
|
20
|
+
/** A nested object field, or `undefined`. */
|
|
21
|
+
function recordField(record, key) {
|
|
22
|
+
return asRecord(record?.[key]);
|
|
23
|
+
}
|
|
24
|
+
/** Tool output as text: strings verbatim, text-block arrays joined, anything else as JSON. */
|
|
25
|
+
function outputText(value) {
|
|
26
|
+
if (typeof value === "string") return value;
|
|
27
|
+
if (value === void 0 || value === null) return "";
|
|
28
|
+
if (Array.isArray(value)) return value.map((item) => {
|
|
29
|
+
return stringField(asRecord(item), "text") ?? (typeof item === "string" ? item : JSON.stringify(item));
|
|
30
|
+
}).join("\n");
|
|
31
|
+
return JSON.stringify(value);
|
|
32
|
+
}
|
|
33
|
+
/** Parse one line as a JSON object; anything else (banners, blank lines) is `undefined`. */
|
|
34
|
+
function parseJsonLine(line) {
|
|
35
|
+
const trimmed = line.trim();
|
|
36
|
+
if (!trimmed.startsWith("{")) return;
|
|
37
|
+
try {
|
|
38
|
+
return asRecord(JSON.parse(trimmed));
|
|
39
|
+
} catch {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build a parser for a JSONL/NDJSON stream. Non-JSON lines (progress
|
|
45
|
+
* banners, warnings) are skipped; each JSON object goes to `onRecord`.
|
|
46
|
+
* `onEnd` may flush buffered state when stdout closes.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* const parser = jsonLinesParser((record) =>
|
|
50
|
+
* record.type === "text" ? [{ type: "message", text: String(record.text), delta: false }] : [],
|
|
51
|
+
* );
|
|
52
|
+
*/
|
|
53
|
+
function jsonLinesParser(onRecord, onEnd = () => []) {
|
|
54
|
+
return {
|
|
55
|
+
line(line) {
|
|
56
|
+
const record = parseJsonLine(line);
|
|
57
|
+
return record === void 0 ? [] : onRecord(record);
|
|
58
|
+
},
|
|
59
|
+
end: onEnd
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
export { asArray, asRecord, jsonLinesParser, numberField, outputText, parseJsonLine, recordField, stringField };
|
|
65
|
+
//# sourceMappingURL=json-lines.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-lines.mjs","names":[],"sources":["../../../../../../../../packages/ai-cli/src/stream/json-lines.ts"],"sourcesContent":["import type { CliParsedEvent, CliStreamParser } from \"../contracts\";\n\n/** A plain JSON object. */\nexport type JsonRecord = Record<string, unknown>;\n\n/** `value` as a JSON object, or `undefined`. */\nexport function asRecord(value: unknown): JsonRecord | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as JsonRecord)\n : undefined;\n}\n\n/** `value` as an array, or an empty array. */\nexport function asArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\n/** A string field, or `undefined`. */\nexport function stringField(record: JsonRecord | undefined, key: string): string | undefined {\n const value = record?.[key];\n\n return typeof value === \"string\" ? value : undefined;\n}\n\n/** A finite number field, or `undefined`. */\nexport function numberField(record: JsonRecord | undefined, key: string): number | undefined {\n const value = record?.[key];\n\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\n/** A nested object field, or `undefined`. */\nexport function recordField(record: JsonRecord | undefined, key: string): JsonRecord | undefined {\n return asRecord(record?.[key]);\n}\n\n/** Tool output as text: strings verbatim, text-block arrays joined, anything else as JSON. */\nexport function outputText(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (value === undefined || value === null) {\n return \"\";\n }\n\n if (Array.isArray(value)) {\n const texts = value.map((item) => {\n const block = asRecord(item);\n const text = stringField(block, \"text\");\n\n return text ?? (typeof item === \"string\" ? item : JSON.stringify(item));\n });\n\n return texts.join(\"\\n\");\n }\n\n return JSON.stringify(value);\n}\n\n/** Parse one line as a JSON object; anything else (banners, blank lines) is `undefined`. */\nexport function parseJsonLine(line: string): JsonRecord | undefined {\n const trimmed = line.trim();\n\n if (!trimmed.startsWith(\"{\")) {\n return undefined;\n }\n\n try {\n return asRecord(JSON.parse(trimmed));\n } catch {\n return undefined;\n }\n}\n\n/**\n * Build a parser for a JSONL/NDJSON stream. Non-JSON lines (progress\n * banners, warnings) are skipped; each JSON object goes to `onRecord`.\n * `onEnd` may flush buffered state when stdout closes.\n *\n * @example\n * const parser = jsonLinesParser((record) =>\n * record.type === \"text\" ? [{ type: \"message\", text: String(record.text), delta: false }] : [],\n * );\n */\nexport function jsonLinesParser(\n onRecord: (record: JsonRecord) => CliParsedEvent[],\n onEnd: () => CliParsedEvent[] = () => [],\n): CliStreamParser {\n return {\n line(line: string): CliParsedEvent[] {\n const record = parseJsonLine(line);\n\n return record === undefined ? [] : onRecord(record);\n },\n end: onEnd,\n };\n}\n"],"mappings":";;AAMA,SAAgB,SAAS,OAAwC;CAC/D,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,IACrE,QACD;AACN;;AAGA,SAAgB,QAAQ,OAA2B;CACjD,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AACzC;;AAGA,SAAgB,YAAY,QAAgC,KAAiC;CAC3F,MAAM,QAAQ,SAAS;CAEvB,OAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;;AAGA,SAAgB,YAAY,QAAgC,KAAiC;CAC3F,MAAM,QAAQ,SAAS;CAEvB,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;;AAGA,SAAgB,YAAY,QAAgC,KAAqC;CAC/F,OAAO,SAAS,SAAS,IAAI;AAC/B;;AAGA,SAAgB,WAAW,OAAwB;CACjD,IAAI,OAAO,UAAU,UACnB,OAAO;CAGT,IAAI,UAAU,UAAa,UAAU,MACnC,OAAO;CAGT,IAAI,MAAM,QAAQ,KAAK,GAQrB,OAPc,MAAM,KAAK,SAAS;EAIhC,OAFa,YADC,SAAS,IACM,GAAG,MAEtB,MAAM,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,IAAI;CACvE,CAEW,CAAC,CAAC,KAAK,IAAI;CAGxB,OAAO,KAAK,UAAU,KAAK;AAC7B;;AAGA,SAAgB,cAAc,MAAsC;CAClE,MAAM,UAAU,KAAK,KAAK;CAE1B,IAAI,CAAC,QAAQ,WAAW,GAAG,GACzB;CAGF,IAAI;EACF,OAAO,SAAS,KAAK,MAAM,OAAO,CAAC;CACrC,QAAQ;EACN;CACF;AACF;;;;;;;;;;;AAYA,SAAgB,gBACd,UACA,cAAsC,CAAC,GACtB;CACjB,OAAO;EACL,KAAK,MAAgC;GACnC,MAAM,SAAS,cAAc,IAAI;GAEjC,OAAO,WAAW,SAAY,CAAC,IAAI,SAAS,MAAM;EACpD;EACA,KAAK;CACP;AACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { StringDecoder } from "node:string_decoder";
|
|
2
|
+
|
|
3
|
+
//#region ../../packages/ai-cli/src/stream/line-splitter.ts
|
|
4
|
+
/** Longest line kept in memory; a longer one is dropped (reported via `onOverflow`). */
|
|
5
|
+
const MAX_LINE_BYTES = 32 * 1024 * 1024;
|
|
6
|
+
/**
|
|
7
|
+
* Split a byte stream into lines. Multi-byte UTF-8 characters split across
|
|
8
|
+
* chunks are decoded correctly, `\r\n` and `\n` both end a line, and a final
|
|
9
|
+
* line without a newline is flushed by `end()`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const splitter = createLineSplitter((line) => console.log(line));
|
|
13
|
+
* splitter.write(Buffer.from('{"a":1}\n{"b"'));
|
|
14
|
+
* splitter.write(Buffer.from(":2}\n"));
|
|
15
|
+
* splitter.end();
|
|
16
|
+
*/
|
|
17
|
+
function createLineSplitter(onLine, onOverflow = () => void 0) {
|
|
18
|
+
const decoder = new StringDecoder("utf8");
|
|
19
|
+
let pending = "";
|
|
20
|
+
let overflowed = false;
|
|
21
|
+
const consume = (text) => {
|
|
22
|
+
pending += text;
|
|
23
|
+
let newline = pending.indexOf("\n");
|
|
24
|
+
while (newline !== -1) {
|
|
25
|
+
const line = pending.slice(0, newline).replace(/\r$/, "");
|
|
26
|
+
pending = pending.slice(newline + 1);
|
|
27
|
+
if (overflowed) overflowed = false;
|
|
28
|
+
else onLine(line);
|
|
29
|
+
newline = pending.indexOf("\n");
|
|
30
|
+
}
|
|
31
|
+
if (pending.length > 33554432) {
|
|
32
|
+
pending = "";
|
|
33
|
+
if (!overflowed) {
|
|
34
|
+
overflowed = true;
|
|
35
|
+
onOverflow();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
return {
|
|
40
|
+
write(chunk) {
|
|
41
|
+
consume(decoder.write(chunk));
|
|
42
|
+
},
|
|
43
|
+
end() {
|
|
44
|
+
consume(decoder.end());
|
|
45
|
+
if (pending.length > 0 && !overflowed) onLine(pending.replace(/\r$/, ""));
|
|
46
|
+
pending = "";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { createLineSplitter };
|
|
53
|
+
//# sourceMappingURL=line-splitter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line-splitter.mjs","names":[],"sources":["../../../../../../../../packages/ai-cli/src/stream/line-splitter.ts"],"sourcesContent":["import { StringDecoder } from \"node:string_decoder\";\n\n/** Longest line kept in memory; a longer one is dropped (reported via `onOverflow`). */\nexport const MAX_LINE_BYTES = 32 * 1024 * 1024;\n\n/**\n * Split a byte stream into lines. Multi-byte UTF-8 characters split across\n * chunks are decoded correctly, `\\r\\n` and `\\n` both end a line, and a final\n * line without a newline is flushed by `end()`.\n *\n * @example\n * const splitter = createLineSplitter((line) => console.log(line));\n * splitter.write(Buffer.from('{\"a\":1}\\n{\"b\"'));\n * splitter.write(Buffer.from(\":2}\\n\"));\n * splitter.end();\n */\nexport function createLineSplitter(\n onLine: (line: string) => void,\n onOverflow: () => void = () => undefined,\n): { write(chunk: Buffer): void; end(): void } {\n const decoder = new StringDecoder(\"utf8\");\n let pending = \"\";\n let overflowed = false;\n\n const consume = (text: string): void => {\n pending += text;\n\n let newline = pending.indexOf(\"\\n\");\n\n while (newline !== -1) {\n const line = pending.slice(0, newline).replace(/\\r$/, \"\");\n\n pending = pending.slice(newline + 1);\n\n if (overflowed) {\n overflowed = false;\n } else {\n onLine(line);\n }\n\n newline = pending.indexOf(\"\\n\");\n }\n\n if (pending.length > MAX_LINE_BYTES) {\n pending = \"\";\n\n if (!overflowed) {\n overflowed = true;\n onOverflow();\n }\n }\n };\n\n return {\n write(chunk: Buffer): void {\n consume(decoder.write(chunk));\n },\n end(): void {\n consume(decoder.end());\n\n if (pending.length > 0 && !overflowed) {\n onLine(pending.replace(/\\r$/, \"\"));\n }\n\n pending = \"\";\n },\n };\n}\n"],"mappings":";;;;AAGA,MAAa,iBAAiB,KAAK,OAAO;;;;;;;;;;;;AAa1C,SAAgB,mBACd,QACA,mBAA+B,QACc;CAC7C,MAAM,UAAU,IAAI,cAAc,MAAM;CACxC,IAAI,UAAU;CACd,IAAI,aAAa;CAEjB,MAAM,WAAW,SAAuB;EACtC,WAAW;EAEX,IAAI,UAAU,QAAQ,QAAQ,IAAI;EAElC,OAAO,YAAY,IAAI;GACrB,MAAM,OAAO,QAAQ,MAAM,GAAG,OAAO,CAAC,CAAC,QAAQ,OAAO,EAAE;GAExD,UAAU,QAAQ,MAAM,UAAU,CAAC;GAEnC,IAAI,YACF,aAAa;QAEb,OAAO,IAAI;GAGb,UAAU,QAAQ,QAAQ,IAAI;EAChC;EAEA,IAAI,QAAQ,mBAAyB;GACnC,UAAU;GAEV,IAAI,CAAC,YAAY;IACf,aAAa;IACb,WAAW;GACb;EACF;CACF;CAEA,OAAO;EACL,MAAM,OAAqB;GACzB,QAAQ,QAAQ,MAAM,KAAK,CAAC;EAC9B;EACA,MAAY;GACV,QAAQ,QAAQ,IAAI,CAAC;GAErB,IAAI,QAAQ,SAAS,KAAK,CAAC,YACzB,OAAO,QAAQ,QAAQ,OAAO,EAAE,CAAC;GAGnC,UAAU;EACZ;CACF;AACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region ../../packages/ai-cli/src/utils/toml.d.ts
|
|
2
|
+
/** A TOML value this writer supports. */
|
|
3
|
+
type TomlValue = string | number | boolean | TomlValue[] | TomlTable;
|
|
4
|
+
/** A TOML table. */
|
|
5
|
+
type TomlTable = {
|
|
6
|
+
[key: string]: TomlValue | undefined;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Serialize a table to TOML: scalars and arrays first, then each nested
|
|
10
|
+
* table as a `[dotted.header]` section. Enough for the CLI config files
|
|
11
|
+
* this package writes (Codex and Mistral Vibe MCP sections).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* toToml({ mcp_servers: { docs: { command: "npx", args: ["-y", "docs-mcp"] } } });
|
|
15
|
+
* // [mcp_servers.docs]
|
|
16
|
+
* // command = "npx"
|
|
17
|
+
* // args = ["-y", "docs-mcp"]
|
|
18
|
+
*/
|
|
19
|
+
declare function toToml(table: TomlTable, prefix?: string[]): string;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { TomlTable, TomlValue, toToml };
|
|
22
|
+
//# sourceMappingURL=toml.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toml.d.mts","names":[],"sources":["../../../../../../../../packages/ai-cli/src/utils/toml.ts"],"mappings":";;KACY,SAAA,+BAAwC,SAAA,KAAc,SAAS;;KAG/D,SAAA;EAAA,CAAe,GAAA,WAAc,SAAS;AAAA;;;AAAA;AAmDlD;;;;;;;;iBAAgB,MAAA,CAAO,KAAA,EAAO,SAAS,EAAE,MAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region ../../packages/ai-cli/src/utils/toml.ts
|
|
2
|
+
function isTable(value) {
|
|
3
|
+
return typeof value === "object" && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
/** A bare key when possible, else a quoted one. */
|
|
6
|
+
function tomlKey(key) {
|
|
7
|
+
return /^[A-Za-z0-9_-]+$/.test(key) ? key : JSON.stringify(key);
|
|
8
|
+
}
|
|
9
|
+
/** A TOML scalar or inline value. JSON string escapes are valid TOML basic-string escapes. */
|
|
10
|
+
function inlineValue(value) {
|
|
11
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
12
|
+
if (typeof value === "number") {
|
|
13
|
+
if (!Number.isFinite(value)) throw new Error("TOML cannot encode a non-finite number");
|
|
14
|
+
return String(value);
|
|
15
|
+
}
|
|
16
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
17
|
+
if (Array.isArray(value)) return `[${value.map(inlineValue).join(", ")}]`;
|
|
18
|
+
return `{ ${Object.entries(value).filter((entry) => entry[1] !== void 0).map(([key, item]) => `${tomlKey(key)} = ${inlineValue(item)}`).join(", ")} }`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Serialize a table to TOML: scalars and arrays first, then each nested
|
|
22
|
+
* table as a `[dotted.header]` section. Enough for the CLI config files
|
|
23
|
+
* this package writes (Codex and Mistral Vibe MCP sections).
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* toToml({ mcp_servers: { docs: { command: "npx", args: ["-y", "docs-mcp"] } } });
|
|
27
|
+
* // [mcp_servers.docs]
|
|
28
|
+
* // command = "npx"
|
|
29
|
+
* // args = ["-y", "docs-mcp"]
|
|
30
|
+
*/
|
|
31
|
+
function toToml(table, prefix = []) {
|
|
32
|
+
const lines = [];
|
|
33
|
+
const nested = [];
|
|
34
|
+
for (const [key, value] of Object.entries(table)) {
|
|
35
|
+
if (value === void 0) continue;
|
|
36
|
+
if (isTable(value)) {
|
|
37
|
+
nested.push([key, value]);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
lines.push(`${tomlKey(key)} = ${inlineValue(value)}`);
|
|
41
|
+
}
|
|
42
|
+
const sections = [];
|
|
43
|
+
if (lines.length > 0) sections.push((prefix.length > 0 ? `[${prefix.map(tomlKey).join(".")}]\n` : "") + lines.join("\n"));
|
|
44
|
+
for (const [key, value] of nested) {
|
|
45
|
+
const section = toToml(value, [...prefix, key]);
|
|
46
|
+
if (section.length > 0) sections.push(section.trimEnd());
|
|
47
|
+
}
|
|
48
|
+
return sections.length > 0 ? `${sections.join("\n\n")}\n` : "";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { toToml, tomlKey };
|
|
53
|
+
//# sourceMappingURL=toml.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toml.mjs","names":[],"sources":["../../../../../../../../packages/ai-cli/src/utils/toml.ts"],"sourcesContent":["/** A TOML value this writer supports. */\nexport type TomlValue = string | number | boolean | TomlValue[] | TomlTable;\n\n/** A TOML table. */\nexport type TomlTable = { [key: string]: TomlValue | undefined };\n\nfunction isTable(value: TomlValue): value is TomlTable {\n return typeof value === \"object\" && !Array.isArray(value);\n}\n\n/** A bare key when possible, else a quoted one. */\nexport function tomlKey(key: string): string {\n return /^[A-Za-z0-9_-]+$/.test(key) ? key : JSON.stringify(key);\n}\n\n/** A TOML scalar or inline value. JSON string escapes are valid TOML basic-string escapes. */\nfunction inlineValue(value: TomlValue): string {\n if (typeof value === \"string\") {\n return JSON.stringify(value);\n }\n\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) {\n throw new Error(\"TOML cannot encode a non-finite number\");\n }\n\n return String(value);\n }\n\n if (typeof value === \"boolean\") {\n return value ? \"true\" : \"false\";\n }\n\n if (Array.isArray(value)) {\n return `[${value.map(inlineValue).join(\", \")}]`;\n }\n\n const entries = Object.entries(value).filter(\n (entry): entry is [string, TomlValue] => entry[1] !== undefined,\n );\n\n return `{ ${entries.map(([key, item]) => `${tomlKey(key)} = ${inlineValue(item)}`).join(\", \")} }`;\n}\n\n/**\n * Serialize a table to TOML: scalars and arrays first, then each nested\n * table as a `[dotted.header]` section. Enough for the CLI config files\n * this package writes (Codex and Mistral Vibe MCP sections).\n *\n * @example\n * toToml({ mcp_servers: { docs: { command: \"npx\", args: [\"-y\", \"docs-mcp\"] } } });\n * // [mcp_servers.docs]\n * // command = \"npx\"\n * // args = [\"-y\", \"docs-mcp\"]\n */\nexport function toToml(table: TomlTable, prefix: string[] = []): string {\n const lines: string[] = [];\n const nested: Array<[string, TomlTable]> = [];\n\n for (const [key, value] of Object.entries(table)) {\n if (value === undefined) {\n continue;\n }\n\n if (isTable(value)) {\n nested.push([key, value]);\n continue;\n }\n\n lines.push(`${tomlKey(key)} = ${inlineValue(value)}`);\n }\n\n const sections: string[] = [];\n\n if (lines.length > 0) {\n sections.push(\n (prefix.length > 0 ? `[${prefix.map(tomlKey).join(\".\")}]\\n` : \"\") + lines.join(\"\\n\"),\n );\n }\n\n for (const [key, value] of nested) {\n const section = toToml(value, [...prefix, key]);\n\n if (section.length > 0) {\n sections.push(section.trimEnd());\n }\n }\n\n return sections.length > 0 ? `${sections.join(\"\\n\\n\")}\\n` : \"\";\n}\n"],"mappings":";AAMA,SAAS,QAAQ,OAAsC;CACrD,OAAO,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC1D;;AAGA,SAAgB,QAAQ,KAAqB;CAC3C,OAAO,mBAAmB,KAAK,GAAG,IAAI,MAAM,KAAK,UAAU,GAAG;AAChE;;AAGA,SAAS,YAAY,OAA0B;CAC7C,IAAI,OAAO,UAAU,UACnB,OAAO,KAAK,UAAU,KAAK;CAG7B,IAAI,OAAO,UAAU,UAAU;EAC7B,IAAI,CAAC,OAAO,SAAS,KAAK,GACxB,MAAM,IAAI,MAAM,wCAAwC;EAG1D,OAAO,OAAO,KAAK;CACrB;CAEA,IAAI,OAAO,UAAU,WACnB,OAAO,QAAQ,SAAS;CAG1B,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,IAAI,MAAM,IAAI,WAAW,CAAC,CAAC,KAAK,IAAI,EAAE;CAO/C,OAAO,KAJS,OAAO,QAAQ,KAAK,CAAC,CAAC,QACnC,UAAwC,MAAM,OAAO,MAGtC,CAAC,CAAC,KAAK,CAAC,KAAK,UAAU,GAAG,QAAQ,GAAG,EAAE,KAAK,YAAY,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;AAChG;;;;;;;;;;;;AAaA,SAAgB,OAAO,OAAkB,SAAmB,CAAC,GAAW;CACtE,MAAM,QAAkB,CAAC;CACzB,MAAM,SAAqC,CAAC;CAE5C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAAG;EAChD,IAAI,UAAU,QACZ;EAGF,IAAI,QAAQ,KAAK,GAAG;GAClB,OAAO,KAAK,CAAC,KAAK,KAAK,CAAC;GACxB;EACF;EAEA,MAAM,KAAK,GAAG,QAAQ,GAAG,EAAE,KAAK,YAAY,KAAK,GAAG;CACtD;CAEA,MAAM,WAAqB,CAAC;CAE5B,IAAI,MAAM,SAAS,GACjB,SAAS,MACN,OAAO,SAAS,IAAI,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,KAAK,GAAG,EAAE,OAAO,MAAM,MAAM,KAAK,IAAI,CACrF;CAGF,KAAK,MAAM,CAAC,KAAK,UAAU,QAAQ;EACjC,MAAM,UAAU,OAAO,OAAO,CAAC,GAAG,QAAQ,GAAG,CAAC;EAE9C,IAAI,QAAQ,SAAS,GACnB,SAAS,KAAK,QAAQ,QAAQ,CAAC;CAEnC;CAEA,OAAO,SAAS,SAAS,IAAI,GAAG,SAAS,KAAK,MAAM,EAAE,MAAM;AAC9D"}
|