import type { CacheConfig } from '@struktoai/mirage-core/cache/file/config'; import type { Resource } from '@struktoai/mirage-core/resource/base'; import { ConsistencyPolicy, Limit, MountBackend, MountMode } from '@struktoai/mirage-core/types'; import type { WorkspaceOptions } from '@struktoai/mirage-core/workspace/workspace/workspace'; import './secrets/constants.ts'; import type { S3Config } from './resource/s3/config.ts'; export declare function interpolateEnv(value: T, env: Record): T; export interface MountBlock { resource: string; mode?: string; config?: Record; command_limits?: Record>; /** vfs (default), fuse, or fskit. Mirrors Python's MountBlock.backend. */ backend?: string; mountpoint?: string; } interface RamIndexBlock { type?: 'ram'; ttl?: number; } interface RedisIndexBlock { type: 'redis'; ttl?: number; url?: string; keyPrefix?: string; } interface RamConsoleBlock { type?: 'ram'; } interface RedisConsoleBlock { type: 'redis'; url?: string; keyPrefix?: string; /** Keys expire this long after the last append; null keeps them. */ ttlSeconds?: number | null; } interface RamStoreGroupBlock { type?: 'ram'; } interface DiskStoreGroupBlock { type: 'disk'; root?: string; } interface RedisStoreGroupBlock { type: 'redis'; url?: string; keyPrefix?: string; } /** * An S3 group IS an S3Config plus the discriminator, so its keys are * the backend's, validated by the s3 config model rather than here. * It hosts only the sessions+meta plane (conditional-PUT CAS), so it * is valid as the `workspace` override and never as the default. */ interface S3StoreGroupBlock extends Partial { type: 's3'; } type StoreGroupBlock = RamStoreGroupBlock | DiskStoreGroupBlock | RedisStoreGroupBlock | S3StoreGroupBlock; /** * The workspace state store: one block, four planes. The top-level * type/url/keyPrefix pick the default backend for every control-plane * group (namespace nodes, observer events, sessions + workspace * metadata); the optional per-group overrides redirect one group to a * different backend. Sessions and workspace metadata move together by * design, so there is one `workspace` override, not two. */ interface StoreBlock { type?: 'ram' | 'disk' | 'redis'; url?: string; keyPrefix?: string; root?: string; namespace?: StoreGroupBlock | null; observer?: StoreGroupBlock | null; workspace?: StoreGroupBlock | null; } /** * One `clis:` entry: install a named CLISpec with its own config. The * section key is the installed head word. Exactly one handler source: * `cli` names a registered spec tree; `script` references a program * file whose content is embedded at load (the docker build-context * model). `runtime` optionally pins the world runtime entry that runs * the script; unset picks the first entry speaking the script's * language. `config` validates through the spec's configModel at * install time (fail loud). A CLI never takes a mode and never shares * a mount's credentials: a binary has no mode, the credential does. */ interface CLIBlock { cli?: string; script?: string; runtime?: string; config?: Record; } export interface WorkspaceConfigRaw { mounts: Record; clis?: Record | null; runtimes?: (string | Record)[] | null; routePolicy?: string | null; /** The profiles (`profiles:`); every entry validated by parseProfiles. */ profiles?: unknown; /** Which profile shapes a session created without one. */ profile?: unknown; mode?: string; consistency?: string; defaultSessionId?: string; defaultAgentId?: string; workspaceId?: string; /** * The normalized block IS a `CacheConfig` — so it is handed to the * workspace as one rather than built here. A store the workspace * builds is a store the workspace closes; building it here would * leave a redis client with no owner once the workspace shut down. */ cache?: CacheConfig | null; index?: RamIndexBlock | RedisIndexBlock | null; store?: StoreBlock | null; /** * Where background-job consoles live. The redis form keys one stream * per job, so a reader in another process can follow a running job; * ram (the default) keeps consoles in memory. Mirrors Python's * ConsoleBlock. */ console?: RamConsoleBlock | RedisConsoleBlock | null; /** * The environment plane: one map, name -> entry. A bare string is * the literal short form; a mapping is an env entry, either a * literal with attrs or a managed pointer (`from`/`ref`/`key`/ * `fetch`). Validated by `validateEnvBlock`, translated by the * workspace. */ env?: Record | null; /** * The source table: one map, instance name -> declaration, spelled * the way `mounts:` is. A managed env entry's `from` names an * instance here, or a source directly when the deployment has one * account of it and nothing to configure. */ secrets?: Record | null; } /** * Interpolate `${VAR}` and check every key, leaving the spelling alone. * * This is the shape that travels: the CLI prepares a config here and * POSTs it, and the daemon runs the same check on what arrives, so the * wire carries Python's snake_case exactly as `model_dump()` does on * that side. Camelizing before sending would make the loader have to * accept its own output, which is how a camelCase spelling Python * rejects would creep back in. */ export declare function checkWorkspaceConfig(source: Record, env?: Record): Record; export declare function loadWorkspaceConfig(source: Record, env?: Record): WorkspaceConfigRaw; /** * Resolve relative script paths and code refs against the config file's * directory. * * A path-form `script`/`route_policy`, a `cli: ./tool.mjs:TREE`, a * `resource: ./wiki.mjs:WikiResource` and a runtime entry's * `name: ./box.mjs:EchoBox` in a config file all mean "next to the file" * (the docker build-context model), never "wherever the server happens * to run". In-memory object configs are untouched. Exported so * the CLI applies the same rebase to a `load`/`clone` override, which is * read without validation and so cannot go through * `checkWorkspaceConfigFile`; mirrors `_absolutize_scripts` in * `mirage/config.py`. */ export declare function absolutizeScripts(raw: Record, base: string): void; /** * Read a config file into the shape that travels: checked, env * interpolated, script paths resolved against the file's directory — * and still spelled the way the file spelled it. What a CLI sends to * the daemon. */ export declare function checkWorkspaceConfigFile(path: string, env?: Record): Record; export declare function loadWorkspaceConfigFile(path: string, env?: Record): WorkspaceConfigRaw; export interface WorkspaceArgs { resources: Record]>; /** * Exactly what `new Workspace` takes, minus the two the loader always * resolves. Spelling the fields out here instead is what once dropped * `clis` and the deny rules on the way to the daemon: a config knob was * parsed and validated, then discarded by a list nobody remembered to * extend. */ options: WorkspaceOptions & { mode: MountMode; consistency: ConsistencyPolicy; }; kernelMounts: Record; } export declare function configToWorkspaceArgs(cfg: WorkspaceConfigRaw): Promise; export {}; //# sourceMappingURL=config.d.ts.map