@moikapy/lich 0.5.0 → 0.6.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 +19 -0
- package/README.md +58 -1
- package/dist/chunk-6M6OAQGN.js +17 -0
- package/dist/chunk-6M6OAQGN.js.map +1 -0
- package/dist/{chunk-CV2YH3FH.js → chunk-7HLVKVIG.js} +18 -5
- package/dist/chunk-7HLVKVIG.js.map +1 -0
- package/dist/chunk-JC2G3XH2.js +92 -0
- package/dist/chunk-JC2G3XH2.js.map +1 -0
- package/dist/cli.d.ts +9 -1
- package/dist/cli.js +102 -15
- package/dist/cli.js.map +1 -1
- package/dist/{gateway-W6S43ETE.js → gateway-RJFZJEUZ.js} +2 -2
- package/dist/index.d.ts +7 -5
- package/dist/index.js +2 -2
- package/dist/{tui-DT7XWDTX.js → tui-LOUJVZ6A.js} +43 -41
- package/dist/tui-LOUJVZ6A.js.map +1 -0
- package/docs/.vitepress/config.mts +2 -1
- package/docs/architecture/agent-loop.md +5 -3
- package/docs/architecture/overview.md +5 -4
- package/docs/getting-started.md +3 -2
- package/docs/index.md +1 -0
- package/docs/user-guide/cli.md +5 -2
- package/docs/user-guide/games.md +93 -0
- package/docs/user-guide/godot.md +1 -1
- package/docs/user-guide/library.md +6 -2
- package/docs/user-guide/tui.md +11 -11
- package/package.json +2 -1
- package/dist/chunk-CV2YH3FH.js.map +0 -1
- package/dist/chunk-ZVK3MUPC.js +0 -7
- package/dist/chunk-ZVK3MUPC.js.map +0 -1
- package/dist/tui-DT7XWDTX.js.map +0 -1
- /package/dist/{gateway-W6S43ETE.js.map → gateway-RJFZJEUZ.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0 (unreleased)
|
|
4
|
+
|
|
5
|
+
- document a per-persona orchestrator example: one agent per NPC, the
|
|
6
|
+
webhook `POST /message` shape, and history serialization the game repo
|
|
7
|
+
copies. lich does not ship the service. see
|
|
8
|
+
examples/persona_orchestrator.
|
|
9
|
+
- document session JSONL as a combat log, with jq recipes for rationale,
|
|
10
|
+
ability use, vetoes, rejects, and `run_end` token totals. see
|
|
11
|
+
docs/user-guide/games.md.
|
|
12
|
+
- append a `run_end` meta record (`stopped_reason`, `usage`) on every
|
|
13
|
+
completed run so token spend is in the transcript. `budget_exhausted`
|
|
14
|
+
is still written when the stop reason is budget.
|
|
15
|
+
- add a display-only undead theme: frozen `lich` strings, `theme` / `--theme`, and `~/.lich/themes/<name>.json` that falls back to the built-in theme when missing or invalid.
|
|
16
|
+
|
|
17
|
+
## 0.5.1
|
|
18
|
+
|
|
19
|
+
- fix the CLI so bun's global bin enters main (symlink argv no longer skips the entry).
|
|
20
|
+
- read LICH_VERSION from package.json so lich --version is not stuck at 0.3.0.
|
|
21
|
+
|
|
3
22
|
## 0.5.0
|
|
4
23
|
|
|
5
24
|
- add a `game_bridge` example plugin that queues batched enemy actions
|
package/README.md
CHANGED
|
@@ -1,10 +1,29 @@
|
|
|
1
|
-
# lich
|
|
1
|
+
# ⚱ lich
|
|
2
2
|
|
|
3
3
|
Lich is a TypeScript AI agent harness (library + CLI) that runs a
|
|
4
4
|
Think-Act-Observe loop: an LLM plans, calls tools, observes results, and
|
|
5
5
|
repeats until it produces a final answer. It ships with provider failover,
|
|
6
6
|
tool guardrails, context compression, and JSONL session persistence.
|
|
7
7
|
|
|
8
|
+
## Lore glossary
|
|
9
|
+
|
|
10
|
+
Lore names are prose only. Identifiers, config keys, event types, and tool
|
|
11
|
+
names do not change. The default system prompt is a myth-free behavior spec;
|
|
12
|
+
mythology lives in display strings only.
|
|
13
|
+
|
|
14
|
+
| Lore term | Actual concept | Where it appears |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| **phylacteries** | JSONL session files in `.lich/sessions/` — conversations survive process death | This glossary; TUI `/sessions` listing label |
|
|
17
|
+
| **vessel-hopping** | Provider failover: 429/5xx retried with backoff, then the next provider takes over | This glossary |
|
|
18
|
+
| **the lair / wards** | `work_dir` confinement + `path_escape` guardrails | This glossary |
|
|
19
|
+
| **lair actions** | Plugin hooks that observe or veto tool calls | This glossary |
|
|
20
|
+
| **familiars** | Gateway adapters (webhook/telegram/discord/twitch) routing into one shared agent | This glossary |
|
|
21
|
+
| **spells** | Builtin tools in the registry | This glossary |
|
|
22
|
+
| **distillation** | Context compression: old turns summarized to fit the token budget | TUI compress notice |
|
|
23
|
+
| **the ritual is spent** | Turn-budget exhaustion | TUI + CLI budget notices |
|
|
24
|
+
| **dormant / deliberating / casting** | idle / thinking / tool phases | TUI status bar phase labels |
|
|
25
|
+
| **mortal** | The human user | TUI user transcript label |
|
|
26
|
+
|
|
8
27
|
## Documentation
|
|
9
28
|
|
|
10
29
|
| Page | Contents |
|
|
@@ -15,6 +34,8 @@ tool guardrails, context compression, and JSONL session persistence.
|
|
|
15
34
|
| [TUI guide](docs/user-guide/tui.md) | Launch, slash commands, status bar, memory semantics. |
|
|
16
35
|
| [Gateway guide](docs/user-guide/gateway.md) | Webhook/Telegram/Discord/Twitch setup and the webhook API. |
|
|
17
36
|
| [Library guide](docs/user-guide/library.md) | Embedding: `create_agent`, events, multi-turn history, errors. |
|
|
37
|
+
| [Games guide](docs/user-guide/games.md) | Session JSONL as a combat log, and jq recipes over it. |
|
|
38
|
+
| [Persona example](examples/persona_orchestrator/README.md) | Per-NPC agents the game repo copies. Not a second core. |
|
|
18
39
|
|
|
19
40
|
## Quick start (CLI)
|
|
20
41
|
|
|
@@ -184,6 +205,42 @@ lich tui
|
|
|
184
205
|
Slash commands: `/help`, `/model`, `/usage`, `/clear`, `/sessions`,
|
|
185
206
|
`/exit` (also `/quit`, `/q`). The transcript shows the newest 50 blocks.
|
|
186
207
|
|
|
208
|
+
## Themes
|
|
209
|
+
|
|
210
|
+
Display strings come from one active theme per process. Set `"theme": "lich"`
|
|
211
|
+
in `.lich/config.json`, or pass `--theme <name>`. The built-in `lich` theme
|
|
212
|
+
is frozen data: `~/.lich/themes/lich.json` is ignored. Any other name is read
|
|
213
|
+
from `~/.lich/themes/<name>.json`. A missing file, invalid JSON, or a file
|
|
214
|
+
that fails the theme schema logs one warning and falls back to `lich`. Themes
|
|
215
|
+
do not change the system prompt, tool descriptions, event types, or slash
|
|
216
|
+
command names.
|
|
217
|
+
|
|
218
|
+
The built-in tagline is `the agent that will not stay dead`, and it appears once, in the TUI banner (`welcome`). Greppable keywords
|
|
219
|
+
stay in place: budget notices still start with `budget exhausted`, and
|
|
220
|
+
compression notices still start with `context compressed`.
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"name": "vampire",
|
|
225
|
+
"agent_name": "vampire",
|
|
226
|
+
"glyph": "🦇",
|
|
227
|
+
"tagline": "night's clerk, unpaid",
|
|
228
|
+
"welcome": "🦇 vampire v{version} — night's clerk, unpaid · {model} ({kind})",
|
|
229
|
+
"goodbye": "dawn approaches",
|
|
230
|
+
"response_label": "vampire",
|
|
231
|
+
"user_label": "mortal",
|
|
232
|
+
"phase_labels": { "idle": "sleeping", "thinking": "scheming", "tool": "feeding" },
|
|
233
|
+
"notices": {
|
|
234
|
+
"budget_exhausted": "budget exhausted — the blood bank is dry (turn cap reached)",
|
|
235
|
+
"compressed": "context compressed — memories enthralled (summary {chars} chars)",
|
|
236
|
+
"sessions": "coffins ({count}):"
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`welcome` substitutes `{version}`, `{model}`, and `{kind}`. `notices.compressed`
|
|
242
|
+
substitutes `{chars}`; `notices.sessions` substitutes `{count}`.
|
|
243
|
+
|
|
187
244
|
## Development
|
|
188
245
|
|
|
189
246
|
```sh
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
function read_package_version() {
|
|
5
|
+
const pkg_path = fileURLToPath(new URL("../package.json", import.meta.url));
|
|
6
|
+
const pkg = JSON.parse(readFileSync(pkg_path, "utf8"));
|
|
7
|
+
if (typeof pkg.version !== "string" || pkg.version.length === 0) {
|
|
8
|
+
throw new Error("package.json is missing version");
|
|
9
|
+
}
|
|
10
|
+
return pkg.version;
|
|
11
|
+
}
|
|
12
|
+
var LICH_VERSION = read_package_version();
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
LICH_VERSION
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=chunk-6M6OAQGN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Public surface of the lich agent harness. Pure re-exports, plus the package version.\n */\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\nfunction read_package_version(): string {\n const pkg_path = fileURLToPath(new URL(\"../package.json\", import.meta.url));\n const pkg = JSON.parse(readFileSync(pkg_path, \"utf8\")) as { version?: unknown };\n if (typeof pkg.version !== \"string\" || pkg.version.length === 0) {\n throw new Error(\"package.json is missing version\");\n }\n return pkg.version;\n}\n\nexport const LICH_VERSION = read_package_version();\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":";AAGA,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAE9B,SAAS,uBAA+B;AACtC,QAAM,WAAW,cAAc,IAAI,IAAI,mBAAmB,YAAY,GAAG,CAAC;AAC1E,QAAM,MAAM,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AACrD,MAAI,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,WAAW,GAAG;AAC/D,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AACA,SAAO,IAAI;AACb;AAEO,IAAM,eAAe,qBAAqB;","names":[]}
|
|
@@ -1930,7 +1930,7 @@ var provider_schema = z.object({
|
|
|
1930
1930
|
fetch_fn: z.custom(() => true).optional()
|
|
1931
1931
|
}).passthrough();
|
|
1932
1932
|
var agent_config_schema = z.object({
|
|
1933
|
-
/**
|
|
1933
|
+
/** Wizard label. The TUI banner uses the active theme welcome string. */
|
|
1934
1934
|
agent_name: z.string().min(1).default("lich"),
|
|
1935
1935
|
system_prompt: z.string().optional(),
|
|
1936
1936
|
max_turns: z.number().int().min(1).default(25),
|
|
@@ -1946,7 +1946,8 @@ var agent_config_schema = z.object({
|
|
|
1946
1946
|
/** Plugin entry module specifiers, relative to work_dir or absolute. */
|
|
1947
1947
|
plugins: z.array(z.string()).default([]),
|
|
1948
1948
|
gateway: gateway_schema,
|
|
1949
|
-
log_level: z.enum(["debug", "info", "warn", "error"]).default("info")
|
|
1949
|
+
log_level: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
1950
|
+
theme: z.string().min(1).default("lich")
|
|
1950
1951
|
}).transform((config) => {
|
|
1951
1952
|
const work_dir = config.work_dir ?? process.cwd();
|
|
1952
1953
|
return {
|
|
@@ -3640,6 +3641,17 @@ function collect_usage(total) {
|
|
|
3640
3641
|
function append_meta(handle, meta) {
|
|
3641
3642
|
return handle.append({ ts: (/* @__PURE__ */ new Date()).toISOString(), kind: "meta", meta });
|
|
3642
3643
|
}
|
|
3644
|
+
function append_run_end(handle, stopped_reason, usage_total) {
|
|
3645
|
+
return append_meta(handle, {
|
|
3646
|
+
event: "run_end",
|
|
3647
|
+
stopped_reason,
|
|
3648
|
+
usage: {
|
|
3649
|
+
prompt_tokens: usage_total.prompt_tokens,
|
|
3650
|
+
completion_tokens: usage_total.completion_tokens,
|
|
3651
|
+
total_tokens: usage_total.total_tokens
|
|
3652
|
+
}
|
|
3653
|
+
});
|
|
3654
|
+
}
|
|
3643
3655
|
function register_plugin_tools(registry, plugins) {
|
|
3644
3656
|
for (const loaded of plugins) {
|
|
3645
3657
|
for (const tool of loaded.plugin.tools ?? []) {
|
|
@@ -3716,7 +3728,7 @@ var Agent = class {
|
|
|
3716
3728
|
await this.call_plugin_run_end(outcome);
|
|
3717
3729
|
}
|
|
3718
3730
|
}
|
|
3719
|
-
const session_path = await this.persist_session(outcome, options);
|
|
3731
|
+
const session_path = await this.persist_session(outcome, options, usage_total);
|
|
3720
3732
|
const full_messages = [...options.history ?? [], ...outcome.messages];
|
|
3721
3733
|
return { outcome, messages: full_messages, usage_total, session_path };
|
|
3722
3734
|
}
|
|
@@ -3750,7 +3762,7 @@ var Agent = class {
|
|
|
3750
3762
|
);
|
|
3751
3763
|
}
|
|
3752
3764
|
/** Best-effort JSONL transcript: never fails the run, returns undefined path on error. */
|
|
3753
|
-
async persist_session(outcome, options) {
|
|
3765
|
+
async persist_session(outcome, options, usage_total) {
|
|
3754
3766
|
try {
|
|
3755
3767
|
const handle = await open_session(this.config.session_dir, options.label);
|
|
3756
3768
|
await append_meta(handle, { event: "run_start", input_chars: options.input.length, history_size: outcome.messages.length });
|
|
@@ -3760,6 +3772,7 @@ var Agent = class {
|
|
|
3760
3772
|
if (outcome.stopped_reason === "budget") {
|
|
3761
3773
|
await append_meta(handle, { event: "budget_exhausted" });
|
|
3762
3774
|
}
|
|
3775
|
+
await append_run_end(handle, outcome.stopped_reason, usage_total);
|
|
3763
3776
|
return handle.path;
|
|
3764
3777
|
} catch (error) {
|
|
3765
3778
|
logger.warn("session persistence failed; continuing without transcript", error);
|
|
@@ -3806,4 +3819,4 @@ export {
|
|
|
3806
3819
|
create_agent_with_plugins,
|
|
3807
3820
|
run_agent
|
|
3808
3821
|
};
|
|
3809
|
-
//# sourceMappingURL=chunk-
|
|
3822
|
+
//# sourceMappingURL=chunk-7HLVKVIG.js.map
|