@moikapy/lich 0.6.0 → 0.7.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 +20 -1
- package/README.md +26 -3
- package/dist/{chunk-JC2G3XH2.js → chunk-JYURFAGB.js} +2 -2
- package/dist/{chunk-7HLVKVIG.js → chunk-QVJCIZIF.js} +732 -10
- package/dist/chunk-QVJCIZIF.js.map +1 -0
- package/dist/chunk-SAEB3QL3.js +58 -0
- package/dist/chunk-SAEB3QL3.js.map +1 -0
- package/dist/cli.js +243 -17
- package/dist/cli.js.map +1 -1
- package/dist/{gateway-RJFZJEUZ.js → gateway-5BG3YCZF.js} +2 -2
- package/dist/index.d.ts +260 -154
- package/dist/index.js +5 -3
- package/dist/{tui-LOUJVZ6A.js → tui-L6RABP2J.js} +4 -4
- package/docs/.vitepress/config.mts +4 -0
- package/docs/architecture/overview.md +31 -18
- package/docs/architecture/plugins.md +1 -1
- package/docs/architecture/tools.md +7 -2
- package/docs/getting-started.md +7 -6
- package/docs/index.md +5 -4
- package/docs/user-guide/cli.md +20 -8
- package/docs/user-guide/games.md +1 -1
- package/docs/user-guide/godot.md +3 -1
- package/docs/user-guide/library.md +4 -2
- package/docs/user-guide/plugins.md +2 -2
- package/docs/user-guide/redot.md +93 -0
- package/docs/user-guide/tui.md +2 -2
- package/examples/game_bridge/README.md +2 -0
- package/optional-mcps/godot/manifest.json +6 -0
- package/optional-mcps/redot/manifest.json +18 -0
- package/package.json +2 -1
- package/dist/chunk-6M6OAQGN.js +0 -17
- package/dist/chunk-6M6OAQGN.js.map +0 -1
- package/dist/chunk-7HLVKVIG.js.map +0 -1
- /package/dist/{chunk-JC2G3XH2.js.map → chunk-JYURFAGB.js.map} +0 -0
- /package/dist/{gateway-RJFZJEUZ.js.map → gateway-5BG3YCZF.js.map} +0 -0
- /package/dist/{tui-LOUJVZ6A.js.map → tui-L6RABP2J.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -23,107 +23,6 @@ interface JsonSchemaObject {
|
|
|
23
23
|
additionalProperties?: boolean;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
interface ToolResult {
|
|
27
|
-
ok: boolean;
|
|
28
|
-
output: string;
|
|
29
|
-
error?: string;
|
|
30
|
-
}
|
|
31
|
-
interface ToolContext {
|
|
32
|
-
work_dir: string;
|
|
33
|
-
env: Record<string, string>;
|
|
34
|
-
signal?: AbortSignal;
|
|
35
|
-
}
|
|
36
|
-
interface Tool {
|
|
37
|
-
name: string;
|
|
38
|
-
description: string;
|
|
39
|
-
parameters: JsonSchemaObject;
|
|
40
|
-
/** Per-tool executor timeout override in ms; unset tools get the 30s default. */
|
|
41
|
-
timeout_ms?: number;
|
|
42
|
-
execute(args: Record<string, unknown>, context: ToolContext): Promise<ToolResult>;
|
|
43
|
-
}
|
|
44
|
-
interface Toolset {
|
|
45
|
-
name: string;
|
|
46
|
-
tools: Tool[];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Plugin surface: user-authored tools and lifecycle hooks loaded at startup.
|
|
51
|
-
*
|
|
52
|
-
* A plugin is a plain object exported from a TS/JS module. Hooks observe and
|
|
53
|
-
* (in the case of before_tool_call) veto tool executions; tools merge into the
|
|
54
|
-
* agent registry after builtin filtering.
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
|
-
/** Runtime info handed to every hook call. */
|
|
58
|
-
interface HookContext {
|
|
59
|
-
work_dir: string;
|
|
60
|
-
/**
|
|
61
|
-
* This plugin's own per-run state sub-map. Every hook invocation receives
|
|
62
|
-
* a ctx exposing only the invoking plugin's bag; the bag is swapped fresh
|
|
63
|
-
* at each run start. Absent only on hand-built contexts outside the runner.
|
|
64
|
-
*/
|
|
65
|
-
state?: Map<string, unknown>;
|
|
66
|
-
}
|
|
67
|
-
/** Argument passed to before_tool_call hooks. */
|
|
68
|
-
interface BeforeToolCallInfo {
|
|
69
|
-
tool_name: string;
|
|
70
|
-
args: Record<string, unknown>;
|
|
71
|
-
}
|
|
72
|
-
/** Return value that vetoes a tool call; other hooks still run. */
|
|
73
|
-
interface BeforeToolCallResult {
|
|
74
|
-
block?: boolean;
|
|
75
|
-
reason?: string;
|
|
76
|
-
}
|
|
77
|
-
/** Argument passed to after_tool_call hooks. */
|
|
78
|
-
interface AfterToolCallInfo extends BeforeToolCallInfo {
|
|
79
|
-
result_summary: string;
|
|
80
|
-
/** Structured executor outcome; gate on this, never parse result_summary. */
|
|
81
|
-
ok: boolean;
|
|
82
|
-
error?: string;
|
|
83
|
-
}
|
|
84
|
-
interface RunEndInfo {
|
|
85
|
-
stopped_reason: string;
|
|
86
|
-
turns_used: number;
|
|
87
|
-
}
|
|
88
|
-
/** Optional lifecycle hooks a plugin may implement. All hooks are awaited. */
|
|
89
|
-
interface PluginHooks {
|
|
90
|
-
before_tool_call?(info: BeforeToolCallInfo, ctx: HookContext): Promise<BeforeToolCallResult | void> | BeforeToolCallResult | void;
|
|
91
|
-
after_tool_call?(info: AfterToolCallInfo, ctx: HookContext): Promise<void> | void;
|
|
92
|
-
on_run_start?(info: {
|
|
93
|
-
input_chars: number;
|
|
94
|
-
}, ctx: HookContext): Promise<void> | void;
|
|
95
|
-
on_run_end?(info: RunEndInfo, ctx: HookContext): Promise<void> | void;
|
|
96
|
-
}
|
|
97
|
-
/** A user plugin: required unique name, optional tools and hooks. */
|
|
98
|
-
interface Plugin {
|
|
99
|
-
name: string;
|
|
100
|
-
version?: string;
|
|
101
|
-
tools?: Tool[];
|
|
102
|
-
hooks?: PluginHooks;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/** A successfully loaded plugin plus the entry path it came from. */
|
|
106
|
-
interface LoadedPlugin {
|
|
107
|
-
plugin: Plugin;
|
|
108
|
-
entry: string;
|
|
109
|
-
}
|
|
110
|
-
/** One failed entry: the specifier and why it failed. */
|
|
111
|
-
interface PluginLoadError {
|
|
112
|
-
entry: string;
|
|
113
|
-
error_message: string;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Load plugins from explicit entry paths (relative to `base_dir` or absolute).
|
|
117
|
-
* Broken imports, missing exports, and duplicate names become error entries;
|
|
118
|
-
* nothing is thrown for a bad plugin.
|
|
119
|
-
*/
|
|
120
|
-
declare function load_plugins(entries: readonly string[], base_dir: string): Promise<{
|
|
121
|
-
plugins: LoadedPlugin[];
|
|
122
|
-
errors: PluginLoadError[];
|
|
123
|
-
}>;
|
|
124
|
-
/** Joined one-liner per load error, for a single warn log. */
|
|
125
|
-
declare function plugin_errors_summary(errors: readonly PluginLoadError[]): string;
|
|
126
|
-
|
|
127
26
|
type FinishReason = "stop" | "tool_calls" | "length" | "error" | "unknown";
|
|
128
27
|
type ProviderErrorKind = "rate_limit" | "network" | "auth" | "overflow" | "bad_request" | "unknown";
|
|
129
28
|
interface ToolCall {
|
|
@@ -270,10 +169,52 @@ declare const agent_config_schema: z.ZodEffects<z.ZodObject<{
|
|
|
270
169
|
}>>;
|
|
271
170
|
log_level: z.ZodDefault<z.ZodEnum<["debug", "info", "warn", "error"]>>;
|
|
272
171
|
theme: z.ZodDefault<z.ZodString>;
|
|
172
|
+
/** Named MCP servers. Each entry is stdio or loopback http. Default off. */
|
|
173
|
+
mcp_servers: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
|
|
174
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
175
|
+
command: z.ZodString;
|
|
176
|
+
args: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
177
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
178
|
+
}, "strict", z.ZodTypeAny, {
|
|
179
|
+
enabled: boolean;
|
|
180
|
+
command: string;
|
|
181
|
+
args: string[];
|
|
182
|
+
env?: Record<string, string> | undefined;
|
|
183
|
+
}, {
|
|
184
|
+
command: string;
|
|
185
|
+
enabled?: boolean | undefined;
|
|
186
|
+
args?: string[] | undefined;
|
|
187
|
+
env?: Record<string, string> | undefined;
|
|
188
|
+
}>, z.ZodObject<{
|
|
189
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
190
|
+
url: z.ZodString;
|
|
191
|
+
}, "strict", z.ZodTypeAny, {
|
|
192
|
+
url: string;
|
|
193
|
+
enabled: boolean;
|
|
194
|
+
}, {
|
|
195
|
+
url: string;
|
|
196
|
+
enabled?: boolean | undefined;
|
|
197
|
+
}>]>>, Record<string, {
|
|
198
|
+
enabled: boolean;
|
|
199
|
+
command: string;
|
|
200
|
+
args: string[];
|
|
201
|
+
env?: Record<string, string> | undefined;
|
|
202
|
+
} | {
|
|
203
|
+
url: string;
|
|
204
|
+
enabled: boolean;
|
|
205
|
+
}>, Record<string, {
|
|
206
|
+
command: string;
|
|
207
|
+
enabled?: boolean | undefined;
|
|
208
|
+
args?: string[] | undefined;
|
|
209
|
+
env?: Record<string, string> | undefined;
|
|
210
|
+
} | {
|
|
211
|
+
url: string;
|
|
212
|
+
enabled?: boolean | undefined;
|
|
213
|
+
}>>>;
|
|
273
214
|
}, "strip", z.ZodTypeAny, {
|
|
274
|
-
plugins: string[];
|
|
275
|
-
agent_name: string;
|
|
276
215
|
max_turns: number;
|
|
216
|
+
log_level: "debug" | "info" | "warn" | "error";
|
|
217
|
+
theme: string;
|
|
277
218
|
providers: z.objectOutputType<{
|
|
278
219
|
kind: z.ZodEnum<["openai_compat", "anthropic", "ollama"]>;
|
|
279
220
|
name: z.ZodString;
|
|
@@ -285,21 +226,30 @@ declare const agent_config_schema: z.ZodEffects<z.ZodObject<{
|
|
|
285
226
|
/** Injectable fetch, mainly for tests; passes through untouched. */
|
|
286
227
|
fetch_fn: z.ZodOptional<z.ZodType<typeof fetch, z.ZodTypeDef, typeof fetch>>;
|
|
287
228
|
}, z.ZodTypeAny, "passthrough">[];
|
|
229
|
+
agent_name: string;
|
|
288
230
|
tools_enabled: string[] | "all";
|
|
289
231
|
context_budget_tokens: number;
|
|
290
232
|
compress_threshold: number;
|
|
291
233
|
terminal_timeout_ms: number;
|
|
292
|
-
|
|
293
|
-
theme: string;
|
|
294
|
-
temperature?: number | undefined;
|
|
295
|
-
max_tokens?: number | undefined;
|
|
296
|
-
system_prompt?: string | undefined;
|
|
234
|
+
plugins: string[];
|
|
297
235
|
work_dir?: string | undefined;
|
|
236
|
+
system_prompt?: string | undefined;
|
|
298
237
|
session_dir?: string | undefined;
|
|
299
238
|
gateway?: {
|
|
300
239
|
platforms: ("webhook" | "telegram" | "discord" | "twitch")[];
|
|
301
240
|
token_envs: Record<string, string>;
|
|
302
241
|
} | undefined;
|
|
242
|
+
temperature?: number | undefined;
|
|
243
|
+
max_tokens?: number | undefined;
|
|
244
|
+
mcp_servers?: Record<string, {
|
|
245
|
+
enabled: boolean;
|
|
246
|
+
command: string;
|
|
247
|
+
args: string[];
|
|
248
|
+
env?: Record<string, string> | undefined;
|
|
249
|
+
} | {
|
|
250
|
+
url: string;
|
|
251
|
+
enabled: boolean;
|
|
252
|
+
}> | undefined;
|
|
303
253
|
}, {
|
|
304
254
|
providers: z.objectInputType<{
|
|
305
255
|
kind: z.ZodEnum<["openai_compat", "anthropic", "ollama"]>;
|
|
@@ -312,44 +262,62 @@ declare const agent_config_schema: z.ZodEffects<z.ZodObject<{
|
|
|
312
262
|
/** Injectable fetch, mainly for tests; passes through untouched. */
|
|
313
263
|
fetch_fn: z.ZodOptional<z.ZodType<typeof fetch, z.ZodTypeDef, typeof fetch>>;
|
|
314
264
|
}, z.ZodTypeAny, "passthrough">[];
|
|
315
|
-
plugins?: string[] | undefined;
|
|
316
|
-
temperature?: number | undefined;
|
|
317
|
-
max_tokens?: number | undefined;
|
|
318
|
-
agent_name?: string | undefined;
|
|
319
|
-
system_prompt?: string | undefined;
|
|
320
|
-
max_turns?: number | undefined;
|
|
321
265
|
work_dir?: string | undefined;
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
compress_threshold?: number | undefined;
|
|
266
|
+
max_turns?: number | undefined;
|
|
267
|
+
system_prompt?: string | undefined;
|
|
325
268
|
session_dir?: string | undefined;
|
|
326
|
-
|
|
269
|
+
log_level?: "debug" | "info" | "warn" | "error" | undefined;
|
|
270
|
+
theme?: string | undefined;
|
|
327
271
|
gateway?: {
|
|
328
272
|
platforms?: ("webhook" | "telegram" | "discord" | "twitch")[] | undefined;
|
|
329
273
|
token_envs?: Record<string, string> | undefined;
|
|
330
274
|
} | undefined;
|
|
331
|
-
|
|
332
|
-
|
|
275
|
+
agent_name?: string | undefined;
|
|
276
|
+
tools_enabled?: string[] | "all" | undefined;
|
|
277
|
+
temperature?: number | undefined;
|
|
278
|
+
max_tokens?: number | undefined;
|
|
279
|
+
context_budget_tokens?: number | undefined;
|
|
280
|
+
compress_threshold?: number | undefined;
|
|
281
|
+
terminal_timeout_ms?: number | undefined;
|
|
282
|
+
plugins?: string[] | undefined;
|
|
283
|
+
mcp_servers?: Record<string, {
|
|
284
|
+
command: string;
|
|
285
|
+
enabled?: boolean | undefined;
|
|
286
|
+
args?: string[] | undefined;
|
|
287
|
+
env?: Record<string, string> | undefined;
|
|
288
|
+
} | {
|
|
289
|
+
url: string;
|
|
290
|
+
enabled?: boolean | undefined;
|
|
291
|
+
}> | undefined;
|
|
333
292
|
}>, {
|
|
334
293
|
work_dir: string;
|
|
335
294
|
providers: ProviderConfig[];
|
|
336
295
|
session_dir: string;
|
|
337
|
-
plugins: string[];
|
|
338
|
-
agent_name: string;
|
|
339
296
|
max_turns: number;
|
|
297
|
+
log_level: "debug" | "info" | "warn" | "error";
|
|
298
|
+
theme: string;
|
|
299
|
+
agent_name: string;
|
|
340
300
|
tools_enabled: string[] | "all";
|
|
341
301
|
context_budget_tokens: number;
|
|
342
302
|
compress_threshold: number;
|
|
343
303
|
terminal_timeout_ms: number;
|
|
344
|
-
|
|
345
|
-
theme: string;
|
|
346
|
-
temperature?: number | undefined;
|
|
347
|
-
max_tokens?: number | undefined;
|
|
304
|
+
plugins: string[];
|
|
348
305
|
system_prompt?: string | undefined;
|
|
349
306
|
gateway?: {
|
|
350
307
|
platforms: ("webhook" | "telegram" | "discord" | "twitch")[];
|
|
351
308
|
token_envs: Record<string, string>;
|
|
352
309
|
} | undefined;
|
|
310
|
+
temperature?: number | undefined;
|
|
311
|
+
max_tokens?: number | undefined;
|
|
312
|
+
mcp_servers?: Record<string, {
|
|
313
|
+
enabled: boolean;
|
|
314
|
+
command: string;
|
|
315
|
+
args: string[];
|
|
316
|
+
env?: Record<string, string> | undefined;
|
|
317
|
+
} | {
|
|
318
|
+
url: string;
|
|
319
|
+
enabled: boolean;
|
|
320
|
+
}> | undefined;
|
|
353
321
|
}, {
|
|
354
322
|
providers: z.objectInputType<{
|
|
355
323
|
kind: z.ZodEnum<["openai_compat", "anthropic", "ollama"]>;
|
|
@@ -362,28 +330,172 @@ declare const agent_config_schema: z.ZodEffects<z.ZodObject<{
|
|
|
362
330
|
/** Injectable fetch, mainly for tests; passes through untouched. */
|
|
363
331
|
fetch_fn: z.ZodOptional<z.ZodType<typeof fetch, z.ZodTypeDef, typeof fetch>>;
|
|
364
332
|
}, z.ZodTypeAny, "passthrough">[];
|
|
365
|
-
plugins?: string[] | undefined;
|
|
366
|
-
temperature?: number | undefined;
|
|
367
|
-
max_tokens?: number | undefined;
|
|
368
|
-
agent_name?: string | undefined;
|
|
369
|
-
system_prompt?: string | undefined;
|
|
370
|
-
max_turns?: number | undefined;
|
|
371
333
|
work_dir?: string | undefined;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
compress_threshold?: number | undefined;
|
|
334
|
+
max_turns?: number | undefined;
|
|
335
|
+
system_prompt?: string | undefined;
|
|
375
336
|
session_dir?: string | undefined;
|
|
376
|
-
|
|
337
|
+
log_level?: "debug" | "info" | "warn" | "error" | undefined;
|
|
338
|
+
theme?: string | undefined;
|
|
377
339
|
gateway?: {
|
|
378
340
|
platforms?: ("webhook" | "telegram" | "discord" | "twitch")[] | undefined;
|
|
379
341
|
token_envs?: Record<string, string> | undefined;
|
|
380
342
|
} | undefined;
|
|
381
|
-
|
|
382
|
-
|
|
343
|
+
agent_name?: string | undefined;
|
|
344
|
+
tools_enabled?: string[] | "all" | undefined;
|
|
345
|
+
temperature?: number | undefined;
|
|
346
|
+
max_tokens?: number | undefined;
|
|
347
|
+
context_budget_tokens?: number | undefined;
|
|
348
|
+
compress_threshold?: number | undefined;
|
|
349
|
+
terminal_timeout_ms?: number | undefined;
|
|
350
|
+
plugins?: string[] | undefined;
|
|
351
|
+
mcp_servers?: Record<string, {
|
|
352
|
+
command: string;
|
|
353
|
+
enabled?: boolean | undefined;
|
|
354
|
+
args?: string[] | undefined;
|
|
355
|
+
env?: Record<string, string> | undefined;
|
|
356
|
+
} | {
|
|
357
|
+
url: string;
|
|
358
|
+
enabled?: boolean | undefined;
|
|
359
|
+
}> | undefined;
|
|
383
360
|
}>;
|
|
384
361
|
type AgentConfig = z.infer<typeof agent_config_schema>;
|
|
385
362
|
declare function parse_agent_config(raw: unknown): AgentConfig;
|
|
386
363
|
|
|
364
|
+
interface ToolResult {
|
|
365
|
+
ok: boolean;
|
|
366
|
+
output: string;
|
|
367
|
+
error?: string;
|
|
368
|
+
}
|
|
369
|
+
interface ToolContext {
|
|
370
|
+
work_dir: string;
|
|
371
|
+
env: Record<string, string>;
|
|
372
|
+
signal?: AbortSignal;
|
|
373
|
+
}
|
|
374
|
+
interface Tool {
|
|
375
|
+
name: string;
|
|
376
|
+
description: string;
|
|
377
|
+
parameters: JsonSchemaObject;
|
|
378
|
+
/** Per-tool executor timeout override in ms; unset tools get the 30s default. */
|
|
379
|
+
timeout_ms?: number;
|
|
380
|
+
execute(args: Record<string, unknown>, context: ToolContext): Promise<ToolResult>;
|
|
381
|
+
}
|
|
382
|
+
interface Toolset {
|
|
383
|
+
name: string;
|
|
384
|
+
tools: Tool[];
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Name-keyed registry of tools and toolsets. Registration rejects duplicate
|
|
389
|
+
* tool names so conflicting builtins fail loudly at startup.
|
|
390
|
+
*/
|
|
391
|
+
declare class ToolRegistry {
|
|
392
|
+
private readonly tools;
|
|
393
|
+
register(tool: Tool): void;
|
|
394
|
+
register_toolset(toolset: Toolset): void;
|
|
395
|
+
get(name: string): Tool | undefined;
|
|
396
|
+
has(name: string): boolean;
|
|
397
|
+
list(): Tool[];
|
|
398
|
+
/** Map registered tools onto the provider-facing wire shape. */
|
|
399
|
+
definitions(): ToolDefinition[];
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
interface LineChild {
|
|
403
|
+
write_line(line: string): void;
|
|
404
|
+
read_line(): Promise<string | undefined>;
|
|
405
|
+
stop(): void;
|
|
406
|
+
failed(): string | undefined;
|
|
407
|
+
}
|
|
408
|
+
type LineSpawner = (command: string, args: readonly string[], env?: Record<string, string>) => LineChild;
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Discover tools/list for each enabled server and register mcp_<server>_<tool>.
|
|
412
|
+
* tools_enabled filters them. An empty allowlist never connects.
|
|
413
|
+
*/
|
|
414
|
+
|
|
415
|
+
interface McpRuntime {
|
|
416
|
+
spawn?: LineSpawner;
|
|
417
|
+
fetch_fn?: typeof fetch;
|
|
418
|
+
env_path?: string;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Plugin surface: user-authored tools and lifecycle hooks loaded at startup.
|
|
423
|
+
*
|
|
424
|
+
* A plugin is a plain object exported from a TS/JS module. Hooks observe and
|
|
425
|
+
* (in the case of before_tool_call) veto tool executions; tools merge into the
|
|
426
|
+
* agent registry after builtin filtering.
|
|
427
|
+
*/
|
|
428
|
+
|
|
429
|
+
/** Runtime info handed to every hook call. */
|
|
430
|
+
interface HookContext {
|
|
431
|
+
work_dir: string;
|
|
432
|
+
/**
|
|
433
|
+
* This plugin's own per-run state sub-map. Every hook invocation receives
|
|
434
|
+
* a ctx exposing only the invoking plugin's bag; the bag is swapped fresh
|
|
435
|
+
* at each run start. Absent only on hand-built contexts outside the runner.
|
|
436
|
+
*/
|
|
437
|
+
state?: Map<string, unknown>;
|
|
438
|
+
}
|
|
439
|
+
/** Argument passed to before_tool_call hooks. */
|
|
440
|
+
interface BeforeToolCallInfo {
|
|
441
|
+
tool_name: string;
|
|
442
|
+
args: Record<string, unknown>;
|
|
443
|
+
}
|
|
444
|
+
/** Return value that vetoes a tool call; other hooks still run. */
|
|
445
|
+
interface BeforeToolCallResult {
|
|
446
|
+
block?: boolean;
|
|
447
|
+
reason?: string;
|
|
448
|
+
}
|
|
449
|
+
/** Argument passed to after_tool_call hooks. */
|
|
450
|
+
interface AfterToolCallInfo extends BeforeToolCallInfo {
|
|
451
|
+
result_summary: string;
|
|
452
|
+
/** Structured executor outcome; gate on this, never parse result_summary. */
|
|
453
|
+
ok: boolean;
|
|
454
|
+
error?: string;
|
|
455
|
+
}
|
|
456
|
+
interface RunEndInfo {
|
|
457
|
+
stopped_reason: string;
|
|
458
|
+
turns_used: number;
|
|
459
|
+
}
|
|
460
|
+
/** Optional lifecycle hooks a plugin may implement. All hooks are awaited. */
|
|
461
|
+
interface PluginHooks {
|
|
462
|
+
before_tool_call?(info: BeforeToolCallInfo, ctx: HookContext): Promise<BeforeToolCallResult | void> | BeforeToolCallResult | void;
|
|
463
|
+
after_tool_call?(info: AfterToolCallInfo, ctx: HookContext): Promise<void> | void;
|
|
464
|
+
on_run_start?(info: {
|
|
465
|
+
input_chars: number;
|
|
466
|
+
}, ctx: HookContext): Promise<void> | void;
|
|
467
|
+
on_run_end?(info: RunEndInfo, ctx: HookContext): Promise<void> | void;
|
|
468
|
+
}
|
|
469
|
+
/** A user plugin: required unique name, optional tools and hooks. */
|
|
470
|
+
interface Plugin {
|
|
471
|
+
name: string;
|
|
472
|
+
version?: string;
|
|
473
|
+
tools?: Tool[];
|
|
474
|
+
hooks?: PluginHooks;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/** A successfully loaded plugin plus the entry path it came from. */
|
|
478
|
+
interface LoadedPlugin {
|
|
479
|
+
plugin: Plugin;
|
|
480
|
+
entry: string;
|
|
481
|
+
}
|
|
482
|
+
/** One failed entry: the specifier and why it failed. */
|
|
483
|
+
interface PluginLoadError {
|
|
484
|
+
entry: string;
|
|
485
|
+
error_message: string;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Load plugins from explicit entry paths (relative to `base_dir` or absolute).
|
|
489
|
+
* Broken imports, missing exports, and duplicate names become error entries;
|
|
490
|
+
* nothing is thrown for a bad plugin.
|
|
491
|
+
*/
|
|
492
|
+
declare function load_plugins(entries: readonly string[], base_dir: string): Promise<{
|
|
493
|
+
plugins: LoadedPlugin[];
|
|
494
|
+
errors: PluginLoadError[];
|
|
495
|
+
}>;
|
|
496
|
+
/** Joined one-liner per load error, for a single warn log. */
|
|
497
|
+
declare function plugin_errors_summary(errors: readonly PluginLoadError[]): string;
|
|
498
|
+
|
|
387
499
|
/**
|
|
388
500
|
* Typed event emitter for the agent loop.
|
|
389
501
|
*
|
|
@@ -492,8 +604,14 @@ declare class Agent {
|
|
|
492
604
|
private readonly registry;
|
|
493
605
|
private readonly executor;
|
|
494
606
|
private readonly hook_runner;
|
|
495
|
-
|
|
607
|
+
private readonly mcp_runtime;
|
|
608
|
+
private mcp_attached;
|
|
609
|
+
constructor(config: AgentConfig, plugins?: readonly LoadedPlugin[], runtime?: {
|
|
610
|
+
mcp?: McpRuntime;
|
|
611
|
+
});
|
|
496
612
|
run(options: AgentRunOptions): Promise<AgentRunResult>;
|
|
613
|
+
/** tools/list once, before the model sees definitions. Empty allowlists never connect. */
|
|
614
|
+
private attach_mcp_once;
|
|
497
615
|
/** Per-run deps: the built-once ToolContext threads through every tool execution. */
|
|
498
616
|
private loop_deps;
|
|
499
617
|
/** Best-effort on_run_start fan-out; hook errors are logged, never fatal. */
|
|
@@ -511,20 +629,8 @@ declare function run_agent(raw_config: unknown, input: string, options?: {
|
|
|
511
629
|
label?: string;
|
|
512
630
|
}): Promise<AgentRunResult>;
|
|
513
631
|
|
|
514
|
-
/**
|
|
515
|
-
|
|
516
|
-
* tool names so conflicting builtins fail loudly at startup.
|
|
517
|
-
*/
|
|
518
|
-
declare class ToolRegistry {
|
|
519
|
-
private readonly tools;
|
|
520
|
-
register(tool: Tool): void;
|
|
521
|
-
register_toolset(toolset: Toolset): void;
|
|
522
|
-
get(name: string): Tool | undefined;
|
|
523
|
-
has(name: string): boolean;
|
|
524
|
-
list(): Tool[];
|
|
525
|
-
/** Map registered tools onto the provider-facing wire shape. */
|
|
526
|
-
definitions(): ToolDefinition[];
|
|
527
|
-
}
|
|
632
|
+
/** Write the client entry. The user sets enabled. Godot has nothing to write. */
|
|
633
|
+
declare function catalog_client_entry(name: string, substitutes?: Record<string, string>): Record<string, unknown> | string;
|
|
528
634
|
|
|
529
635
|
interface ExecutorDefaults {
|
|
530
636
|
work_dir?: string;
|
|
@@ -588,4 +694,4 @@ declare class HookedToolRunner {
|
|
|
588
694
|
|
|
589
695
|
declare const LICH_VERSION: string;
|
|
590
696
|
|
|
591
|
-
export { type AfterToolCallInfo, Agent, type AgentConfig, AgentEmitter, type AgentEvent, type AgentEventHandler, type AgentEvents, type AgentRunOptions, type AgentRunResult, type BeforeToolCallInfo, type BeforeToolCallResult, type ChatOptions, type ChatResult, type HookContext, HookedToolRunner, LICH_VERSION, type LoadedPlugin, type LoopOutcome, type LoopParams, type Message, type Plugin, type PluginHooks, type PluginLoadError, type ProviderConfig, ProviderError, type RunEndInfo, type Tool, type ToolCall, type ToolContext, type ToolDefinition, ToolExecutor, ToolRegistry, type ToolResult, type Usage, create_agent, create_agent_with_plugins, load_plugins, parse_agent_config, plugin_errors_summary, register_builtin_tools, run_agent };
|
|
697
|
+
export { type AfterToolCallInfo, Agent, type AgentConfig, AgentEmitter, type AgentEvent, type AgentEventHandler, type AgentEvents, type AgentRunOptions, type AgentRunResult, type BeforeToolCallInfo, type BeforeToolCallResult, type ChatOptions, type ChatResult, type HookContext, HookedToolRunner, LICH_VERSION, type LoadedPlugin, type LoopOutcome, type LoopParams, type Message, type Plugin, type PluginHooks, type PluginLoadError, type ProviderConfig, ProviderError, type RunEndInfo, type Tool, type ToolCall, type ToolContext, type ToolDefinition, ToolExecutor, ToolRegistry, type ToolResult, type Usage, catalog_client_entry, create_agent, create_agent_with_plugins, load_plugins, parse_agent_config, plugin_errors_summary, register_builtin_tools, run_agent };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
LICH_VERSION
|
|
3
|
-
|
|
2
|
+
LICH_VERSION,
|
|
3
|
+
catalog_client_entry
|
|
4
|
+
} from "./chunk-SAEB3QL3.js";
|
|
4
5
|
import {
|
|
5
6
|
Agent,
|
|
6
7
|
AgentEmitter,
|
|
@@ -15,7 +16,7 @@ import {
|
|
|
15
16
|
plugin_errors_summary,
|
|
16
17
|
register_builtin_tools,
|
|
17
18
|
run_agent
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-QVJCIZIF.js";
|
|
19
20
|
export {
|
|
20
21
|
Agent,
|
|
21
22
|
AgentEmitter,
|
|
@@ -24,6 +25,7 @@ export {
|
|
|
24
25
|
ProviderError,
|
|
25
26
|
ToolExecutor,
|
|
26
27
|
ToolRegistry,
|
|
28
|
+
catalog_client_entry,
|
|
27
29
|
create_agent,
|
|
28
30
|
create_agent_with_plugins,
|
|
29
31
|
load_plugins,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
fill_template,
|
|
3
3
|
load_theme
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JYURFAGB.js";
|
|
5
5
|
import {
|
|
6
6
|
LICH_VERSION
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SAEB3QL3.js";
|
|
8
8
|
import {
|
|
9
9
|
create_agent_with_plugins,
|
|
10
10
|
truncate_text
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-QVJCIZIF.js";
|
|
12
12
|
|
|
13
13
|
// src/tui.tsx
|
|
14
14
|
import { render } from "ink";
|
|
@@ -435,4 +435,4 @@ async function run_tui(config) {
|
|
|
435
435
|
export {
|
|
436
436
|
run_tui
|
|
437
437
|
};
|
|
438
|
-
//# sourceMappingURL=tui-
|
|
438
|
+
//# sourceMappingURL=tui-L6RABP2J.js.map
|
|
@@ -29,6 +29,9 @@ export default defineConfig({
|
|
|
29
29
|
{ text: 'TUI guide', link: '/user-guide/tui' },
|
|
30
30
|
{ text: 'Gateway guide', link: '/user-guide/gateway' },
|
|
31
31
|
{ text: 'Library guide', link: '/user-guide/library' },
|
|
32
|
+
{ text: 'Plugins guide', link: '/user-guide/plugins' },
|
|
33
|
+
{ text: 'Godot guide', link: '/user-guide/godot' },
|
|
34
|
+
{ text: 'Redot guide', link: '/user-guide/redot' },
|
|
32
35
|
{ text: 'Games guide', link: '/user-guide/games' }
|
|
33
36
|
]
|
|
34
37
|
},
|
|
@@ -39,6 +42,7 @@ export default defineConfig({
|
|
|
39
42
|
{ text: 'Agent loop', link: '/architecture/agent-loop' },
|
|
40
43
|
{ text: 'Providers', link: '/architecture/providers' },
|
|
41
44
|
{ text: 'Tools', link: '/architecture/tools' },
|
|
45
|
+
{ text: 'Plugins', link: '/architecture/plugins' },
|
|
42
46
|
{ text: 'Extending', link: '/architecture/extending' }
|
|
43
47
|
]
|
|
44
48
|
}
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
# Architecture Overview
|
|
2
2
|
|
|
3
|
-
Lich
|
|
3
|
+
Lich is a small TypeScript AI agent harness: it drives a chat model in a
|
|
4
4
|
think-act-observe loop, lets the model call tools, compresses history when the
|
|
5
|
-
context budget demands it, and persists transcripts.
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
context budget demands it, and persists transcripts. The published npm package
|
|
6
|
+
is 0.6.0. This tree also includes unreleased editor MCP (changelog 0.7.0);
|
|
7
|
+
`package.json` is still 0.6.0, so `lich --version` prints `0.6.0`. It runs on
|
|
8
|
+
Node >= 20 and on Bun, is ESM with NodeNext resolution, and its runtime
|
|
9
|
+
dependencies are `zod` (config validation), `ink`, and `react` (the TUI).
|
|
10
|
+
Everything else is Node/Bun built-ins.
|
|
8
11
|
|
|
9
12
|
This page is the map. The follow-up pages go deep on each area:
|
|
10
13
|
[agent loop](./agent-loop.md), [providers](./providers.md),
|
|
11
|
-
[tools](./tools.md), and [extending](./extending.md).
|
|
14
|
+
[tools](./tools.md), [plugins](./plugins.md), and [extending](./extending.md).
|
|
12
15
|
|
|
13
16
|
## Layer diagram
|
|
14
17
|
|
|
15
18
|
```mermaid
|
|
16
19
|
flowchart TB
|
|
17
20
|
subgraph entry["Entry surfaces"]
|
|
18
|
-
CLI["src/cli.ts<br/>one-shot
|
|
21
|
+
CLI["src/cli.ts<br/>one-shot, chat, tui,<br/>gateway, mcp"]
|
|
19
22
|
TUI["src/tui/app.tsx<br/>ink TUI"]
|
|
20
23
|
GW["src/gateway/runner.ts<br/>webhook, telegram,<br/>discord, twitch"]
|
|
21
24
|
LIB["src/index.ts<br/>library exports"]
|
|
@@ -94,36 +97,42 @@ Why this matters:
|
|
|
94
97
|
Walkthrough of a single `Agent.run({ input })` call
|
|
95
98
|
([`src/agent/agent.ts`](../../src/agent/agent.ts)):
|
|
96
99
|
|
|
97
|
-
1. **
|
|
100
|
+
1. **MCP attach, once.** Before the first model call, enabled `mcp_servers`
|
|
101
|
+
are connected (`initialize`, `notifications/initialized`, then `tools/list`)
|
|
102
|
+
and registered as `mcp_<server>_<tool>`. An empty `tools_enabled` never
|
|
103
|
+
connects. Disabled servers are skipped. A connect failure logs a warning
|
|
104
|
+
and the run continues. This client is in this source only (0.7.0 unreleased).
|
|
105
|
+
2. **Usage collector attached.** `run()` subscribes a `collect_usage` handler
|
|
98
106
|
on `agent.events`; every `llm_end` event adds the call's token usage into a
|
|
99
107
|
per-run `Usage` total. The subscription is removed in a `finally` block.
|
|
100
|
-
|
|
108
|
+
3. **Seed messages.** The caller's `history` (if any) is copied into a fresh
|
|
101
109
|
array and the new user message is appended. The caller's array is never
|
|
102
110
|
mutated.
|
|
103
|
-
|
|
111
|
+
4. **Loop starts.** `run_conversation(deps, seed, params)` first applies the
|
|
104
112
|
system prompt via `seed_system_prompt` (prepend, or replace an existing
|
|
105
113
|
system message if its content differs) and then enters the turn loop
|
|
106
114
|
described in [agent loop](./agent-loop.md).
|
|
107
|
-
|
|
115
|
+
5. **Each turn.** Abort check at the top of the turn, optional compression
|
|
108
116
|
check, then one LLM call through the router (`chat_with_failover`, which
|
|
109
117
|
walks providers with bounded in-place retries). The assistant message is
|
|
110
118
|
pushed onto the history.
|
|
111
|
-
|
|
112
|
-
through the `ToolExecutor` (30 s
|
|
113
|
-
and a `tool` message is appended per call.
|
|
119
|
+
6. **Tools.** If the assistant message carries `tool_calls`, each call runs
|
|
120
|
+
through the `ToolExecutor` (per-tool `timeout_ms`, else 30 s; abort linking,
|
|
121
|
+
output clamping) and a `tool` message is appended per call. `terminal` sets
|
|
122
|
+
300000 ms; `run_tests` sets 600000. The loop then starts the next
|
|
114
123
|
turn. A turn with no tool calls is the final turn.
|
|
115
|
-
|
|
124
|
+
7. **Outcome.** The loop returns a `LoopOutcome`: the full `messages` array,
|
|
116
125
|
the final assistant message (or the last one seen), the last `ChatResult`
|
|
117
126
|
on a real final, `turns_used`, and a `stopped_reason` of `final`, `budget`,
|
|
118
127
|
or `aborted`.
|
|
119
|
-
|
|
128
|
+
8. **Session persist.** `persist_session()` appends one `meta` record
|
|
120
129
|
(`run_start`), then one `message` record per outcome message, then a
|
|
121
130
|
`budget_exhausted` meta record if the budget stopped the run, then a
|
|
122
131
|
`run_end` meta record (`stopped_reason`, `usage`) for every completed
|
|
123
132
|
run, to a JSONL file under `session_dir` (default
|
|
124
133
|
`<work_dir>/.lich/sessions`). Persistence is best-effort: failures are
|
|
125
134
|
logged and the run still succeeds with `session_path: undefined`.
|
|
126
|
-
|
|
135
|
+
9. **Return.** `AgentRunResult` bundles the outcome, the full transcript
|
|
127
136
|
(prior history plus the new exchange), the collected `usage_total`, and the
|
|
128
137
|
session path.
|
|
129
138
|
|
|
@@ -150,8 +159,11 @@ Walkthrough of a single `Agent.run({ input })` call
|
|
|
150
159
|
| Path | Responsibility |
|
|
151
160
|
| --- | --- |
|
|
152
161
|
| `src/index.ts` | Public library surface; pure re-exports plus `LICH_VERSION`. |
|
|
153
|
-
| `src/cli.ts` |
|
|
154
|
-
| `src/cli_config.ts` | Config file discovery, loading, flag overrides, template. |
|
|
162
|
+
| `src/cli.ts` | CLI: one-shot, `chat`, `tui`, `gateway`, `init`, `config`, `update`, `mcp`. |
|
|
163
|
+
| `src/cli_config.ts` | Config file discovery, loading, flag overrides, template, writer. |
|
|
164
|
+
| `src/cli_update.ts` | `lich update`: npm view, then `npm install -g` when newer. Git clones are told to `git pull`. |
|
|
165
|
+
| `src/cli_mcp.ts` | `lich mcp` list/add/enable/disable/remove against work-dir config. |
|
|
166
|
+
| `src/mcp/*` | MCP client: catalog, stdio/loopback HTTP, tool registration. |
|
|
155
167
|
| `src/agent/agent.ts` | `Agent`: wires router, registry, executor; sessions; usage. |
|
|
156
168
|
| `src/agent/loop.ts` | `run_conversation`: the think-act-observe loop. |
|
|
157
169
|
| `src/agent/config.ts` | Zod config schema, defaults, derived `session_dir`, freeze. |
|
|
@@ -170,6 +182,7 @@ Walkthrough of a single `Agent.run({ input })` call
|
|
|
170
182
|
| `src/tools/registry.ts` | Name-keyed tool registry; duplicate rejection. |
|
|
171
183
|
| `src/tools/executor.ts` | Never-throw execution with timeout and abort. |
|
|
172
184
|
| `src/tools/builtin/*` | Builtin tools, including `run_tests` (see [tools](./tools.md)). |
|
|
185
|
+
| `src/plugins/*` | Plugin loader and hooks. Gatekeeper registers `git_commit` in code. |
|
|
173
186
|
| `src/gateway/bus.ts` | Conversation-keyed runner over one shared `Agent`. |
|
|
174
187
|
| `src/gateway/runner.ts` | Adapter construction, signal handling, process lifetime. |
|
|
175
188
|
| `src/gateway/{telegram,discord,twitch,webhook}.ts` | Platform adapters. |
|