Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions agent-service/src/agent/texera-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type ReActStepCallback = (step: ReActStep) => void;
/**
* A single Texera agent instance.
*
* Owns the conversation (ReAct step tree with HEAD/checkout semantics), the
* Owns the conversation (ReAct step tree with HEAD tracking), the
* workflow being edited (`WorkflowState`), cached operator execution results
* (`WorkflowResultState`), and the tool surface exposed to the LLM. Each call
* to `sendMessage` drives one multi-step generation via the Vercel AI SDK,
Expand Down Expand Up @@ -298,16 +298,6 @@ export class TexeraAgent {
return Array.from(this.stepsById.values()).filter(s => s.id !== INITIAL_STEP_ID);
}

checkout(stepId: string): boolean {
const step = this.stepsById.get(stepId);
if (!step && stepId !== INITIAL_STEP_ID) return false;
this.head = stepId;
if (step?.afterWorkflowContent) {
this.workflowState.setWorkflowContent(step.afterWorkflowContent);
}
return true;
}

setStepCallback(callback: ReActStepCallback | null): void {
this.stepCallback = callback;
}
Expand Down
28 changes: 1 addition & 27 deletions agent-service/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,31 +308,6 @@ const agentsRouter = new Elysia({ prefix: "/agents" })
return { status: "cleared" };
})

.post("/:id/checkout", ({ params: { id }, body }) => {
const agent = getAgent(id);
const { stepId } = body as { stepId: string };
if (!stepId) throw new Error("stepId is required");

const success = agent.checkout(stepId);
if (!success) throw new Error(`Step ${stepId} not found or checkout failed`);

const allSteps = agent.getAllSteps();
const workflowContent = agent.getWorkflowState().getWorkflowContent();

broadcastToAgent(id, {
type: "headChange",
headId: stepId,
steps: allSteps,
workflowContent,
operatorResults: getOperatorResultSummaries(agent),
});

return {
status: "checked out",
headId: stepId,
};
})

.get("/:id/operator-types", ({ params: { id } }) => {
const agent = getAgent(id);
const metadataStore = agent.getMetadataStore();
Expand Down Expand Up @@ -431,14 +406,13 @@ interface OperatorResultSummaryWs {
}

interface WsOutgoingMessage {
type: "step" | "state" | "error" | "complete" | "init" | "headChange";
type: "step" | "state" | "error" | "complete" | "init";
step?: ReActStep;
state?: string;
error?: string;
steps?: ReActStep[];
headId?: string;
operatorResults?: Record<string, OperatorResultSummaryWs>;
workflowContent?: any;
}

function getOperatorResultSummaries(agent: TexeraAgent): Record<string, OperatorResultSummaryWs> {
Expand Down
32 changes: 0 additions & 32 deletions frontend/src/app/workspace/service/agent/agent.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -534,30 +534,6 @@ export class AgentService {
}
break;

case "headChange":
// HEAD moved (checkout) — update HEAD, visible steps, and workflow
if (message.headId !== undefined) {
tracking.headIdSubject.next(message.headId);
}
if (message.steps && Array.isArray(message.steps)) {
const steps = message.steps.map((s: any) => this.convertApiReActStep(s));
tracking.reActStepsSubject.next(steps);
}
// Update workflow content from agent service (ground truth)
if (message.workflowContent) {
tracking.wsWorkflowActive = true;
const workflow: Workflow = {
...(message.workflowMetadata || tracking.workflowSubject.getValue() || {}),
content: message.workflowContent,
};
tracking.workflowSubject.next(workflow as Workflow);
}
// Update operator results on HEAD change
if (message.operatorResults) {
this.updateOperatorResultSummaries(message.operatorResults);
}
break;

case "error":
// Error occurred
console.error(`Agent ${agentId} error:`, message.error);
Expand Down Expand Up @@ -1025,14 +1001,6 @@ export class AgentService {
return tracking ? tracking.headIdSubject.getValue() : null;
}

/**
* Checkout to a specific step (move HEAD, restore workflow).
* The backend broadcasts headChange + visible steps via WebSocket to all clients.
*/
public checkoutStep(agentId: string, stepId: string): Observable<any> {
return this.http.post(`${this.AGENT_API_BASE}/agents/${agentId}/checkout`, { stepId });
}

/**
* Get visible steps for an agent (current snapshot).
*/
Expand Down
Loading