@moikapy/lich 0.3.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.
@@ -0,0 +1,7 @@
1
+ // src/index.ts
2
+ var LICH_VERSION = "0.3.0";
3
+
4
+ export {
5
+ LICH_VERSION
6
+ };
7
+ //# sourceMappingURL=chunk-ZVK3MUPC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Public surface of the lich agent harness. Pure re-exports only.\n */\nexport const LICH_VERSION = \"0.3.0\";\n\nexport { Agent, create_agent, run_agent, create_agent_with_plugins } from \"./agent/agent.js\";\nexport type { AgentRunOptions, AgentRunResult } from \"./agent/agent.js\";\nexport type { AgentConfig } from \"./agent/config.js\";\nexport { parse_agent_config } from \"./agent/config.js\";\nexport { AgentEmitter } from \"./agent/events.js\";\nexport type { AgentEvent, AgentEventHandler, AgentEvents } from \"./agent/events.js\";\nexport type { LoopOutcome, LoopParams } from \"./agent/loop.js\";\nexport type {\n ChatOptions,\n ChatResult,\n Message,\n ProviderConfig,\n ToolCall,\n ToolDefinition,\n Usage,\n} from \"./providers/types.js\";\nexport { ProviderError } from \"./providers/types.js\";\nexport { ToolExecutor } from \"./tools/executor.js\";\nexport { ToolRegistry } from \"./tools/registry.js\";\nexport type { Tool, ToolContext, ToolResult } from \"./tools/types.js\";\nexport { register_builtin_tools } from \"./tools/builtin/index.js\";\nexport { HookedToolRunner } from \"./plugins/hooks.js\";\nexport { load_plugins, plugin_errors_summary } from \"./plugins/loader.js\";\nexport type { LoadedPlugin, PluginLoadError } from \"./plugins/loader.js\";\nexport type {\n AfterToolCallInfo,\n BeforeToolCallInfo,\n BeforeToolCallResult,\n HookContext,\n Plugin,\n PluginHooks,\n RunEndInfo,\n} from \"./plugins/types.js\";"],"mappings":";AAGO,IAAM,eAAe;","names":[]}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/cli.js ADDED
@@ -0,0 +1,409 @@
1
+ import {
2
+ LICH_VERSION
3
+ } from "./chunk-ZVK3MUPC.js";
4
+ import {
5
+ create_agent,
6
+ parse_agent_config,
7
+ safe_json_parse
8
+ } from "./chunk-P52U5M3L.js";
9
+
10
+ // src/cli.ts
11
+ import { readFileSync as readFileSync2 } from "fs";
12
+ import { createInterface } from "readline";
13
+ import path2 from "path";
14
+ import { pathToFileURL } from "url";
15
+
16
+ // src/cli_config.ts
17
+ import { existsSync, mkdirSync, readFileSync } from "fs";
18
+ import { homedir } from "os";
19
+ import path from "path";
20
+ var LICH_DIRNAME = ".lich";
21
+ var CONFIG_RELPATH = `${LICH_DIRNAME}/config.json`;
22
+ var DEFAULT_USER_CONFIG = ".config/lich/config.json";
23
+ function config_search_paths(work_dir) {
24
+ const root = work_dir ?? process.cwd();
25
+ const first = path.resolve(root, CONFIG_RELPATH);
26
+ const second = path.resolve(homedir(), DEFAULT_USER_CONFIG);
27
+ return first === second ? [first] : [first, second];
28
+ }
29
+ function find_config_file(explicit) {
30
+ if (explicit !== void 0) {
31
+ if (existsSync(explicit) === false) {
32
+ throw new Error(`config not found: ${explicit}`);
33
+ }
34
+ return explicit;
35
+ }
36
+ for (const candidate of config_search_paths()) {
37
+ if (existsSync(candidate) === true) {
38
+ return candidate;
39
+ }
40
+ }
41
+ return void 0;
42
+ }
43
+ function load_config(explicit) {
44
+ const found = find_config_file(explicit);
45
+ if (found === void 0) {
46
+ return void 0;
47
+ }
48
+ const raw = readFileSync(found, "utf8");
49
+ const parsed = safe_json_parse(raw);
50
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
51
+ throw new Error(`invalid config json: ${found}`);
52
+ }
53
+ return parsed;
54
+ }
55
+ function config_template() {
56
+ const kind = process.env.LICH_PROVIDER_KIND ?? "ollama";
57
+ const provider = {
58
+ kind,
59
+ name: "main",
60
+ model: process.env.LICH_MODEL ?? "<model-name>"
61
+ };
62
+ if (kind === "ollama") {
63
+ provider["base_url"] = "http://localhost:11434";
64
+ }
65
+ return JSON.stringify({ providers: [provider], max_turns: 25 }, null, 2);
66
+ }
67
+
68
+ // src/cli.ts
69
+ var FLAG_KEYS = {
70
+ "--work-dir": "work_dir",
71
+ "--max-turns": "max_turns",
72
+ "--model": "provider_model",
73
+ "--provider-kind": "provider_kind",
74
+ "--base-url": "provider_base_url",
75
+ "--api-key-env": "provider_api_key_env",
76
+ "--system-prompt": "system_prompt",
77
+ "--session-dir": "session_dir",
78
+ "--log-level": "log_level"
79
+ };
80
+ var DEFAULT_BASE_URLS = {
81
+ openai_compat: "https://api.openai.com/v1",
82
+ anthropic: "https://api.anthropic.com",
83
+ ollama: "http://localhost:11434"
84
+ };
85
+ var DEFAULT_ENV_API_KEYS = {
86
+ openai_compat: "OPENAI_API_KEY",
87
+ anthropic: "ANTHROPIC_API_KEY",
88
+ ollama: void 0
89
+ // ollama needs no api key
90
+ };
91
+ function usage_text() {
92
+ return [
93
+ "lich \u2014 a TypeScript AI agent harness",
94
+ "",
95
+ "Usage:",
96
+ ' lich "one shot task" run a single task and print the reply',
97
+ " lich chat interactive chat (commands: /exit, /quit)",
98
+ " lich tui interactive terminal UI (ink)",
99
+ " lich gateway <plat..> messaging gateway (webhook|telegram|discord|twitch)",
100
+ " lich config print a starter config template (save as .lich/config.json)",
101
+ " lich --help show this help",
102
+ " lich --version print version",
103
+ "",
104
+ "Flags (before or after the subcommand):",
105
+ " --config <path> JSON config file parsed by parse_agent_config",
106
+ " --work-dir <path> working directory for tools",
107
+ " --max-turns <n> loop turn budget (default 25)",
108
+ " --model <m> model name (default from LICH_MODEL)",
109
+ " --provider-kind <k> openai_compat | anthropic | ollama (default LICH_PROVIDER_KIND)",
110
+ " --base-url <u> provider base url (default LICH_BASE_URL)",
111
+ " --api-key-env <NAME> env var holding the api key (default LICH_API_KEY_ENV; unused by ollama)",
112
+ " --system-prompt <s> system prompt override",
113
+ " --session-dir <path> session transcript directory",
114
+ " --log-level <level> debug | info | warn | error"
115
+ ].join("\n");
116
+ }
117
+ function error_message(error) {
118
+ return error instanceof Error ? error.message : String(error);
119
+ }
120
+ function error_for_mode(mode, base_message) {
121
+ if (mode === "tui") {
122
+ return "lich tui: no model configured \u2014 set LICH_MODEL (e.g. glm-5.3-flash:cloud), pass --model, or create .lich/config.json (`lich config` prints a template)";
123
+ }
124
+ if (mode === "gateway") {
125
+ return "lich gateway: no model configured \u2014 set LICH_MODEL (e.g. glm-5.3-flash:cloud), pass --model, or create .lich/config.json (`lich config` prints a template)";
126
+ }
127
+ if (mode === "chat") {
128
+ return "lich chat: no model configured \u2014 set LICH_MODEL (e.g. glm-5.3-flash:cloud), pass --model, or create .lich/config.json (`lich config` prints a template)";
129
+ }
130
+ return base_message;
131
+ }
132
+ function parse_args(argv) {
133
+ const options = { overrides: {}, positionals: [] };
134
+ for (let index = 0; index < argv.length; index += 1) {
135
+ const arg = argv[index];
136
+ if (arg === void 0) {
137
+ break;
138
+ }
139
+ if (arg === "--help") {
140
+ options.help = true;
141
+ continue;
142
+ }
143
+ if (arg === "--version") {
144
+ options.version = true;
145
+ continue;
146
+ }
147
+ if (arg === "--config") {
148
+ const value2 = argv[index + 1];
149
+ if (value2 === void 0) {
150
+ throw new Error("--config requires a path");
151
+ }
152
+ options.config_path = value2;
153
+ index += 1;
154
+ continue;
155
+ }
156
+ const override_key = FLAG_KEYS[arg];
157
+ if (override_key === void 0) {
158
+ if (arg.startsWith("--") === true) {
159
+ throw new Error(`unknown flag: ${arg}`);
160
+ }
161
+ options.positionals.push(arg);
162
+ continue;
163
+ }
164
+ const value = argv[index + 1];
165
+ if (value === void 0 || value.startsWith("--") === true) {
166
+ throw new Error(`${arg} requires a value`);
167
+ }
168
+ options.overrides[override_key] = value;
169
+ index += 1;
170
+ }
171
+ return options;
172
+ }
173
+ function env_provider(overrides) {
174
+ const kind_value = overrides["provider_kind"] ?? process.env.LICH_PROVIDER_KIND ?? "openai_compat";
175
+ if (kind_value !== "openai_compat" && kind_value !== "anthropic" && kind_value !== "ollama") {
176
+ throw new Error(`unknown provider kind "${kind_value}" (expected openai_compat, anthropic, or ollama)`);
177
+ }
178
+ const kind = kind_value;
179
+ const model = overrides["provider_model"] ?? process.env.LICH_MODEL;
180
+ if (model === void 0 || model.length === 0) {
181
+ throw new Error("no model configured: set LICH_MODEL, pass --model, or create .lich/config.json (`lich config` prints a template)");
182
+ }
183
+ return {
184
+ kind,
185
+ name: "default",
186
+ model,
187
+ base_url: overrides["provider_base_url"] ?? process.env.LICH_BASE_URL ?? DEFAULT_BASE_URLS[kind],
188
+ api_key_env: overrides["provider_api_key_env"] ?? process.env.LICH_API_KEY_ENV ?? DEFAULT_ENV_API_KEYS[kind]
189
+ };
190
+ }
191
+ function load_config_file(config_path) {
192
+ try {
193
+ const raw = readFileSync2(config_path, "utf8");
194
+ const parsed = JSON.parse(raw);
195
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
196
+ throw new Error("config root must be a JSON object");
197
+ }
198
+ return parsed;
199
+ } catch (error) {
200
+ throw new Error(`cannot use config file ${config_path}: ${error_message(error)}`);
201
+ }
202
+ }
203
+ function apply_provider_override(config, overrides) {
204
+ const keys = ["provider_kind", "provider_model", "provider_base_url", "provider_api_key_env"];
205
+ const any_present = keys.some((key) => overrides[key] !== void 0);
206
+ if (any_present === false) {
207
+ return;
208
+ }
209
+ const providers = config["providers"];
210
+ if (Array.isArray(providers) === false || providers.length === 0) {
211
+ config["providers"] = [env_provider(overrides)];
212
+ return;
213
+ }
214
+ const first = providers[0];
215
+ if (typeof first !== "object" || first === null) {
216
+ throw new Error("config providers[0] must be an object");
217
+ }
218
+ const provider = first;
219
+ for (const key of keys) {
220
+ const value = overrides[key];
221
+ if (value !== void 0) {
222
+ provider[key.replace("provider_", "")] = value;
223
+ }
224
+ }
225
+ }
226
+ function apply_overrides(config, overrides) {
227
+ for (const key of ["work_dir", "system_prompt", "session_dir", "log_level"]) {
228
+ if (overrides[key] !== void 0) {
229
+ config[key] = overrides[key];
230
+ }
231
+ }
232
+ if (overrides["max_turns"] !== void 0) {
233
+ const turns = Number(overrides["max_turns"]);
234
+ if (Number.isInteger(turns) === false || turns < 1) {
235
+ throw new Error("--max-turns must be a positive integer");
236
+ }
237
+ config["max_turns"] = turns;
238
+ }
239
+ apply_provider_override(config, overrides);
240
+ }
241
+ function build_config(options) {
242
+ const base = options.config_path === void 0 ? load_config() ?? { providers: [env_provider(options.overrides)] } : load_config_file(options.config_path);
243
+ apply_overrides(base, options.overrides);
244
+ const providers = base["providers"];
245
+ if (Array.isArray(providers) === false || providers.length === 0) {
246
+ throw new Error("no model configured: set LICH_MODEL, pass --model, or create .lich/config.json (`lich config` prints a template)");
247
+ }
248
+ return parse_agent_config(base);
249
+ }
250
+ function build_config_for(options, mode) {
251
+ try {
252
+ return build_config(options);
253
+ } catch (error) {
254
+ throw new Error(error_for_mode(mode, error_message(error)));
255
+ }
256
+ }
257
+ function attach_progress(emitter) {
258
+ return emitter.on((event) => {
259
+ if (event.type === "turn_start") {
260
+ process.stderr.write(`
261
+ [lich] turn ${event.turn}`);
262
+ return;
263
+ }
264
+ if (event.type === "tool_call_end") {
265
+ const status = event.result.ok === true ? "ok" : `error: ${event.result.error ?? ""}`;
266
+ process.stderr.write(`
267
+ [lich] ${event.call.name}: ${status}`);
268
+ return;
269
+ }
270
+ if (event.type === "final") {
271
+ process.stderr.write("\n");
272
+ }
273
+ });
274
+ }
275
+ async function run_one_shot(config, input) {
276
+ const agent = create_agent(config);
277
+ const stop_progress = attach_progress(agent.events);
278
+ let result;
279
+ try {
280
+ result = await agent.run({ input });
281
+ } finally {
282
+ stop_progress();
283
+ }
284
+ const final = result.outcome.final;
285
+ if (final !== void 0 && final.content.length > 0) {
286
+ process.stdout.write(`${final.content}
287
+ `);
288
+ }
289
+ if (result.outcome.stopped_reason === "budget") {
290
+ process.stderr.write(`[lich] budget exhausted after ${result.outcome.turns_used} turns
291
+ `);
292
+ return 1;
293
+ }
294
+ if (result.outcome.stopped_reason === "aborted") {
295
+ process.stderr.write("[lich] run aborted\n");
296
+ return 1;
297
+ }
298
+ return 0;
299
+ }
300
+ async function run_chat_turn(agent, input) {
301
+ const stop_progress = attach_progress(agent.events);
302
+ try {
303
+ const result = await agent.run({ input });
304
+ const final = result.outcome.final;
305
+ if (final !== void 0 && final.content.length > 0) {
306
+ process.stdout.write(`${final.content}
307
+ `);
308
+ }
309
+ process.stdout.write(`[turns ${result.outcome.turns_used} | tokens ${result.usage_total.total_tokens}]
310
+ `);
311
+ } catch (error) {
312
+ process.stderr.write(`[lich] ${error_message(error)}
313
+ `);
314
+ } finally {
315
+ stop_progress();
316
+ }
317
+ }
318
+ function ask_line(rl) {
319
+ return new Promise((resolve) => {
320
+ const on_close = () => resolve("");
321
+ rl.question("> ", (answer) => {
322
+ rl.removeListener("close", on_close);
323
+ resolve(answer);
324
+ });
325
+ rl.once("close", on_close);
326
+ });
327
+ }
328
+ async function run_chat(config) {
329
+ const agent = create_agent(config);
330
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
331
+ try {
332
+ for (; ; ) {
333
+ const line = await ask_line(rl);
334
+ if (line.trim() === "") {
335
+ return 0;
336
+ }
337
+ const command = line.trim();
338
+ if (command === "/exit" || command === "/quit") {
339
+ return 0;
340
+ }
341
+ await run_chat_turn(agent, command);
342
+ }
343
+ } finally {
344
+ rl.close();
345
+ }
346
+ }
347
+ async function run_tui_entry(config) {
348
+ const { run_tui } = await import("./tui-V7ATLIKW.js");
349
+ return run_tui(config);
350
+ }
351
+ async function run_gateway_entry(config, platforms) {
352
+ const { run_gateway } = await import("./gateway-CWPVIU3W.js");
353
+ return run_gateway(config, platforms.length === 0 ? ["webhook"] : platforms);
354
+ }
355
+ function is_main_module() {
356
+ const entry = process.argv[1];
357
+ if (entry === void 0) {
358
+ return false;
359
+ }
360
+ return import.meta.url === pathToFileURL(path2.resolve(entry)).href;
361
+ }
362
+ async function main(argv) {
363
+ const options = parse_args(argv);
364
+ if (options.help === true) {
365
+ process.stdout.write(`${usage_text()}
366
+ `);
367
+ return 0;
368
+ }
369
+ if (options.version === true) {
370
+ process.stdout.write(`${LICH_VERSION}
371
+ `);
372
+ return 0;
373
+ }
374
+ const [first] = options.positionals;
375
+ if (first === void 0) {
376
+ process.stderr.write(`${usage_text()}
377
+ `);
378
+ return 1;
379
+ }
380
+ if (first === "config") {
381
+ process.stdout.write(`${config_template()}
382
+ `);
383
+ return 0;
384
+ }
385
+ if (first === "chat") {
386
+ if (options.positionals.length > 1) {
387
+ throw new Error("chat mode takes no task argument");
388
+ }
389
+ return run_chat(build_config_for(options, first));
390
+ }
391
+ if (first === "tui") {
392
+ return run_tui_entry(build_config_for(options, first));
393
+ }
394
+ if (first === "gateway") {
395
+ return run_gateway_entry(build_config_for(options, first), options.positionals.slice(1));
396
+ }
397
+ return run_one_shot(build_config_for(options, "one-shot"), options.positionals.join(" "));
398
+ }
399
+ if (is_main_module() === true) {
400
+ main(process.argv.slice(2)).then((code) => {
401
+ process.exitCode = code;
402
+ }).catch((error) => {
403
+ process.stderr.write(`lich: ${error_message(error)}
404
+ `);
405
+ process.stderr.write("run `lich --help` for usage\n");
406
+ process.exitCode = 1;
407
+ });
408
+ }
409
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/cli_config.ts"],"sourcesContent":["/**\n * Thin zero-dependency CLI for lich: one-shot tasks, interactive chat,\n * config files, and environment-based provider resolution.\n */\nimport { readFileSync } from \"node:fs\";\nimport { createInterface, type Interface } from \"node:readline\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { create_agent, type Agent, type AgentRunResult } from \"./agent/agent.js\";\nimport { parse_agent_config, type AgentConfig } from \"./agent/config.js\";\nimport { AgentEmitter } from \"./agent/events.js\";\nimport { LICH_VERSION } from \"./index.js\";\nimport { load_config, config_template } from \"./cli_config.js\";\n\ntype ProviderKind = \"openai_compat\" | \"anthropic\" | \"ollama\";\n\ninterface CliOptions {\n config_path?: string;\n help?: boolean;\n version?: boolean;\n overrides: Record<string, string>;\n positionals: string[];\n}\n\nconst FLAG_KEYS: Record<string, string> = {\n \"--work-dir\": \"work_dir\",\n \"--max-turns\": \"max_turns\",\n \"--model\": \"provider_model\",\n \"--provider-kind\": \"provider_kind\",\n \"--base-url\": \"provider_base_url\",\n \"--api-key-env\": \"provider_api_key_env\",\n \"--system-prompt\": \"system_prompt\",\n \"--session-dir\": \"session_dir\",\n \"--log-level\": \"log_level\",\n};\n\nconst DEFAULT_BASE_URLS: Record<ProviderKind, string> = {\n openai_compat: \"https://api.openai.com/v1\",\n anthropic: \"https://api.anthropic.com\",\n ollama: \"http://localhost:11434\",\n};\n\nconst DEFAULT_ENV_API_KEYS: Record<ProviderKind, string | undefined> = {\n openai_compat: \"OPENAI_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n ollama: undefined, // ollama needs no api key\n};\n\nfunction usage_text(): string {\n return [\n \"lich — a TypeScript AI agent harness\",\n \"\",\n \"Usage:\",\n ' lich \"one shot task\" run a single task and print the reply',\n \" lich chat interactive chat (commands: /exit, /quit)\",\n \" lich tui interactive terminal UI (ink)\",\n \" lich gateway <plat..> messaging gateway (webhook|telegram|discord|twitch)\",\n \" lich config print a starter config template (save as .lich/config.json)\",\n \" lich --help show this help\",\n \" lich --version print version\",\n \"\",\n \"Flags (before or after the subcommand):\",\n \" --config <path> JSON config file parsed by parse_agent_config\",\n \" --work-dir <path> working directory for tools\",\n \" --max-turns <n> loop turn budget (default 25)\",\n \" --model <m> model name (default from LICH_MODEL)\",\n \" --provider-kind <k> openai_compat | anthropic | ollama (default LICH_PROVIDER_KIND)\",\n \" --base-url <u> provider base url (default LICH_BASE_URL)\",\n \" --api-key-env <NAME> env var holding the api key (default LICH_API_KEY_ENV; unused by ollama)\",\n \" --system-prompt <s> system prompt override\",\n \" --session-dir <path> session transcript directory\",\n \" --log-level <level> debug | info | warn | error\",\n ].join(\"\\n\");\n}\n\nfunction error_message(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Mode-aware config failure message; one-shot keeps the generic variant. */\nfunction error_for_mode(mode: string, base_message: string): string {\n if (mode === \"tui\") {\n return \"lich tui: no model configured — set LICH_MODEL (e.g. glm-5.3-flash:cloud), pass --model, or create .lich/config.json (`lich config` prints a template)\";\n }\n if (mode === \"gateway\") {\n return \"lich gateway: no model configured — set LICH_MODEL (e.g. glm-5.3-flash:cloud), pass --model, or create .lich/config.json (`lich config` prints a template)\";\n }\n if (mode === \"chat\") {\n return \"lich chat: no model configured — set LICH_MODEL (e.g. glm-5.3-flash:cloud), pass --model, or create .lich/config.json (`lich config` prints a template)\";\n }\n return base_message;\n}\n\nfunction parse_args(argv: string[]): CliOptions {\n const options: CliOptions = { overrides: {}, positionals: [] };\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (arg === undefined) {\n break;\n }\n if (arg === \"--help\") {\n options.help = true;\n continue;\n }\n if (arg === \"--version\") {\n options.version = true;\n continue;\n }\n if (arg === \"--config\") {\n const value = argv[index + 1];\n if (value === undefined) {\n throw new Error(\"--config requires a path\");\n }\n options.config_path = value;\n index += 1;\n continue;\n }\n const override_key = FLAG_KEYS[arg];\n if (override_key === undefined) {\n if (arg.startsWith(\"--\") === true) {\n throw new Error(`unknown flag: ${arg}`);\n }\n options.positionals.push(arg);\n continue;\n }\n const value = argv[index + 1];\n if (value === undefined || value.startsWith(\"--\") === true) {\n throw new Error(`${arg} requires a value`);\n }\n options.overrides[override_key] = value;\n index += 1;\n }\n return options;\n}\n\nfunction env_provider(overrides: Record<string, string>): Record<string, unknown> {\n const kind_value = overrides[\"provider_kind\"] ?? process.env.LICH_PROVIDER_KIND ?? \"openai_compat\";\n if (kind_value !== \"openai_compat\" && kind_value !== \"anthropic\" && kind_value !== \"ollama\") {\n throw new Error(`unknown provider kind \"${kind_value}\" (expected openai_compat, anthropic, or ollama)`);\n }\n const kind: ProviderKind = kind_value;\n const model = overrides[\"provider_model\"] ?? process.env.LICH_MODEL;\n if (model === undefined || model.length === 0) {\n throw new Error(\"no model configured: set LICH_MODEL, pass --model, or create .lich/config.json (`lich config` prints a template)\");\n }\n return {\n kind,\n name: \"default\",\n model,\n base_url: overrides[\"provider_base_url\"] ?? process.env.LICH_BASE_URL ?? DEFAULT_BASE_URLS[kind],\n api_key_env: overrides[\"provider_api_key_env\"] ?? process.env.LICH_API_KEY_ENV ?? DEFAULT_ENV_API_KEYS[kind],\n };\n}\n\nfunction load_config_file(config_path: string): Record<string, unknown> {\n try {\n const raw = readFileSync(config_path, \"utf8\");\n const parsed = JSON.parse(raw) as unknown;\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(\"config root must be a JSON object\");\n }\n return parsed as Record<string, unknown>;\n } catch (error) {\n throw new Error(`cannot use config file ${config_path}: ${error_message(error)}`);\n }\n}\n\nfunction apply_provider_override(config: Record<string, unknown>, overrides: Record<string, string>): void {\n const keys = [\"provider_kind\", \"provider_model\", \"provider_base_url\", \"provider_api_key_env\"] as const;\n const any_present = keys.some((key) => overrides[key] !== undefined);\n if (any_present === false) {\n return;\n }\n const providers = config[\"providers\"];\n if (Array.isArray(providers) === false || providers.length === 0) {\n config[\"providers\"] = [env_provider(overrides)];\n return;\n }\n const first = providers[0];\n if (typeof first !== \"object\" || first === null) {\n throw new Error(\"config providers[0] must be an object\");\n }\n const provider = first as Record<string, unknown>;\n for (const key of keys) {\n const value = overrides[key];\n if (value !== undefined) {\n provider[key.replace(\"provider_\", \"\")] = value;\n }\n }\n}\n\nfunction apply_overrides(config: Record<string, unknown>, overrides: Record<string, string>): void {\n for (const key of [\"work_dir\", \"system_prompt\", \"session_dir\", \"log_level\"]) {\n if (overrides[key] !== undefined) {\n config[key] = overrides[key];\n }\n }\n if (overrides[\"max_turns\"] !== undefined) {\n const turns = Number(overrides[\"max_turns\"]);\n if (Number.isInteger(turns) === false || turns < 1) {\n throw new Error(\"--max-turns must be a positive integer\");\n }\n config[\"max_turns\"] = turns;\n }\n apply_provider_override(config, overrides);\n}\n\nfunction build_config(options: CliOptions): AgentConfig {\n const base =\n options.config_path === undefined ? load_config() ?? { providers: [env_provider(options.overrides)] } : load_config_file(options.config_path);\n apply_overrides(base, options.overrides);\n const providers = base[\"providers\"];\n if (Array.isArray(providers) === false || providers.length === 0) {\n throw new Error(\"no model configured: set LICH_MODEL, pass --model, or create .lich/config.json (`lich config` prints a template)\");\n }\n return parse_agent_config(base);\n}\n\n/** build_config with the failure message prefixed for the invoking subcommand. */\nfunction build_config_for(options: CliOptions, mode: string): AgentConfig {\n try {\n return build_config(options);\n } catch (error) {\n throw new Error(error_for_mode(mode, error_message(error)));\n }\n}\n\nfunction attach_progress(emitter: AgentEmitter): () => void {\n return emitter.on((event) => {\n if (event.type === \"turn_start\") {\n process.stderr.write(`\\n[lich] turn ${event.turn}`);\n return;\n }\n if (event.type === \"tool_call_end\") {\n const status = event.result.ok === true ? \"ok\" : `error: ${event.result.error ?? \"\"}`;\n process.stderr.write(`\\n[lich] ${event.call.name}: ${status}`);\n return;\n }\n if (event.type === \"final\") {\n process.stderr.write(\"\\n\");\n }\n });\n}\n\nasync function run_one_shot(config: unknown, input: string): Promise<number> {\n const agent = create_agent(config);\n const stop_progress = attach_progress(agent.events);\n let result: AgentRunResult;\n try {\n result = await agent.run({ input });\n } finally {\n stop_progress();\n }\n const final = result.outcome.final;\n if (final !== undefined && final.content.length > 0) {\n process.stdout.write(`${final.content}\\n`);\n }\n if (result.outcome.stopped_reason === \"budget\") {\n process.stderr.write(`[lich] budget exhausted after ${result.outcome.turns_used} turns\\n`);\n return 1;\n }\n if (result.outcome.stopped_reason === \"aborted\") {\n process.stderr.write(\"[lich] run aborted\\n\");\n return 1;\n }\n return 0;\n}\n\nasync function run_chat_turn(agent: Agent, input: string): Promise<void> {\n const stop_progress = attach_progress(agent.events);\n try {\n const result = await agent.run({ input });\n const final = result.outcome.final;\n if (final !== undefined && final.content.length > 0) {\n process.stdout.write(`${final.content}\\n`);\n }\n process.stdout.write(`[turns ${result.outcome.turns_used} | tokens ${result.usage_total.total_tokens}]\\n`);\n } catch (error) {\n process.stderr.write(`[lich] ${error_message(error)}\\n`);\n } finally {\n stop_progress();\n }\n}\n\nfunction ask_line(rl: Interface): Promise<string> {\n return new Promise((resolve) => {\n const on_close = (): void => resolve(\"\");\n rl.question(\"> \", (answer) => {\n rl.removeListener(\"close\", on_close);\n resolve(answer);\n });\n rl.once(\"close\", on_close);\n });\n}\n\nasync function run_chat(config: unknown): Promise<number> {\n const agent = create_agent(config);\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n for (;;) {\n const line = await ask_line(rl);\n if (line.trim() === \"\") {\n return 0;\n }\n const command = line.trim();\n if (command === \"/exit\" || command === \"/quit\") {\n return 0;\n }\n await run_chat_turn(agent, command);\n }\n } finally {\n rl.close();\n }\n}\n\nasync function run_tui_entry(config: ReturnType<typeof build_config>): Promise<number> {\n const { run_tui } = await import(\"./tui.js\");\n return run_tui(config);\n}\n\nasync function run_gateway_entry(\n config: ReturnType<typeof build_config>,\n platforms: string[],\n): Promise<number> {\n const { run_gateway } = await import(\"./gateway.js\");\n return run_gateway(config, platforms.length === 0 ? [\"webhook\"] : platforms);\n}\n\nfunction is_main_module(): boolean {\n const entry = process.argv[1];\n if (entry === undefined) {\n return false;\n }\n return import.meta.url === pathToFileURL(path.resolve(entry)).href;\n}\n\nasync function main(argv: string[]): Promise<number> {\n const options = parse_args(argv);\n if (options.help === true) {\n process.stdout.write(`${usage_text()}\\n`);\n return 0;\n }\n if (options.version === true) {\n process.stdout.write(`${LICH_VERSION}\\n`);\n return 0;\n }\n const [first] = options.positionals;\n if (first === undefined) {\n process.stderr.write(`${usage_text()}\\n`);\n return 1;\n }\n if (first === \"config\") {\n process.stdout.write(`${config_template()}\\n`);\n return 0;\n }\n if (first === \"chat\") {\n if (options.positionals.length > 1) {\n throw new Error(\"chat mode takes no task argument\");\n }\n return run_chat(build_config_for(options, first));\n }\n if (first === \"tui\") {\n return run_tui_entry(build_config_for(options, first));\n }\n if (first === \"gateway\") {\n return run_gateway_entry(build_config_for(options, first), options.positionals.slice(1));\n }\n return run_one_shot(build_config_for(options, \"one-shot\"), options.positionals.join(\" \"));\n}\n\nif (is_main_module() === true) {\n main(process.argv.slice(2))\n .then((code) => {\n process.exitCode = code;\n })\n .catch((error) => {\n process.stderr.write(`lich: ${error_message(error)}\\n`);\n process.stderr.write(\"run `lich --help` for usage\\n\");\n process.exitCode = 1;\n });\n}","/**\n * Config-file discovery for the CLI: an ordered search chain, safe loading,\n * and a starter template so `lich tui` works with zero environment setup.\n */\nimport { existsSync, mkdirSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { safe_json_parse } from \"./util/json.js\";\n\nconst LICH_DIRNAME = \".lich\";\nconst CONFIG_RELPATH = `${LICH_DIRNAME}/config.json`;\nconst DEFAULT_USER_CONFIG = \".config/lich/config.json\";\n\n/** Ordered absolute chain: work_dir (default cwd) first, then the user config home. */\nexport function config_search_paths(work_dir?: string): string[] {\n const root = work_dir ?? process.cwd();\n const first = path.resolve(root, CONFIG_RELPATH);\n const second = path.resolve(homedir(), DEFAULT_USER_CONFIG);\n return first === second ? [first] : [first, second];\n}\n\n/** Explicit path must exist (else throw); otherwise walk the chain, undefined when absent. */\nexport function find_config_file(explicit?: string): string | undefined {\n if (explicit !== undefined) {\n if (existsSync(explicit) === false) {\n throw new Error(`config not found: ${explicit}`);\n }\n return explicit;\n }\n for (const candidate of config_search_paths()) {\n if (existsSync(candidate) === true) {\n return candidate;\n }\n }\n return undefined;\n}\n\n/** Load the first config found as an object; undefined when absent, throw on bad json. */\nexport function load_config(explicit?: string): Record<string, unknown> | undefined {\n const found = find_config_file(explicit);\n if (found === undefined) {\n return undefined;\n }\n const raw = readFileSync(found, \"utf8\");\n const parsed = safe_json_parse<unknown>(raw);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(`invalid config json: ${found}`);\n }\n return parsed as Record<string, unknown>;\n}\n\n/** Starter config honoring LICH_* env hints; `lich config` prints it. */\nexport function config_template(): string {\n const kind = process.env.LICH_PROVIDER_KIND ?? \"ollama\";\n const provider: Record<string, unknown> = {\n kind,\n name: \"main\",\n model: process.env.LICH_MODEL ?? \"<model-name>\",\n };\n if (kind === \"ollama\") {\n provider[\"base_url\"] = \"http://localhost:11434\";\n }\n return JSON.stringify({ providers: [provider], max_turns: 25 }, null, 2);\n}\n\n/** mkdir -p `${work_dir}/.lich` and return the directory path. */\nexport function ensure_lich_config_dir(work_dir: string): string {\n const dir = path.resolve(work_dir, LICH_DIRNAME);\n mkdirSync(dir, { recursive: true });\n return dir;\n}"],"mappings":"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","names":["readFileSync","path","value","readFileSync","path"]}