kimi-code / packages /klient /README.md
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
d522ffa verified
|
Raw History Blame Contribute Delete
4.64 kB
# @moonshot-ai/klient
Contract-driven client SDK for the agent-core-v2 engine. One facade, two
transports β€” you pick the transport **once** at creation; everything after
that is byte-identical:
```ts
import { bootstrap, logSeed, resolveLoggingConfig } from '@moonshot-ai/agent-core-v2';
import { createKlient } from '@moonshot-ai/klient/memory'; // or '/ipc'
const { app } = bootstrap({ homeDir }, [
...logSeed(resolveLoggingConfig({ homeDir, env: process.env })),
]);
const klient = createKlient({ scope: app });
const env = await klient.global.env();
const sessions = await klient.global.sessions.list({ limit: 20 });
const session = await klient.global.sessions.create({ workDir: process.cwd() });
const agent = klient.session(session.id).agent('main');
agent.events.on('assistant.delta', (e) => process.stdout.write(e.delta));
agent.events.on('prompt.completed', () => console.log('\ndone'));
await agent.prompt({ input: [{ type: 'text', text: 'Say OK.' }] });
await klient.close();
```
## Architecture
```
facade (klient.global.*, klient.session(id).*, session.agent(id).*, *.events.*)
↓ single-object params, zod-validated
contract (procedure schemas, shared by all transports)
↓
KlientChannel { call, listen } ← the only transport SPI
↓
ipc β”‚ memory
```
- **Facade** β€” aggregated methods, no engine service tokens, no
`onDid*`/`onWill*` event names. There is no escape hatch to raw services:
the facade is the public contract.
- `klient.global.*` β€” `sessions.*` (incl. `create`), `workspaces.*`,
`config.*`, `providers.*`, `models.*`, `catalog.*`, `auth.*`, `flags.*`,
`plugins.*`, `hostFs.*`, `env()`.
- `klient.session(id).*` β€” `get/setTitle/update/status/close/archive/
restore/fork/createChild`, `approvals.*`, `questions.*`,
`interactions.*`, `agents()`.
- `session.agent(id).*` β€” `prompt/steer/cancel/runShellCommand/
cancelShellCommand/getModel/setModel/setPermission/getUsage/getContext/
getPlan*/getTasks*/stopTask/getTaskOutput`.
- **Contract** β€” every method has a zod input tuple + output schema, validated
on the client before send / after receive (default on; `validate: false` to
disable). Validation is sub-Β΅s for typical payloads β€” cheaper than the JSON
serialization the wire already pays.
- **Events** β€” `klient.events.on(...)` for the global bus
(`config.changed`, `kosong.models.changed`, `session.archived`, …),
`session(id).events.on('metadata.changed' | 'interactions.changed' |
'interactions.resolved')`, and `agent(id).events.on('turn.started' |
'assistant.delta' | 'tool.call.started' | 'prompt.completed' | …)`.
Underlying subscriptions are shared and ref-counted; payloads are
validated; bad payloads drop to `events.onError`.
## Transports
| entry | options | events |
|---|---|---|
| `@moonshot-ai/klient/ipc` | `{ socketPath, token? }` | same socket |
| `@moonshot-ai/klient/memory` | `{ scope }` (a bootstrapped engine app scope) | direct emitter/bus subscription |
`ipc` and `memory` share one in-process dispatcher, so they behave identically
by construction; `memory` additionally JSON round-trips every value so results
cross the same JSON boundary a socket transport would impose. The IPC host
ships with the transport: `serveKlientIpc({ scope, socketPath })`.
The same conformance suite runs against both transports in this
package's tests (`test/helpers/conformance.ts` β€” one test file per transport).
This package also hosts the e2e suites (the retired `server-e2e` package was
folded in here):
- `test/e2e/legacy/` + `test/e2e/harness/` β€” the legacy `/api/v1` live suites
and their client harness (skip unless `KIMI_SERVER_URL` is set; the v1
surface has no in-memory equivalent, so these stay live-server-only).
The docker e2e runner (`pnpm docker:e2e`) runs this whole vitest suite inside
a container against a container-local server. See `AGENTS.md` for the testing
rules.
## Scope
The facade covers the global (app), session, and agent surfaces shown above.
What it deliberately leaves out (for now): onWill/hook-style interception
(engine hooks are in-process `OrderedHookSlot`s and not wire-exposable), file
upload (v1 multipart REST only), and the terminal surface (v1 REST + WS
only).
## Smoke check
```sh
pnpm -C packages/klient smoke
```
`examples/smoke.ts` boots an in-process engine (memory transport) and asserts
the `global` facade end-to-end β€” no server needed. `examples/basic.ts` is a
shorter narrated tour; `examples/context-usage.ts` traces context-size
readings through a real prompt (requires `KIMI_EXAMPLE_MODEL` +
`KIMI_EXAMPLE_API_KEY`).