# Resources See also: `specs/designs/01-data/resource-events.md` for the per-workspace status/event subscription API. ## Overview The Resources layer provides live runtime status for all managed objects. While configuration is persisted in Git (via the Catalog), runtime state (phase, readiness, error conditions) is read directly from the Kubernetes API server. The `Resources` class is the top-level entry point; it holds one `WorkspaceResources` per workspace, each backed by a `K8sClient` that maintains a synchronized in-memory cache via Kubernetes informers. All cache reads are **synchronous and allocation-free** — there are no per-request API calls for status data. ## Architecture ``` Resources └── Map WorkspaceResources ├── models: ModelResources ├── tools: ToolResources ├── kbs: KBResources ├── documents: DocumentResources ├── agents: AgentResources ├── stacks: StackResources ├── secrets: SecretResources └── subscribe(handler): unsubscribe ModelResources / ToolResources / KBResources / DocumentResources / AgentResources ├── getManagedModels / getManagedTools ├── getManagedModelResources / getManagedToolResources → CoreResources (Deployments + Pods + Services) ├── getManagedModelStatus / getManagedToolStatus ├── getExternalModels / getExternalTools └── getExternalModelStatus / getExternalToolStatus ``` `Resources` is initialized by `Server` at startup. `getWorkspaceResources(workspaceId)` returns the `WorkspaceResources` for the requested workspace ID; route handlers call this using `locals.workspace.id`. Workspaces with `deployment.type === 'local'` have no `K8sClient` and no live resource data. ## Watched Resources `K8sModelResources` starts informers for these resource types in the workspace namespace: | Resource | Group | Version | Label selector | | ---------------- | --------------- | ---------- | ------------------------------- | | `managedmodels` | `locostack.com` | `v1alpha1` | — | | `externalmodels` | `locostack.com` | `v1alpha1` | — | | `deployments` | `apps` | `v1` | `locostack.com/component=Model` | | `pods` | `core` | `v1` | `locostack.com/component=Model` | | `services` | `core` | `v1` | `locostack.com/component=Model` | `K8sToolResources` mirrors the same pattern for tools (label `locostack.com/component=Tool`), watching `managedtools` and `externaltools`. **Lazy initialization**: the first call to any method triggers informer startup and waits for the initial LIST to complete. Concurrent calls share the same initialization promise. ## K8sClient — list-watch cache `K8sClient` implements the list-watch cache used by both `K8sModelResources` and `K8sToolResources`. **List-watch pattern**: start with a full LIST to get the current state and a `resourceVersion`, then WATCH from that version to stream deltas. On stream close or error, relist and rewatch. All updates are applied synchronously to an in-memory `Map`; reads are O(1) lookups. **Reconnection**: on informer error, the client logs the failure and restarts the informer after a 5-second delay. The stale cache continues to serve reads during the reconnect window. **KubeConfig resolution**: - `apiUrl` + `token` provided → explicit out-of-cluster config - both absent → `loadFromDefault()` (in-cluster service account, then `~/.kube/config`) `skipTlsVerify` disables certificate verification (dev only).