Skip to content

Commit c67e02b

Browse files
committed
align with main
1 parent b833380 commit c67e02b

File tree

1 file changed

+52
-28
lines changed
  • typescript-sdk/integrations/langgraph/src

1 file changed

+52
-28
lines changed

typescript-sdk/integrations/langgraph/src/agent.ts

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,11 @@ export class LangGraphAgent extends AbstractAgent {
159159
// Therefore, this value should either hold null, or the only edition of state that should be used.
160160
this.activeRun!.manuallyEmittedState = null;
161161

162-
this.activeRun!.nodeName = input.forwardedProps?.nodeName;
162+
const nodeNameInput = forwardedProps?.nodeName;
163+
this.activeRun!.nodeName = nodeNameInput;
164+
if (this.activeRun!.nodeName === '__end__') {
165+
this.activeRun!.nodeName = undefined;
166+
}
163167

164168
const threadId = inputThreadId ?? randomUUID();
165169

@@ -176,19 +180,20 @@ export class LangGraphAgent extends AbstractAgent {
176180

177181
state.messages = agentStateValues.messages;
178182
state = this.langGraphDefaultMergeState(state, aguiToLangChainMessage, tools);
183+
const graphInfo = await this.client.assistants.getGraph(this.assistant.assistant_id);
179184

180185
const mode =
181186
threadId && this.activeRun!.nodeName != "__end__" && this.activeRun!.nodeName
182187
? "continue"
183188
: "start";
184189

185190
if (mode === "continue" && !forwardedProps?.command?.resume) {
191+
const nodeBefore = graphInfo.edges.find(e => e.target === this.activeRun!.nodeName);
186192
await this.client.threads.updateState(threadId, {
187193
values: state,
188-
asNode: this.activeRun!.nodeName,
194+
asNode: nodeBefore?.source,
189195
});
190196
}
191-
192197
this.activeRun!.schemaKeys = await this.getSchemaKeys();
193198

194199
const payloadInput = getStreamPayloadInput({
@@ -197,8 +202,6 @@ export class LangGraphAgent extends AbstractAgent {
197202
schemaKeys: this.activeRun!.schemaKeys,
198203
});
199204

200-
const graphInfo = await this.client.assistants.getGraph(this.assistant.assistant_id);
201-
202205
let payloadConfig: LangGraphConfig | undefined;
203206
const configsToMerge = [this.assistantConfig, forwardedProps?.config].filter(
204207
Boolean,
@@ -244,6 +247,7 @@ export class LangGraphAgent extends AbstractAgent {
244247
});
245248
return subscriber.complete();
246249
}
250+
247251
const streamResponse = this.client.runs.stream(threadId, this.assistant.assistant_id, payload);
248252

249253
this.activeRun!.prevNodeName = null;
@@ -262,6 +266,7 @@ export class LangGraphAgent extends AbstractAgent {
262266
if (!payload.streamMode.includes(streamResponseChunk.event as StreamMode)) {
263267
continue;
264268
}
269+
265270
// Force event type, as data is not properly defined on the LG side.
266271
type EventsChunkData = {
267272
__interrupt__?: any;
@@ -295,20 +300,11 @@ export class LangGraphAgent extends AbstractAgent {
295300
this.activeRun!.id = metadata.run_id;
296301

297302
if (currentNodeName && currentNodeName !== this.activeRun!.nodeName) {
298-
if (this.activeRun!.nodeName) {
299-
this.dispatchEvent({
300-
type: EventType.STEP_FINISHED,
301-
stepName: this.activeRun!.nodeName,
302-
});
303+
if (this.activeRun!.nodeName && this.activeRun!.nodeName !== nodeNameInput) {
304+
this.endStep()
303305
}
304306

305-
if (currentNodeName) {
306-
this.dispatchEvent({
307-
type: EventType.STEP_STARTED,
308-
stepName: currentNodeName,
309-
});
310-
this.activeRun!.nodeName = currentNodeName;
311-
}
307+
this.startStep(currentNodeName)
312308
}
313309

314310
shouldExit =
@@ -326,7 +322,7 @@ export class LangGraphAgent extends AbstractAgent {
326322
// we only want to update the node name under certain conditions
327323
// since we don't need any internal node names to be sent to the frontend
328324
if (graphInfo["nodes"].some((node) => node.id === currentNodeName)) {
329-
this.activeRun!.nodeName = currentNodeName;
325+
this.activeRun!.nodeName = currentNodeName
330326
}
331327

332328
updatedState = this.activeRun!.manuallyEmittedState ?? latestStateValues;
@@ -362,10 +358,17 @@ export class LangGraphAgent extends AbstractAgent {
362358
}
363359

364360
state = await this.client.threads.getState(threadId);
365-
const interrupts = (state.tasks?.[0]?.interrupts ?? []) as Interrupt[];
366-
this.activeRun!.nodeName = interrupts
367-
? this.activeRun!.nodeName
368-
: Object.keys(state.metadata.writes)[0];
361+
const tasks = state.tasks
362+
const interrupts = (tasks?.[0]?.interrupts ?? []) as Interrupt[];
363+
const isEndNode = state.next.length === 0
364+
const writes = state.metadata.writes ?? {}
365+
366+
let newNodeName = this.activeRun!.nodeName!
367+
368+
if (!interrupts?.length) {
369+
newNodeName = isEndNode ? '__end__' : (state.next[0] ?? Object.keys(writes)[0]);
370+
}
371+
369372

370373
interrupts.forEach((interrupt) => {
371374
this.dispatchEvent({
@@ -377,6 +380,12 @@ export class LangGraphAgent extends AbstractAgent {
377380
});
378381
});
379382

383+
if (this.activeRun!.nodeName != newNodeName) {
384+
this.endStep()
385+
this.startStep(newNodeName)
386+
}
387+
388+
this.endStep()
380389
this.dispatchEvent({
381390
type: EventType.STATE_SNAPSHOT,
382391
snapshot: this.getStateSnapshot(state.values),
@@ -385,17 +394,13 @@ export class LangGraphAgent extends AbstractAgent {
385394
type: EventType.MESSAGES_SNAPSHOT,
386395
messages: langchainMessagesToAgui(state.values.messages ?? []),
387396
});
388-
if (this.activeRun!.nodeName) {
389-
this.dispatchEvent({
390-
type: EventType.STEP_FINISHED,
391-
stepName: this.activeRun!.nodeName!,
392-
});
393-
}
397+
394398
this.dispatchEvent({
395399
type: EventType.RUN_FINISHED,
396400
threadId,
397401
runId: this.activeRun!.id,
398402
});
403+
this.activeRun = undefined;
399404
return subscriber.complete();
400405
} catch (e) {
401406
return subscriber.error(e);
@@ -834,6 +839,25 @@ export class LangGraphAgent extends AbstractAgent {
834839
tools: [...(state.tools ?? []), ...tools],
835840
};
836841
}
842+
843+
startStep(nodeName: string) {
844+
this.dispatchEvent({
845+
type: EventType.STEP_STARTED,
846+
stepName: nodeName,
847+
});
848+
this.activeRun!.nodeName = nodeName;
849+
}
850+
851+
endStep() {
852+
if (!this.activeRun!.nodeName) {
853+
throw new Error("No active step to end");
854+
}
855+
this.dispatchEvent({
856+
type: EventType.STEP_FINISHED,
857+
stepName: this.activeRun!.nodeName!,
858+
});
859+
this.activeRun!.nodeName = undefined;
860+
}
837861
}
838862

839863
export * from "./types";

0 commit comments

Comments
 (0)