feat: sandbox session tool visibility

This commit is contained in:
Peter Steinberger
2026-01-06 08:40:21 +00:00
parent ef58399fcd
commit 3693449d7e
18 changed files with 479 additions and 8 deletions

View File

@@ -26,6 +26,8 @@ export type SessionChatType = "direct" | "group" | "room";
export type SessionEntry = {
sessionId: string;
updatedAt: number;
/** Parent session key that spawned this session (used for sandbox session-tool scoping). */
spawnedBy?: string;
systemSent?: boolean;
abortedLastRun?: boolean;
chatType?: SessionChatType;

View File

@@ -77,6 +77,8 @@ export type AgentElevatedAllowFromConfig = {
};
export type WhatsAppConfig = {
/** Optional per-account WhatsApp configuration (multi-account). */
accounts?: Record<string, WhatsAppAccountConfig>;
/** Optional allowlist for WhatsApp direct chats (E.164). */
allowFrom?: string[];
/** Optional allowlist for WhatsApp group senders (E.164). */
@@ -98,6 +100,23 @@ export type WhatsAppConfig = {
>;
};
export type WhatsAppAccountConfig = {
/** If false, do not start this WhatsApp account provider. Default: true. */
enabled?: boolean;
/** Override auth directory (Baileys multi-file auth state). */
authDir?: string;
allowFrom?: string[];
groupAllowFrom?: string[];
groupPolicy?: GroupPolicy;
textChunkLimit?: number;
groups?: Record<
string,
{
requireMention?: boolean;
}
>;
};
export type BrowserProfileConfig = {
/** CDP port for this profile. Allocated once at creation, persisted permanently. */
cdpPort?: number;
@@ -488,6 +507,37 @@ export type RoutingConfig = {
timeoutSeconds?: number;
};
groupChat?: GroupChatConfig;
/** Default agent id when no binding matches. Default: "main". */
defaultAgentId?: string;
agentToAgent?: {
/** Enable agent-to-agent messaging tools. Default: false. */
enabled?: boolean;
/** Allowlist of agent ids or patterns (implementation-defined). */
allow?: string[];
};
agents?: Record<
string,
{
workspace?: string;
agentDir?: string;
model?: string;
sandbox?: {
mode?: "off" | "non-main" | "all";
perSession?: boolean;
workspaceRoot?: string;
};
}
>;
bindings?: Array<{
agentId: string;
match: {
surface: string;
surfaceAccountId?: string;
peer?: { kind: "dm" | "group" | "channel"; id: string };
guildId?: string;
teamId?: string;
};
}>;
queue?: {
mode?: QueueMode;
bySurface?: QueueModeBySurface;
@@ -836,6 +886,12 @@ export type ClawdbotConfig = {
sandbox?: {
/** Enable sandboxing for sessions. */
mode?: "off" | "non-main" | "all";
/**
* Session tools visibility for sandboxed sessions.
* - "spawned": only allow session tools to target sessions spawned from this session (default)
* - "all": allow session tools to target any session
*/
sessionToolsVisibility?: "spawned" | "all";
/** Use one container per session (recommended for hard isolation). */
perSession?: boolean;
/** Root directory for sandbox workspaces. */

View File

@@ -201,6 +201,61 @@ const RoutingSchema = z
.object({
groupChat: GroupChatSchema,
transcribeAudio: TranscribeAudioSchema,
defaultAgentId: z.string().optional(),
agentToAgent: z
.object({
enabled: z.boolean().optional(),
allow: z.array(z.string()).optional(),
})
.optional(),
agents: z
.record(
z.string(),
z
.object({
workspace: z.string().optional(),
agentDir: z.string().optional(),
model: z.string().optional(),
sandbox: z
.object({
mode: z
.union([
z.literal("off"),
z.literal("non-main"),
z.literal("all"),
])
.optional(),
perSession: z.boolean().optional(),
workspaceRoot: z.string().optional(),
})
.optional(),
})
.optional(),
)
.optional(),
bindings: z
.array(
z.object({
agentId: z.string(),
match: z.object({
surface: z.string(),
surfaceAccountId: z.string().optional(),
peer: z
.object({
kind: z.union([
z.literal("dm"),
z.literal("group"),
z.literal("channel"),
]),
id: z.string(),
})
.optional(),
guildId: z.string().optional(),
teamId: z.string().optional(),
}),
}),
)
.optional(),
queue: z
.object({
mode: QueueModeSchema.optional(),
@@ -504,6 +559,9 @@ export const ClawdbotSchema = z.object({
mode: z
.union([z.literal("off"), z.literal("non-main"), z.literal("all")])
.optional(),
sessionToolsVisibility: z
.union([z.literal("spawned"), z.literal("all")])
.optional(),
perSession: z.boolean().optional(),
workspaceRoot: z.string().optional(),
docker: z
@@ -608,6 +666,32 @@ export const ClawdbotSchema = z.object({
.optional(),
whatsapp: z
.object({
accounts: z
.record(
z.string(),
z
.object({
enabled: z.boolean().optional(),
/** Override auth directory for this WhatsApp account (Baileys multi-file auth state). */
authDir: z.string().optional(),
allowFrom: z.array(z.string()).optional(),
groupAllowFrom: z.array(z.string()).optional(),
groupPolicy: GroupPolicySchema.optional().default("open"),
textChunkLimit: z.number().int().positive().optional(),
groups: z
.record(
z.string(),
z
.object({
requireMention: z.boolean().optional(),
})
.optional(),
)
.optional(),
})
.optional(),
)
.optional(),
allowFrom: z.array(z.string()).optional(),
groupAllowFrom: z.array(z.string()).optional(),
groupPolicy: GroupPolicySchema.optional().default("open"),