Skip to content

Workspaced ​

Type, in @jr2/orchestrator/src/workspace.ts. It is an export of @jr2/orchestrator, on the Authoring surface page, in Workspaces and Repos.

ts
type Workspaced<TInput, TSlots extends string> = WithoutEmptyIndex<TInput> & {
  workspace: WorkspaceHandles<TSlots>;
};

The input of a workspace() body: the run input, plus workspace, the handles that the Workspace adds (workspace.repos, workspace.branch, workspace.review). Use it as the type of the body's input.

The first argument is the run input: the input schema of the workspace(). The second is the Repo Slots that the body reads, by name ("app" or "app" | "docs"). Under repos: open, write string: the body cannot know the names, so it reads the slots in order. For a workspace() with no repos, write never. The second argument has no default.

A body under a root workspace() also gets the fields of HostInjectedInput. Add them when the body reads them: Workspaced<HostInjectedInput & RunInput, "app">.

Its fields are the fields of the run input, and workspace. The run input can have no fields: Workspaced<z.infer<typeof door>, "app"> for the door z.object({}) holds only workspace.

Fields: each field of WithoutEmptyIndex, and these:

  • workspace: WorkspaceHandles<TSlots>

Example

ts
import { z } from "zod";
import { agent, defineEvent, fail, jr2Setup, workspace, type Workspaced } from "@jr2/orchestrator";

const done = defineEvent({
  name: "done",
  description: "Call this when REVIEW.md is written.",
  input: z.object({}),
});
const runInput = z.object({ branch: z.string(), sha: z.string() });
type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;

const body = jr2Setup({
  types: {} as { input: BodyInput; context: BodyInput },
  events: [done],
  actors: {
    reviewer: agent({
      model: "anthropic/claude-haiku-5-5",
      instructions: "You review one commit and write REVIEW.md.",
      workspace: "read",
    }),
    fail: fail(),
  },
}).createMachine({
  id: "review",
  context: ({ input }) => input,
  on: { "workspace.lost": ".lost", "agent.fault": ".failed" },
  initial: "reviewing",
  states: {
    reviewing: {
      invoke: {
        src: "reviewer",
        input: ({ context }) => ({
          prompt: `Review commit ${context.sha} on ${context.workspace.branch}.`,
          cwd: context.workspace.review?.app ?? context.workspace.repos.app,
        }),
      },
      on: { done: "finished" },
    },
    finished: { type: "final" },
    failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
    lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
  },
});

export const machine = workspace(body, {
  input: runInput,
  repos: { app: "https://github.com/you/app.git" },
  spec: ({ input }) => ({ branch: input.branch, reviewSha: input.sha }),
});

See also

The docs of Kit version 0.5.1. Each page is also at its .md URL.