SPB Git

Repository Public

api.ts 5.8 KB 107 lines typescript

1/** Browser-facing DTOs (REST /api/v1). Auth DTOs are unchanged from Claude Remote and live in the server. */2import { z } from 'zod';3import { Budget, DoneCriterion, Effort, Provider, ResultEnvelope, RiskClass, RunStatus, Usage } from './core.js';45const iso = z.string();6export const Id = z.string().uuid();78export const Branding = z.object({ agent: z.literal('aos'), productName: z.string(), agentName: z.string() });910export const ProjectDto = z.object({11  id: Id, name: z.string(), description: z.string(), path: z.string(), gitRemote: z.string().nullable(),12  gitBranch: z.string().nullable(), instructions: z.string(), missions: z.number(), createdAt: iso,13});14export type ProjectDto = z.infer<typeof ProjectDto>;15export const CreateProject = z.object({16  name: z.string().min(1).max(80), description: z.string().max(2000).default(''),17  mode: z.enum(['create', 'existing', 'clone']), path: z.string().max(300).optional(), gitUrl: z.string().max(500).optional(),18  instructions: z.string().max(8000).default(''),19});2021export const ModelInfo = z.object({22  provider: Provider, id: z.string(), label: z.string(), tier: z.enum(['frontier', 'main', 'worker', 'volume']),23  contextTokens: z.number().nullable(), maxOutputTokens: z.number().nullable(),24  inputUsd: z.number().nullable(), outputUsd: z.number().nullable(), efforts: z.array(Effort), available: z.boolean(),25});26export type ModelInfo = z.infer<typeof ModelInfo>;2728export const RunDto = z.object({29  id: Id, missionId: Id, parentRunId: Id.nullable(), depth: z.number(), role: z.string(),30  objective: z.string(), provider: Provider, model: z.string(), effort: Effort.nullable(),31  status: RunStatus, usage: Usage, budget: Budget, sandboxTier: z.number(),32  result: ResultEnvelope.nullable(), createdAt: iso, startedAt: iso.nullable(), endedAt: iso.nullable(),33  pendingWaits: z.number(),34});35export type RunDto = z.infer<typeof RunDto>;3637export const MissionDto = z.object({38  id: Id, projectId: Id.nullable(), projectName: z.string().nullable(), title: z.string(), objective: z.string(),39  doneCriteria: z.array(DoneCriterion), status: RunStatus, budgetUsd: z.number(), spentUsd: z.number(),40  network: z.enum(['none', 'open']), rootRunId: Id.nullable(), runs: z.number(), pendingWaits: z.number(),41  createdAt: iso, startedAt: iso.nullable(), endedAt: iso.nullable(),42  // Additive (integration, 2026-11-10): provider / model / effort of the ROOT run, so a list needs no request per mission.43  provider: Provider.nullable().optional(), model: z.string().nullable().optional(), effort: Effort.nullable().optional(),44});45export type MissionDto = z.infer<typeof MissionDto>;4647export const CreateMission = z.object({48  projectId: Id,49  title: z.string().min(1).max(160).optional(), // default: first 80 chars of objective50  objective: z.string().min(1).max(8000),51  doneCriteria: z.array(z.string().min(1).max(1000)).max(50).default([]), // empty ⇒ the agent proposes them first, owner sees them52  provider: Provider.optional(), model: z.string().max(80).optional(), effort: Effort.optional(), // default from settings53  budgetUsd: z.number().positive().max(1000).optional(),54  network: z.enum(['none', 'open']).default('none'),55});56export type CreateMission = z.infer<typeof CreateMission>;5758export const StepDto = z.object({59  runId: Id, seq: z.number(), kind: z.string(), name: z.string(), effect: z.string(),60  status: z.enum(['started', 'completed', 'failed', 'needs_reconcile']),61  request: z.unknown(), result: z.unknown().nullable(), error: z.unknown().nullable(), usage: Usage.partial().nullable(),62  startedAt: iso, completedAt: iso.nullable(),63});64export type StepDto = z.infer<typeof StepDto>;6566export const WaitDto = z.object({67  id: Id, runId: Id, missionId: Id, missionTitle: z.string(), stepSeq: z.number(),68  kind: z.enum(['approval', 'question', 'timer', 'child']),69  payload: z.record(z.string(), z.unknown()),70  status: z.enum(['pending', 'resolved', 'expired', 'cancelled']),71  resolution: z.record(z.string(), z.unknown()).nullable(), resolveBy: iso.nullable(), createdAt: iso, resolvedAt: iso.nullable(),72});73export type WaitDto = z.infer<typeof WaitDto>;74export const ResolveWait = z.discriminatedUnion('kind', [75  z.object({ kind: z.literal('approval'), decision: z.enum(['approve', 'deny']), remember: z.boolean().default(false), note: z.string().max(2000).optional() }),76  z.object({ kind: z.literal('question'), answer: z.string().max(8000) }),77]);78export type ResolveWait = z.infer<typeof ResolveWait>;7980export const PolicyRuleDto = z.object({81  id: Id, projectId: Id.nullable(), decision: z.enum(['deny', 'ask', 'allow']), tool: z.string(),82  match: z.record(z.string(), z.unknown()), note: z.string(), createdAt: iso,83});84export const CreatePolicyRule = PolicyRuleDto.omit({ id: true, createdAt: true });8586export const AosSettings = z.object({87  theme: z.enum(['light', 'dark', 'system']).default('light'),88  defaultProvider: Provider.default('anthropic'),89  defaultModel: z.string().default('claude-opus-5-5'),90  defaultEffort: Effort.default('high'),91  missionBudgetUsd: z.number().positive().default(15),92  dailyBudgetUsd: z.number().positive().default(60),93  maxConcurrentRuns: z.number().int().min(1).max(32).default(4),94  approvalTimeoutHours: z.number().min(1).max(24 * 14).default(72),95  notifications: z.object({ inApp: z.boolean(), detail: z.enum(['generic', 'titles']) }).default({ inApp: true, detail: 'titles' }),96  layout: z.record(z.string(), z.unknown()).default({}),97});98export type AosSettings = z.infer<typeof AosSettings>;99100export const SpendSummary = z.object({101  todayUsd: z.number(), dailyBudgetUsd: z.number(), last7Days: z.array(z.object({ day: z.string(), usd: z.number() })),102  byModel: z.array(z.object({ provider: Provider, model: z.string(), usd: z.number(), inputTokens: z.number(), outputTokens: z.number() })),103});104export type SpendSummary = z.infer<typeof SpendSummary>;105106export const RiskLabel = RiskClass;107
Files main
Menu

Theme