Sakura Data Models
Comprehensive reference for all TypeScript types, Zod schemas, and database table definitions across the Sakura monorepo.
Table of Contents
- Core CLI Types
- Provider & LLM Types
- Plan Types
- Session Types
- Configuration Schemas
- Tool System Types
- MCP Types
- Plugin Types
- Planning Types
- Scaffold Types
- Auth Types
- API Database Schemas
- Entity Relationship Diagram
- Validation Rules Summary
1. Core CLI Types
Sources: src/types.ts
Intent
Classifies the user's request into one of six routing categories.
type Intent = "AWS" | "CODE" | "SHELL" | "GIT" | "DOCKER" | "GENERAL";
| Value | Description |
|---|---|
AWS | AWS CLI operations (S3, EC2, IAM, Lambda, etc.) |
CODE | Code editing, refactoring, diff application |
SHELL | General shell/OS commands |
GIT | Git operations |
DOCKER | Docker operations |
GENERAL | Conversational or unclassified requests |
ProviderName
type ProviderName = "openai" | "anthropic";
RouteDecision
The output of the intent routing engine.
type RouteDecision = {
intent: Intent;
complexity?: "simple" | "complex";
matchedRules: string[];
recommendedProvider?: ProviderName;
};
| Field | Type | Description |
|---|---|---|
intent | Intent | Classified intent |
complexity | "simple" | "complex" | Inferred from prompt signals |
matchedRules | string[] | Rule names that triggered the classification |
recommendedProvider | ProviderName? | Optional provider hint |
Complexity signals (from src/routing.ts):
- Complex:
set up,create,configure,refactor,implement,migrate,debug,fix,deploy,build,rewrite,restructure,convert,replace X with,add X to,change X to,move X to,split,merge,integrate - Simple:
list,show,get,describe,check,what,read,search,find,explain,tell me,how does,count,status - Fallback: prompts longer than 200 characters are classified as
complex
2. Provider & LLM Types
Sources: src/providers/provider.ts
ChatMessage
type ChatMessage =
| { role: "user" | "assistant"; content: string }
| { role: "tool"; toolCallId: string; content: string };
Note: Tool-role messages are filtered out before sending to both OpenAI and Anthropic APIs, as they reference function call IDs not present in the simplified history format.
ProviderRequest
type ProviderRequest = {
prompt: string;
system?: string;
model?: string;
taskType?: string;
temperature?: number;
history?: ChatMessage[];
image?: { base64: string; mimeType: string };
tools?: { name: string; description: string; parameters: Record<string, unknown> }[];
thinking?: boolean;
};
| Field | Type | Description |
|---|---|---|
prompt | string | The user's current message |
system | string? | System prompt override |
model | string? | Model identifier |
taskType | string? | Hint for routing/logging (e.g. "aws_translate", "compact") |
temperature | number? | Sampling temperature (0–2) |
history | ChatMessage[]? | Prior conversation turns |
image | object? | Base64-encoded image attachment |
tools | array? | Tool schemas to expose to the model |
thinking | boolean? | Enable extended thinking (Anthropic only) |
ToolCall
type ToolCall = {
id: string;
name: string;
arguments: Record<string, unknown>;
};
ProviderResponse
type ProviderResponse = {
provider: ProviderName;
model: string;
text: string;
toolCalls?: ToolCall[];
thinking?: string;
usage?: {
inputTokens?: number;
outputTokens?: number;
creditsCharged?: number;
creditsPrecise?: number;
creditsRemaining?: number | string;
};
};
LlmProvider Interface
interface LlmProvider {
readonly name: ProviderName;
complete(req: ProviderRequest): Promise<ProviderResponse>;
stream?(req: ProviderRequest): AsyncIterable<string>;
}
Three concrete implementations:
| Class | Source | Description |
|---|---|---|
OpenAIProvider | src/providers/openai.ts | Direct OpenAI API (Responses API) |
AnthropicProvider | src/providers/anthropic.ts | Direct Anthropic API with prompt caching |
ApiProvider | src/providers/api.ts | Sakura API proxy (used when logged in) |
Provider-specific defaults:
| Provider | Default Model | Max Tokens | Thinking |
|---|---|---|---|
| OpenAI | gpt-5.2 | — | No |
| Anthropic | claude-sonnet-4-20250514 | 4096 (16000 with thinking) | Yes |
| ApiProvider | Delegates to server | — | — |
ApiProvider payload constraints (to avoid API Gateway 30s timeout):
- History capped at last 10 messages
- Individual messages truncated at 3,000 characters
3. Plan Types
Sources: src/types.ts, src/planning/store.ts
PlanRisk
type PlanRisk = "readonly" | "mutating";
PlanBase
type PlanBase = {
id: string;
createdAt: string; // ISO 8601
summary: string;
risk: PlanRisk;
provenance: {
provider: ProviderName | "none";
model: string;
routingRules: string[];
};
};
AwsPlan
type AwsPlan = PlanBase & {
type: "aws";
aws: {
argv: string[]; // CLI arguments without "aws" prefix
};
};
CodePlan
type CodePlan = PlanBase & {
type: "code";
code: {
patchUnifiedDiff: string; // Unified diff format
};
};
Plan
type Plan = AwsPlan | CodePlan;
Zod Schemas (Runtime Validation)
Sources: src/planning/store.ts
const ProvenanceSchema = z.object({
provider: z.union([z.enum(["openai", "anthropic"]), z.literal("none")]),
model: z.string(),
routingRules: z.array(z.string())
});
const PlanBaseSchema = z.object({
id: z.string(),
createdAt: z.string(),
summary: z.string(),
risk: z.enum(["readonly", "mutating"]),
provenance: ProvenanceSchema
});
const PlanSchema = z.discriminatedUnion("type", [
PlanBaseSchema.extend({
type: z.literal("aws"),
aws: z.object({ argv: z.array(z.string()) })
}),
PlanBaseSchema.extend({
type: z.literal("code"),
code: z.object({ patchUnifiedDiff: z.string() })
})
]);
Storage: Plans are persisted to .sakura/plans/<id>.json and .sakura/plans/latest.json.
4. Session Types
Sources: src/sessions/store.ts
Session
// Zod schema
const SessionSchema = z.object({
id: z.string(),
cwd: z.string(),
createdAt: z.string(), // ISO 8601
updatedAt: z.string(), // ISO 8601
messages: z.array(
z.object({
role: z.enum(["user", "assistant"]),
content: z.string()
})
)
});
type Session = z.infer<typeof SessionSchema>;
Note: Session IDs are derived from a SHA-1 hash of
process.cwd()combined with the directory basename, producing stable per-project session identifiers.
Storage: Sessions are persisted to .sakura/sessions/<id>.json.
ReplContext
Sources: src/repl/types.ts
The live runtime state of the interactive REPL.
type ReplContext = {
rl: readline.Interface;
provider: LlmProvider;
claudeProvider?: LlmProvider; // Optional secondary Claude provider for handoff
sessions: SessionStore;
activeSession: Session;
history: ChatMessage[];
activeModel: string | undefined;
temperature: number;
pendingImage: ImageData | null;
plannerMode: boolean;
lastEditedPath?: string;
opts: ReplOptions;
config: SakuraConfig;
updatePrompt: () => void;
};
ReplOptions
type ReplOptions = {
configPath?: string;
profile?: string;
provider?: "openai" | "anthropic";
model?: string;
temperature?: number;
trace?: boolean;
resume?: boolean;
};
5. Configuration Schemas
Sources: src/config.ts
ProfileSchema
const ProfileSchema = z.object({
provider: z.enum(["openai", "anthropic"]).default("openai"),
model: z.string().optional(),
temperature: z.number().min(0).max(2).default(0.2),
awsProfile: z.string().optional(),
awsRegion: z.string().optional()
});
type SakuraProfile = z.infer<typeof ProfileSchema>;
PhaseSchema
Controls the /phase command behavior for multi-phase project builds.
const PhaseSchema = z.object({
language: z.enum(["typescript", "python", "go", "rust"]).default("typescript"),
buildCommand: z.string().default("pnpm build"),
lintCommand: z.string().optional(),
referenceFiles: z.array(z.string()).default([]),
projectContext: z.string().default(""),
});
ConfigSchema
const ConfigSchema = z.object({
version: z.literal(1),
defaultProfile: z.string().default("default"),
profiles: z.record(ProfileSchema).default({
default: { provider: "openai", model: "gpt-5.2", temperature: 0.2 }
}),
maxPlanAgeHours: z.number().min(0).default(4),
phase: PhaseSchema.default({}),
});
type SakuraConfig = z.infer<typeof ConfigSchema>;
Default config file (.sakura/config.toml):
version = 1
defaultProfile = "default"
[profiles.default]
provider = "openai"
model = "gpt-5.2"
temperature = 0.2
[profiles.coding-claude]
provider = "anthropic"
model = "claude-sonnet-4-20250514"
temperature = 0.2
Settings
Sources: src/util/settings.ts
Runtime-adjustable settings stored in JSON (global: ~/.sakura-cli/settings.json, local: .sakura/settings.json).
type Settings = {
model?: string;
provider?: string;
temperature?: number;
theme?: boolean;
autoCompactThreshold?: number;
maxOutputChars?: number;
trustMode?: "ask" | "trust-session";
};
6. Tool System Types
Sources: src/tools/registry.ts, src/tools/executor.ts
TrustLevel
type TrustLevel =
| "trusted" // Always executes without prompt
| "trust_read_only" // Auto-approves reads; prompts for writes/mutations
| "trust_working_dir" // Auto-approves paths within cwd; prompts for outside
| "not_trusted"; // Always prompts
ToolDefinition
type ToolDefinition = {
name: string;
description: string;
trustLevel: TrustLevel;
parameters: Record<string, unknown>; // JSON Schema object
execute: (args: Record<string, unknown>) => Promise<ToolResult>;
};
ToolResult
type ToolResult = {
success: boolean;
output: string;
error?: string;
};
ToolCall
type ToolCall = {
id: string;
name: string;
arguments: Record<string, unknown>;
};
Registered Tools
Sources: src/tools/index.ts, src/tools/implementations/
| Tool Name | Trust Level | Description |
|---|---|---|
read | trust_working_dir | Read file or list directory |
create_file | trusted | Create a new file (fails if exists) |
edit | trusted | Surgically edit existing file (find_replace, insert_after, replace, delete) |
shell | trusted | Run shell command (skips approval in tool loop) |
glob | trust_working_dir | Find files matching glob pattern |
grep | trust_working_dir | Regex search across project files |
code | trust_read_only | Analyze code structure (symbols, search, structure) |
aws | trust_read_only | Run AWS CLI command |
introspect | trusted | Query Sakura's own capabilities |
session | not_trusted | Session info |
report | not_trusted | Signal report generation intent |
subagent | not_trusted | Parallel subtask delegation |
fetch | trusted | HTTP fetch with HTML→text conversion |
batch_create | trusted |