2026-01-14 01:08:15 +00:00
import { z } from "zod" ;
import { parseDurationMs } from "../cli/parse-duration.js" ;
import {
GroupChatSchema ,
HumanDelaySchema ,
IdentitySchema ,
2026-01-24 19:15:54 -05:00
ToolsLinksSchema ,
2026-01-17 03:52:37 +00:00
ToolsMediaSchema ,
2026-01-14 01:08:15 +00:00
} from "./zod-schema.core.js" ;
2026-02-13 16:19:21 +01:00
import { sensitive } from "./zod-schema.sensitive.js" ;
2026-01-14 01:08:15 +00:00
export const HeartbeatSchema = z
. object ( {
every : z.string ( ) . optional ( ) ,
2026-01-21 20:30:29 +00:00
activeHours : z
. object ( {
start : z.string ( ) . optional ( ) ,
end : z.string ( ) . optional ( ) ,
timezone : z.string ( ) . optional ( ) ,
} )
. strict ( )
. optional ( ) ,
2026-01-14 01:08:15 +00:00
model : z.string ( ) . optional ( ) ,
2026-01-19 15:42:07 -05:00
session : z.string ( ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
includeReasoning : z.boolean ( ) . optional ( ) ,
2026-01-24 13:17:02 +00:00
target : z.string ( ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
to : z.string ( ) . optional ( ) ,
2026-02-05 06:49:12 +09:00
accountId : z.string ( ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
prompt : z.string ( ) . optional ( ) ,
ackMaxChars : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. superRefine ( ( val , ctx ) = > {
2026-01-31 16:19:20 +09:00
if ( ! val . every ) {
return ;
}
2026-01-14 01:08:15 +00:00
try {
parseDurationMs ( val . every , { defaultUnit : "m" } ) ;
} catch {
ctx . addIssue ( {
code : z.ZodIssueCode.custom ,
path : [ "every" ] ,
message : "invalid duration (use ms, s, m, h)" ,
} ) ;
}
2026-01-21 20:30:29 +00:00
const active = val . activeHours ;
2026-01-31 16:19:20 +09:00
if ( ! active ) {
return ;
}
2026-01-21 20:30:29 +00:00
const timePattern = /^([01]\d|2[0-3]|24):([0-5]\d)$/ ;
const validateTime = ( raw : string | undefined , opts : { allow24 : boolean } , path : string ) = > {
2026-01-31 16:19:20 +09:00
if ( ! raw ) {
return ;
}
2026-01-21 20:30:29 +00:00
if ( ! timePattern . test ( raw ) ) {
ctx . addIssue ( {
code : z.ZodIssueCode.custom ,
path : [ "activeHours" , path ] ,
message : 'invalid time (use "HH:MM" 24h format)' ,
} ) ;
return ;
}
const [ hourStr , minuteStr ] = raw . split ( ":" ) ;
const hour = Number ( hourStr ) ;
const minute = Number ( minuteStr ) ;
if ( hour === 24 && minute !== 0 ) {
ctx . addIssue ( {
code : z.ZodIssueCode.custom ,
path : [ "activeHours" , path ] ,
message : "invalid time (24:00 is the only allowed 24:xx value)" ,
} ) ;
return ;
}
if ( hour === 24 && ! opts . allow24 ) {
ctx . addIssue ( {
code : z.ZodIssueCode.custom ,
path : [ "activeHours" , path ] ,
message : "invalid time (start cannot be 24:00)" ,
} ) ;
}
} ;
validateTime ( active . start , { allow24 : false } , "start" ) ;
validateTime ( active . end , { allow24 : true } , "end" ) ;
2026-01-14 01:08:15 +00:00
} )
. optional ( ) ;
export const SandboxDockerSchema = z
. object ( {
image : z.string ( ) . optional ( ) ,
containerPrefix : z.string ( ) . optional ( ) ,
workdir : z.string ( ) . optional ( ) ,
readOnlyRoot : z.boolean ( ) . optional ( ) ,
tmpfs : z.array ( z . string ( ) ) . optional ( ) ,
network : z.string ( ) . optional ( ) ,
user : z.string ( ) . optional ( ) ,
capDrop : z.array ( z . string ( ) ) . optional ( ) ,
env : z.record ( z . string ( ) , z . string ( ) ) . optional ( ) ,
setupCommand : z.string ( ) . optional ( ) ,
pidsLimit : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
memory : z.union ( [ z . string ( ) , z . number ( ) ] ) . optional ( ) ,
memorySwap : z.union ( [ z . string ( ) , z . number ( ) ] ) . optional ( ) ,
cpus : z.number ( ) . positive ( ) . optional ( ) ,
ulimits : z
. record (
z . string ( ) ,
z . union ( [
z . string ( ) ,
z . number ( ) ,
2026-01-19 05:59:29 +00:00
z
. object ( {
soft : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
hard : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
} )
. strict ( ) ,
2026-01-14 01:08:15 +00:00
] ) ,
)
. optional ( ) ,
seccompProfile : z.string ( ) . optional ( ) ,
apparmorProfile : z.string ( ) . optional ( ) ,
dns : z.array ( z . string ( ) ) . optional ( ) ,
extraHosts : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-15 02:58:20 +00:00
binds : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ;
export const SandboxBrowserSchema = z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
image : z.string ( ) . optional ( ) ,
containerPrefix : z.string ( ) . optional ( ) ,
cdpPort : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
vncPort : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
noVncPort : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
headless : z.boolean ( ) . optional ( ) ,
enableNoVnc : z.boolean ( ) . optional ( ) ,
allowHostControl : z.boolean ( ) . optional ( ) ,
autoStart : z.boolean ( ) . optional ( ) ,
autoStartTimeoutMs : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ;
export const SandboxPruneSchema = z
. object ( {
idleHours : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
maxAgeDays : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ;
2026-01-26 10:17:50 -08:00
const ToolPolicyBaseSchema = z
2026-01-14 01:08:15 +00:00
. object ( {
allow : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-25 00:29:28 -08:00
alsoAllow : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
deny : z.array ( z . string ( ) ) . optional ( ) ,
} )
2026-01-26 10:17:50 -08:00
. strict ( ) ;
export const ToolPolicySchema = ToolPolicyBaseSchema . superRefine ( ( value , ctx ) = > {
if ( value . allow && value . allow . length > 0 && value . alsoAllow && value . alsoAllow . length > 0 ) {
ctx . addIssue ( {
code : z.ZodIssueCode.custom ,
2026-01-27 02:44:13 +05:30
message :
"tools policy cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)" ,
2026-01-26 10:17:50 -08:00
} ) ;
}
} ) . optional ( ) ;
2026-01-14 01:08:15 +00:00
2026-01-15 04:07:29 +00:00
export const ToolsWebSearchSchema = z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
2026-01-27 21:06:53 -08:00
provider : z.union ( [ z . literal ( "brave" ) , z . literal ( "perplexity" ) , z . literal ( "grok" ) ] ) . optional ( ) ,
2026-02-13 16:19:21 +01:00
apiKey : z.string ( ) . optional ( ) . register ( sensitive ) ,
2026-01-15 04:07:29 +00:00
maxResults : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
timeoutSeconds : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
cacheTtlMinutes : z.number ( ) . nonnegative ( ) . optional ( ) ,
2026-01-19 13:03:03 -05:00
perplexity : z
. object ( {
2026-02-13 16:19:21 +01:00
apiKey : z.string ( ) . optional ( ) . register ( sensitive ) ,
2026-01-19 13:03:03 -05:00
baseUrl : z.string ( ) . optional ( ) ,
model : z.string ( ) . optional ( ) ,
} )
. strict ( )
. optional ( ) ,
2026-01-27 21:06:53 -08:00
grok : z
. object ( {
2026-02-13 16:19:21 +01:00
apiKey : z.string ( ) . optional ( ) . register ( sensitive ) ,
2026-01-27 21:06:53 -08:00
model : z.string ( ) . optional ( ) ,
inlineCitations : z.boolean ( ) . optional ( ) ,
} )
. strict ( )
. optional ( ) ,
2026-01-15 04:07:29 +00:00
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-15 04:07:29 +00:00
. optional ( ) ;
export const ToolsWebFetchSchema = z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
maxChars : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
2026-02-03 17:35:51 -08:00
maxCharsCap : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
2026-01-15 04:07:29 +00:00
timeoutSeconds : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
cacheTtlMinutes : z.number ( ) . nonnegative ( ) . optional ( ) ,
2026-01-21 02:52:27 +00:00
maxRedirects : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
2026-01-15 04:07:29 +00:00
userAgent : z.string ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-15 04:07:29 +00:00
. optional ( ) ;
export const ToolsWebSchema = z
. object ( {
search : ToolsWebSearchSchema ,
fetch : ToolsWebFetchSchema ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-15 04:07:29 +00:00
. optional ( ) ;
2026-01-14 01:08:15 +00:00
export const ToolProfileSchema = z
2026-01-14 14:31:43 +00:00
. union ( [ z . literal ( "minimal" ) , z . literal ( "coding" ) , z . literal ( "messaging" ) , z . literal ( "full" ) ] )
2026-01-14 01:08:15 +00:00
. optional ( ) ;
2026-01-19 03:38:51 +00:00
export const ToolPolicyWithProfileSchema = z
. object ( {
allow : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-25 00:29:28 -08:00
alsoAllow : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-19 03:38:51 +00:00
deny : z.array ( z . string ( ) ) . optional ( ) ,
profile : ToolProfileSchema ,
} )
2026-01-26 10:17:50 -08:00
. strict ( )
. superRefine ( ( value , ctx ) = > {
if ( value . allow && value . allow . length > 0 && value . alsoAllow && value . alsoAllow . length > 0 ) {
ctx . addIssue ( {
code : z.ZodIssueCode.custom ,
message :
"tools.byProvider policy cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)" ,
} ) ;
}
} ) ;
2026-01-15 04:33:35 +00:00
2026-01-14 01:08:15 +00:00
// Provider docking: allowlists keyed by provider id (no schema updates when adding providers).
export const ElevatedAllowFromSchema = z
. record ( z . string ( ) , z . array ( z . union ( [ z . string ( ) , z . number ( ) ] ) ) )
. optional ( ) ;
export const AgentSandboxSchema = z
. object ( {
2026-01-14 14:31:43 +00:00
mode : z.union ( [ z . literal ( "off" ) , z . literal ( "non-main" ) , z . literal ( "all" ) ] ) . optional ( ) ,
workspaceAccess : z.union ( [ z . literal ( "none" ) , z . literal ( "ro" ) , z . literal ( "rw" ) ] ) . optional ( ) ,
sessionToolsVisibility : z.union ( [ z . literal ( "spawned" ) , z . literal ( "all" ) ] ) . optional ( ) ,
scope : z.union ( [ z . literal ( "session" ) , z . literal ( "agent" ) , z . literal ( "shared" ) ] ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
perSession : z.boolean ( ) . optional ( ) ,
workspaceRoot : z.string ( ) . optional ( ) ,
docker : SandboxDockerSchema ,
browser : SandboxBrowserSchema ,
prune : SandboxPruneSchema ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ;
export const AgentToolsSchema = z
. object ( {
profile : ToolProfileSchema ,
allow : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-25 00:29:28 -08:00
alsoAllow : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
deny : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-15 05:11:54 +00:00
byProvider : z.record ( z . string ( ) , ToolPolicyWithProfileSchema ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
elevated : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
allowFrom : ElevatedAllowFromSchema ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
2026-01-19 00:35:39 +00:00
exec : z
. object ( {
host : z.enum ( [ "sandbox" , "gateway" , "node" ] ) . optional ( ) ,
security : z.enum ( [ "deny" , "allowlist" , "full" ] ) . optional ( ) ,
ask : z.enum ( [ "off" , "on-miss" , "always" ] ) . optional ( ) ,
node : z.string ( ) . optional ( ) ,
pathPrepend : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-21 21:44:28 +00:00
safeBins : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-19 00:35:39 +00:00
backgroundMs : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
timeoutSec : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
2026-01-22 00:49:02 +00:00
approvalRunningNoticeMs : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
2026-01-19 00:35:39 +00:00
cleanupMs : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
notifyOnExit : z.boolean ( ) . optional ( ) ,
applyPatch : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
allowModels : z.array ( z . string ( ) ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-19 00:35:39 +00:00
. optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-19 00:35:39 +00:00
. optional ( ) ,
2026-01-14 01:08:15 +00:00
sandbox : z
. object ( {
tools : ToolPolicySchema ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-26 10:17:50 -08:00
. superRefine ( ( value , ctx ) = > {
if ( value . allow && value . allow . length > 0 && value . alsoAllow && value . alsoAllow . length > 0 ) {
ctx . addIssue ( {
code : z.ZodIssueCode.custom ,
message :
"agent tools cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)" ,
} ) ;
}
} )
2026-01-14 01:08:15 +00:00
. optional ( ) ;
export const MemorySearchSchema = z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
2026-01-17 18:53:48 +00:00
sources : z.array ( z . union ( [ z . literal ( "memory" ) , z . literal ( "sessions" ) ] ) ) . optional ( ) ,
2026-01-28 21:49:38 -05:00
extraPaths : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-17 18:53:48 +00:00
experimental : z
. object ( {
sessionMemory : z.boolean ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-17 18:53:48 +00:00
. optional ( ) ,
2026-02-07 10:09:32 +13:00
provider : z
. union ( [ z . literal ( "openai" ) , z . literal ( "local" ) , z . literal ( "gemini" ) , z . literal ( "voyage" ) ] )
. optional ( ) ,
2026-01-14 01:08:15 +00:00
remote : z
. object ( {
baseUrl : z.string ( ) . optional ( ) ,
2026-02-13 16:19:21 +01:00
apiKey : z.string ( ) . optional ( ) . register ( sensitive ) ,
2026-01-14 01:08:15 +00:00
headers : z.record ( z . string ( ) , z . string ( ) ) . optional ( ) ,
2026-01-17 22:31:12 +00:00
batch : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
wait : z.boolean ( ) . optional ( ) ,
2026-01-18 01:24:16 +00:00
concurrency : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
2026-01-17 22:31:12 +00:00
pollIntervalMs : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
timeoutMinutes : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-17 22:31:12 +00:00
. optional ( ) ,
2026-01-14 01:08:15 +00:00
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
2026-01-18 15:29:16 +00:00
fallback : z
2026-02-07 10:09:32 +13:00
. union ( [
z . literal ( "openai" ) ,
z . literal ( "gemini" ) ,
z . literal ( "local" ) ,
z . literal ( "voyage" ) ,
z . literal ( "none" ) ,
] )
2026-01-18 15:29:16 +00:00
. optional ( ) ,
2026-01-14 01:08:15 +00:00
model : z.string ( ) . optional ( ) ,
local : z
. object ( {
modelPath : z.string ( ) . optional ( ) ,
modelCacheDir : z.string ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
store : z
. object ( {
driver : z.literal ( "sqlite" ) . optional ( ) ,
path : z.string ( ) . optional ( ) ,
2026-01-17 18:02:25 +00:00
vector : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
extensionPath : z.string ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-17 18:02:25 +00:00
. optional ( ) ,
2026-01-14 01:08:15 +00:00
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
chunking : z
. object ( {
tokens : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
overlap : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
sync : z
. object ( {
onSessionStart : z.boolean ( ) . optional ( ) ,
onSearch : z.boolean ( ) . optional ( ) ,
watch : z.boolean ( ) . optional ( ) ,
watchDebounceMs : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
intervalMinutes : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
2026-01-21 10:37:52 +00:00
sessions : z
. object ( {
deltaBytes : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
deltaMessages : z.number ( ) . int ( ) . nonnegative ( ) . optional ( ) ,
} )
. strict ( )
. optional ( ) ,
2026-01-14 01:08:15 +00:00
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
query : z
. object ( {
maxResults : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
minScore : z.number ( ) . min ( 0 ) . max ( 1 ) . optional ( ) ,
2026-01-18 01:42:25 +00:00
hybrid : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
vectorWeight : z.number ( ) . min ( 0 ) . max ( 1 ) . optional ( ) ,
textWeight : z.number ( ) . min ( 0 ) . max ( 1 ) . optional ( ) ,
candidateMultiplier : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-18 01:42:25 +00:00
. optional ( ) ,
2026-01-14 01:08:15 +00:00
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
2026-01-18 01:35:58 +00:00
cache : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
maxEntries : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-18 01:35:58 +00:00
. optional ( ) ,
2026-01-14 01:08:15 +00:00
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ;
export const AgentModelSchema = z . union ( [
z . string ( ) ,
2026-01-19 03:38:51 +00:00
z
. object ( {
primary : z.string ( ) . optional ( ) ,
fallbacks : z.array ( z . string ( ) ) . optional ( ) ,
} )
. strict ( ) ,
2026-01-14 01:08:15 +00:00
] ) ;
2026-01-19 03:38:51 +00:00
export const AgentEntrySchema = z
. object ( {
2026-01-19 05:59:29 +00:00
id : z.string ( ) ,
default : z . boolean ( ) . optional ( ) ,
name : z.string ( ) . optional ( ) ,
workspace : z.string ( ) . optional ( ) ,
agentDir : z.string ( ) . optional ( ) ,
model : AgentModelSchema.optional ( ) ,
2026-02-02 21:31:17 -05:00
skills : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-19 05:59:29 +00:00
memorySearch : MemorySearchSchema ,
humanDelay : HumanDelaySchema.optional ( ) ,
heartbeat : HeartbeatSchema ,
identity : IdentitySchema ,
groupChat : GroupChatSchema ,
subagents : z
. object ( {
allowAgents : z.array ( z . string ( ) ) . optional ( ) ,
model : z
. union ( [
z . string ( ) ,
z
. object ( {
primary : z.string ( ) . optional ( ) ,
fallbacks : z.array ( z . string ( ) ) . optional ( ) ,
} )
. strict ( ) ,
] )
. optional ( ) ,
2026-02-02 12:14:17 -08:00
thinking : z.string ( ) . optional ( ) ,
2026-01-19 05:59:29 +00:00
} )
. strict ( )
. optional ( ) ,
sandbox : AgentSandboxSchema ,
tools : AgentToolsSchema ,
} )
2026-01-19 03:38:51 +00:00
. strict ( ) ;
2026-01-14 01:08:15 +00:00
export const ToolsSchema = z
. object ( {
profile : ToolProfileSchema ,
allow : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-25 00:29:28 -08:00
alsoAllow : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
deny : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-15 05:11:54 +00:00
byProvider : z.record ( z . string ( ) , ToolPolicyWithProfileSchema ) . optional ( ) ,
2026-01-15 04:07:29 +00:00
web : ToolsWebSchema ,
2026-01-17 03:52:37 +00:00
media : ToolsMediaSchema ,
2026-01-24 19:15:54 -05:00
links : ToolsLinksSchema ,
2026-01-17 03:17:08 +00:00
message : z
. object ( {
allowCrossContextSend : z.boolean ( ) . optional ( ) ,
crossContext : z
. object ( {
allowWithinProvider : z.boolean ( ) . optional ( ) ,
allowAcrossProviders : z.boolean ( ) . optional ( ) ,
marker : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
prefix : z.string ( ) . optional ( ) ,
suffix : z.string ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-17 03:17:08 +00:00
. optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-17 03:17:08 +00:00
. optional ( ) ,
broadcast : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-17 03:17:08 +00:00
. optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-17 03:17:08 +00:00
. optional ( ) ,
2026-01-14 01:08:15 +00:00
agentToAgent : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
allow : z.array ( z . string ( ) ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
elevated : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
allowFrom : ElevatedAllowFromSchema ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
exec : z
. object ( {
2026-01-18 04:27:33 +00:00
host : z.enum ( [ "sandbox" , "gateway" , "node" ] ) . optional ( ) ,
security : z.enum ( [ "deny" , "allowlist" , "full" ] ) . optional ( ) ,
ask : z.enum ( [ "off" , "on-miss" , "always" ] ) . optional ( ) ,
node : z.string ( ) . optional ( ) ,
2026-01-19 00:35:39 +00:00
pathPrepend : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-21 21:44:28 +00:00
safeBins : z.array ( z . string ( ) ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
backgroundMs : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
timeoutSec : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
cleanupMs : z.number ( ) . int ( ) . positive ( ) . optional ( ) ,
2026-01-17 05:43:27 +00:00
notifyOnExit : z.boolean ( ) . optional ( ) ,
2026-01-14 01:08:15 +00:00
applyPatch : z
. object ( {
enabled : z.boolean ( ) . optional ( ) ,
allowModels : z.array ( z . string ( ) ) . optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
subagents : z
. object ( {
tools : ToolPolicySchema ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
sandbox : z
. object ( {
tools : ToolPolicySchema ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-14 01:08:15 +00:00
. optional ( ) ,
} )
2026-01-19 03:38:51 +00:00
. strict ( )
2026-01-26 10:17:50 -08:00
. superRefine ( ( value , ctx ) = > {
if ( value . allow && value . allow . length > 0 && value . alsoAllow && value . alsoAllow . length > 0 ) {
ctx . addIssue ( {
code : z.ZodIssueCode.custom ,
message :
"tools cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)" ,
} ) ;
}
} )
2026-01-14 01:08:15 +00:00
. optional ( ) ;