mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-16 02:01:35 +00:00
feat(foundry): checkpoint actor and workspace refactor
This commit is contained in:
parent
32f3c6c3bc
commit
dbe57d45b9
81 changed files with 3441 additions and 2332 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import type { WorkbenchModelId } from "./workbench.js";
|
||||
import type { WorkspaceModelId } from "./workspace.js";
|
||||
|
||||
export type FoundryBillingPlanId = "free" | "team";
|
||||
export type FoundryBillingStatus = "active" | "trialing" | "past_due" | "scheduled_cancel";
|
||||
|
|
@ -14,6 +14,7 @@ export interface FoundryUser {
|
|||
githubLogin: string;
|
||||
roleLabel: string;
|
||||
eligibleOrganizationIds: string[];
|
||||
defaultModel: WorkspaceModelId;
|
||||
}
|
||||
|
||||
export interface FoundryOrganizationMember {
|
||||
|
|
@ -59,7 +60,6 @@ export interface FoundryOrganizationSettings {
|
|||
slug: string;
|
||||
primaryDomain: string;
|
||||
seatAccrualMode: "first_prompt";
|
||||
defaultModel: WorkbenchModelId;
|
||||
autoImportRepos: boolean;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ export const CreateTaskInputSchema = z.object({
|
|||
explicitTitle: z.string().trim().min(1).optional(),
|
||||
explicitBranchName: z.string().trim().min(1).optional(),
|
||||
sandboxProviderId: SandboxProviderIdSchema.optional(),
|
||||
agentType: AgentTypeSchema.optional(),
|
||||
onBranch: z.string().trim().min(1).optional(),
|
||||
});
|
||||
export type CreateTaskInput = z.infer<typeof CreateTaskInputSchema>;
|
||||
|
|
@ -69,9 +68,7 @@ export const TaskRecordSchema = z.object({
|
|||
task: z.string().min(1),
|
||||
sandboxProviderId: SandboxProviderIdSchema,
|
||||
status: TaskStatusSchema,
|
||||
statusMessage: z.string().nullable(),
|
||||
activeSandboxId: z.string().nullable(),
|
||||
activeSessionId: z.string().nullable(),
|
||||
sandboxes: z.array(
|
||||
z.object({
|
||||
sandboxId: z.string().min(1),
|
||||
|
|
@ -83,17 +80,12 @@ export const TaskRecordSchema = z.object({
|
|||
updatedAt: z.number().int(),
|
||||
}),
|
||||
),
|
||||
agentType: z.string().nullable(),
|
||||
prSubmitted: z.boolean(),
|
||||
diffStat: z.string().nullable(),
|
||||
prUrl: z.string().nullable(),
|
||||
prAuthor: z.string().nullable(),
|
||||
ciStatus: z.string().nullable(),
|
||||
reviewStatus: z.string().nullable(),
|
||||
reviewer: z.string().nullable(),
|
||||
conflictsWithMain: z.string().nullable(),
|
||||
hasUnpushed: z.string().nullable(),
|
||||
parentBranch: z.string().nullable(),
|
||||
createdAt: z.number().int(),
|
||||
updatedAt: z.number().int(),
|
||||
});
|
||||
|
|
@ -112,6 +104,7 @@ export type TaskSummary = z.infer<typeof TaskSummarySchema>;
|
|||
|
||||
export const TaskActionInputSchema = z.object({
|
||||
organizationId: OrganizationIdSchema,
|
||||
repoId: RepoIdSchema,
|
||||
taskId: z.string().min(1),
|
||||
});
|
||||
export type TaskActionInput = z.infer<typeof TaskActionInputSchema>;
|
||||
|
|
@ -180,7 +173,7 @@ export const HistoryQueryInputSchema = z.object({
|
|||
});
|
||||
export type HistoryQueryInput = z.infer<typeof HistoryQueryInputSchema>;
|
||||
|
||||
export const HistoryEventSchema = z.object({
|
||||
export const AuditLogEventSchema = z.object({
|
||||
id: z.number().int(),
|
||||
organizationId: OrganizationIdSchema,
|
||||
repoId: z.string().nullable(),
|
||||
|
|
@ -190,7 +183,7 @@ export const HistoryEventSchema = z.object({
|
|||
payloadJson: z.string().min(1),
|
||||
createdAt: z.number().int(),
|
||||
});
|
||||
export type HistoryEvent = z.infer<typeof HistoryEventSchema>;
|
||||
export type AuditLogEvent = z.infer<typeof AuditLogEventSchema>;
|
||||
|
||||
export const PruneInputSchema = z.object({
|
||||
organizationId: OrganizationIdSchema,
|
||||
|
|
@ -201,6 +194,7 @@ export type PruneInput = z.infer<typeof PruneInputSchema>;
|
|||
|
||||
export const KillInputSchema = z.object({
|
||||
organizationId: OrganizationIdSchema,
|
||||
repoId: RepoIdSchema,
|
||||
taskId: z.string().min(1),
|
||||
deleteBranch: z.boolean(),
|
||||
abandon: z.boolean(),
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ export * from "./contracts.js";
|
|||
export * from "./config.js";
|
||||
export * from "./logging.js";
|
||||
export * from "./realtime-events.js";
|
||||
export * from "./workbench.js";
|
||||
export * from "./workspace.js";
|
||||
export * from "./organization.js";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { FoundryAppSnapshot } from "./app-shell.js";
|
||||
import type { WorkbenchOpenPrSummary, WorkbenchRepositorySummary, WorkbenchSessionDetail, WorkbenchTaskDetail, WorkbenchTaskSummary } from "./workbench.js";
|
||||
import type { OrganizationSummarySnapshot, WorkspaceSessionDetail, WorkspaceTaskDetail } from "./workspace.js";
|
||||
|
||||
export interface SandboxProcessSnapshot {
|
||||
id: string;
|
||||
|
|
@ -16,20 +16,13 @@ export interface SandboxProcessSnapshot {
|
|||
}
|
||||
|
||||
/** Organization-level events broadcast by the organization actor. */
|
||||
export type OrganizationEvent =
|
||||
| { type: "taskSummaryUpdated"; taskSummary: WorkbenchTaskSummary }
|
||||
| { type: "taskRemoved"; taskId: string }
|
||||
| { type: "repoAdded"; repo: WorkbenchRepositorySummary }
|
||||
| { type: "repoUpdated"; repo: WorkbenchRepositorySummary }
|
||||
| { type: "repoRemoved"; repoId: string }
|
||||
| { type: "pullRequestUpdated"; pullRequest: WorkbenchOpenPrSummary }
|
||||
| { type: "pullRequestRemoved"; prId: string };
|
||||
export type OrganizationEvent = { type: "organizationUpdated"; snapshot: OrganizationSummarySnapshot };
|
||||
|
||||
/** Task-level events broadcast by the task actor. */
|
||||
export type TaskEvent = { type: "taskDetailUpdated"; detail: WorkbenchTaskDetail };
|
||||
export type TaskEvent = { type: "taskUpdated"; detail: WorkspaceTaskDetail };
|
||||
|
||||
/** Session-level events broadcast by the task actor and filtered by sessionId on the client. */
|
||||
export type SessionEvent = { type: "sessionUpdated"; session: WorkbenchSessionDetail };
|
||||
export type SessionEvent = { type: "sessionUpdated"; session: WorkspaceSessionDetail };
|
||||
|
||||
/** App-level events broadcast by the app organization actor. */
|
||||
export type AppEvent = { type: "appUpdated"; snapshot: FoundryAppSnapshot };
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type { AgentType, SandboxProviderId, TaskStatus } from "./contracts.js";
|
||||
import type { SandboxProviderId, TaskStatus } from "./contracts.js";
|
||||
|
||||
export type WorkbenchTaskStatus = TaskStatus | "new";
|
||||
export type WorkbenchAgentKind = "Claude" | "Codex" | "Cursor";
|
||||
export type WorkbenchModelId =
|
||||
export type WorkspaceTaskStatus = TaskStatus | "new";
|
||||
export type WorkspaceAgentKind = "Claude" | "Codex" | "Cursor";
|
||||
export type WorkspaceModelId =
|
||||
| "claude-sonnet-4"
|
||||
| "claude-opus-4"
|
||||
| "gpt-5.3-codex"
|
||||
|
|
@ -11,9 +11,9 @@ export type WorkbenchModelId =
|
|||
| "gpt-5.1-codex-max"
|
||||
| "gpt-5.2"
|
||||
| "gpt-5.1-codex-mini";
|
||||
export type WorkbenchSessionStatus = "pending_provision" | "pending_session_create" | "ready" | "running" | "idle" | "error";
|
||||
export type WorkspaceSessionStatus = "pending_provision" | "pending_session_create" | "ready" | "running" | "idle" | "error";
|
||||
|
||||
export interface WorkbenchTranscriptEvent {
|
||||
export interface WorkspaceTranscriptEvent {
|
||||
id: string;
|
||||
eventIndex: number;
|
||||
sessionId: string;
|
||||
|
|
@ -23,23 +23,23 @@ export interface WorkbenchTranscriptEvent {
|
|||
payload: unknown;
|
||||
}
|
||||
|
||||
export interface WorkbenchComposerDraft {
|
||||
export interface WorkspaceComposerDraft {
|
||||
text: string;
|
||||
attachments: WorkbenchLineAttachment[];
|
||||
attachments: WorkspaceLineAttachment[];
|
||||
updatedAtMs: number | null;
|
||||
}
|
||||
|
||||
/** Session metadata without transcript content. */
|
||||
export interface WorkbenchSessionSummary {
|
||||
export interface WorkspaceSessionSummary {
|
||||
id: string;
|
||||
/** Stable UI session id used for routing and task-local identity. */
|
||||
sessionId: string;
|
||||
/** Underlying sandbox session id when provisioning has completed. */
|
||||
sandboxSessionId?: string | null;
|
||||
sessionName: string;
|
||||
agent: WorkbenchAgentKind;
|
||||
model: WorkbenchModelId;
|
||||
status: WorkbenchSessionStatus;
|
||||
agent: WorkspaceAgentKind;
|
||||
model: WorkspaceModelId;
|
||||
status: WorkspaceSessionStatus;
|
||||
thinkingSinceMs: number | null;
|
||||
unread: boolean;
|
||||
created: boolean;
|
||||
|
|
@ -47,44 +47,44 @@ export interface WorkbenchSessionSummary {
|
|||
}
|
||||
|
||||
/** Full session content — only fetched when viewing a specific session. */
|
||||
export interface WorkbenchSessionDetail {
|
||||
export interface WorkspaceSessionDetail {
|
||||
/** Stable UI session id used for the session topic key and routing. */
|
||||
sessionId: string;
|
||||
sandboxSessionId: string | null;
|
||||
sessionName: string;
|
||||
agent: WorkbenchAgentKind;
|
||||
model: WorkbenchModelId;
|
||||
status: WorkbenchSessionStatus;
|
||||
agent: WorkspaceAgentKind;
|
||||
model: WorkspaceModelId;
|
||||
status: WorkspaceSessionStatus;
|
||||
thinkingSinceMs: number | null;
|
||||
unread: boolean;
|
||||
created: boolean;
|
||||
errorMessage?: string | null;
|
||||
draft: WorkbenchComposerDraft;
|
||||
transcript: WorkbenchTranscriptEvent[];
|
||||
draft: WorkspaceComposerDraft;
|
||||
transcript: WorkspaceTranscriptEvent[];
|
||||
}
|
||||
|
||||
export interface WorkbenchFileChange {
|
||||
export interface WorkspaceFileChange {
|
||||
path: string;
|
||||
added: number;
|
||||
removed: number;
|
||||
type: "M" | "A" | "D";
|
||||
}
|
||||
|
||||
export interface WorkbenchFileTreeNode {
|
||||
export interface WorkspaceFileTreeNode {
|
||||
name: string;
|
||||
path: string;
|
||||
isDir: boolean;
|
||||
children?: WorkbenchFileTreeNode[];
|
||||
children?: WorkspaceFileTreeNode[];
|
||||
}
|
||||
|
||||
export interface WorkbenchLineAttachment {
|
||||
export interface WorkspaceLineAttachment {
|
||||
id: string;
|
||||
filePath: string;
|
||||
lineNumber: number;
|
||||
lineContent: string;
|
||||
}
|
||||
|
||||
export interface WorkbenchHistoryEvent {
|
||||
export interface WorkspaceHistoryEvent {
|
||||
id: string;
|
||||
messageId: string;
|
||||
preview: string;
|
||||
|
|
@ -94,78 +94,67 @@ export interface WorkbenchHistoryEvent {
|
|||
detail: string;
|
||||
}
|
||||
|
||||
export type WorkbenchDiffLineKind = "context" | "add" | "remove" | "hunk";
|
||||
export type WorkspaceDiffLineKind = "context" | "add" | "remove" | "hunk";
|
||||
|
||||
export interface WorkbenchParsedDiffLine {
|
||||
kind: WorkbenchDiffLineKind;
|
||||
export interface WorkspaceParsedDiffLine {
|
||||
kind: WorkspaceDiffLineKind;
|
||||
lineNumber: number;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface WorkbenchPullRequestSummary {
|
||||
number: number;
|
||||
status: "draft" | "ready";
|
||||
}
|
||||
|
||||
export interface WorkbenchOpenPrSummary {
|
||||
prId: string;
|
||||
repoId: string;
|
||||
repoFullName: string;
|
||||
export interface WorkspacePullRequestSummary {
|
||||
number: number;
|
||||
title: string;
|
||||
state: string;
|
||||
url: string;
|
||||
headRefName: string;
|
||||
baseRefName: string;
|
||||
repoFullName: string;
|
||||
authorLogin: string | null;
|
||||
isDraft: boolean;
|
||||
updatedAtMs: number;
|
||||
}
|
||||
|
||||
export interface WorkbenchSandboxSummary {
|
||||
export interface WorkspaceSandboxSummary {
|
||||
sandboxProviderId: SandboxProviderId;
|
||||
sandboxId: string;
|
||||
cwd: string | null;
|
||||
}
|
||||
|
||||
/** Sidebar-level task data. Materialized in the organization actor's SQLite. */
|
||||
export interface WorkbenchTaskSummary {
|
||||
export interface WorkspaceTaskSummary {
|
||||
id: string;
|
||||
repoId: string;
|
||||
title: string;
|
||||
status: WorkbenchTaskStatus;
|
||||
status: WorkspaceTaskStatus;
|
||||
repoName: string;
|
||||
updatedAtMs: number;
|
||||
branch: string | null;
|
||||
pullRequest: WorkbenchPullRequestSummary | null;
|
||||
pullRequest: WorkspacePullRequestSummary | null;
|
||||
/** Summary of sessions — no transcript content. */
|
||||
sessionsSummary: WorkbenchSessionSummary[];
|
||||
sessionsSummary: WorkspaceSessionSummary[];
|
||||
}
|
||||
|
||||
/** Full task detail — only fetched when viewing a specific task. */
|
||||
export interface WorkbenchTaskDetail extends WorkbenchTaskSummary {
|
||||
export interface WorkspaceTaskDetail extends WorkspaceTaskSummary {
|
||||
/** Original task prompt/instructions shown in the detail view. */
|
||||
task: string;
|
||||
/** Agent choice used when creating new sandbox sessions for this task. */
|
||||
agentType: AgentType | null;
|
||||
/** Underlying task runtime status preserved for detail views and error handling. */
|
||||
runtimeStatus: TaskStatus;
|
||||
statusMessage: string | null;
|
||||
activeSessionId: string | null;
|
||||
diffStat: string | null;
|
||||
prUrl: string | null;
|
||||
reviewStatus: string | null;
|
||||
fileChanges: WorkbenchFileChange[];
|
||||
fileChanges: WorkspaceFileChange[];
|
||||
diffs: Record<string, string>;
|
||||
fileTree: WorkbenchFileTreeNode[];
|
||||
fileTree: WorkspaceFileTreeNode[];
|
||||
minutesUsed: number;
|
||||
/** Sandbox info for this task. */
|
||||
sandboxes: WorkbenchSandboxSummary[];
|
||||
sandboxes: WorkspaceSandboxSummary[];
|
||||
activeSandboxId: string | null;
|
||||
}
|
||||
|
||||
/** Repo-level summary for organization sidebar. */
|
||||
export interface WorkbenchRepositorySummary {
|
||||
export interface WorkspaceRepositorySummary {
|
||||
id: string;
|
||||
label: string;
|
||||
/** Aggregated branch/task overview state (replaces getRepoOverview polling). */
|
||||
|
|
@ -176,121 +165,126 @@ export interface WorkbenchRepositorySummary {
|
|||
/** Organization-level snapshot — initial fetch for the organization topic. */
|
||||
export interface OrganizationSummarySnapshot {
|
||||
organizationId: string;
|
||||
repos: WorkbenchRepositorySummary[];
|
||||
taskSummaries: WorkbenchTaskSummary[];
|
||||
openPullRequests: WorkbenchOpenPrSummary[];
|
||||
repos: WorkspaceRepositorySummary[];
|
||||
taskSummaries: WorkspaceTaskSummary[];
|
||||
}
|
||||
|
||||
export interface WorkbenchSession extends WorkbenchSessionSummary {
|
||||
draft: WorkbenchComposerDraft;
|
||||
transcript: WorkbenchTranscriptEvent[];
|
||||
export interface WorkspaceSession extends WorkspaceSessionSummary {
|
||||
draft: WorkspaceComposerDraft;
|
||||
transcript: WorkspaceTranscriptEvent[];
|
||||
}
|
||||
|
||||
export interface WorkbenchTask {
|
||||
export interface WorkspaceTask {
|
||||
id: string;
|
||||
repoId: string;
|
||||
title: string;
|
||||
status: WorkbenchTaskStatus;
|
||||
status: WorkspaceTaskStatus;
|
||||
runtimeStatus?: TaskStatus;
|
||||
statusMessage?: string | null;
|
||||
repoName: string;
|
||||
updatedAtMs: number;
|
||||
branch: string | null;
|
||||
pullRequest: WorkbenchPullRequestSummary | null;
|
||||
sessions: WorkbenchSession[];
|
||||
fileChanges: WorkbenchFileChange[];
|
||||
pullRequest: WorkspacePullRequestSummary | null;
|
||||
sessions: WorkspaceSession[];
|
||||
fileChanges: WorkspaceFileChange[];
|
||||
diffs: Record<string, string>;
|
||||
fileTree: WorkbenchFileTreeNode[];
|
||||
fileTree: WorkspaceFileTreeNode[];
|
||||
minutesUsed: number;
|
||||
activeSandboxId?: string | null;
|
||||
}
|
||||
|
||||
export interface WorkbenchRepo {
|
||||
export interface WorkspaceRepo {
|
||||
id: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface WorkbenchRepositorySection {
|
||||
export interface WorkspaceRepositorySection {
|
||||
id: string;
|
||||
label: string;
|
||||
updatedAtMs: number;
|
||||
tasks: WorkbenchTask[];
|
||||
tasks: WorkspaceTask[];
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchSnapshot {
|
||||
export interface TaskWorkspaceSnapshot {
|
||||
organizationId: string;
|
||||
repos: WorkbenchRepo[];
|
||||
repositories: WorkbenchRepositorySection[];
|
||||
tasks: WorkbenchTask[];
|
||||
repos: WorkspaceRepo[];
|
||||
repositories: WorkspaceRepositorySection[];
|
||||
tasks: WorkspaceTask[];
|
||||
}
|
||||
|
||||
export interface WorkbenchModelOption {
|
||||
id: WorkbenchModelId;
|
||||
export interface WorkspaceModelOption {
|
||||
id: WorkspaceModelId;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface WorkbenchModelGroup {
|
||||
export interface WorkspaceModelGroup {
|
||||
provider: string;
|
||||
models: WorkbenchModelOption[];
|
||||
models: WorkspaceModelOption[];
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchSelectInput {
|
||||
export interface TaskWorkspaceSelectInput {
|
||||
repoId: string;
|
||||
taskId: string;
|
||||
authSessionId?: string;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchCreateTaskInput {
|
||||
export interface TaskWorkspaceCreateTaskInput {
|
||||
repoId: string;
|
||||
task: string;
|
||||
title?: string;
|
||||
branch?: string;
|
||||
onBranch?: string;
|
||||
model?: WorkbenchModelId;
|
||||
model?: WorkspaceModelId;
|
||||
authSessionId?: string;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchRenameInput {
|
||||
export interface TaskWorkspaceRenameInput {
|
||||
repoId: string;
|
||||
taskId: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchSendMessageInput {
|
||||
export interface TaskWorkspaceSendMessageInput {
|
||||
taskId: string;
|
||||
sessionId: string;
|
||||
text: string;
|
||||
attachments: WorkbenchLineAttachment[];
|
||||
attachments: WorkspaceLineAttachment[];
|
||||
authSessionId?: string;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchSessionInput {
|
||||
export interface TaskWorkspaceSessionInput {
|
||||
taskId: string;
|
||||
sessionId: string;
|
||||
authSessionId?: string;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchRenameSessionInput extends TaskWorkbenchSessionInput {
|
||||
export interface TaskWorkspaceRenameSessionInput extends TaskWorkspaceSessionInput {
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchChangeModelInput extends TaskWorkbenchSessionInput {
|
||||
model: WorkbenchModelId;
|
||||
export interface TaskWorkspaceChangeModelInput extends TaskWorkspaceSessionInput {
|
||||
model: WorkspaceModelId;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchUpdateDraftInput extends TaskWorkbenchSessionInput {
|
||||
export interface TaskWorkspaceUpdateDraftInput extends TaskWorkspaceSessionInput {
|
||||
text: string;
|
||||
attachments: WorkbenchLineAttachment[];
|
||||
attachments: WorkspaceLineAttachment[];
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchSetSessionUnreadInput extends TaskWorkbenchSessionInput {
|
||||
export interface TaskWorkspaceSetSessionUnreadInput extends TaskWorkspaceSessionInput {
|
||||
unread: boolean;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchDiffInput {
|
||||
export interface TaskWorkspaceDiffInput {
|
||||
repoId: string;
|
||||
taskId: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchCreateTaskResponse {
|
||||
export interface TaskWorkspaceCreateTaskResponse {
|
||||
taskId: string;
|
||||
sessionId?: string;
|
||||
}
|
||||
|
||||
export interface TaskWorkbenchAddSessionResponse {
|
||||
export interface TaskWorkspaceAddSessionResponse {
|
||||
sessionId: string;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue