Skip to content

p-vbordei/cube-runtime

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cube-runtime

The own-the-loop 5-phase cognition runtime: synchronous fakes-first core plus an additive async real path, behind swappable CognitionFace / AsyncCognitionFace contracts.

Status: M2 · part of the Vollko cube platform. Language: TypeScript (Bun/Node) · deps: cube-spine only.

The loop is backend-agnostic. The synchronous LoopEngine + FakeBackend is the fakes-first CI contract — it runs offline, deterministically, with no API keys. The async path (AsyncLoopEngine + AsyncModelBackend) is additive: it mirrors the same 5-phase shape (Review → Hypothesis → Investigate → Verify → Synthesize) but awaits a real LLM over HTTP. The sync core is never patched — the async engine is a separate class that delegates to an AsyncModelBackend. The real model backend lives in the sibling cube-runtime-anthropic package; this package defines only the interfaces.

Budget caps and pattern-based loop detection are enforced in code; each phase emits a cognition.* envelope on the cube-spine bus. Multimodal inputs (GenerateArgs.images) are part of the contract; text-only backends silently ignore the field.

Dev: bun install, bun test, bun run typecheck (tsc --noEmit).

This package depends on its sibling cube-spine via a file:../cube-spine path dependency. Clone it alongside this repo (same parent directory) before bun install — a standalone clone will not install or build.

Usage

Synchronous (fakes-first, no API keys)

import { Bus } from "cube-spine";
import { LoopEngine, FakeBackend, ToolRegistry } from "cube-runtime";

const bus = new Bus();
bus.subscribe("*", (e) => console.log(e.topic));

const tools = new ToolRegistry().register("lookup", (args) => ({ found: args.id }));

const engine = new LoopEngine({
  backend: new FakeBackend({ synthesize: { text: "final answer" } }),
  bus,
  who: "did:web:agent",
  tools,
});

const result = engine.run({ task: "summarize the incident" });
console.log(result.output); // "final answer"
console.log(result.phases); // ["review", "hypothesis", "investigate", "verify", "synthesize"]

Async (real model backend, e.g. cube-runtime-anthropic)

A real LLM call is async — HTTP cannot resolve synchronously. AsyncLoopEngine is the additive path that mirrors the same 5-phase loop but awaits an AsyncModelBackend. The sync LoopEngine remains the fakes-first contract that the platform's tests rest on; this is purely additive.

import { Bus } from "cube-spine";
import { AsyncLoopEngine, FakeAsyncBackend } from "cube-runtime";

// In production swap FakeAsyncBackend for the cube-runtime-anthropic adapter.
const engine = new AsyncLoopEngine({
  backend: new FakeAsyncBackend({ synthesize: { text: "done" } }),
  bus: new Bus(),
  who: "did:web:agent",
});

const result = await engine.run({ task: "analyze the outage" });
console.log(result.output); // "done"

Multimodal inputs

Pass base64-encoded images via GenerateArgs.images. Text-only backends ignore the field.

import { FakeBackend, LoopEngine } from "cube-runtime";
import type { ImageContent } from "cube-runtime";

const image: ImageContent = {
  mediaType: "image/png",
  dataBase64: "<base64-bytes>",
};
// Images are forwarded through GenerateArgs inside the engine;
// a multimodal backend reads them, a text-only backend skips them.

Public API

Everything is exported from the package root (cube-runtime).

Synchronous core (fakes-first CI contract)

  • LoopEngine, PHASES, type LoopEngineArgs — the own-the-loop 5-phase engine (run(args): CognitionResult).
  • BudgetMeter — hard step/token caps enforced in code; halts the loop when exhausted.
  • LoopGuard — pattern-based loop detection; halts when the same tool-call signature repeats.
  • ProgressJournal — rolling structured context fed into each phase; not a full transcript replay.

Async real path (additive, for real LLM I/O)

  • AsyncLoopEngine, type AsyncLoopEngineArgs — mirrors LoopEngine but awaits an AsyncModelBackend; implements AsyncCognitionFace.
  • FakeAsyncBackend, type FakeScript — deterministic AsyncModelBackend for tests/offline use of the async path.
  • NoOpAsyncExecutor — default async executor (no durability); implements AsyncDurableExecutor.

Contracts (from ./contracts)

  • NoOpExecutor — default sync executor (no durability); implements DurableExecutor.
  • NoOpAsyncExecutor — default async executor (no durability); implements AsyncDurableExecutor.
  • type CognitionFace — sync contract: run(args: RunArgs): CognitionResult.
  • type AsyncCognitionFace — async contract: run(args: RunArgs): Promise<CognitionResult>.
  • type ModelBackend — sync: generate(args: GenerateArgs): ModelResponse.
  • type AsyncModelBackend — async: generate(args: GenerateArgs): Promise<ModelResponse>. The real implementation lives in cube-runtime-anthropic.
  • type DurableExecutor — sync: run<T>(name, fn): T.
  • type AsyncDurableExecutor — async: run<T>(name, fn): Promise<T>.
  • type GenerateArgs{ phase, prompt, context, reasoningEffort?, images? }.
  • type ImageContent{ mediaType: string, dataBase64: string } — base64-encoded image for multimodal backends; text-only backends ignore it.
  • types ModelResponse, ToolCall, CognitionResult, RunArgs.

Backends & execution

  • FakeBackend, type FakeScript — deterministic sync backend for tests/offline runs.
  • FakeAsyncBackend, type FakeScript — deterministic async backend (CI contract for the async path).
  • FileExecutor — durable sync executor: memoizes each step to a JSON file so a crashed run can resume.

Tools

  • ToolRegistry, types Tool, ToolOutcome — the registry the loop calls in the Investigate phase.
  • registerWithRisk, manifestFor, listManifests, types RiskGate, RiskLevel, ToolManifest — risk-aware tool registration; high-risk tools can be gated at call time.

Scheduling

  • schedule, types ExecutionStep, WorkItem — order work by mutation safety: mutating items run serially, read-only items are batched in parallel; causal order is preserved.

Model routing & BYOK

  • ModelRouter, types AgentRole, ModelCatalogEntry — pure role → ModelBackend router.
  • ModelCatalog, describeBackend, enforceGateway, expandModelConfig, types CustomModelConfig, GatewayPolicy — bring-your-own-key config (env-expanded, never logged), an org gateway allowlist, and a cost-aware model catalog.

Spec mode (plan-then-approve)

  • planFromOutput, readOnlyTools, requireApproval, types ApprovalGate, Plan, ToolPredicate — read-only analysis emits a structured plan; a single approval gate sits between the plan and any write.

Sessions

  • SessionStore, types CreateOpts, SessionFilter, SessionRecord — continue, fork, and tag a unit of work, with JSON persistence and an injectable clock.

Part of the Vollko cube platform — a polyrepo of composable, zero-dependency building blocks for AI-native organizations. See reference-constellation for the whole stack running end-to-end; packages depend on each other via file:../, so clone the siblings alongside this one.


Apache-2.0 © 2026 Vlad Bordei bordeivlad@gmail.com · https://github.com/p-vbordei

About

Own-the-loop 5-phase agent cognition runtime behind a swappable model backend. Part of the Vollko cube platform.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors