clawmini 0.0.1 → 0.0.2
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/README.md +60 -77
- package/dist/adapter-discord/index.mjs +2 -2
- package/dist/{chats-Zd_HXDHx.mjs → chats-BcbxvPlj.mjs} +2 -2
- package/dist/{chats-Zd_HXDHx.mjs.map → chats-BcbxvPlj.mjs.map} +1 -1
- package/dist/{chats-DKgTeU7i.mjs → chats-CpRQrNHj.mjs} +2 -2
- package/dist/{chats-DKgTeU7i.mjs.map → chats-CpRQrNHj.mjs.map} +1 -1
- package/dist/cli/index.mjs +4 -3
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lite.mjs +48 -0
- package/dist/cli/lite.mjs.map +1 -1
- package/dist/daemon/index.mjs +311 -19
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/{lite-Dl7WXyaH.mjs → lite-DBUuHsX0.mjs} +2 -2
- package/dist/{lite-Dl7WXyaH.mjs.map → lite-DBUuHsX0.mjs.map} +1 -1
- package/dist/policy-utils-BvfOK6Ih.mjs +114 -0
- package/dist/policy-utils-BvfOK6Ih.mjs.map +1 -0
- package/dist/web/_app/immutable/chunks/{CSvS_NwK.js → B3YcEpQV.js} +1 -1
- package/dist/web/_app/immutable/chunks/{COekwvP2.js → CAZeqksE.js} +1 -1
- package/dist/web/_app/immutable/entry/{app.B-vZe7PN.js → app.ZuicLpkH.js} +2 -2
- package/dist/web/_app/immutable/entry/start.DuQwh4Nz.js +1 -0
- package/dist/web/_app/immutable/nodes/{0.B5WFN0zw.js → 0.BB1CjKco.js} +1 -1
- package/dist/web/_app/immutable/nodes/{1.D1wtJb2k.js → 1.CdSgEHu9.js} +1 -1
- package/dist/web/_app/immutable/nodes/{3.BB5wCoBf.js → 3.CKp7Wkn8.js} +1 -1
- package/dist/web/_app/immutable/nodes/{4.Dr2jvAXK.js → 4.FyeoMY-Y.js} +1 -1
- package/dist/web/_app/immutable/nodes/{5.BJl7oM3b.js → 5.D6mVN7l7.js} +1 -1
- package/dist/web/_app/version.json +1 -1
- package/dist/web/index.html +6 -6
- package/dist/{workspace-CSgfo_2J.mjs → workspace-BC1ahx4R.mjs} +13 -2
- package/dist/workspace-BC1ahx4R.mjs.map +1 -0
- package/docs/CLI_REFERENCE.md +35 -0
- package/docs/guides/sandbox_policies.md +12 -5
- package/package.json +1 -1
- package/web/.svelte-kit/ambient.d.ts +2 -6
- package/web/.svelte-kit/generated/server/internal.js +1 -1
- package/web/.svelte-kit/output/client/.vite/manifest.json +25 -25
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{CSvS_NwK.js → B3YcEpQV.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{COekwvP2.js → CAZeqksE.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/entry/{app.B-vZe7PN.js → app.ZuicLpkH.js} +2 -2
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.DuQwh4Nz.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{0.B5WFN0zw.js → 0.BB1CjKco.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{1.D1wtJb2k.js → 1.CdSgEHu9.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{3.BB5wCoBf.js → 3.CKp7Wkn8.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{4.Dr2jvAXK.js → 4.FyeoMY-Y.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.BJl7oM3b.js → 5.D6mVN7l7.js} +1 -1
- package/web/.svelte-kit/output/client/_app/version.json +1 -1
- package/web/.svelte-kit/output/server/chunks/internal.js +1 -1
- package/web/.svelte-kit/output/server/manifest-full.js +1 -1
- package/web/.svelte-kit/output/server/manifest.js +1 -1
- package/web/.svelte-kit/output/server/nodes/0.js +1 -1
- package/web/.svelte-kit/output/server/nodes/1.js +1 -1
- package/web/.svelte-kit/output/server/nodes/3.js +1 -1
- package/web/.svelte-kit/output/server/nodes/4.js +1 -1
- package/web/.svelte-kit/output/server/nodes/5.js +1 -1
- package/dist/web/_app/immutable/entry/start.oP1AgKhs.js +0 -1
- package/dist/workspace-CSgfo_2J.mjs.map +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.oP1AgKhs.js +0 -1
package/README.md
CHANGED
|
@@ -1,98 +1,91 @@
|
|
|
1
1
|
# Clawmini
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**The secure, local-first orchestrator for your AI agents.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Clawmini gives you the power of a proactive personal AI assistant, without compromising your system's security. Unlike other local agents that run with unrestricted access to your machine, Clawmini is built from the ground up with **sandboxing**, **human-in-the-loop approvals**, and **strict network isolation**.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Safe Concurrency:** Automatically manages state and handles race conditions, queuing background commands safely to prevent file lock issues.
|
|
9
|
-
- **Built-in & Bring-Your-Own UI:** Includes a fast, beautifully designed SvelteKit Web UI to visually manage agents, chats, and monitor real-time execution. Alternatively, easily build and connect your own interfaces to its local API.
|
|
10
|
-
- **Agent Templates:** Quickly scaffold new agents using built-in or custom templates (e.g. `gemini`), automatically merging configuration settings.
|
|
11
|
-
- **Routers & Middleware Pipeline:** Process user messages through an extensible pipeline to dynamically alter content, target specific agents or sessions, and expand slash commands before they reach an agent.
|
|
12
|
-
- **Local File System Storage:** Everything is stored completely locally in `.clawmini/` within your workspace as transparent JSON/JSONL files. No cloud syncing required.
|
|
13
|
-
- **Sandboxed Agent API:** The daemon can optionally expose a secure HTTP server configured via the `api` setting in `.clawmini/settings.json`, allowing remote or containerized access. Give agents a minimal zero-dependency standalone client exported via `clawmini export-lite`. It securely authenticates with the Agent API using dynamically generated HMAC tokens (`CLAW_API_TOKEN`) to allow sandboxed agents to log messages and manage cron jobs without needing direct access to the host's Unix socket.
|
|
14
|
-
- **Proactivity:** Incoming messages or events from various external sources can be proactively routed back to the user or directly to the agent for autonomous handling.
|
|
7
|
+
Bring your favorite CLI agents (Gemini CLI, Claude Code, OpenAI Codex, etc.), and Clawmini provides the memory, the chat support, and the security boundaries.
|
|
15
8
|
|
|
16
|
-
|
|
9
|
+
## Why Clawmini?
|
|
17
10
|
|
|
18
|
-
|
|
11
|
+
🛡️ **Zero-Trust Security by Default**
|
|
12
|
+
Run agents safely. Clawmini uses built-in sandboxing (macOS seatbelt or containerized environments) to restrict what your AI can touch. Sensitive actions require your explicit approval before execution.
|
|
19
13
|
|
|
20
|
-
|
|
14
|
+
🧠 **Persistent Memory & Proactivity**
|
|
15
|
+
Your agents don't just react; they act. Clawmini allows agents to schedule recurring tasks (cron jobs), maintain long-term context across sessions, and proactively notify you of updates or route messages from external sources.
|
|
21
16
|
|
|
22
|
-
|
|
17
|
+
💻 **Beautiful Web UI & Chat App Extensibility**
|
|
18
|
+
No need to stay in the terminal. Manage your agents and chat with them through a fast, built-in Web interface running entirely on `localhost`. Hook up Discord to chat on-the-go, or easily build your adapters against the local API.
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
clawmini init --agent coder --agent-template gemini-cladding
|
|
27
|
-
|
|
28
|
-
# Start the local web interface on http://localhost:8080
|
|
29
|
-
clawmini web
|
|
30
|
-
```
|
|
20
|
+
🔌 **Bring Your Own Agent**
|
|
21
|
+
Clawmini isn't tied to one model. It orchestrates _any_ CLI-based agent, acting as the secure bridge between the AI and your filesystem.
|
|
31
22
|
|
|
32
|
-
##
|
|
23
|
+
## Quick Start: Meet Jeeves
|
|
33
24
|
|
|
34
|
-
|
|
25
|
+
Let's set up a secure, sandboxed agent named Jeeves using the Gemini CLI template.
|
|
35
26
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
- `clawmini export-lite [--out <path>] [--stdout]`: Export the standalone `clawmini-lite` client script for use in sandboxed environments.
|
|
27
|
+
```bash
|
|
28
|
+
# 1. Install globally
|
|
29
|
+
npm install -g clawmini
|
|
40
30
|
|
|
41
|
-
|
|
31
|
+
# 2. Initialize a workspace and create your first sandboxed agent
|
|
32
|
+
# For a more OpenClaw-like experience, try the gemini-claw template
|
|
33
|
+
mkdir my-workspace && cd my-workspace
|
|
34
|
+
clawmini init --agent jeeves --agent-template gemini --environment macos
|
|
42
35
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- `clawmini chats delete <id>`: Remove a chat and its associated history.
|
|
46
|
-
- `clawmini chats set-default <id>`: Update the globally configured default chat for the workspace.
|
|
36
|
+
# 3. Start the background daemon
|
|
37
|
+
clawmini up
|
|
47
38
|
|
|
48
|
-
|
|
39
|
+
# 4. Open the Web UI to start chatting!
|
|
40
|
+
clawmini web
|
|
41
|
+
```
|
|
49
42
|
|
|
50
|
-
|
|
51
|
-
- `clawmini messages tail [-n NUM] [--json] [--chat <id>]`: Display the most recent messages and command logs in a chat.
|
|
43
|
+
**Try asking Jeeves:** _"Summarize the recent changes in my git repository."_ Jeeves will run securely in its sandbox, read the diffs, and report back.
|
|
52
44
|
|
|
53
|
-
###
|
|
45
|
+
### Common Slash Commands
|
|
54
46
|
|
|
55
|
-
-
|
|
56
|
-
- `clawmini agents add <id> [-d, --directory <dir>] [-t, --template <name>] [-e, --env <KEY=VALUE>...]`: Create a new agent, optionally setting its working directory, applying a template, and environment variables.
|
|
57
|
-
- `clawmini agents update <id> [-d, --directory <dir>] [-e, --env <KEY=VALUE>...]`: Update an existing agent's configuration.
|
|
58
|
-
- `clawmini agents delete <id>`: Remove an agent.
|
|
47
|
+
You can use these built-in slash commands in your chat interfaces:
|
|
59
48
|
|
|
60
|
-
|
|
49
|
+
- `/new`: Clear previous context and start a new conversation thread.
|
|
50
|
+
- `/stop`: Stop all running commands and drop any queued messages.
|
|
51
|
+
- `/interrupt [message]`: Interrupt the current thinking, batching together all queued messages and sending them immediately.
|
|
52
|
+
- `/pending`: View any pending permission requests from your agent.
|
|
53
|
+
- `/approve [id]`: Approve a specific pending agent request.
|
|
54
|
+
- `/reject [id]`: Reject a specific pending agent request.
|
|
61
55
|
|
|
62
|
-
|
|
63
|
-
- `clawmini cron add <name> [--cron <expr> | --every <duration> | --at <iso-time>] [-m, --message <text>]`: Create a new scheduled job. Supports standard cron expressions, recurring intervals (e.g., `10m`), or one-off executions at a specific time.
|
|
64
|
-
- `clawmini cron delete <name> [--chat <id>]`: Remove an existing scheduled job.
|
|
56
|
+
### Guides & Integrations
|
|
65
57
|
|
|
66
|
-
|
|
58
|
+
- [Discord Integration Setup](./docs/guides/discord_adapter_setup.md)
|
|
59
|
+
- [Configuring Permission Requests](./docs/guides/sandbox_policies.md)
|
|
67
60
|
|
|
68
|
-
|
|
61
|
+
## How It Works
|
|
69
62
|
|
|
70
|
-
|
|
63
|
+
**User** ↔️ **Web UI / CLI** ↔️ **Daemon** ↔️ **Sandbox / Environment** ↔️ **Agent**
|
|
71
64
|
|
|
72
|
-
|
|
65
|
+
The daemon securely authenticates with the Agent API using dynamically generated HMAC tokens (`CLAW_API_TOKEN`), allowing sandboxed agents to operate safely without direct access to the host's Unix socket.
|
|
73
66
|
|
|
74
|
-
|
|
67
|
+
### Built-in Environments
|
|
75
68
|
|
|
76
|
-
|
|
69
|
+
- `cladding` (most secure): A container-based sandbox using [cladding](https://github.com/dstoc/cladding)
|
|
70
|
+
- `macos`: A macOS sandbox environment that restricts write-access to the workspace.
|
|
71
|
+
- `macos-proxy`: A more constrained macOS sandbox that limits network access to an allowlist.
|
|
77
72
|
|
|
78
|
-
|
|
73
|
+
### Extensible Pipeline (Routers)
|
|
79
74
|
|
|
80
|
-
|
|
75
|
+
Process user messages before they reach an agent. Dynamically alter content, target specific agents, or expand slash commands (e.g., `/new` to clear context, `/foo` to expand a command script).
|
|
81
76
|
|
|
82
|
-
|
|
83
|
-
- `@clawmini/slash-command`: Expands slash commands (e.g., `/foo`) with the contents of matching files in your `.clawmini/commands/` directory.
|
|
77
|
+
## Next Steps: Build Autonomous Workflows
|
|
84
78
|
|
|
85
|
-
|
|
79
|
+
Once you're comfortable, Clawmini offers powerful tools for advanced users:
|
|
86
80
|
|
|
87
|
-
|
|
81
|
+
- **The `gemini-claw` Template:** Scaffold a complete autonomous assistant with built-in memory management (`MEMORY.md`), identity (`SOUL.md`), and heartbeat checks (`HEARTBEAT.md`) for proactive tasking.
|
|
82
|
+
- **`clawmini-lite`:** Deploy agents into heavily restricted containers. Export the minimal, zero-dependency client (`clawmini export-lite`) to securely authenticate with the daemon, allowing the agent to log actions and request permissions without host access.
|
|
88
83
|
|
|
89
|
-
|
|
84
|
+
---
|
|
90
85
|
|
|
91
|
-
|
|
86
|
+
## Documentation & References
|
|
92
87
|
|
|
93
|
-
|
|
94
|
-
- `gemini-cladding`: A template configured to run the `gemini` CLI wrapped inside `cladding` for enhanced security.
|
|
95
|
-
- `gemini-claw-cladding`: A comprehensive template that sets up an autonomous personal assistant workspace (OpenClaw). It includes the `gemini-cladding` setup plus a full suite of scaffolding files like `GEMINI.md`, `SOUL.md`, `MEMORY.md`, and `HEARTBEAT.md` to establish the agent's identity, memory, and proactive capabilities.
|
|
88
|
+
For a full list of commands for managing chats, messages, agents, background jobs, and environments, please see the [CLI Command Reference](./docs/CLI_REFERENCE.md).
|
|
96
89
|
|
|
97
90
|
## Development Setup
|
|
98
91
|
|
|
@@ -103,35 +96,25 @@ Clawmini is a monorepo consisting of a Node.js TypeScript CLI/Daemon and an embe
|
|
|
103
96
|
- Node.js (v18+)
|
|
104
97
|
- npm
|
|
105
98
|
|
|
106
|
-
### Setup
|
|
99
|
+
### Setup & Scripts
|
|
107
100
|
|
|
108
101
|
```bash
|
|
109
|
-
# Install dependencies
|
|
102
|
+
# Install dependencies and build the project
|
|
110
103
|
npm install
|
|
111
|
-
|
|
112
|
-
# Build the CLI, Daemon, and statically compile the Web UI
|
|
113
104
|
npm run build
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Development Scripts
|
|
117
105
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
# Watch mode for the CLI
|
|
106
|
+
# Development Watch Modes
|
|
122
107
|
npm run dev:cli
|
|
123
|
-
|
|
124
|
-
# Watch mode for the Daemon
|
|
125
108
|
npm run dev:daemon
|
|
126
109
|
|
|
127
|
-
#
|
|
110
|
+
# Linting & Testing
|
|
128
111
|
npm run format
|
|
129
112
|
npm run lint
|
|
130
113
|
npm run check
|
|
131
114
|
npm run test
|
|
132
115
|
```
|
|
133
116
|
|
|
134
|
-
|
|
117
|
+
**Architecture Notes:**
|
|
135
118
|
|
|
136
119
|
- **Separation of Concerns:** The daemon (`src/daemon`) acts as the stateful orchestrator and queue manager, while the CLI (`src/cli`) is simply a thin TRPC client connecting via a UNIX socket.
|
|
137
|
-
- **Web UI:** The `web/` directory is a SvelteKit application built with `@sveltejs/adapter-static`. Running `npm run build` bundles the web UI into `dist/web`, which is
|
|
120
|
+
- **Web UI:** The `web/` directory is a SvelteKit application built with `@sveltejs/adapter-static`. Running `npm run build` bundles the web UI into `dist/web`, which is served statically by the `clawmini web` Node.js server. Real-time updates use Server-Sent Events (SSE) tailing local `.clawmini/chats/:id/chat.jsonl` files.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { l as getSocketPath, o as getClawminiDir, u as getWorkspaceRoot } from "../workspace-
|
|
2
|
+
import { l as getSocketPath, o as getClawminiDir, u as getWorkspaceRoot } from "../workspace-BC1ahx4R.mjs";
|
|
3
3
|
import { t as createUnixSocketFetch } from "../fetch-BjZVyU3Z.mjs";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
@@ -387,7 +387,7 @@ async function main() {
|
|
|
387
387
|
console.log(`Received message from ${message.author.tag}: ${message.content}`);
|
|
388
388
|
const downloadedFiles = [];
|
|
389
389
|
if (message.attachments.size > 0) {
|
|
390
|
-
const { getClawminiDir } = await import("../workspace-
|
|
390
|
+
const { getClawminiDir } = await import("../workspace-BC1ahx4R.mjs").then((n) => n.v);
|
|
391
391
|
const tmpDir = path.join(getClawminiDir(process.cwd()), "tmp", "discord");
|
|
392
392
|
await fs$1.mkdir(tmpDir, { recursive: true });
|
|
393
393
|
const maxSizeMB = config.maxAttachmentSizeMB ?? 25;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-95iHPtFO.mjs";
|
|
2
|
-
import { n as appendMessage$1 } from "./chats-
|
|
2
|
+
import { n as appendMessage$1 } from "./chats-CpRQrNHj.mjs";
|
|
3
3
|
import { EventEmitter } from "node:events";
|
|
4
4
|
|
|
5
5
|
//#region src/daemon/events.ts
|
|
@@ -26,4 +26,4 @@ async function appendMessage(id, message, startDir = process.cwd()) {
|
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
28
28
|
export { daemonEvents as a, DAEMON_EVENT_TYPING as i, chats_exports as n, emitTyping as o, DAEMON_EVENT_MESSAGE_APPENDED as r, appendMessage as t };
|
|
29
|
-
//# sourceMappingURL=chats-
|
|
29
|
+
//# sourceMappingURL=chats-BcbxvPlj.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chats-
|
|
1
|
+
{"version":3,"file":"chats-BcbxvPlj.mjs","names":["shared.appendMessage"],"sources":["../src/daemon/events.ts","../src/daemon/chats.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\nimport type { ChatMessage } from '../shared/chats.js';\n\nexport const daemonEvents = new EventEmitter();\n\nexport const DAEMON_EVENT_MESSAGE_APPENDED = 'message-appended';\nexport const DAEMON_EVENT_TYPING = 'typing';\n\nexport function emitMessageAppended(chatId: string, message: ChatMessage) {\n daemonEvents.emit(DAEMON_EVENT_MESSAGE_APPENDED, { chatId, message });\n}\n\nexport function emitTyping(chatId: string) {\n daemonEvents.emit(DAEMON_EVENT_TYPING, { chatId });\n}\n","import * as shared from '../shared/chats.js';\nimport { emitMessageAppended } from './events.js';\n\nexport async function appendMessage(\n id: string,\n message: shared.ChatMessage,\n startDir = process.cwd()\n): Promise<void> {\n await shared.appendMessage(id, message, startDir);\n emitMessageAppended(id, message);\n}\n\nexport {\n type ChatMessage,\n type UserMessage,\n type CommandLogMessage,\n getChatsDir,\n isValidChatId,\n createChat,\n listChats,\n deleteChat,\n getMessages,\n getDefaultChatId,\n setDefaultChatId,\n DEFAULT_CHAT_ID,\n} from '../shared/chats.js';\n"],"mappings":";;;;;AAGA,MAAa,eAAe,IAAI,cAAc;AAE9C,MAAa,gCAAgC;AAC7C,MAAa,sBAAsB;AAEnC,SAAgB,oBAAoB,QAAgB,SAAsB;AACxE,cAAa,KAAK,+BAA+B;EAAE;EAAQ;EAAS,CAAC;;AAGvE,SAAgB,WAAW,QAAgB;AACzC,cAAa,KAAK,qBAAqB,EAAE,QAAQ,CAAC;;;;;;ACVpD,eAAsB,cACpB,IACA,SACA,WAAW,QAAQ,KAAK,EACT;AACf,OAAMA,gBAAqB,IAAI,SAAS,SAAS;AACjD,qBAAoB,IAAI,QAAQ"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as getSettingsPath, o as getClawminiDir } from "./workspace-
|
|
1
|
+
import { c as getSettingsPath, o as getClawminiDir } from "./workspace-BC1ahx4R.mjs";
|
|
2
2
|
import { n as pathIsInsideDir } from "./fs-B5wW0oaH.mjs";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -88,4 +88,4 @@ async function setDefaultChatId(id, startDir = process.cwd()) {
|
|
|
88
88
|
|
|
89
89
|
//#endregion
|
|
90
90
|
export { getChatsDir as a, isValidChatId as c, deleteChat as i, listChats as l, appendMessage as n, getDefaultChatId as o, createChat as r, getMessages as s, DEFAULT_CHAT_ID as t, setDefaultChatId as u };
|
|
91
|
-
//# sourceMappingURL=chats-
|
|
91
|
+
//# sourceMappingURL=chats-CpRQrNHj.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chats-
|
|
1
|
+
{"version":3,"file":"chats-CpRQrNHj.mjs","names":["fs"],"sources":["../src/shared/chats.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { getClawminiDir, getSettingsPath } from './workspace.js';\nimport { pathIsInsideDir } from './utils/fs.js';\n\nexport const DEFAULT_CHAT_ID = 'default';\n\nexport interface UserMessage {\n id: string;\n role: 'user';\n content: string;\n timestamp: string;\n}\n\nexport interface CommandLogMessage {\n id: string;\n messageId: string;\n role: 'log';\n source?: 'router';\n content: string;\n stderr: string;\n timestamp: string;\n command: string;\n cwd: string;\n exitCode: number;\n stdout?: string;\n files?: string[];\n level?: 'default' | 'debug' | 'verbose';\n}\n\nexport type ChatMessage = UserMessage | CommandLogMessage;\n\nexport async function getChatsDir(startDir = process.cwd()): Promise<string> {\n const dir = path.join(getClawminiDir(startDir), 'chats');\n if (!existsSync(dir)) {\n await fs.mkdir(dir, { recursive: true });\n }\n return dir;\n}\n\nexport function isValidChatId(chatId: string): boolean {\n if (!chatId || chatId.length === 0) return false;\n return /^[a-zA-Z0-9_-]+$/.test(chatId);\n}\n\nfunction assertValidChatId(id: string): void {\n if (!isValidChatId(id)) {\n throw new Error(`Invalid chat ID: ${id}`);\n }\n}\n\nexport async function createChat(id: string, startDir = process.cwd()): Promise<void> {\n assertValidChatId(id);\n const chatsDir = await getChatsDir(startDir);\n const chatDir = path.join(chatsDir, id);\n if (!existsSync(chatDir)) {\n await fs.mkdir(chatDir, { recursive: true });\n }\n const chatFile = path.join(chatDir, 'chat.jsonl');\n if (!existsSync(chatFile)) {\n await fs.writeFile(chatFile, '');\n }\n}\n\nexport async function listChats(startDir = process.cwd()): Promise<string[]> {\n const chatsDir = await getChatsDir(startDir);\n try {\n const entries = await fs.readdir(chatsDir, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nexport async function deleteChat(id: string, startDir = process.cwd()): Promise<void> {\n assertValidChatId(id);\n const chatsDir = await getChatsDir(startDir);\n const chatDir = path.join(chatsDir, id);\n\n if (!pathIsInsideDir(chatDir, chatsDir)) {\n throw new Error(`Security Error: Cannot delete chat directory outside of ${chatsDir}`);\n }\n\n if (existsSync(chatDir)) {\n await fs.rm(chatDir, { recursive: true, force: true });\n }\n}\n\nexport async function appendMessage(\n id: string,\n message: ChatMessage,\n startDir = process.cwd()\n): Promise<void> {\n assertValidChatId(id);\n const chatsDir = await getChatsDir(startDir);\n const chatDir = path.join(chatsDir, id);\n if (!existsSync(chatDir)) {\n await createChat(id, startDir);\n }\n const chatFile = path.join(chatDir, 'chat.jsonl');\n await fs.appendFile(chatFile, JSON.stringify(message) + '\\n');\n}\n\nexport async function getMessages(\n id: string,\n limit?: number,\n startDir = process.cwd()\n): Promise<ChatMessage[]> {\n assertValidChatId(id);\n const chatsDir = await getChatsDir(startDir);\n const chatFile = path.join(chatsDir, id, 'chat.jsonl');\n if (!existsSync(chatFile)) {\n throw new Error(`Chat directory or file for '${id}' not found.`);\n }\n const content = await fs.readFile(chatFile, 'utf8');\n const lines = content.split('\\n').filter((line) => line.trim() !== '');\n const messages = lines.map((line) => JSON.parse(line) as ChatMessage);\n\n if (limit !== undefined && limit > 0) {\n return messages.slice(-limit);\n }\n return messages;\n}\n\nexport async function getDefaultChatId(startDir = process.cwd()): Promise<string> {\n const settingsPath = getSettingsPath(startDir);\n if (!existsSync(settingsPath)) return DEFAULT_CHAT_ID;\n\n try {\n const content = await fs.readFile(settingsPath, 'utf8');\n const settings = JSON.parse(content);\n return settings.chats?.defaultId || DEFAULT_CHAT_ID;\n } catch {\n return DEFAULT_CHAT_ID;\n }\n}\n\nexport async function setDefaultChatId(id: string, startDir = process.cwd()): Promise<void> {\n assertValidChatId(id);\n const settingsPath = getSettingsPath(startDir);\n let settings: { chats?: { defaultId?: string; [key: string]: unknown }; [key: string]: unknown } =\n {};\n if (existsSync(settingsPath)) {\n try {\n const content = await fs.readFile(settingsPath, 'utf8');\n settings = JSON.parse(content);\n } catch {\n // Ignore invalid JSON\n }\n }\n\n if (!settings.chats) {\n settings.chats = {};\n }\n settings.chats.defaultId = id;\n\n const clawminiDir = getClawminiDir(startDir);\n if (!existsSync(clawminiDir)) {\n await fs.mkdir(clawminiDir, { recursive: true });\n }\n\n await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));\n}\n"],"mappings":"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"}
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as getAgent, b as
|
|
2
|
+
import { S as writeSettings, _ as readSettings, a as getAgent, b as writeAgentSettings, d as isValidAgentId, f as listAgents, l as getSocketPath, m as readChatSettings, n as deleteAgent, o as getClawminiDir, r as enableEnvironment, t as applyTemplateToAgent, x as writeChatSettings } from "../workspace-BC1ahx4R.mjs";
|
|
3
3
|
import { n as pathIsInsideDir } from "../fs-B5wW0oaH.mjs";
|
|
4
|
-
import { a as getChatsDir, c as isValidChatId, i as deleteChat, l as listChats, o as getDefaultChatId, r as createChat, s as getMessages, t as DEFAULT_CHAT_ID, u as setDefaultChatId } from "../chats-
|
|
4
|
+
import { a as getChatsDir, c as isValidChatId, i as deleteChat, l as listChats, o as getDefaultChatId, r as createChat, s as getMessages, t as DEFAULT_CHAT_ID, u as setDefaultChatId } from "../chats-CpRQrNHj.mjs";
|
|
5
5
|
import { t as createUnixSocketFetch } from "../fetch-BjZVyU3Z.mjs";
|
|
6
|
-
import { i as writeLiteScript, r as getLiteScriptContent, t as exportLiteToAllEnvironments } from "../lite-
|
|
6
|
+
import { i as writeLiteScript, r as getLiteScriptContent, t as exportLiteToAllEnvironments } from "../lite-DBUuHsX0.mjs";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
import fs from "node:fs";
|
|
9
9
|
import path from "node:path";
|
|
@@ -56,6 +56,7 @@ const initCmd = new Command("init").description("Initialize a new .clawmini sett
|
|
|
56
56
|
"@clawmini/slash-new",
|
|
57
57
|
"@clawmini/slash-stop",
|
|
58
58
|
"@clawmini/slash-interrupt",
|
|
59
|
+
"@clawmini/slash-policies",
|
|
59
60
|
"@clawmini/slash-command"
|
|
60
61
|
],
|
|
61
62
|
api: true
|