Skip to content

Data Model

Documentation of JSON structures persisted in ./.runeya/ (the DATA_DIR, relative to the current repository).

projects.json

typescript
interface Project {
  id: string        // UUID
  name: string      // max 128
  description?: string
  createdAt: string // ISO 8601
  updatedAt: string
}

services.json

typescript
interface ServiceConfig {
  id: string           // UUID (= processId côté agent)
  name: string         // max 128
  description?: string // max 512
  command: string      // max 2048
  cwd: string          // répertoire de travail, max 2048
  shell: boolean       // false par défaut
  projectId: string    // UUID du projet parent
  agentId: string      // UUID de l'agent assigné
  parserIds: string[]  // UUIDs des parsers JS, dans l'ordre

  // Variables secrètes (chiffrées AES-256-GCM)
  envSecrets: Array<{
    key: string
    value: string  // format: iv:authTag:ciphertext (hex)
  }>

  // Environnements service-scoped
  environments?: Array<{
    reference: string   // nom de l'env global
    activateOn: string  // nom de l'env actif déclencheur
    overrides: Record<string, Variable>  // variableId → Variable
  }>

  createdAt: string
  updatedAt: string
}

environments.json

typescript
interface Environment {
  id: string
  name: string            // max 128
  immutable?: boolean     // protégé contre suppression
  variables: Record<string, Variable>  // variableId → Variable
  createdAt: string
  updatedAt: string
}

interface Variable {
  key: string     // Nom de la variable d'env
  value: string   // Valeur (ciphertext si secret)
  secret: boolean
}

agents.json

typescript
interface Agent {
  id: string
  name: string
  url: string              // http://127.0.0.1:9546
  passphrase: string       // chiffré AES-256-GCM
  registeredAt: string
  lastSeenAt?: string
}

settings.json

typescript
interface Settings {
  mode: 'local-simple'
  notifications: NotificationPreferences
  logParsers: JSLogParser[]
  scenarios: Scenario[]
  enterprises: Enterprise[]
}

interface NotificationPreferences {
  scenario_waiting_input: boolean
  ai_conversation_complete: boolean
  ai_conversation_error: boolean
  service_error_log: boolean
  service_status_changed: boolean
  service_health_changed: boolean
}

interface JSLogParser {
  id: string       // UUID
  name: string     // max 128
  code: string     // code JS sandbox, max 16KB
  version: 1 | 2  // 1 = (raw, stream) => result, 2 = (line) => line
}

settings.json — Scenarios

Scenarios are stored in settings.json under the scenarios: Scenario[] key.

typescript
interface Scenario {
  id: string           // UUID, max 128
  name: string         // max 200
  description?: string // max 2000
  nodes: ScenarioNode[]   // max 50
  edges: ScenarioEdge[]   // max 100
  groups: ScenarioGroup[] // max 20
  createdAt: number    // epoch ms
  updatedAt: number    // epoch ms
}

interface ScenarioNode {
  id: string          // UUID, max 128
  type: 'prompt' | 'ask_user'
  label: string       // max 200
  prompt: string      // max 50 000 chars
  position: { x: number; y: number }
  allPredecessors: boolean   // inject all predecessor outputs into context
  contextNodeIds: string[]   // explicit node IDs to inject (max 50)
  groupId?: string           // parent group UUID (max 128)
  aiCli: 'claude-code' | 'codex'
  model: string       // model alias, e.g. 'sonnet' (max 128)
  effort: 'low' | 'normal' | 'high'
}

interface ScenarioEdge {
  id: string          // UUID, max 128
  source: string      // source node ID (max 128)
  target: string      // target node ID (max 128)
  description: string // branch label, max 500 (used for AI routing)
}

interface ScenarioGroup {
  id: string          // UUID, max 128
  label: string       // max 200
  position: { x: number; y: number }
  width: number       // 100–5000, default 300
  height: number      // 80–5000, default 200
  borderColor?: string // max 50
  bgColor?: string     // max 50
  textColor?: string   // max 50
}

Conditional branching (AI-driven)

When a prompt node has multiple outgoing edges, the runner automatically injects numbered choices into the AI prompt:

Reply PASS1 for "<edge 1 description>" or PASS2 for "<edge 2 description>"

The AI must end its response with PASS1 or PASS2 on its own line. The runner extracts this token from the last line of the response and follows the corresponding edge.

  • Node with 1 edge: unchanged behavior (PASS / FAIL).
  • Node with 0 edges: terminal node, scenario ends.
  • Invalid token: the run stops with an error.

settings.json — Enterprises

Enterprises are stored in settings.json under the enterprises: Enterprise[] key.

typescript
interface Enterprise {
  id: string             // UUID, max 128
  name: string           // max 200
  description?: string   // max 2000
  leaderId: string       // must reference an existing person
  teams: EnterpriseTeam[]    // max 100
  people: EnterprisePerson[] // max 500
  createdAt: number      // epoch ms
  updatedAt: number      // epoch ms
}

interface EnterpriseTeam {
  id: string             // UUID, max 128
  name: string           // max 200
  description?: string   // max 1000
}

interface EnterprisePerson {
  id: string             // UUID, max 128
  parentId: string | null // direct manager (optional)
  teamId: string | null   // team (optional)
  firstName: string      // max 120
  lastName: string       // max 120
  age: number | null     // 16..90
  prompt: string         // max 50 000
  autoGenerated: boolean
}

Business constraints:

  • leaderId must reference an existing person.
  • parentId must reference an existing person (when set).
  • Hierarchy cycles are rejected.

conversations.private.json

AI conversation history. Messages are encrypted at rest (AES-256-GCM) in encryptedMessages.

typescript
interface ConversationOnDisk {
  id: string
  title: string              // max 200
  encryptedMessages: string  // encrypted JSON payload of messages
  isCli?: boolean
  contextUsage?: {
    inputTokens: number
    contextWindow: number
  }
  scenarioId?: string        // set when the conversation is a scenario run
  enterpriseId?: string      // set when the conversation is an enterprise run
  archived?: boolean
  createdAt: number          // epoch ms
  updatedAt: number          // epoch ms
}

Note: scenario run conversation titles can be edited by users and can also be AI-generated via scenario.generateName.

enterprise-runs/<conversationId>/

Workspace automatically created when an enterprise conversation is created.

  • README.md: enterprise overview, leader, members, and rules.
  • USER_REQUEST.md: initial user brief (enterpriseInput).
  • <slug>_<personId>.md: one file per person (prompt + work log).

schema-version.json

json
{ "version": 3 }

Utilisé par le système de migration pour détecter les anciennes versions de données.

.encryption.key

Fichier binaire contenant 32 bytes (256 bits) de données aléatoires. Permissions : 0o600 (lecture seule pour l'owner). Jamais commitée, jamais loggée.

Entity Relationships

Project (1) ──────────────── (N) Service

                                    ├── (1) Agent

                                    ├── (N) JSLogParser (via parserIds)

                                    └── (N) Environment (service-scoped)

                                                └── référence → Environment global (1)

Settings
  ├── (N) JSLogParser
  ├── (N) Scenario
  │         ├── (N) ScenarioNode
  │         ├── (N) ScenarioEdge  (source → target, description)
  │         └── (N) ScenarioGroup
  └── (N) Enterprise
            ├── (N) EnterpriseTeam
            └── (N) EnterprisePerson (parentId → EnterprisePerson)

Released under the MIT License.