feat: mount store rw for main agent and add requiresTrigger to register_group
- Mount store/ separately as read-write so the main agent can access the SQLite database directly. - Add requiresTrigger parameter to the register_group MCP tool (host IPC already supported it, but the tool never exposed it). Defaults to false (no trigger). - Update group registration instructions to ask user about trigger. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -460,6 +460,12 @@ Use available_groups.json to find the JID for a group. The folder name must be c
|
||||
'Channel-prefixed folder name (e.g., "whatsapp_family-chat", "telegram_dev-team")',
|
||||
),
|
||||
trigger: z.string().describe('Trigger word (e.g., "@Andy")'),
|
||||
requiresTrigger: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
'Whether messages must start with the trigger word. Default: false (respond to all messages). Set to true for busy groups with many participants where you only want the agent to respond when explicitly mentioned.',
|
||||
),
|
||||
},
|
||||
async (args) => {
|
||||
if (!isMain) {
|
||||
@@ -480,6 +486,7 @@ Use available_groups.json to find the JID for a group. The folder name must be c
|
||||
name: args.name,
|
||||
folder: args.folder,
|
||||
trigger: args.trigger,
|
||||
requiresTrigger: args.requiresTrigger ?? false,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ private_key, .secret
|
||||
|
||||
**Read-Only Project Root:**
|
||||
|
||||
The main group's project root is mounted read-only. Writable paths the agent needs (group folder, IPC, `.claude/`) are mounted separately. This prevents the agent from modifying host application code (`src/`, `dist/`, `package.json`, etc.) which would bypass the sandbox entirely on next restart.
|
||||
The main group's project root is mounted read-only. Writable paths the agent needs (store, group folder, IPC, `.claude/`) are mounted separately. This prevents the agent from modifying host application code (`src/`, `dist/`, `package.json`, etc.) which would bypass the sandbox entirely on next restart. The `store/` directory is mounted read-write so the main agent can access the SQLite database directly.
|
||||
|
||||
### 3. Session Isolation
|
||||
|
||||
@@ -88,6 +88,7 @@ Each NanoClaw group gets its own OneCLI agent identity. This allows different cr
|
||||
| Capability | Main Group | Non-Main Group |
|
||||
|------------|------------|----------------|
|
||||
| Project root access | `/workspace/project` (ro) | None |
|
||||
| Store (SQLite DB) | `/workspace/project/store` (rw) | None |
|
||||
| Group folder | `/workspace/group` (rw) | `/workspace/group` (rw) |
|
||||
| Global memory | Implicit via project | `/workspace/global` (ro) |
|
||||
| Additional mounts | Configurable | Read-only unless allowed |
|
||||
|
||||
@@ -83,15 +83,16 @@ Anthropic credentials must be either an API key from console.anthropic.com (`ANT
|
||||
|
||||
## Container Mounts
|
||||
|
||||
Main has read-only access to the project and read-write access to its group folder:
|
||||
Main has read-only access to the project, read-write access to the store (SQLite DB), and read-write access to its group folder:
|
||||
|
||||
| Container Path | Host Path | Access |
|
||||
|----------------|-----------|--------|
|
||||
| `/workspace/project` | Project root | read-only |
|
||||
| `/workspace/project/store` | `store/` | read-write |
|
||||
| `/workspace/group` | `groups/main/` | read-write |
|
||||
|
||||
Key paths inside the container:
|
||||
- `/workspace/project/store/messages.db` - SQLite database
|
||||
- `/workspace/project/store/messages.db` - SQLite database (read-write)
|
||||
- `/workspace/project/store/messages.db` (registered_groups table) - Group config
|
||||
- `/workspace/project/groups/` - All group folders
|
||||
|
||||
@@ -172,10 +173,11 @@ Fields:
|
||||
### Adding a Group
|
||||
|
||||
1. Query the database to find the group's JID
|
||||
2. Use the `register_group` MCP tool with the JID, name, folder, and trigger
|
||||
3. Optionally include `containerConfig` for additional mounts
|
||||
4. The group folder is created automatically: `/workspace/project/groups/{folder-name}/`
|
||||
5. Optionally create an initial `CLAUDE.md` for the group
|
||||
2. Ask the user whether the group should require a trigger word before registering
|
||||
3. Use the `register_group` MCP tool with the JID, name, folder, trigger, and the chosen `requiresTrigger` setting
|
||||
4. Optionally include `containerConfig` for additional mounts
|
||||
5. The group folder is created automatically: `/workspace/project/groups/{folder-name}/`
|
||||
6. Optionally create an initial `CLAUDE.md` for the group
|
||||
|
||||
Folder naming convention — channel prefix with underscore separator:
|
||||
- WhatsApp "Family Chat" → `whatsapp_family-chat`
|
||||
|
||||
@@ -68,7 +68,7 @@ function buildVolumeMounts(
|
||||
|
||||
if (isMain) {
|
||||
// Main gets the project root read-only. Writable paths the agent needs
|
||||
// (group folder, IPC, .claude/) are mounted separately below.
|
||||
// (store, group folder, IPC, .claude/) are mounted separately below.
|
||||
// Read-only prevents the agent from modifying host application code
|
||||
// (src/, dist/, package.json, etc.) which would bypass the sandbox
|
||||
// entirely on next restart.
|
||||
@@ -89,6 +89,15 @@ function buildVolumeMounts(
|
||||
});
|
||||
}
|
||||
|
||||
// Main gets writable access to the store (SQLite DB) so it can
|
||||
// query and write to the database directly.
|
||||
const storeDir = path.join(projectRoot, 'store');
|
||||
mounts.push({
|
||||
hostPath: storeDir,
|
||||
containerPath: '/workspace/project/store',
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
// Main also gets its group folder as the working directory
|
||||
mounts.push({
|
||||
hostPath: groupDir,
|
||||
|
||||
Reference in New Issue
Block a user