feat: add per-session model selection
This commit is contained in:
@@ -30,11 +30,11 @@ cp docs/templates/TOOLS.md ~/.clawdis/workspace/TOOLS.md
|
||||
cp docs/AGENTS.default.md ~/.clawdis/workspace/AGENTS.md
|
||||
```
|
||||
|
||||
4) Optional: choose a different workspace by setting `inbound.workspace` (supports `~`):
|
||||
4) Optional: choose a different workspace by setting `agent.workspace` (supports `~`):
|
||||
|
||||
```json5
|
||||
{
|
||||
inbound: {
|
||||
agent: {
|
||||
workspace: "~/clawd"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ read_when:
|
||||
- Session selection:
|
||||
- If `--session-id` is given, reuse it.
|
||||
- Else if `--to <e164>` is given, derive the session key from `inbound.session.scope` (direct chats collapse to `inbound.session.mainKey`).
|
||||
- Runs the embedded Pi agent (configured via `inbound.agent`).
|
||||
- Runs the embedded Pi agent (configured via `agent`).
|
||||
- Thinking/verbose:
|
||||
- Flags `--thinking <off|minimal|low|medium|high>` and `--verbose <on|off>` persist into the session store.
|
||||
- Output:
|
||||
|
||||
@@ -10,13 +10,13 @@ CLAWDIS runs a single embedded agent runtime derived from **p-mono** (internal n
|
||||
|
||||
## Workspace (required)
|
||||
|
||||
You must set an agent home directory via `inbound.workspace`. CLAWDIS uses this as the agent’s **only** working directory (`cwd`) for tools and context.
|
||||
You must set an agent home directory via `agent.workspace`. CLAWDIS uses this as the agent’s **only** working directory (`cwd`) for tools and context.
|
||||
|
||||
Recommended: use `clawdis setup` to create `~/.clawdis/clawdis.json` if missing and initialize the workspace files.
|
||||
|
||||
## Bootstrap files (injected)
|
||||
|
||||
Inside `inbound.workspace`, CLAWDIS expects these user-editable files:
|
||||
Inside `agent.workspace`, CLAWDIS expects these user-editable files:
|
||||
- `AGENTS.md` — operating instructions + “memory”
|
||||
- `SOUL.md` — persona, boundaries, tone
|
||||
- `TOOLS.md` — user-maintained tool notes (e.g. `imsg`, `sag`, conventions)
|
||||
@@ -75,7 +75,7 @@ Incoming user messages are queued while the agent is streaming. The queue is che
|
||||
## Configuration (minimal)
|
||||
|
||||
At minimum, set:
|
||||
- `inbound.workspace`
|
||||
- `agent.workspace`
|
||||
- `inbound.allowFrom` (strongly recommended)
|
||||
|
||||
---
|
||||
|
||||
@@ -94,7 +94,7 @@ Tip: treat this folder like Clawd’s “memory” and make it a git repo (ideal
|
||||
clawdis setup
|
||||
```
|
||||
|
||||
Optional: choose a different workspace with `inbound.workspace` (supports `~`).
|
||||
Optional: choose a different workspace with `agent.workspace` (supports `~`).
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -149,7 +149,7 @@ Example:
|
||||
|
||||
## Heartbeats (proactive mode)
|
||||
|
||||
When `inbound.agent.heartbeatMinutes > 0`, CLAWDIS periodically runs a heartbeat prompt (default: `HEARTBEAT`).
|
||||
When `agent.heartbeatMinutes > 0`, CLAWDIS periodically runs a heartbeat prompt (default: `HEARTBEAT`).
|
||||
|
||||
- If the agent replies with `HEARTBEAT_OK` (exact token), CLAWDIS suppresses outbound delivery for that heartbeat.
|
||||
|
||||
|
||||
@@ -11,18 +11,16 @@ CLAWDIS reads an optional **JSON5** config from `~/.clawdis/clawdis.json` (comme
|
||||
If the file is missing, CLAWDIS uses safe-ish defaults (embedded Pi agent + per-sender sessions + workspace `~/clawd`). You usually only need a config to:
|
||||
- restrict who can trigger the bot (`inbound.allowFrom`)
|
||||
- tune group mention behavior (`inbound.groupChat`)
|
||||
- set the agent’s workspace (`inbound.workspace`)
|
||||
- tune the embedded agent (`inbound.agent`) and session behavior (`inbound.session`)
|
||||
- set the agent’s workspace (`agent.workspace`)
|
||||
- tune the embedded agent (`agent`) and session behavior (`inbound.session`)
|
||||
- set the agent’s identity (`identity`)
|
||||
|
||||
## Minimal config (recommended starting point)
|
||||
|
||||
```json5
|
||||
{
|
||||
inbound: {
|
||||
allowFrom: ["+15555550123"],
|
||||
workspace: "~/clawd"
|
||||
}
|
||||
agent: { workspace: "~/clawd" },
|
||||
inbound: { allowFrom: ["+15555550123"] }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -86,7 +84,7 @@ Group messages default to **require mention** (either metadata mention or regex
|
||||
}
|
||||
```
|
||||
|
||||
### `inbound.workspace`
|
||||
### `agent.workspace`
|
||||
|
||||
Sets the **single global workspace directory** used by the agent for file operations.
|
||||
|
||||
@@ -94,29 +92,33 @@ Default: `~/clawd`.
|
||||
|
||||
```json5
|
||||
{
|
||||
inbound: { workspace: "~/clawd" }
|
||||
agent: { workspace: "~/clawd" }
|
||||
}
|
||||
```
|
||||
|
||||
### `inbound.agent`
|
||||
### `agent`
|
||||
|
||||
Controls the embedded agent runtime (provider/model/thinking/verbose/timeouts).
|
||||
`allowedModels` lets `/model` list/filter and enforce a per-session allowlist
|
||||
(omit to show the full catalog).
|
||||
|
||||
```json5
|
||||
{
|
||||
inbound: {
|
||||
workspace: "~/clawd",
|
||||
agent: {
|
||||
provider: "anthropic",
|
||||
model: "claude-opus-4-5",
|
||||
thinkingDefault: "low",
|
||||
verboseDefault: "off",
|
||||
timeoutSeconds: 600,
|
||||
mediaMaxMb: 5,
|
||||
heartbeatMinutes: 30,
|
||||
contextTokens: 200000
|
||||
}
|
||||
}
|
||||
agent: {
|
||||
provider: "anthropic",
|
||||
model: "claude-opus-4-5",
|
||||
allowedModels: [
|
||||
"anthropic/claude-opus-4-5",
|
||||
"anthropic/claude-sonnet-4-1"
|
||||
],
|
||||
thinkingDefault: "low",
|
||||
verboseDefault: "off",
|
||||
timeoutSeconds: 600,
|
||||
mediaMaxMb: 5,
|
||||
heartbeatMinutes: 30,
|
||||
contextTokens: 200000
|
||||
},
|
||||
inbound: { workspace: "~/clawd" }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -132,7 +134,7 @@ When `models.providers` is present, Clawdis writes/merges a `models.json` into
|
||||
- default behavior: **merge** (keeps existing providers, overrides on name)
|
||||
- set `models.mode: "replace"` to overwrite the file contents
|
||||
|
||||
Select the model via `inbound.agent.provider` + `inbound.agent.model`.
|
||||
Select the model via `agent.provider` + `agent.model`.
|
||||
|
||||
```json5
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ Goal: add a simple heartbeat poll for the embedded agent that only notifies user
|
||||
- Keep existing WhatsApp length guidance; forbid burying the sentinel inside alerts.
|
||||
|
||||
## Config & defaults
|
||||
- New config key: `inbound.agent.heartbeatMinutes` (number of minutes; `0` disables).
|
||||
- New config key: `agent.heartbeatMinutes` (number of minutes; `0` disables).
|
||||
- Default: 30 minutes.
|
||||
- New optional idle override for heartbeats: `inbound.session.heartbeatIdleMinutes` (defaults to `idleMinutes`). Heartbeat skips do **not** update the session `updatedAt` so idle expiry still works.
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ CLAWDIS is now **web-only** (Baileys). This document captures the current media
|
||||
## Web Provider Behavior
|
||||
- Input: local file path **or** HTTP(S) URL.
|
||||
- Flow: load into a Buffer, detect media kind, and build the correct payload:
|
||||
- **Images:** resize & recompress to JPEG (max side 2048px) targeting `inbound.agent.mediaMaxMb` (default 5 MB), capped at 6 MB.
|
||||
- **Images:** resize & recompress to JPEG (max side 2048px) targeting `agent.mediaMaxMb` (default 5 MB), capped at 6 MB.
|
||||
- **Audio/Voice/Video:** pass-through up to 16 MB; audio is sent as a voice note (`ptt: true`).
|
||||
- **Documents:** anything else, up to 100 MB, with filename preserved when available.
|
||||
- MIME detection prefers magic bytes, then headers, then file extension.
|
||||
|
||||
@@ -8,7 +8,7 @@ read_when:
|
||||
|
||||
# Workspace Memory v2 (offline): proposal + research
|
||||
|
||||
Target: Clawd-style workspace (`inbound.workspace`, default `~/clawd`) where “memory” is stored as one Markdown file per day (`memory/YYYY-MM-DD.md`) plus a small set of stable files (e.g. `memory.md`, `SOUL.md`).
|
||||
Target: Clawd-style workspace (`agent.workspace`, default `~/clawd`) where “memory” is stored as one Markdown file per day (`memory/YYYY-MM-DD.md`) plus a small set of stable files (e.g. `memory.md`, `SOUL.md`).
|
||||
|
||||
This doc proposes an **offline-first** memory architecture that keeps Markdown as the canonical, reviewable source of truth, but adds **structured recall** (search, entity summaries, confidence updates) via a derived index.
|
||||
|
||||
@@ -159,7 +159,7 @@ Recommendation: **deep integration in Clawdis**, but keep a separable core libra
|
||||
|
||||
### Why integrate into Clawdis?
|
||||
- Clawdis already knows:
|
||||
- the workspace path (`inbound.workspace`)
|
||||
- the workspace path (`agent.workspace`)
|
||||
- the session model + heartbeats
|
||||
- logging + troubleshooting patterns
|
||||
- You want the agent itself to call the tools:
|
||||
@@ -225,4 +225,3 @@ Open question:
|
||||
- Letta / MemGPT concepts: “core memory blocks” + “archival memory” + tool-driven self-editing memory.
|
||||
- Hindsight Technical Report: “retain / recall / reflect”, four-network memory, narrative fact extraction, opinion confidence evolution.
|
||||
- SuCo: arXiv 2411.14754 (2024): “Subspace Collision” approximate nearest neighbor retrieval.
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ read_when:
|
||||
## Resolution order
|
||||
1. Inline directive on the message (applies only to that message).
|
||||
2. Session override (set by sending a directive-only message).
|
||||
3. Global default (`inbound.agent.thinkingDefault` in config).
|
||||
3. Global default (`agent.thinkingDefault` in config).
|
||||
4. Fallback: off.
|
||||
|
||||
## Setting a session default
|
||||
|
||||
@@ -80,13 +80,13 @@ Status: WhatsApp Web via Baileys only. Gateway owns the single session.
|
||||
|
||||
## Media limits + optimization
|
||||
- Default cap: 5 MB (per media item).
|
||||
- Override: `inbound.agent.mediaMaxMb`.
|
||||
- Override: `agent.mediaMaxMb`.
|
||||
- Images are auto-optimized to JPEG under cap (resize + quality sweep).
|
||||
- Oversize media => error; media reply falls back to text warning.
|
||||
|
||||
## Heartbeats
|
||||
- **Gateway heartbeat** logs connection health (`web.heartbeatSeconds`, default 60s).
|
||||
- **Reply heartbeat** asks agent on a timer (`inbound.agent.heartbeatMinutes`).
|
||||
- **Reply heartbeat** asks agent on a timer (`agent.heartbeatMinutes`).
|
||||
- Uses `HEARTBEAT` prompt + `HEARTBEAT_TOKEN` skip behavior.
|
||||
- Skips if queue busy or last inbound was a group.
|
||||
- Falls back to last direct recipient if needed.
|
||||
@@ -103,8 +103,8 @@ Status: WhatsApp Web via Baileys only. Gateway owns the single session.
|
||||
- `inbound.groupChat.historyLimit`
|
||||
- `inbound.messagePrefix` (inbound prefix)
|
||||
- `inbound.responsePrefix` (outbound prefix)
|
||||
- `inbound.agent.mediaMaxMb`
|
||||
- `inbound.agent.heartbeatMinutes`
|
||||
- `agent.mediaMaxMb`
|
||||
- `agent.heartbeatMinutes`
|
||||
- `inbound.session.*` (scope, idle, store, mainKey)
|
||||
- `web.heartbeatSeconds`
|
||||
- `web.reconnect.*`
|
||||
@@ -118,4 +118,3 @@ Status: WhatsApp Web via Baileys only. Gateway owns the single session.
|
||||
- `src/web/auto-reply.test.ts` (mention gating, history injection, reply flow)
|
||||
- `src/web/monitor-inbox.test.ts` (inbound parsing + reply context)
|
||||
- `src/web/outbound.test.ts` (send mapping + media)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user