mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-16 22:03:52 +00:00
Rename Foundry handoffs to tasks (#239)
* Restore foundry onboarding stack * Consolidate foundry rename * Create foundry tasks without prompts * Rename Foundry handoffs to tasks
This commit is contained in:
parent
d30cc0bcc8
commit
d75e8c31d1
281 changed files with 9242 additions and 4356 deletions
|
|
@ -1,197 +0,0 @@
|
|||
import type {
|
||||
HandoffWorkbenchAddTabResponse,
|
||||
HandoffWorkbenchChangeModelInput,
|
||||
HandoffWorkbenchCreateHandoffInput,
|
||||
HandoffWorkbenchCreateHandoffResponse,
|
||||
HandoffWorkbenchDiffInput,
|
||||
HandoffWorkbenchRenameInput,
|
||||
HandoffWorkbenchRenameSessionInput,
|
||||
HandoffWorkbenchSelectInput,
|
||||
HandoffWorkbenchSetSessionUnreadInput,
|
||||
HandoffWorkbenchSendMessageInput,
|
||||
HandoffWorkbenchSnapshot,
|
||||
HandoffWorkbenchTabInput,
|
||||
HandoffWorkbenchUpdateDraftInput,
|
||||
} from "@openhandoff/shared";
|
||||
import type { BackendClient } from "../backend-client.js";
|
||||
import { groupWorkbenchProjects } from "../workbench-model.js";
|
||||
import type { HandoffWorkbenchClient } from "../workbench-client.js";
|
||||
|
||||
export interface RemoteWorkbenchClientOptions {
|
||||
backend: BackendClient;
|
||||
workspaceId: string;
|
||||
}
|
||||
|
||||
class RemoteWorkbenchStore implements HandoffWorkbenchClient {
|
||||
private readonly backend: BackendClient;
|
||||
private readonly workspaceId: string;
|
||||
private snapshot: HandoffWorkbenchSnapshot;
|
||||
private readonly listeners = new Set<() => void>();
|
||||
private unsubscribeWorkbench: (() => void) | null = null;
|
||||
private refreshPromise: Promise<void> | null = null;
|
||||
private refreshRetryTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
constructor(options: RemoteWorkbenchClientOptions) {
|
||||
this.backend = options.backend;
|
||||
this.workspaceId = options.workspaceId;
|
||||
this.snapshot = {
|
||||
workspaceId: options.workspaceId,
|
||||
repos: [],
|
||||
projects: [],
|
||||
handoffs: [],
|
||||
};
|
||||
}
|
||||
|
||||
getSnapshot(): HandoffWorkbenchSnapshot {
|
||||
return this.snapshot;
|
||||
}
|
||||
|
||||
subscribe(listener: () => void): () => void {
|
||||
this.listeners.add(listener);
|
||||
this.ensureStarted();
|
||||
return () => {
|
||||
this.listeners.delete(listener);
|
||||
if (this.listeners.size === 0 && this.refreshRetryTimeout) {
|
||||
clearTimeout(this.refreshRetryTimeout);
|
||||
this.refreshRetryTimeout = null;
|
||||
}
|
||||
if (this.listeners.size === 0 && this.unsubscribeWorkbench) {
|
||||
this.unsubscribeWorkbench();
|
||||
this.unsubscribeWorkbench = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async createHandoff(input: HandoffWorkbenchCreateHandoffInput): Promise<HandoffWorkbenchCreateHandoffResponse> {
|
||||
const created = await this.backend.createWorkbenchHandoff(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
return created;
|
||||
}
|
||||
|
||||
async markHandoffUnread(input: HandoffWorkbenchSelectInput): Promise<void> {
|
||||
await this.backend.markWorkbenchUnread(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async renameHandoff(input: HandoffWorkbenchRenameInput): Promise<void> {
|
||||
await this.backend.renameWorkbenchHandoff(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async renameBranch(input: HandoffWorkbenchRenameInput): Promise<void> {
|
||||
await this.backend.renameWorkbenchBranch(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async archiveHandoff(input: HandoffWorkbenchSelectInput): Promise<void> {
|
||||
await this.backend.runAction(this.workspaceId, input.handoffId, "archive");
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async publishPr(input: HandoffWorkbenchSelectInput): Promise<void> {
|
||||
await this.backend.publishWorkbenchPr(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async revertFile(input: HandoffWorkbenchDiffInput): Promise<void> {
|
||||
await this.backend.revertWorkbenchFile(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async updateDraft(input: HandoffWorkbenchUpdateDraftInput): Promise<void> {
|
||||
await this.backend.updateWorkbenchDraft(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async sendMessage(input: HandoffWorkbenchSendMessageInput): Promise<void> {
|
||||
await this.backend.sendWorkbenchMessage(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async stopAgent(input: HandoffWorkbenchTabInput): Promise<void> {
|
||||
await this.backend.stopWorkbenchSession(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async setSessionUnread(input: HandoffWorkbenchSetSessionUnreadInput): Promise<void> {
|
||||
await this.backend.setWorkbenchSessionUnread(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async renameSession(input: HandoffWorkbenchRenameSessionInput): Promise<void> {
|
||||
await this.backend.renameWorkbenchSession(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async closeTab(input: HandoffWorkbenchTabInput): Promise<void> {
|
||||
await this.backend.closeWorkbenchSession(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
async addTab(input: HandoffWorkbenchSelectInput): Promise<HandoffWorkbenchAddTabResponse> {
|
||||
const created = await this.backend.createWorkbenchSession(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
return created;
|
||||
}
|
||||
|
||||
async changeModel(input: HandoffWorkbenchChangeModelInput): Promise<void> {
|
||||
await this.backend.changeWorkbenchModel(this.workspaceId, input);
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
private ensureStarted(): void {
|
||||
if (!this.unsubscribeWorkbench) {
|
||||
this.unsubscribeWorkbench = this.backend.subscribeWorkbench(this.workspaceId, () => {
|
||||
void this.refresh().catch(() => {
|
||||
this.scheduleRefreshRetry();
|
||||
});
|
||||
});
|
||||
}
|
||||
void this.refresh().catch(() => {
|
||||
this.scheduleRefreshRetry();
|
||||
});
|
||||
}
|
||||
|
||||
private scheduleRefreshRetry(): void {
|
||||
if (this.refreshRetryTimeout || this.listeners.size === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.refreshRetryTimeout = setTimeout(() => {
|
||||
this.refreshRetryTimeout = null;
|
||||
void this.refresh().catch(() => {
|
||||
this.scheduleRefreshRetry();
|
||||
});
|
||||
}, 1_000);
|
||||
}
|
||||
|
||||
private async refresh(): Promise<void> {
|
||||
if (this.refreshPromise) {
|
||||
await this.refreshPromise;
|
||||
return;
|
||||
}
|
||||
|
||||
this.refreshPromise = (async () => {
|
||||
const nextSnapshot = await this.backend.getWorkbench(this.workspaceId);
|
||||
if (this.refreshRetryTimeout) {
|
||||
clearTimeout(this.refreshRetryTimeout);
|
||||
this.refreshRetryTimeout = null;
|
||||
}
|
||||
this.snapshot = {
|
||||
...nextSnapshot,
|
||||
projects: nextSnapshot.projects ?? groupWorkbenchProjects(nextSnapshot.repos, nextSnapshot.handoffs),
|
||||
};
|
||||
for (const listener of [...this.listeners]) {
|
||||
listener();
|
||||
}
|
||||
})().finally(() => {
|
||||
this.refreshPromise = null;
|
||||
});
|
||||
|
||||
await this.refreshPromise;
|
||||
}
|
||||
}
|
||||
|
||||
export function createRemoteWorkbenchClient(options: RemoteWorkbenchClientOptions): HandoffWorkbenchClient {
|
||||
return new RemoteWorkbenchStore(options);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue