bb.workspace and bb.workspace-ui
The headless bb.workspace plugin owns workspace data and routing. The bb.workspace-ui plugin presents projects and environments.
Purpose
bb.workspace gives app and server plugins one stable workspace model. It owns projects, environments, routing, and environment providers.
bb.workspace-ui supplies the default project switcher and environment pages. It requires the bb.workspace service.
The data plugin has consumers beyond its own UI. It therefore ships headless and carries no presentation assumptions.
The bb.workspace plugin (data)
bb.workspace declares no surfaces. A service replacement does not need to implement React components, pages, or shell controls.
Surfaces
| ID | kind | replaceable | props contract sketch | notes |
|---|---|---|---|---|
| — | — | — | — | This plugin declares no surfaces. |
bb.workspace-ui owns workspace presentation. The data service returns no React nodes, icons, colors, or renderer choices.
Services
| ID | kind | replaceable | default provider | edge use | notes |
|---|---|---|---|---|---|
bb.workspace |
single |
yes | bb.workspace |
required, optional, or watched |
Owns projects, environments, and pure route functions. |
bb.workspace.envProvider |
keyed |
yes | first-party claimant for each provider ID | used by bb.workspace as a watched keyed edge |
Joins a server provider to one private host role. |
bb.workspace
The service token matches by ID and semver. A required consumer restarts after a winner change. The first-party implementation uses kernel storage, realtime, host RPC, and HTTP ports.
import { defineService } from "@get-bb/plugin/server";
export const workspaceService = defineService<WorkspaceService>(
"bb.workspace",
"1.0",
);
export interface WorkspaceService {
readonly projects: WorkspaceProjects;
readonly environments: WorkspaceEnvironments;
readonly hosts: WorkspaceHosts;
readonly terminals: WorkspaceTerminals;
readonly routing: WorkspaceRouting;
watch(listener: (event: WorkspaceSystemChangeEvent) => void): Dispose;
}
export interface WorkspaceProjects {
list(query?: ProjectListQuery): Promise<ProjectPage>;
get(projectId: ProjectId): Promise<Project>;
create(input: ProjectCreateInput): Promise<Project>;
update(projectId: ProjectId, patch: ProjectPatch): Promise<Project>;
delete(projectId: ProjectId): Promise<{ deleted: true }>;
reorder(projectIds: readonly ProjectId[]): Promise<readonly ProjectId[]>;
branches(input: ProjectBranchesInput): Promise<readonly BranchInfo[]>;
commands(projectId: ProjectId): Promise<readonly ProjectCommand[]>;
defaultExecutionOptions(projectId: ProjectId): Promise<ExecutionDefaults>;
files(input: ProjectFilesInput): Promise<ProjectFilePage>;
fileContent(input: ProjectFileContentInput): Promise<ProjectFileContent>;
paths(projectId: ProjectId): Promise<readonly WorkspacePath[]>;
promptHistory(input: ProjectPromptHistoryInput): Promise<PromptHistoryPage>;
catalogSnapshot(query?: ProjectListQuery): Promise<ProjectCatalogSnapshot>;
readonly attachments: WorkspaceProjectAttachments;
readonly sources: WorkspaceProjectSources;
watch(
selector: { projectId?: ProjectId },
listener: (event: ProjectChangeEvent) => void,
): Dispose;
}
export interface WorkspaceProjectAttachments {
copy(input: ProjectAttachmentCopyInput): Promise<void>;
read(input: ProjectAttachmentReadInput): Promise<ProjectAttachmentContent>;
upload(input: ProjectAttachmentUploadInput): Promise<ProjectAttachment>;
}
export interface WorkspaceProjectSources {
add(projectId: ProjectId, input: ProjectSourceCreateInput): Promise<ProjectSource>;
update(sourceId: SourceId, patch: ProjectSourcePatch): Promise<ProjectSource>;
delete(sourceId: SourceId): Promise<{ deleted: true }>;
}
export interface WorkspaceEnvironments {
list(query?: EnvironmentListQuery): Promise<EnvironmentPage>;
get(environmentId: EnvironmentId): Promise<Environment>;
update(environmentId: EnvironmentId, patch: EnvironmentPatch): Promise<Environment>;
archiveThreads(environmentId: EnvironmentId): Promise<{ archivedThreadIds: ThreadId[] }>;
providers(hostId: HostId): Promise<readonly EnvironmentProviderDescriptor[]>;
provision(
input: EnvironmentProvisionInput,
options?: { signal?: AbortSignal },
): AsyncIterable<EnvironmentProvisionEvent>;
reconnect(environmentId: EnvironmentId): Promise<Environment>;
destroy(
environmentId: EnvironmentId,
options?: { signal?: AbortSignal },
): Promise<void>;
status(input: EnvironmentStatusInput): Promise<EnvironmentStatus>;
paths(environmentId: EnvironmentId): Promise<readonly WorkspacePath[]>;
commit(input: EnvironmentCommitInput): Promise<CommitResult>;
squashMerge(input: EnvironmentSquashMergeInput): Promise<SquashMergeResult>;
diff(input: EnvironmentDiffInput): Promise<EnvironmentDiff>;
diffBranches(environmentId: EnvironmentId): Promise<readonly BranchInfo[]>;
diffFiles(input: EnvironmentDiffInput): Promise<EnvironmentDiffFilePage>;
diffFile(input: EnvironmentDiffFileInput): Promise<EnvironmentDiffFile>;
diffPatch(input: EnvironmentDiffPatchInput): Promise<EnvironmentPatchResult>;
pullRequest(environmentId: EnvironmentId): Promise<EnvironmentPullRequest | null>;
markPullRequestDraft(environmentId: EnvironmentId): Promise<EnvironmentPullRequest>;
markPullRequestReady(environmentId: EnvironmentId): Promise<EnvironmentPullRequest>;
mergePullRequest(input: EnvironmentPullRequestMergeInput): Promise<MergeResult>;
watch(
selector: { environmentId?: EnvironmentId },
listener: (event: EnvironmentChangeEvent) => void,
): Dispose;
}
export interface WorkspaceHosts {
list(): Promise<readonly HostRecord[]>;
get(hostId: HostId): Promise<HostRecord>;
update(hostId: HostId, patch: HostPatch): Promise<HostRecord>;
delete(hostId: HostId): Promise<{ deleted: true }>;
directory(input: HostDirectoryInput): Promise<HostDirectoryPage>;
pathsExist(hostId: HostId, paths: readonly string[]): Promise<readonly boolean[]>;
pickFolder(hostId: HostId, options?: FolderPickerOptions): Promise<string | null>;
cloneDefaultPath(hostId: HostId, projectId: ProjectId): Promise<string>;
createJoinCode(): Promise<HostJoinCode>;
retryUpdate(hostId: HostId): Promise<HostRecord>;
providerCliStatus(hostId: HostId, providerId: string): Promise<ProviderCliStatus>;
installProviderCli(hostId: HostId, providerId: string): Promise<ProviderCliInstallResult>;
watch(listener: (event: HostChangeEvent) => void): Dispose;
}
export interface WorkspaceTerminals {
list(scope: TerminalScope): Promise<readonly TerminalRecord[]>;
create(input: TerminalCreateInput): Promise<TerminalRecord>;
get(terminalId: string): Promise<TerminalRecord>;
input(terminalId: string, data: string): Promise<void>;
output(terminalId: string, cursor?: string): Promise<TerminalOutput>;
resize(terminalId: string, columns: number, rows: number): Promise<void>;
rename(terminalId: string, title: string): Promise<TerminalRecord>;
restart(terminalId: string): Promise<TerminalRecord>;
close(terminalId: string): Promise<void>;
}
export type WorkspaceSystemChangeEvent =
| { kind: "host"; hostId: HostId | null }
| { kind: "environment"; environmentId: EnvironmentId | null }
| { kind: "project"; projectId: ProjectId | null };
export interface WorkspaceRouting {
parse(url: URL): WorkspaceRoute | null;
href(target: WorkspaceTarget): string;
context(route: WorkspaceRoute): WorkspaceContext;
}The watch methods replace entity filters on the broad old realtime subscription.
A watched service edge receives provider availability changes without a plugin restart.
The service uses the following record shapes.
export type ProjectId = string & { readonly __projectId: unique symbol };
export type EnvironmentId = string & { readonly __environmentId: unique symbol };
export type HostId = string & { readonly __hostId: unique symbol };
export type SourceId = string & { readonly __sourceId: unique symbol };
export type ThreadId = string & { readonly __threadId: unique symbol };
export interface Project {
id: ProjectId;
name: string;
description: string | null;
personal: boolean;
order: number;
sources: readonly ProjectSource[];
createdAt: string;
updatedAt: string;
}
export interface ProjectSource {
id: SourceId;
projectId: ProjectId;
hostId: HostId;
path: string;
gitRemoteUrl: string | null;
default: boolean;
}
export interface Environment {
id: EnvironmentId;
projectId: ProjectId;
hostId: HostId;
providerId: EnvironmentProviderId;
state: "provisioning" | "ready" | "retiring" | "destroying" | "destroyed" | "failed";
managed: boolean;
handle: JsonObject | null;
summary: EnvironmentSummary | null;
createdAt: string;
updatedAt: string;
}
export interface EnvironmentSummary {
label: string;
path: string | null;
isRepo: boolean;
isWorktree: boolean;
branch: string | null;
baseBranch: string | null;
defaultBranch: string | null;
}
export type EnvironmentProvisionEvent =
| { kind: "progress"; step: string; text: string; status: "started" | "completed" | "failed" }
| { kind: "output"; line: string }
| { kind: "ready"; environment: Environment };
export type WorkspaceTarget =
| { kind: "compose"; projectId?: ProjectId; initialPrompt?: string; focusPrompt?: boolean }
| { kind: "project"; projectId: ProjectId }
| { kind: "environment"; environmentId: EnvironmentId; subPath?: string }
| { kind: "thread"; threadId: ThreadId }
| { kind: "plugin-panel"; pluginId: string; path: string; subPath?: string }
| { kind: "thread-panel"; threadId: ThreadId; panelId: string; params?: JsonValue }
| { kind: "file-preview"; source: WorkspaceFileSource; path: string }
| { kind: "file-external"; source: WorkspaceFileSource; path: string }
| { kind: "url"; url: string };
export type WorkspaceRoute = Exclude<
WorkspaceTarget,
{ kind: "file-external" | "url" }
>;
export interface WorkspaceContext {
projectId: ProjectId | null;
environmentId: EnvironmentId | null;
threadId: ThreadId | null;
route: WorkspaceRoute;
}Methods use explicit input records for operations with more than one value.
All list methods return bounded pages and a continuation token.
The generated contract.json contains the complete schemas and limits.
bb.workspace.envProvider
This keyed contract uses EnvironmentProviderId as its key.
The key has the form <pluginId>/<name>. One winner serves each key.
export type EnvironmentProviderId = `${string}/${string}`;
export const environmentProvider = defineKeyedService<
EnvironmentProviderId,
EnvironmentProviderService
>("bb.workspace.envProvider", "1.0");
export interface EnvironmentProviderService {
describe(): Promise<EnvironmentProviderDescriptor>;
provision(
request: ProviderProvisionRequest,
options?: { signal?: AbortSignal },
): AsyncIterable<ProviderProvisionEvent>;
reconnect(request: ProviderReconnectRequest): Promise<EnvironmentHandle>;
destroy(
request: ProviderDestroyRequest,
options?: { signal?: AbortSignal },
): Promise<void>;
summarize(handle: EnvironmentHandle): Promise<EnvironmentSummary>;
}
export interface EnvironmentProviderDescriptor {
id: EnvironmentProviderId;
label: string;
ownsRoot: boolean;
optionsSchema: JsonSchema;
}
export type EnvironmentHandle =
| {
kind: "local-path";
root: string;
writeRoots: readonly string[];
persisted: JsonObject;
}
| {
kind: "custom";
writeRoots: readonly string[];
persisted: JsonObject;
};
export interface ProviderProvisionRequest<Options extends JsonObject = JsonObject> {
environmentId: EnvironmentId;
projectId: ProjectId;
hostId: HostId;
source: ProjectSource | null;
options: Options;
}
export interface ProviderReconnectRequest {
environmentId: EnvironmentId;
hostId: HostId;
handle: EnvironmentHandle;
}
export interface ProviderDestroyRequest extends ProviderReconnectRequest {}
export type ProviderProvisionEvent =
| { kind: "progress"; step: string; text: string; status: "started" | "completed" | "failed" }
| { kind: "output"; line: string }
| { kind: "done"; handle: EnvironmentHandle };The public provider service stays on the server. Its server half calls a private typed host role for all host work. The provider must reject a handle that does not match its environment and owned root.
Exports
Module imports select exact first-party code. Service calls follow the current winner.
| Module | Export | Use |
|---|---|---|
@bb/workspace/contracts |
workspaceService, environmentProvider, all service records |
Declares server edges and shared schemas. |
@bb/workspace/app |
useWorkspace, useWorkspaceContext, useWorkspaceNavigate |
Reads app state and starts route actions. |
@bb/workspace/routing |
parseWorkspaceRoute, workspaceHref |
Uses pure route functions without React. |
@bb/workspace/host |
defineEnvironmentProvider, provisionWorkspace, personalWorkspaceRoot, validatePersonalWorkspacePath |
Implements a provider host role. |
The app contracts replace the broad old BbContext and BbNavigate names.
export interface WorkspaceNavigation {
toThread(threadId: ThreadId): void;
toProject(projectId: ProjectId): void;
toEnvironment(environmentId: EnvironmentId, subPath?: string): void;
toPluginPanel(path: string, options?: { subPath?: string; replace?: boolean }): void;
toCompose(options?: { projectId?: ProjectId; initialPrompt?: string; focusPrompt?: boolean }): void;
openThreadPanel(options: ThreadPanelTarget): boolean;
openUrl(url: string): boolean;
openFilePreview(options: WorkspaceFileOpenOptions): boolean;
openFileExternally(options: WorkspaceFileOpenOptions): boolean;
}
export function useWorkspaceContext(): WorkspaceContext;
export function useWorkspaceNavigate(): WorkspaceNavigation;
export interface WorkspaceAppClient {
readonly projects: WorkspaceProjectClient;
readonly environments: WorkspaceEnvironmentClient;
readonly navigation: WorkspaceNavigation;
}
export function useWorkspace(): WorkspaceAppClient;The app client follows the current bb.workspace service winner.
It keeps request state and cache details outside the public contract.
Host roles
Each bb.workspace.envProvider claimant declares one private role.
The role ID is bb.workspace.envProvider.host, and its name supplies the public key suffix.
export interface EnvironmentProvider<Options extends JsonObject> {
name: string;
label: string;
ownsRoot: boolean;
options: StandardSchemaV1<Options>;
provision(request: HostProvisionRequest<Options>, context: EnvironmentProviderContext): Promise<EnvironmentHandle>;
reconnect(request: HostReconnectRequest, context: EnvironmentProviderContext): Promise<EnvironmentHandle>;
destroy(request: HostDestroyRequest, context: EnvironmentProviderContext): Promise<void>;
summarize(handle: EnvironmentHandle, context: EnvironmentProviderContext): Promise<EnvironmentSummary>;
}
export interface EnvironmentProviderContext {
signal: AbortSignal;
lifecycle: { signal: AbortSignal };
paths: { dataDir: string; tempDir: string };
progress: EnvironmentProgressSink;
workspace: EnvironmentWorkspaceFactory;
}
export interface EnvironmentProgressSink {
step(key: string, text: string, status: "started" | "completed" | "failed"): void;
output(line: string): void;
}The host package supplies a contained workspace helper. It absorbs the old host workspace object and keeps filesystem paths private to the host.
export interface EnvironmentWorkspaceFactory {
provision(options: ProvisionWorkspaceInput): Promise<EnvironmentWorkspace>;
personalRoot(dataDir: string): string;
validatePersonalPath(input: PersonalPathInput): string;
}
export interface EnvironmentWorkspace {
readonly path: string;
readonly managed: boolean;
readonly isGitRepo: boolean;
readonly isWorktree: boolean;
getDefaultBranch(): Promise<string | null>;
getCurrentBranch(): Promise<string | null>;
getHeadSha(): Promise<string | null>;
getLocalStateFingerprint(): Promise<string>;
getSharedGitRefsFingerprint(): Promise<string>;
getAdditionalWorkspaceWriteRoots(): Promise<readonly string[]>;
getStatus(options?: WorkspaceStatusOptions): Promise<EnvironmentStatus>;
getDiff(options?: WorkspaceDiffOptions): Promise<EnvironmentDiff>;
diffFiles(options: WorkspaceDiffFilesInput): Promise<EnvironmentDiffFilePage>;
diffPatch(options: WorkspaceDiffPatchInput): Promise<EnvironmentPatchResult>;
getPullRequest(): Promise<EnvironmentPullRequest | null>;
listFiles(): Promise<readonly WorkspacePath[]>;
commit(options: WorkspaceCommitOptions): Promise<CommitResult>;
reset(): Promise<void>;
squashMerge(options: WorkspaceSquashMergeOptions): Promise<SquashMergeResult>;
runPullRequestAction(action: PullRequestAction): Promise<EnvironmentPullRequest>;
destroy(): Promise<void>;
}
export type ProvisionWorkspaceInput =
| { mode: "unmanaged"; path: string }
| { mode: "managed-worktree"; sourcePath: string; environmentId: EnvironmentId; branch?: string }
| { mode: "personal"; environmentId: EnvironmentId; targetPath?: string }
| { mode: "reconnect-managed-worktree"; environmentId: EnvironmentId; path: string };
export interface WorkspaceStatusOptions {
mergeBaseBranch?: string;
maxUntrackedLineStatFiles?: number;
maxUntrackedLineStatBytes?: number;
}
export interface WorkspaceDiffOptions {
target?: WorkspaceDiffTarget;
maxDiffBytes?: number;
maxFileListBytes?: number;
maxUntrackedFiles?: number;
}
export interface WorkspaceDiffFilesInput {
target: WorkspaceDiffTarget;
maxFiles: number;
}
export interface WorkspaceDiffPatchInput {
target: WorkspaceDiffTarget;
paths: readonly string[];
maxBytesPerFile: number;
}
export interface WorkspaceCommitOptions {
message: string;
noVerify: boolean;
}
export interface WorkspaceSquashMergeOptions {
targetBranch: string;
commitMessage: string;
}
export type PullRequestAction = "mark-draft" | "mark-ready" | "merge";The server half owns the public provider token. Consumers never call the private host role. The kernel inspector joins both records under one provider key.
Example
This plugin adds a scratch environment provider. It consumes the workspace service and adds no UI claim.
{
"id": "acme.scratch-workspace",
"version": "2.0.0",
"claims": [
{
"service": "bb.workspace.envProvider",
"key": "acme.scratch-workspace/scratch",
"version": "1.0.0"
}
],
"requires": [{ "service": "bb.workspace", "range": "^1" }],
"artifacts": {
"server": "./dist/server.js",
"host": "./dist/host.js"
}
}// server.ts
import { defineServerPlugin } from "@get-bb/plugin/server";
import { environmentProvider, workspaceService } from "@bb/workspace/contracts";
export default defineServerPlugin(async (api) => {
const workspace = await api.services.use(workspaceService);
const host = api.hostRoles.client(scratchHostRole);
api.services.provide(environmentProvider.key("acme.scratch-workspace/scratch"), {
describe: () => host.call("describe", {}),
provision: (request, options) => host.stream("provision", request, options),
reconnect: (request) => host.call("reconnect", request),
destroy: (request, options) => host.call("destroy", request, options),
summarize: (handle) => host.call("summarize", { handle }),
});
return workspace.environments.watch({}, (event) => {
api.log.debug(`environment ${event.environmentId} changed`);
});
});The host artifact uses defineEnvironmentProvider. It returns a contained local-path handle.
The bb.workspace-ui plugin
bb.workspace-ui is the default presentation for the workspace domain. It requires the bb.workspace service through a required edge.
The plugin renders project and environment data. It does not own, copy, or wrap the data service.
Surfaces
| ID | kind | replaceable | props contract sketch | notes |
|---|---|---|---|---|
bb.workspace-ui.projectSwitcher |
single |
yes | ProjectSwitcherProps |
Shows the current project and starts project selection. The winner receives Original. |
bb.workspace-ui.environmentPage |
keyed |
yes | EnvironmentPageProps |
Uses a page ID as the key. First-party keys are overview, changes, and pull-request. |
These surfaces exist only while bb.workspace-ui declares them. A different presentation can omit either surface.
bb.workspace-ui.projectSwitcher
The shell supplies route state and callbacks. The surface does not own project data.
export interface ProjectSwitcherProps {
activeProjectId: ProjectId | null;
presentation: "compact" | "full";
disabled?: boolean;
onSelect(projectId: ProjectId): void;
onCreate(): void;
}
export type ProjectSwitcherSurface = SingleSurface<ProjectSwitcherProps>;
api.surfaces.provide(
"bb.workspace-ui.projectSwitcher",
({ Original, props }) => <Original {...props} presentation="compact" />,
);A winner calls onSelect after a user choice. The router then changes the route.
bb.workspace-ui.environmentPage
The page key selects one environment view. Each key has one global winner.
export type EnvironmentPageId = "overview" | "changes" | "pull-request";
export interface EnvironmentPageProps {
page: EnvironmentPageId;
environmentId: EnvironmentId;
projectId: ProjectId;
threadId: ThreadId | null;
compact: boolean;
navigate: WorkspaceNavigation;
}
export type EnvironmentPageSurface = KeyedSurface<
EnvironmentPageId,
EnvironmentPageProps
>;
api.surfaces.provide("bb.workspace-ui.environmentPage", {
key: "changes",
component: ChangesPage,
});A keyed winner does not receive Original. A failed winner returns to the default claimant for that key.
Required service edge
The manifest declares a required edge on bb.workspace. The loader activates bb.workspace-ui only after the data service becomes ready.
{
"id": "bb.workspace-ui",
"requires": [{ "service": "bb.workspace", "range": "^1" }]
}A workspace service winner change restarts bb.workspace-ui with a fresh service handle.
Services
| ID | kind | replaceable | notes |
|---|---|---|---|
| — | — | — | This presentation plugin provides no service. |
Exports
| Module | Export | Use |
|---|---|---|
@bb/workspace-ui/components |
ProjectSwitcher, EnvironmentOverviewPage, EnvironmentChangesPage, EnvironmentPullRequestPage |
Imports exact first-party presentation components. |
Surface claims follow the current winner. These module imports always select the first-party implementation.
Host roles
bb.workspace-ui declares no host role. It gets all workspace data through its required service edge.
Example
This app plugin replaces only the project switcher. It requires bb.workspace for project data and route actions.
{
"id": "acme.compact-workspace-ui",
"version": "2.0.0",
"claims": [{ "surface": "bb.workspace-ui.projectSwitcher" }],
"requires": [{ "service": "bb.workspace", "range": "^1" }],
"artifacts": { "app": "./dist/app.js" }
}// app.tsx
import { definePlugin } from "@get-bb/plugin/app";
import { useWorkspace, useWorkspaceNavigate } from "@bb/workspace/app";
function CompactSwitcher() {
const workspace = useWorkspace();
const navigate = useWorkspaceNavigate();
const projects = workspace.projects.useList();
return (
<select
value={workspace.projects.activeId ?? ""}
onChange={(event) => navigate.toProject(event.target.value as ProjectId)}
>
{projects.data.map((project) => (
<option key={project.id} value={project.id}>{project.name}</option>
))}
</select>
);
}
export default definePlugin((api) => {
api.surfaces.provide("bb.workspace-ui.projectSwitcher", () => (
<CompactSwitcher />
));
});Covers
| old item ID | new contract/verb | note |
|---|---|---|
server.sdk.environments |
bb.workspace service: environments |
Replaces the broad SDK area. |
server.sdk.environments.archiveThreads |
bb.workspace service: environments.archiveThreads() |
The implementation uses its required bb.threads edge. |
server.sdk.environments.commit |
bb.workspace service: environments.commit() |
Keeps an explicit commit input. |
server.sdk.environments.diff |
bb.workspace service: environments.diff() |
Returns a bounded diff record. |
server.sdk.environments.diffBranches |
bb.workspace service: environments.diffBranches() |
Lists valid comparison branches. |
server.sdk.environments.diffFile |
bb.workspace service: environments.diffFile() |
Returns one changed file. |
server.sdk.environments.diffFiles |
bb.workspace service: environments.diffFiles() |
Returns a bounded file page. |
server.sdk.environments.diffPatch |
bb.workspace service: environments.diffPatch() |
Returns bounded patches for selected paths. |
server.sdk.environments.get |
bb.workspace service: environments.get() |
Reads one environment. |
server.sdk.environments.pullRequest |
bb.workspace service: environments.pullRequest() |
Returns pull request state or null. |
server.sdk.environments.markPullRequestDraft |
bb.workspace service: environments.markPullRequestDraft() |
Uses a typed environment ID. |
server.sdk.environments.markPullRequestReady |
bb.workspace service: environments.markPullRequestReady() |
Uses a typed environment ID. |
server.sdk.environments.mergePullRequest |
bb.workspace service: environments.mergePullRequest() |
Keeps merge options in one input record. |
server.sdk.environments.paths |
bb.workspace service: environments.paths() |
Lists roots for one environment. |
server.sdk.environments.squashMerge |
bb.workspace service: environments.squashMerge() |
Keeps target and message options. |
server.sdk.environments.status |
bb.workspace service: environments.status() |
Returns workspace and Git status. |
server.sdk.environments.update |
bb.workspace service: environments.update() |
Updates environment metadata. |
server.sdk.projects |
bb.workspace service: projects |
Replaces the broad SDK area. |
server.sdk.projects.attachments |
bb.workspace service: projects.attachments |
Keeps attachment operations under projects. |
server.sdk.projects.attachments.copy |
bb.workspace service: projects.attachments.copy() |
Copies one attachment. |
server.sdk.projects.attachments.read |
bb.workspace service: projects.attachments.read() |
Reads one attachment. |
server.sdk.projects.attachments.upload |
bb.workspace service: projects.attachments.upload() |
Uploads one attachment. |
server.sdk.projects.branches |
bb.workspace service: projects.branches() |
Lists source branches. |
server.sdk.projects.commands |
bb.workspace service: projects.commands() |
Lists project commands. |
server.sdk.projects.create |
bb.workspace service: projects.create() |
Creates one project. |
server.sdk.projects.defaultExecutionOptions |
bb.workspace service: projects.defaultExecutionOptions() |
Reads project execution defaults. |
server.sdk.projects.delete |
bb.workspace service: projects.delete() |
Deletes one project. |
server.sdk.projects.fileContent |
bb.workspace service: projects.fileContent() |
Reads source content through workspace containment. |
server.sdk.projects.files |
bb.workspace service: projects.files() |
Lists source files through workspace containment. |
server.sdk.projects.get |
bb.workspace service: projects.get() |
Reads one project. |
server.sdk.projects.list |
bb.workspace service: projects.list() |
Returns a bounded project page. |
server.sdk.projects.paths |
bb.workspace service: projects.paths() |
Lists project source roots. |
server.sdk.projects.promptHistory |
bb.workspace service: projects.promptHistory() |
Reads bounded prompt history. |
server.sdk.projects.reorder |
bb.workspace service: projects.reorder() |
Applies one explicit project order. |
server.sdk.projects.sidebarBootstrap |
bb.workspace service: projects.catalogSnapshot() |
Replaces sidebar-specific output with a presentation-neutral project catalog. |
server.sdk.projects.sources |
bb.workspace service: projects.sources |
Keeps source operations under projects. |
server.sdk.projects.sources.add |
bb.workspace service: projects.sources.add() |
Adds one source. |
server.sdk.projects.sources.delete |
bb.workspace service: projects.sources.delete() |
Deletes one source. |
server.sdk.projects.sources.update |
bb.workspace service: projects.sources.update() |
Updates one source. |
server.sdk.projects.update |
bb.workspace service: projects.update() |
Updates project metadata. |
server.sdk.subscribe.projectChanged |
bb.workspace service: projects.watch() |
Replaces the broad realtime subscription filter. |
server.sdk.subscribe.environmentChanged |
bb.workspace service: environments.watch() |
Replaces the broad realtime subscription filter. |
app.hooks.useBbContext |
@bb/workspace/app: useWorkspaceContext() |
Adds environment and typed route state. |
app.hooks.useBbNavigate |
@bb/workspace/app: useWorkspaceNavigate() |
Returns typed workspace route actions. |
app.contracts.BbContext |
@bb/workspace/contracts: WorkspaceContext |
Replaces the project-and-thread-only route record. |
app.contracts.BbNavigate |
@bb/workspace/contracts: WorkspaceNavigation |
Replaces the broad navigation type. |
app.contracts.BbNavigate.toThread |
WorkspaceNavigation.toThread() |
Keeps thread route navigation. |
app.contracts.BbNavigate.toProject |
WorkspaceNavigation.toProject() |
Keeps project route navigation. |
app.contracts.BbNavigate.toPluginPanel |
WorkspaceNavigation.toPluginPanel() |
Keeps plugin panel routes. |
app.contracts.BbNavigate.toCompose |
WorkspaceNavigation.toCompose() |
Adds an optional typed project ID. |
app.contracts.BbNavigate.openThreadPanel |
WorkspaceNavigation.openThreadPanel() |
Keeps thread panel routing. |
app.contracts.BbNavigate.openUrl |
WorkspaceNavigation.openUrl() |
Keeps host-controlled URL opening. |
host.workspace |
@bb/workspace/host: EnvironmentWorkspace |
Keeps the host-only workspace object. |
host.workspace.queries |
EnvironmentWorkspace query methods |
Keeps all status, diff, branch, fingerprint, pull request, and file queries. |
host.workspace.mutations |
EnvironmentWorkspace mutation methods |
Keeps commit, reset, merge, pull request, and destroy operations. |
host.workspace.provision |
EnvironmentWorkspaceFactory.provision() |
Creates or reconnects a contained workspace. |
host.workspace.provisionArgs |
ProvisionWorkspaceInput |
Keeps all four provisioning modes. |
host.workspace.personalRoot |
EnvironmentWorkspaceFactory.personalRoot() |
Returns the managed personal root. |
host.workspace.validatePersonalPath |
EnvironmentWorkspaceFactory.validatePersonalPath() |
Validates a personal target path. |
host.workspace.statusOptions |
WorkspaceStatusOptions |
Keeps status work limits. |
host.workspace.diffOptions |
WorkspaceDiffOptions |
Keeps diff work limits. |
host.workspace.diffFilesArgs |
WorkspaceDiffFilesInput |
Keeps file count limits. |
host.workspace.diffPatchArgs |
WorkspaceDiffPatchInput |
Keeps path and byte limits. |
host.workspace.commitOptions |
WorkspaceCommitOptions |
Keeps the message and hook choice. |
host.workspace.squashMergeOptions |
WorkspaceSquashMergeOptions |
Keeps the target branch and commit message. |
host.workspace.pullRequestAction |
PullRequestAction |
Keeps the typed pull request action. |
app.contracts.PluginHomepageSectionProps |
bb.thread-ui.composer.actions: ComposerActionContext |
The default composer declares and renders this presentation surface. |
app.contracts.PluginHomepageSectionProps.projectId |
ComposerActionContext.scope |
A new-thread scope carries the nullable project ID. |
app.contracts.PluginHomepageSectionRegistration |
bb.thread-ui.composer.actions: ComposerActionContribution |
A stack contribution replaces the fixed homepage slot. |
app.contracts.PluginHomepageSectionRegistration.component |
ComposerActionContribution.component |
The component receives the composer action context. |
app.contracts.PluginHomepageSectionRegistration.id |
ComposerActionContribution.id |
The contribution keeps one stable ID. |
app.contracts.PluginHomepageSectionRegistration.title |
ComposerActionContribution.component |
The component renders its own heading. |
app.slots.homepageSection |
bb.thread-ui.composer.actions surface with placement: "stack" |
The default composer owns this presentation-only affordance. |
server.sdk.hosts |
bb.workspace service: hosts |
The named workspace service owns enrolled host operations. |
server.sdk.hosts.cloneDefaultPath |
bb.workspace service: hosts.cloneDefaultPath() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.createJoinCode |
bb.workspace service: hosts.createJoinCode() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.delete |
bb.workspace service: hosts.delete() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.directory |
bb.workspace service: hosts.directory() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.get |
bb.workspace service: hosts.get() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.installProviderCli |
bb.workspace service: hosts.installProviderCli() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.list |
bb.workspace service: hosts.list() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.pathsExist |
bb.workspace service: hosts.pathsExist() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.pickFolder |
bb.workspace service: hosts.pickFolder() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.providerCliStatus |
bb.workspace service: hosts.providerCliStatus() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.retryUpdate |
bb.workspace service: hosts.retryUpdate() |
The workspace owner keeps explicit host identity. |
server.sdk.hosts.update |
bb.workspace service: hosts.update() |
The workspace owner keeps explicit host identity. |
server.sdk.subscribe.hostChanged |
bb.workspace service: hosts.watch() |
The host watcher replaces the broad realtime selector. |
server.sdk.subscribe.systemChanged |
bb.workspace service: watch() |
The workspace watcher reports host, environment, and project changes. |
server.sdk.terminals |
bb.workspace service: terminals |
The named workspace service owns terminal sessions. |
server.sdk.terminals.close |
bb.workspace service: terminals.close() |
The workspace owner keeps terminal identity and scope. |
server.sdk.terminals.create |
bb.workspace service: terminals.create() |
The workspace owner keeps terminal identity and scope. |
server.sdk.terminals.get |
bb.workspace service: terminals.get() |
The workspace owner keeps terminal identity and scope. |
server.sdk.terminals.input |
bb.workspace service: terminals.input() |
The workspace owner keeps terminal identity and scope. |
server.sdk.terminals.list |
bb.workspace service: terminals.list() |
The workspace owner keeps terminal identity and scope. |
server.sdk.terminals.output |
bb.workspace service: terminals.output() |
The workspace owner keeps terminal identity and scope. |
server.sdk.terminals.rename |
bb.workspace service: terminals.rename() |
The workspace owner keeps terminal identity and scope. |
server.sdk.terminals.resize |
bb.workspace service: terminals.resize() |
The workspace owner keeps terminal identity and scope. |
server.sdk.terminals.restart |
bb.workspace service: terminals.restart() |
The workspace owner keeps terminal identity and scope. |