resources.md 3.6 KB

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<workspaceId, { workspace, k8sClient?, resources: WorkspaceResources }>

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<name, object>; 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).