Repository navigation
Expand file tree
/
Copy pathports.ts
More file actions
90 lines (82 loc) · 3.27 KB
/
Copy pathports.ts
File metadata and controls
90 lines (82 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import type { CompletionAdapter } from "adminforth";
import type { DetectedLanguage, PreviousUserMessage } from "../domain/languageDetect.js";
import type {
AgentMessage,
AgentStreamChunk,
AgentTurnContext,
AgentTurnObservability,
PendingInterrupt,
} from "../domain/turnTypes.js";
export type AgentModelPurpose = "primary" | "summary";
/**
* The LLM provider adapter contract (the "provider port"). Extends AdminForth's
* CompletionAdapter with the agent-spec factory. Declared in the application layer
* so the infrastructure (llm/) depends on this contract — not the other way around.
*/
export type AgentModeCompletionAdapter = CompletionAdapter & {
getLangChainAgentSpec(params: {
maxTokens: number;
purpose: AgentModelPurpose;
}): Promise<{ model: unknown; middleware?: unknown[] }> | { model: unknown; middleware?: unknown[] };
};
/**
* Input for a single streamed agent turn. Either a fresh set of messages, or a
* human-in-the-loop resume payload for a previously interrupted turn.
*/
export type LlmStreamInput = {
completionAdapter: AgentModeCompletionAdapter;
systemPrompt: string;
input: { messages: AgentMessage[] } | { resume: unknown };
context: AgentTurnContext;
observability: AgentTurnObservability;
branchFromCheckpointId?: string;
};
/**
* The boundary between the application layer and the concrete LLM runtime
* (LangChain / LangGraph). Everything provider-specific — model construction,
* the agent graph, middleware, the raw stream shape, and the LangGraph interrupt
* shape — lives behind this port and is normalized before crossing it.
*/
export interface LlmPort {
/**
* Run one turn and return a normalized stream of typed chunks.
*/
streamTurn(input: LlmStreamInput): Promise<AsyncIterable<AgentStreamChunk>>;
/**
* Detect the language the assistant should answer in for the current message.
*/
detectLanguage(input: {
completionAdapter: AgentModeCompletionAdapter;
prompt: string;
previousUserMessages: PreviousUserMessage[];
}): Promise<DetectedLanguage | null>;
/**
* Rebuild the pending human-in-the-loop interrupts for a session from persisted
* checkpoint state (used when the in-process cache is empty — after a restart or
* on another instance). Returns already-normalized descriptors, each carrying the
* tool calls it is waiting on; the LangGraph interrupt shape never leaves the llm
* layer. Throws on a checkpoint/runtime failure (the caller must not treat that as
* "no pending interrupt").
*/
getPendingInterrupts(input: {
completionAdapter: AgentModeCompletionAdapter;
sessionId: string;
}): Promise<PendingInterrupt[]>;
/**
* Return the session thread's latest (tip) checkpoint id, or null when the thread
* has no persisted state. Recorded on each turn so message editing can fork from
* the previous turn's checkpoint.
*/
getLatestCheckpointId(input: {
completionAdapter: AgentModeCompletionAdapter;
sessionId: string;
}): Promise<string | null>;
/**
* Drop the entire LangGraph checkpoint thread for a session. Used when editing the
* first message, where there is no earlier checkpoint to fork from.
*/
resetThreadCheckpoints(input: {
completionAdapter: AgentModeCompletionAdapter;
sessionId: string;
}): Promise<void>;
}