@modelprofile.com/flexharness-agent 9.9.0 → 9.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts_agent/classes.sessionengine.d.ts +2 -2
- package/dist_ts_agent/classes.sessionengine.js +135 -11
- package/dist_ts_agent/index.d.ts +4 -2
- package/dist_ts_agent/index.js +3 -2
- package/dist_ts_agent/smartagent.events.d.ts +7 -0
- package/dist_ts_agent/smartagent.events.js +1 -1
- package/dist_ts_agent/smartagent.interfaces.d.ts +24 -1
- package/dist_ts_agent/smartagent.interfaces.js +1 -1
- package/dist_ts_agent/smartagent.pendinginput.d.ts +58 -0
- package/dist_ts_agent/smartagent.pendinginput.js +92 -0
- package/dist_ts_agent/smartagent.persistence.js +6 -1
- package/dist_ts_agent/smartagent.transactions.d.ts +9 -0
- package/dist_ts_agent/smartagent.transactions.js +92 -5
- package/package.json +2 -2
- package/readme.md +24 -0
- package/ts_agent/classes.sessionengine.ts +143 -6
- package/ts_agent/index.ts +11 -0
- package/ts_agent/readme.md +24 -0
- package/ts_agent/smartagent.events.ts +7 -0
- package/ts_agent/smartagent.interfaces.ts +25 -0
- package/ts_agent/smartagent.pendinginput.ts +116 -0
- package/ts_agent/smartagent.persistence.ts +6 -0
- package/ts_agent/smartagent.transactions.ts +106 -5
|
@@ -96,9 +96,85 @@ export const getAgentGenerationTransactions = (events) => {
|
|
|
96
96
|
return transactions;
|
|
97
97
|
};
|
|
98
98
|
export const isTransactionalGeneration = (events, generationId) => getAgentGenerationTransactions(events).has(generationId);
|
|
99
|
+
/** The model output that closes a tool call its stopped generation left without a result. */
|
|
100
|
+
export const INTERRUPTED_TOOL_CALL_RESULT = 'The tool call was interrupted before its result was recorded; its effect is unknown.';
|
|
101
|
+
const isModelOutputEvent = (event) => event.type === 'assistant-message'
|
|
102
|
+
|| event.type === 'tool-call'
|
|
103
|
+
|| event.type === 'tool-result'
|
|
104
|
+
|| event.type === 'model-message';
|
|
105
|
+
/**
|
|
106
|
+
* Whether the events of a transactional generation are part of the model context. An accepted
|
|
107
|
+
* generation is, and so is the generation that is executing. A generation its owner stopped
|
|
108
|
+
* stays in the context once the model produced output in it: its prompt, the input it took in
|
|
109
|
+
* while it ran and what the model produced before the stop. One stopped before any model output
|
|
110
|
+
* left no trace in the conversation and is not shown, so its prompt can be sent again. Rejected
|
|
111
|
+
* generations, and generations interrupted by an abort, a failure or a restart, are not shown.
|
|
112
|
+
*/
|
|
113
|
+
const isModelVisibleTransaction = (transaction, producedOutput) => transaction.state === 'accepted'
|
|
114
|
+
|| transaction.state === 'execution-started'
|
|
115
|
+
|| (transaction.state === 'interrupted'
|
|
116
|
+
&& transaction.outcome?.stopped === true
|
|
117
|
+
&& transaction.executionStarted !== undefined
|
|
118
|
+
&& producedOutput.has(transaction.generationId));
|
|
119
|
+
/** The generations whose model produced output in `events`. */
|
|
120
|
+
const generationsWithModelOutput = (events) => {
|
|
121
|
+
const producedOutput = new Set();
|
|
122
|
+
for (const event of events) {
|
|
123
|
+
if (event.generationId && isModelOutputEvent(event))
|
|
124
|
+
producedOutput.add(event.generationId);
|
|
125
|
+
}
|
|
126
|
+
return producedOutput;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Whether the transactional generation `generationId` is part of the model context of later
|
|
130
|
+
* generations, by the rule `filterModelVisibleAgentEvents` applies: it was accepted, is
|
|
131
|
+
* executing, or was stopped by its owner after its model produced output. False for a
|
|
132
|
+
* generation `events` holds no transaction of.
|
|
133
|
+
*/
|
|
134
|
+
export const isGenerationInModelContext = (events, generationId) => {
|
|
135
|
+
const transaction = getAgentGenerationTransactions(events).get(generationId);
|
|
136
|
+
return transaction !== undefined
|
|
137
|
+
&& isModelVisibleTransaction(transaction, generationsWithModelOutput(events));
|
|
138
|
+
};
|
|
139
|
+
const interruptedToolResult = (toolCallId, toolName, source) => ({
|
|
140
|
+
id: `${source.id}:interrupted:${toolCallId}`,
|
|
141
|
+
timestamp: source.timestamp,
|
|
142
|
+
type: 'tool-result',
|
|
143
|
+
toolCallId,
|
|
144
|
+
toolName,
|
|
145
|
+
error: INTERRUPTED_TOOL_CALL_RESULT,
|
|
146
|
+
modelOutput: { type: 'error-text', value: INTERRUPTED_TOOL_CALL_RESULT },
|
|
147
|
+
generationId: source.generationId,
|
|
148
|
+
inferenceId: source.inferenceId,
|
|
149
|
+
causationId: source.causationId,
|
|
150
|
+
parentIds: [source.id],
|
|
151
|
+
});
|
|
99
152
|
export const filterModelVisibleAgentEvents = (events) => {
|
|
100
153
|
const transactions = getAgentGenerationTransactions(events);
|
|
154
|
+
const producedOutput = generationsWithModelOutput(events);
|
|
155
|
+
const resultedToolCalls = new Set();
|
|
156
|
+
for (const event of events) {
|
|
157
|
+
if (!event.generationId)
|
|
158
|
+
continue;
|
|
159
|
+
if (event.type === 'tool-result')
|
|
160
|
+
resultedToolCalls.add(`${event.generationId}\0${event.toolCallId}`);
|
|
161
|
+
if (event.type === 'assistant-message' && Array.isArray(event.content)) {
|
|
162
|
+
for (const part of event.content) {
|
|
163
|
+
if (part.type === 'tool-result') {
|
|
164
|
+
resultedToolCalls.add(`${event.generationId}\0${part.toolCallId}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
101
169
|
const visibleEvents = [];
|
|
170
|
+
/** Closes each tool call a stopped generation left open, right after the call. */
|
|
171
|
+
const closeOpenToolCall = (toolCallId, toolName, source) => {
|
|
172
|
+
const key = `${source.generationId}\0${toolCallId}`;
|
|
173
|
+
if (resultedToolCalls.has(key))
|
|
174
|
+
return;
|
|
175
|
+
resultedToolCalls.add(key);
|
|
176
|
+
visibleEvents.push(interruptedToolResult(toolCallId, toolName, source));
|
|
177
|
+
};
|
|
102
178
|
for (const event of events) {
|
|
103
179
|
if (isControlEvent(event))
|
|
104
180
|
continue;
|
|
@@ -111,10 +187,21 @@ export const filterModelVisibleAgentEvents = (events) => {
|
|
|
111
187
|
continue;
|
|
112
188
|
}
|
|
113
189
|
const transaction = transactions.get(event.generationId);
|
|
114
|
-
if (!transaction
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
190
|
+
if (transaction && !isModelVisibleTransaction(transaction, producedOutput))
|
|
191
|
+
continue;
|
|
192
|
+
visibleEvents.push(event);
|
|
193
|
+
if (transaction?.state !== 'interrupted')
|
|
194
|
+
continue;
|
|
195
|
+
if (event.type === 'tool-call' && event.providerExecuted !== true) {
|
|
196
|
+
closeOpenToolCall(event.toolCallId, event.toolName, event);
|
|
197
|
+
}
|
|
198
|
+
else if (event.type === 'assistant-message' && Array.isArray(event.content)) {
|
|
199
|
+
for (const part of event.content) {
|
|
200
|
+
if (part.type === 'tool-call' && part.providerExecuted !== true) {
|
|
201
|
+
closeOpenToolCall(part.toolCallId, part.toolName, event);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
118
205
|
}
|
|
119
206
|
return visibleEvents;
|
|
120
207
|
};
|
|
@@ -138,4 +225,4 @@ export const getUncertainToolExecutionIntents = (events, generationId) => {
|
|
|
138
225
|
}
|
|
139
226
|
return [...uncertain.values()];
|
|
140
227
|
};
|
|
141
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhZ2VudC50cmFuc2FjdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19hZ2VudC9zbWFydGFnZW50LnRyYW5zYWN0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUEyQkEsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFrQixFQUErQixFQUFFLENBQ3pFLEtBQUssQ0FBQyxJQUFJLEtBQUssa0JBQWtCO09BQzlCLEtBQUssQ0FBQyxJQUFJLEtBQUssOEJBQThCO09BQzdDLEtBQUssQ0FBQyxJQUFJLEtBQUssZ0NBQWdDO09BQy9DLEtBQUssQ0FBQyxJQUFJLEtBQUssb0JBQW9CO09BQ25DLEtBQUssQ0FBQyxJQUFJLEtBQUssdUJBQXVCO09BQ3RDLEtBQUssQ0FBQyxJQUFJLEtBQUssK0JBQStCLENBQUM7QUFFcEQsTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQUcsQ0FDNUMsTUFBOEIsRUFDWSxFQUFFO0lBZTVDLE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxFQUFtQyxDQUFDO0lBQy9ELE1BQU0sUUFBUSxHQUFHLENBQUMsWUFBb0IsRUFBMkIsRUFBRTtRQUNqRSxJQUFJLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLEtBQUssR0FBRztnQkFDTixVQUFVLEVBQUUsQ0FBQztnQkFDYixVQUFVLEVBQUUsQ0FBQyxDQUFDO2dCQUNkLFlBQVksRUFBRSxDQUFDO2dCQUNmLFlBQVksRUFBRSxDQUFDLENBQUM7Z0JBQ2hCLGNBQWMsRUFBRSxDQUFDO2dCQUNqQixjQUFjLEVBQUUsQ0FBQyxDQUFDO2dCQUNsQixZQUFZLEVBQUUsQ0FBQztnQkFDZixZQUFZLEVBQUUsQ0FBQyxDQUFDO2FBQ2pCLENBQUM7WUFDRixXQUFXLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN2QyxDQUFDO1FBQ0QsT0FB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
|
|
228
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhZ2VudC50cmFuc2FjdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19hZ2VudC9zbWFydGFnZW50LnRyYW5zYWN0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUE0QkEsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFrQixFQUErQixFQUFFLENBQ3pFLEtBQUssQ0FBQyxJQUFJLEtBQUssa0JBQWtCO09BQzlCLEtBQUssQ0FBQyxJQUFJLEtBQUssOEJBQThCO09BQzdDLEtBQUssQ0FBQyxJQUFJLEtBQUssZ0NBQWdDO09BQy9DLEtBQUssQ0FBQyxJQUFJLEtBQUssb0JBQW9CO09BQ25DLEtBQUssQ0FBQyxJQUFJLEtBQUssdUJBQXVCO09BQ3RDLEtBQUssQ0FBQyxJQUFJLEtBQUssK0JBQStCLENBQUM7QUFFcEQsTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQUcsQ0FDNUMsTUFBOEIsRUFDWSxFQUFFO0lBZTVDLE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxFQUFtQyxDQUFDO0lBQy9ELE1BQU0sUUFBUSxHQUFHLENBQUMsWUFBb0IsRUFBMkIsRUFBRTtRQUNqRSxJQUFJLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLEtBQUssR0FBRztnQkFDTixVQUFVLEVBQUUsQ0FBQztnQkFDYixVQUFVLEVBQUUsQ0FBQyxDQUFDO2dCQUNkLFlBQVksRUFBRSxDQUFDO2dCQUNmLFlBQVksRUFBRSxDQUFDLENBQUM7Z0JBQ2hCLGNBQWMsRUFBRSxDQUFDO2dCQUNqQixjQUFjLEVBQUUsQ0FBQyxDQUFDO2dCQUNsQixZQUFZLEVBQUUsQ0FBQztnQkFDZixZQUFZLEVBQUUsQ0FBQyxDQUFDO2FBQ2pCLENBQUM7WUFDRixXQUFXLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN2QyxDQUFDO1FBQ0QsT0FB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
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "Task Venture Capital GmbH",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@modelprofile.com/flexharness-agent",
|
|
5
|
-
"version": "9.
|
|
5
|
+
"version": "9.10.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"description": "Standalone event-driven agent runtime with generation transactions, context and tool execution contracts.",
|
|
8
8
|
"main": "./dist_ts_agent/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@modelprofile.com/flexharness-models": "9.
|
|
21
|
+
"@modelprofile.com/flexharness-models": "9.10.0",
|
|
22
22
|
"ai": "^7.0.107",
|
|
23
23
|
"zod": "^4.4.1",
|
|
24
24
|
"@noble/hashes": "^2.4.0",
|
package/readme.md
CHANGED
|
@@ -274,10 +274,34 @@ export async function createReviewedDraft(
|
|
|
274
274
|
|
|
275
275
|
The `review` callback belongs to your application. While awaiting acceptance, `candidate.messages` includes the candidate, but `getModelMessages()` excludes it from ordinary future context. Acceptance includes the generation; rejection keeps it in the canonical event history while excluding it from future context. Generation IDs identify transactions within a session; use a distinct ID for each new transaction.
|
|
276
276
|
|
|
277
|
+
`generate({ transaction, stop })` takes a second signal for the owner's stop, the way a user stops a turn. It ends the generation like `abort`, but the interrupted outcome records the stop (`stopped: true`, also accepted by `finalizeGeneration(transaction, 'interrupted', { stopped: true })` for a generation stopped after its execution completed). A stopped generation stays in future context once its model produced output: its prompt, the input it took in, the text its running model step streamed and the tool calls it issued. Each tool call without a recorded result is closed with an error result saying its effect is unknown, so the next request is well-formed for every provider. A generation stopped before any model output leaves no trace, so its prompt can be sent again without appearing twice. `isGenerationInModelContext(events, generationId)` applies the same rule to a list of events, for a caller that needs to know whether a finished generation stayed in context. Aborted and failed generations, and generations a restart interrupted, stay out of future context as before. `stop` requires a transactional generation.
|
|
278
|
+
|
|
277
279
|
Closing a session or restoring a stored session interrupts unfinished transactions. Restoration does not automatically rerun them. Persisted transactions require an `IAgentEventStoreV2` store with `eventSchemaVersion: 2`; without a store, transactions are process-local.
|
|
278
280
|
|
|
279
281
|
A rejected generation does not roll back external tool effects. The runtime records transactional tool-execution intents and results. If a crash leaves an intent without a known result, inspect `listUncertainToolExecutions()` and reconcile the external operation through `reconcileToolExecution()` before treating its outcome as known. This is not a general exactly-once guarantee for external services.
|
|
280
282
|
|
|
283
|
+
## Take input while a generation runs
|
|
284
|
+
|
|
285
|
+
Pass an `AgentPendingInputQueue` to `generate({ pendingInput })` to let the user steer a running generation. The generation takes waiting input in at every step boundary, after the tool results of the previous model step are recorded and before the next model call, and records each input as a user message of the generation (`inputId` set). A running tool call is never interrupted. `onInputApplied` is called for each input once it is durable, before the next model call; every durable input is reported, also when reporting an earlier one throws, and the generation then fails with that error. Input the generation could not record durably counts as never taken in: the generation gives it back to the queue with `restore()`.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import { AgentPendingInputQueue } from '@modelprofile.com/flexharness-agent';
|
|
289
|
+
|
|
290
|
+
const pendingInput = new AgentPendingInputQueue();
|
|
291
|
+
const transaction = await session.beginGeneration('Plan the release.');
|
|
292
|
+
const generation = session.generate({
|
|
293
|
+
transaction,
|
|
294
|
+
pendingInput,
|
|
295
|
+
onInputApplied: ({ inputId, eventId }) => markApplied(inputId, eventId),
|
|
296
|
+
});
|
|
297
|
+
// While the generation runs:
|
|
298
|
+
pendingInput.add({ inputId: 'steer-1', content: 'Keep the migration out of it.' });
|
|
299
|
+
await generation;
|
|
300
|
+
const unapplied = pendingInput.close(); // input the generation never took in
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
The generation closes the queue when it ends, whether it completed, failed or was aborted. `close()` returns the inputs it never took in, the same list on every call once the generation has ended; input that arrives during the last model step is among them, and so is input the generation drained but could not record durably. After closing, `add()` throws `AgentPendingInputRejectedError` with reason `closed`, and a reused `inputId` is refused with reason `duplicate`. The caller decides what becomes of unapplied input, for example sending it as the next turn.
|
|
304
|
+
|
|
281
305
|
## Events, storage and context
|
|
282
306
|
|
|
283
307
|
Canonical events retain user and assistant messages, tool calls and results, runtime events, compaction records and transaction outcomes. `getEvents()` returns this history; `getModelMessages()` projects the model-visible conversation through the configured `contextBuilder`, which defaults to `buildModelMessages`.
|
|
@@ -20,8 +20,13 @@ import {
|
|
|
20
20
|
type IUserMessageEvent,
|
|
21
21
|
type TAgentEvent,
|
|
22
22
|
type TAgentGenerationOutcome,
|
|
23
|
+
type TAgentToolCallPart,
|
|
23
24
|
type TAgentToolResultOutput,
|
|
24
25
|
} from './smartagent.events.js';
|
|
26
|
+
import type {
|
|
27
|
+
AgentPendingInputQueue,
|
|
28
|
+
IAgentAppliedInput,
|
|
29
|
+
} from './smartagent.pendinginput.js';
|
|
25
30
|
import {
|
|
26
31
|
AgentGenerationLeaseCleanupError,
|
|
27
32
|
ContextOverflowError,
|
|
@@ -31,6 +36,7 @@ import {
|
|
|
31
36
|
type IAgentGenerationLease,
|
|
32
37
|
type IAgentCompactOptions,
|
|
33
38
|
type IAgentBeginGenerationOptions,
|
|
39
|
+
type IAgentFinalizeGenerationOptions,
|
|
34
40
|
type IAgentSession,
|
|
35
41
|
type IAgentSessionAbortOptions,
|
|
36
42
|
type IAgentSessionChange,
|
|
@@ -101,8 +107,11 @@ interface IScheduledGeneration {
|
|
|
101
107
|
cache?: TAgentCacheSetting;
|
|
102
108
|
maxSteps?: number;
|
|
103
109
|
abort?: AbortSignal;
|
|
110
|
+
stop?: AbortSignal;
|
|
104
111
|
transaction?: IAgentGenerationHandle;
|
|
105
112
|
prepare?: TAgentGenerationPrepare;
|
|
113
|
+
pendingInput?: AgentPendingInputQueue;
|
|
114
|
+
onInputApplied?: (input: IAgentAppliedInput) => void | Promise<void>;
|
|
106
115
|
timer: NodeJS.Timeout;
|
|
107
116
|
controller: AbortController;
|
|
108
117
|
removeAbortListener: () => void;
|
|
@@ -821,6 +830,7 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
821
830
|
generationId: string,
|
|
822
831
|
outcome: TAgentGenerationOutcome,
|
|
823
832
|
reason?: string,
|
|
833
|
+
stopped = false,
|
|
824
834
|
): Promise<void> {
|
|
825
835
|
const transaction = this.transaction(generationId);
|
|
826
836
|
if (
|
|
@@ -853,6 +863,7 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
853
863
|
generationId,
|
|
854
864
|
outcome,
|
|
855
865
|
reason,
|
|
866
|
+
...(stopped ? { stopped: true } : {}),
|
|
856
867
|
parentIds: [parent.id],
|
|
857
868
|
}));
|
|
858
869
|
await this.flushPersistence();
|
|
@@ -874,6 +885,7 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
874
885
|
public finalizeGeneration(
|
|
875
886
|
transaction: IAgentGenerationHandle,
|
|
876
887
|
outcome: TAgentGenerationOutcome,
|
|
888
|
+
options: IAgentFinalizeGenerationOptions = {},
|
|
877
889
|
): Promise<void> {
|
|
878
890
|
const capabilityError = this.transactionalStoreCapabilityError();
|
|
879
891
|
if (capabilityError) return Promise.reject(capabilityError);
|
|
@@ -881,6 +893,9 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
881
893
|
if (!['accepted', 'rejected', 'interrupted'].includes(outcome)) {
|
|
882
894
|
throw new Error(`Invalid transactional generation outcome "${String(outcome)}".`);
|
|
883
895
|
}
|
|
896
|
+
if (options.stopped === true && outcome !== 'interrupted') {
|
|
897
|
+
throw new Error('Only an interrupted transactional generation can be stopped.');
|
|
898
|
+
}
|
|
884
899
|
const state = this.verifyGenerationClaim(transaction);
|
|
885
900
|
if (!('begun' in state)) {
|
|
886
901
|
if (state.outcome === outcome) return;
|
|
@@ -888,7 +903,12 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
888
903
|
`Transactional generation "${transaction.generationId}" already has outcome "${state.outcome}".`,
|
|
889
904
|
);
|
|
890
905
|
}
|
|
891
|
-
await this.appendGenerationOutcome(
|
|
906
|
+
await this.appendGenerationOutcome(
|
|
907
|
+
transaction.generationId,
|
|
908
|
+
outcome,
|
|
909
|
+
undefined,
|
|
910
|
+
options.stopped === true,
|
|
911
|
+
);
|
|
892
912
|
});
|
|
893
913
|
}
|
|
894
914
|
|
|
@@ -1024,6 +1044,9 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1024
1044
|
? this.transactionalStoreCapabilityError()
|
|
1025
1045
|
: undefined;
|
|
1026
1046
|
if (capabilityError) return Promise.reject(capabilityError);
|
|
1047
|
+
if (options.stop && !options.transaction) {
|
|
1048
|
+
return Promise.reject(new Error('A stop signal requires a transactional generation.'));
|
|
1049
|
+
}
|
|
1027
1050
|
if (!options.key.trim()) return Promise.reject(new Error('Scheduled generation key must not be empty.'));
|
|
1028
1051
|
const debounceMs = options.debounceMs ?? 50;
|
|
1029
1052
|
if (!Number.isSafeInteger(debounceMs) || debounceMs < 0) {
|
|
@@ -1039,7 +1062,10 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1039
1062
|
|| existing.cache !== options.cache
|
|
1040
1063
|
|| existing.maxSteps !== options.maxSteps
|
|
1041
1064
|
|| existing.abort !== options.abort
|
|
1065
|
+
|| existing.stop !== options.stop
|
|
1042
1066
|
|| existing.prepare !== options.prepare
|
|
1067
|
+
|| existing.pendingInput !== options.pendingInput
|
|
1068
|
+
|| existing.onInputApplied !== options.onInputApplied
|
|
1043
1069
|
|| existing.transaction?.generationId !== options.transaction?.generationId
|
|
1044
1070
|
|| existing.transaction?.claimToken !== options.transaction?.claimToken
|
|
1045
1071
|
) {
|
|
@@ -1053,8 +1079,9 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1053
1079
|
return existing.promise;
|
|
1054
1080
|
}
|
|
1055
1081
|
|
|
1056
|
-
|
|
1057
|
-
|
|
1082
|
+
const endedBy = options.abort?.aborted ? options.abort : options.stop?.aborted ? options.stop : undefined;
|
|
1083
|
+
if (endedBy) {
|
|
1084
|
+
const abortReason = endedBy.reason ?? new DOMException('Aborted', 'AbortError');
|
|
1058
1085
|
if (!options.transaction) return Promise.reject(abortReason);
|
|
1059
1086
|
return this.queueExclusive(async () => {
|
|
1060
1087
|
const transaction = this.verifyGenerationClaim(options.transaction!);
|
|
@@ -1082,9 +1109,11 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1082
1109
|
const controller = new AbortController();
|
|
1083
1110
|
const onAbort = () => this.cancelScheduledGeneration(
|
|
1084
1111
|
options.key,
|
|
1085
|
-
options.abort?.
|
|
1112
|
+
(options.abort?.aborted ? options.abort.reason : options.stop?.reason)
|
|
1113
|
+
?? new DOMException('Aborted', 'AbortError'),
|
|
1086
1114
|
);
|
|
1087
1115
|
options.abort?.addEventListener('abort', onAbort, { once: true });
|
|
1116
|
+
options.stop?.addEventListener('abort', onAbort, { once: true });
|
|
1088
1117
|
const scheduled: IScheduledGeneration = {
|
|
1089
1118
|
state: 'debouncing',
|
|
1090
1119
|
debounceMs,
|
|
@@ -1095,11 +1124,17 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1095
1124
|
cache: options.cache,
|
|
1096
1125
|
maxSteps: options.maxSteps,
|
|
1097
1126
|
abort: options.abort,
|
|
1127
|
+
stop: options.stop,
|
|
1098
1128
|
transaction: options.transaction,
|
|
1099
1129
|
prepare: options.prepare,
|
|
1130
|
+
pendingInput: options.pendingInput,
|
|
1131
|
+
onInputApplied: options.onInputApplied,
|
|
1100
1132
|
timer: setTimeout(() => this.startScheduledGeneration(options.key), debounceMs),
|
|
1101
1133
|
controller,
|
|
1102
|
-
removeAbortListener: () =>
|
|
1134
|
+
removeAbortListener: () => {
|
|
1135
|
+
options.abort?.removeEventListener('abort', onAbort);
|
|
1136
|
+
options.stop?.removeEventListener('abort', onAbort);
|
|
1137
|
+
},
|
|
1103
1138
|
promise,
|
|
1104
1139
|
resolve,
|
|
1105
1140
|
reject,
|
|
@@ -1120,8 +1155,11 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1120
1155
|
cache: scheduled.cache,
|
|
1121
1156
|
maxSteps: scheduled.maxSteps,
|
|
1122
1157
|
abort: scheduled.controller.signal,
|
|
1158
|
+
stop: scheduled.stop,
|
|
1123
1159
|
transaction: scheduled.transaction,
|
|
1124
1160
|
prepare: scheduled.prepare,
|
|
1161
|
+
pendingInput: scheduled.pendingInput,
|
|
1162
|
+
onInputApplied: scheduled.onInputApplied,
|
|
1125
1163
|
}).then(
|
|
1126
1164
|
(result) => this.settleScheduledGeneration(key, scheduled, () => scheduled.resolve(result)),
|
|
1127
1165
|
(error) => this.settleScheduledGeneration(key, scheduled, () => scheduled.reject(error)),
|
|
@@ -1149,6 +1187,7 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1149
1187
|
const cancellationReason = reason
|
|
1150
1188
|
?? new DOMException('Scheduled generation cancelled', 'AbortError');
|
|
1151
1189
|
if (!scheduled.controller.signal.aborted) scheduled.controller.abort(cancellationReason);
|
|
1190
|
+
scheduled.pendingInput?.close();
|
|
1152
1191
|
if (!scheduled.transaction) {
|
|
1153
1192
|
scheduled.reject(cancellationReason);
|
|
1154
1193
|
return true;
|
|
@@ -1720,6 +1759,9 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1720
1759
|
? this.transactionalStoreCapabilityError()
|
|
1721
1760
|
: undefined;
|
|
1722
1761
|
if (capabilityError) return Promise.reject(capabilityError);
|
|
1762
|
+
if (options.stop && !options.transaction) {
|
|
1763
|
+
return Promise.reject(new Error('A stop signal requires a transactional generation.'));
|
|
1764
|
+
}
|
|
1723
1765
|
const run = this.generationQueue.then(async () => {
|
|
1724
1766
|
if (!options.transaction) options.abort?.throwIfAborted();
|
|
1725
1767
|
if (!options.transaction && this.sessionAbortController.signal.aborted) {
|
|
@@ -1730,6 +1772,9 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1730
1772
|
if (this.maintenanceError !== undefined) throw this.maintenanceError;
|
|
1731
1773
|
await this.runEventRetentionLocked();
|
|
1732
1774
|
return this.generateLocked(options);
|
|
1775
|
+
}).finally(() => {
|
|
1776
|
+
// The generation takes no further input; what it never took in stays with the queue.
|
|
1777
|
+
options.pendingInput?.close();
|
|
1733
1778
|
});
|
|
1734
1779
|
this.generationQueue = run.then(() => undefined, () => undefined);
|
|
1735
1780
|
// A transactional generation is not raced against its abort signal: it settles when its
|
|
@@ -1801,6 +1846,7 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1801
1846
|
this.sessionAbortController.signal,
|
|
1802
1847
|
generationAbortController.signal,
|
|
1803
1848
|
options.abort,
|
|
1849
|
+
options.stop,
|
|
1804
1850
|
]);
|
|
1805
1851
|
|
|
1806
1852
|
let lease: IAgentGenerationLease | undefined;
|
|
@@ -1862,6 +1908,8 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1862
1908
|
const reportCompactionUsage: TAgentModelCallUsageReporter = (call) =>
|
|
1863
1909
|
recordModelCallUsage({ ...call, source: 'compaction', generationId });
|
|
1864
1910
|
let currentInferenceId: string | undefined;
|
|
1911
|
+
/** Text the current inference streamed so far, kept if the inference is interrupted. */
|
|
1912
|
+
let inferenceText = '';
|
|
1865
1913
|
let latestInferenceVisibleIds = new Set(this.events.map((event) => event.id));
|
|
1866
1914
|
const completedInferenceIds = new Set<string>();
|
|
1867
1915
|
const reasoningTextById = new Map<string, string>();
|
|
@@ -1889,10 +1937,90 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1889
1937
|
: undefined,
|
|
1890
1938
|
}));
|
|
1891
1939
|
currentInferenceId = marker.id;
|
|
1940
|
+
inferenceText = '';
|
|
1892
1941
|
latestInferenceVisibleIds = new Set(this.events.map((event) => event.id));
|
|
1893
1942
|
await this.flushPersistence();
|
|
1894
1943
|
return marker.id;
|
|
1895
1944
|
};
|
|
1945
|
+
const applyPendingInput = async (): Promise<void> => {
|
|
1946
|
+
const inputs = options.pendingInput?.drain() ?? [];
|
|
1947
|
+
if (inputs.length === 0) return;
|
|
1948
|
+
const applied: IAgentAppliedInput[] = [];
|
|
1949
|
+
try {
|
|
1950
|
+
for (const input of inputs) {
|
|
1951
|
+
const event = this.commitEvent(createAgentEvent<IUserMessageEvent>({
|
|
1952
|
+
type: 'user-message',
|
|
1953
|
+
content: input.content,
|
|
1954
|
+
inputId: input.inputId,
|
|
1955
|
+
generationId,
|
|
1956
|
+
parentIds: this.events.length > 0
|
|
1957
|
+
? [this.events[this.events.length - 1].id]
|
|
1958
|
+
: undefined,
|
|
1959
|
+
}));
|
|
1960
|
+
applied.push({
|
|
1961
|
+
inputId: input.inputId,
|
|
1962
|
+
eventId: event.id,
|
|
1963
|
+
generationId,
|
|
1964
|
+
completedSteps: stepCount,
|
|
1965
|
+
});
|
|
1966
|
+
}
|
|
1967
|
+
await this.flushPersistence();
|
|
1968
|
+
} catch (error) {
|
|
1969
|
+
// Input that is not durable was not taken in: the queue returns it from close().
|
|
1970
|
+
options.pendingInput!.restore(inputs);
|
|
1971
|
+
throw error;
|
|
1972
|
+
}
|
|
1973
|
+
// Every durable input is reported, also when reporting an earlier one failed.
|
|
1974
|
+
const callbackErrors: unknown[] = [];
|
|
1975
|
+
for (const input of applied) {
|
|
1976
|
+
try {
|
|
1977
|
+
await this.invokeGenerationCallback(() => options.onInputApplied?.(input));
|
|
1978
|
+
} catch (error) {
|
|
1979
|
+
callbackErrors.push(error);
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
if (callbackErrors.length === 1) throw callbackErrors[0];
|
|
1983
|
+
if (callbackErrors.length > 1) {
|
|
1984
|
+
throw new AggregateError(callbackErrors, 'Reporting applied pending input failed.');
|
|
1985
|
+
}
|
|
1986
|
+
};
|
|
1987
|
+
/**
|
|
1988
|
+
* Keeps what a stopped inference produced: the text it streamed and the tool calls it
|
|
1989
|
+
* issued, as one assistant message of the generation. Tool calls without a result are
|
|
1990
|
+
* closed when the stopped generation is rendered for the model.
|
|
1991
|
+
*/
|
|
1992
|
+
const commitInterruptedInference = async (): Promise<void> => {
|
|
1993
|
+
const inferenceId = currentInferenceId;
|
|
1994
|
+
if (!options.stop?.aborted || !inferenceId || completedInferenceIds.has(inferenceId)) return;
|
|
1995
|
+
completedInferenceIds.add(inferenceId);
|
|
1996
|
+
if (this.events.some((event) =>
|
|
1997
|
+
event.type === 'assistant-message' && event.inferenceId === inferenceId)) return;
|
|
1998
|
+
const toolCallParts: TAgentToolCallPart[] = this.events
|
|
1999
|
+
.filter((event): event is IToolCallEvent =>
|
|
2000
|
+
event.type === 'tool-call'
|
|
2001
|
+
&& event.generationId === generationId
|
|
2002
|
+
&& event.inferenceId === inferenceId)
|
|
2003
|
+
.map((event) => ({
|
|
2004
|
+
type: 'tool-call',
|
|
2005
|
+
toolCallId: event.toolCallId,
|
|
2006
|
+
toolName: event.toolName,
|
|
2007
|
+
input: event.input,
|
|
2008
|
+
...(event.providerExecuted === undefined ? {} : { providerExecuted: event.providerExecuted }),
|
|
2009
|
+
...(event.providerOptions === undefined ? {} : { providerOptions: event.providerOptions }),
|
|
2010
|
+
}));
|
|
2011
|
+
if (!inferenceText && toolCallParts.length === 0) return;
|
|
2012
|
+
this.commitEvent(createAgentEvent<IAssistantMessageEvent>({
|
|
2013
|
+
type: 'assistant-message',
|
|
2014
|
+
content: [
|
|
2015
|
+
...(inferenceText ? [{ type: 'text' as const, text: inferenceText }] : []),
|
|
2016
|
+
...toolCallParts,
|
|
2017
|
+
],
|
|
2018
|
+
generationId,
|
|
2019
|
+
inferenceId,
|
|
2020
|
+
causationId: inferenceId,
|
|
2021
|
+
}));
|
|
2022
|
+
await this.flushPersistence();
|
|
2023
|
+
};
|
|
1896
2024
|
const allTools = this.wrapToolsForGeneration(
|
|
1897
2025
|
generationId,
|
|
1898
2026
|
runtime.tools,
|
|
@@ -1918,6 +2046,7 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1918
2046
|
let streamError: unknown;
|
|
1919
2047
|
try {
|
|
1920
2048
|
currentInferenceId = undefined;
|
|
2049
|
+
inferenceText = '';
|
|
1921
2050
|
const result = plugins.streamText({
|
|
1922
2051
|
model: runtime.model,
|
|
1923
2052
|
instructions: runtime.system,
|
|
@@ -1929,6 +2058,7 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1929
2058
|
maxRetries: 0,
|
|
1930
2059
|
abortSignal: combinedAbort.signal,
|
|
1931
2060
|
prepareStep: async () => {
|
|
2061
|
+
await applyPendingInput();
|
|
1932
2062
|
await beginInference();
|
|
1933
2063
|
return { messages: this.buildContext(this.eventsByIds(latestInferenceVisibleIds)) };
|
|
1934
2064
|
},
|
|
@@ -1959,7 +2089,9 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
1959
2089
|
const chunkType = String((chunk as { type?: unknown }).type ?? '');
|
|
1960
2090
|
if (chunkType === 'text-delta') {
|
|
1961
2091
|
const textChunk = chunk as { delta?: string; textDelta?: string; text?: string };
|
|
1962
|
-
|
|
2092
|
+
const delta = textChunk.delta ?? textChunk.textDelta ?? textChunk.text ?? '';
|
|
2093
|
+
inferenceText += delta;
|
|
2094
|
+
this.options.onToken?.(delta);
|
|
1963
2095
|
return;
|
|
1964
2096
|
}
|
|
1965
2097
|
if (chunkType === 'tool-result') {
|
|
@@ -2245,8 +2377,11 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
2245
2377
|
flushReasoning();
|
|
2246
2378
|
const effectiveError = streamError ?? error;
|
|
2247
2379
|
if (combinedAbort.signal.aborted) {
|
|
2380
|
+
await commitInterruptedInference();
|
|
2248
2381
|
throw combinedAbort.signal.reason ?? new DOMException('Aborted', 'AbortError');
|
|
2249
2382
|
}
|
|
2383
|
+
// A failed attempt is retried or fails the generation; its partial text is not kept.
|
|
2384
|
+
inferenceText = '';
|
|
2250
2385
|
if (effectiveError instanceof DOMException && effectiveError.name === 'AbortError') {
|
|
2251
2386
|
throw effectiveError;
|
|
2252
2387
|
}
|
|
@@ -2344,6 +2479,7 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
2344
2479
|
generationId,
|
|
2345
2480
|
'interrupted',
|
|
2346
2481
|
this.transactionOutcomeErrorReason(effectiveError),
|
|
2482
|
+
options.stop?.aborted === true,
|
|
2347
2483
|
);
|
|
2348
2484
|
} else {
|
|
2349
2485
|
const transaction = this.transaction(generationId);
|
|
@@ -2366,6 +2502,7 @@ export class AgentSessionEngine implements IAgentSession {
|
|
|
2366
2502
|
generationId,
|
|
2367
2503
|
'interrupted',
|
|
2368
2504
|
this.transactionOutcomeErrorReason(abortError),
|
|
2505
|
+
options.stop?.aborted === true,
|
|
2369
2506
|
);
|
|
2370
2507
|
throw abortError;
|
|
2371
2508
|
}
|
package/ts_agent/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export {
|
|
|
6
6
|
getAgentGenerationTransactions,
|
|
7
7
|
getOpenAgentGenerationTransactions,
|
|
8
8
|
getUncertainToolExecutionIntents,
|
|
9
|
+
isGenerationInModelContext,
|
|
9
10
|
isTransactionalGeneration,
|
|
10
11
|
} from './smartagent.transactions.js';
|
|
11
12
|
export {
|
|
@@ -13,6 +14,15 @@ export {
|
|
|
13
14
|
createAgentEventId,
|
|
14
15
|
modelMessagesToAgentEvents,
|
|
15
16
|
} from './smartagent.events.js';
|
|
17
|
+
export {
|
|
18
|
+
AgentPendingInputQueue,
|
|
19
|
+
AgentPendingInputRejectedError,
|
|
20
|
+
} from './smartagent.pendinginput.js';
|
|
21
|
+
export type {
|
|
22
|
+
IAgentAppliedInput,
|
|
23
|
+
IAgentPendingInput,
|
|
24
|
+
TAgentPendingInputRejection,
|
|
25
|
+
} from './smartagent.pendinginput.js';
|
|
16
26
|
export { ToolRegistry } from './smartagent.classes.toolregistry.js';
|
|
17
27
|
export { AgentModelCallUsageRecorder } from './smartagent.usage.js';
|
|
18
28
|
export type { IAgentModelCallUsageRecorderModel } from './smartagent.usage.js';
|
|
@@ -35,6 +45,7 @@ export type {
|
|
|
35
45
|
IAgentCompactOptions,
|
|
36
46
|
IAgentEventRetentionOptions,
|
|
37
47
|
IAgentBeginGenerationOptions,
|
|
48
|
+
IAgentFinalizeGenerationOptions,
|
|
38
49
|
IAgentGenerateOptions,
|
|
39
50
|
IAgentGenerateResult,
|
|
40
51
|
IAgentGenerationHandle,
|
package/ts_agent/readme.md
CHANGED
|
@@ -274,10 +274,34 @@ export async function createReviewedDraft(
|
|
|
274
274
|
|
|
275
275
|
The `review` callback belongs to your application. While awaiting acceptance, `candidate.messages` includes the candidate, but `getModelMessages()` excludes it from ordinary future context. Acceptance includes the generation; rejection keeps it in the canonical event history while excluding it from future context. Generation IDs identify transactions within a session; use a distinct ID for each new transaction.
|
|
276
276
|
|
|
277
|
+
`generate({ transaction, stop })` takes a second signal for the owner's stop, the way a user stops a turn. It ends the generation like `abort`, but the interrupted outcome records the stop (`stopped: true`, also accepted by `finalizeGeneration(transaction, 'interrupted', { stopped: true })` for a generation stopped after its execution completed). A stopped generation stays in future context once its model produced output: its prompt, the input it took in, the text its running model step streamed and the tool calls it issued. Each tool call without a recorded result is closed with an error result saying its effect is unknown, so the next request is well-formed for every provider. A generation stopped before any model output leaves no trace, so its prompt can be sent again without appearing twice. `isGenerationInModelContext(events, generationId)` applies the same rule to a list of events, for a caller that needs to know whether a finished generation stayed in context. Aborted and failed generations, and generations a restart interrupted, stay out of future context as before. `stop` requires a transactional generation.
|
|
278
|
+
|
|
277
279
|
Closing a session or restoring a stored session interrupts unfinished transactions. Restoration does not automatically rerun them. Persisted transactions require an `IAgentEventStoreV2` store with `eventSchemaVersion: 2`; without a store, transactions are process-local.
|
|
278
280
|
|
|
279
281
|
A rejected generation does not roll back external tool effects. The runtime records transactional tool-execution intents and results. If a crash leaves an intent without a known result, inspect `listUncertainToolExecutions()` and reconcile the external operation through `reconcileToolExecution()` before treating its outcome as known. This is not a general exactly-once guarantee for external services.
|
|
280
282
|
|
|
283
|
+
## Take input while a generation runs
|
|
284
|
+
|
|
285
|
+
Pass an `AgentPendingInputQueue` to `generate({ pendingInput })` to let the user steer a running generation. The generation takes waiting input in at every step boundary, after the tool results of the previous model step are recorded and before the next model call, and records each input as a user message of the generation (`inputId` set). A running tool call is never interrupted. `onInputApplied` is called for each input once it is durable, before the next model call; every durable input is reported, also when reporting an earlier one throws, and the generation then fails with that error. Input the generation could not record durably counts as never taken in: the generation gives it back to the queue with `restore()`.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import { AgentPendingInputQueue } from '@modelprofile.com/flexharness-agent';
|
|
289
|
+
|
|
290
|
+
const pendingInput = new AgentPendingInputQueue();
|
|
291
|
+
const transaction = await session.beginGeneration('Plan the release.');
|
|
292
|
+
const generation = session.generate({
|
|
293
|
+
transaction,
|
|
294
|
+
pendingInput,
|
|
295
|
+
onInputApplied: ({ inputId, eventId }) => markApplied(inputId, eventId),
|
|
296
|
+
});
|
|
297
|
+
// While the generation runs:
|
|
298
|
+
pendingInput.add({ inputId: 'steer-1', content: 'Keep the migration out of it.' });
|
|
299
|
+
await generation;
|
|
300
|
+
const unapplied = pendingInput.close(); // input the generation never took in
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
The generation closes the queue when it ends, whether it completed, failed or was aborted. `close()` returns the inputs it never took in, the same list on every call once the generation has ended; input that arrives during the last model step is among them, and so is input the generation drained but could not record durably. After closing, `add()` throws `AgentPendingInputRejectedError` with reason `closed`, and a reused `inputId` is refused with reason `duplicate`. The caller decides what becomes of unapplied input, for example sending it as the next turn.
|
|
304
|
+
|
|
281
305
|
## Events, storage and context
|
|
282
306
|
|
|
283
307
|
Canonical events retain user and assistant messages, tool calls and results, runtime events, compaction records and transaction outcomes. `getEvents()` returns this history; `getModelMessages()` projects the model-visible conversation through the configured `contextBuilder`, which defaults to `buildModelMessages`.
|
|
@@ -35,6 +35,8 @@ export interface IUserMessageEvent extends IAgentEventBase {
|
|
|
35
35
|
type: 'user-message';
|
|
36
36
|
content: TAgentUserMessage['content'];
|
|
37
37
|
providerOptions?: TAgentUserMessage['providerOptions'];
|
|
38
|
+
/** Set when a running generation took the message in from its pending input. */
|
|
39
|
+
inputId?: string;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
export interface IAssistantMessageEvent extends IAgentEventBase {
|
|
@@ -106,6 +108,11 @@ export interface IGenerationOutcomeEvent extends IAgentEventBase {
|
|
|
106
108
|
generationId: string;
|
|
107
109
|
outcome: TAgentGenerationOutcome;
|
|
108
110
|
reason?: string;
|
|
111
|
+
/**
|
|
112
|
+
* Set on an `interrupted` outcome whose owner stopped the generation: what its model produced
|
|
113
|
+
* stays in the model context.
|
|
114
|
+
*/
|
|
115
|
+
stopped?: boolean;
|
|
109
116
|
}
|
|
110
117
|
|
|
111
118
|
export interface IToolExecutionIntentEvent extends IAgentEventBase {
|