@modelprofile.com/flexharness 8.3.0 → 8.4.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/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.flexharness.d.ts +10 -0
- package/dist_ts/classes.flexharness.js +58 -4
- package/dist_ts/interfaces.d.ts +24 -1
- package/dist_ts/interfaces.js +1 -1
- package/dist_ts/plugins.d.ts +1 -1
- package/dist_ts/plugins.js +1 -1
- package/dist_ts_compaction/plugins.d.ts +5 -2
- package/dist_ts_compaction/plugins.js +5 -3
- package/dist_ts_compaction/smartagent.compaction.d.ts +8 -1
- package/dist_ts_compaction/smartagent.compaction.js +52 -10
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.flexharness.ts +65 -3
- package/ts/interfaces.ts +25 -0
- package/ts/plugins.ts +2 -0
- package/ts_compaction/plugins.ts +8 -2
- package/ts_compaction/smartagent.compaction.ts +56 -9
package/dist_ts/interfaces.d.ts
CHANGED
|
@@ -17,6 +17,12 @@ export type TFlexAgentToolCallFinishEvent = Parameters<NonNullable<TFlexAgentSes
|
|
|
17
17
|
/** A usage or rate limit a model provider reported; `resetsAt` is in epoch milliseconds. */
|
|
18
18
|
export type TFlexModelLimit = plugins.IModelLimitInfo;
|
|
19
19
|
export type TFlexRetryReason = plugins.TAgentRetryReason;
|
|
20
|
+
/**
|
|
21
|
+
* The usage outcome of one model call: `reported` with the provider's `usage` and
|
|
22
|
+
* `responseModelId`, or `unreported` with a `reason` (`aborted`, `failed` or `missing`).
|
|
23
|
+
* Every call carries `provider` and `requestedModelId`; key usage caps on those two.
|
|
24
|
+
*/
|
|
25
|
+
export type TFlexModelCallUsage = plugins.TAgentModelCallUsage;
|
|
20
26
|
export interface IFlexTextPromptPart {
|
|
21
27
|
type: 'text';
|
|
22
28
|
text: string;
|
|
@@ -95,6 +101,11 @@ export interface IFlexMessage {
|
|
|
95
101
|
completedAt?: string;
|
|
96
102
|
parts: TFlexMessagePart[];
|
|
97
103
|
model?: IFlexModelIdentity;
|
|
104
|
+
/**
|
|
105
|
+
* On a terminal assistant message: the usage the provider reported for the run's model calls.
|
|
106
|
+
* For a failed or cancelled run it is a lower bound when a `model.usage` event of the run was
|
|
107
|
+
* `unreported`.
|
|
108
|
+
*/
|
|
98
109
|
usage?: IFlexUsage;
|
|
99
110
|
error?: string;
|
|
100
111
|
/** The model limit that failed this run, next to its error. */
|
|
@@ -356,6 +367,7 @@ export interface IFlexTerminalProjection {
|
|
|
356
367
|
userMessage: IFlexMessage;
|
|
357
368
|
assistantMessage: IFlexMessage;
|
|
358
369
|
model?: IFlexModelIdentity;
|
|
370
|
+
/** The usage the provider reported for the run's model calls, whatever the status. */
|
|
359
371
|
usage?: IFlexUsage;
|
|
360
372
|
finishReason?: string;
|
|
361
373
|
steps?: number;
|
|
@@ -933,6 +945,17 @@ export interface IFlexRunRetryingEvent extends IFlexEventBase {
|
|
|
933
945
|
readonly delayMs: number;
|
|
934
946
|
readonly reason: TFlexRetryReason;
|
|
935
947
|
}
|
|
948
|
+
/**
|
|
949
|
+
* The usage outcome of one model call of a session, emitted once per call whatever the run's
|
|
950
|
+
* outcome. `source: 'generation'` is a model step of the run `runId`. `source: 'compaction'` is a
|
|
951
|
+
* model call of a context compaction the context compactor reported; `runId` names the run whose
|
|
952
|
+
* context overflow caused it and is absent for `compactSession()` and event retention.
|
|
953
|
+
*/
|
|
954
|
+
export type TFlexModelUsageEvent = IFlexEventBase & {
|
|
955
|
+
readonly type: 'model.usage';
|
|
956
|
+
readonly runId?: string;
|
|
957
|
+
readonly source: 'generation' | 'compaction';
|
|
958
|
+
} & Readonly<TFlexModelCallUsage>;
|
|
936
959
|
export interface IFlexPromptQueueEvent extends IFlexEventBase {
|
|
937
960
|
readonly type: 'prompt.queued' | 'prompt.started' | 'prompt.running' | 'prompt.finished';
|
|
938
961
|
readonly queueId: string;
|
|
@@ -951,6 +974,6 @@ export interface IFlexErrorInfo {
|
|
|
951
974
|
/** Set when a model usage or rate limit caused the error. */
|
|
952
975
|
limit?: TFlexModelLimit;
|
|
953
976
|
}
|
|
954
|
-
export type TFlexHarnessEvent = IFlexSessionCreatedEvent | IFlexSessionUpdatedEvent | IFlexSessionDeletedEvent | IFlexRunStartedEvent | IFlexMessageChangedEvent | TFlexPartEvent | IFlexPermissionRequestedEvent | IFlexPermissionResolvedEvent | IFlexRunFinishedEvent | IFlexRunRetryingEvent | IFlexPromptQueueEvent | IFlexSessionHistoryChangedEvent;
|
|
977
|
+
export type TFlexHarnessEvent = IFlexSessionCreatedEvent | IFlexSessionUpdatedEvent | IFlexSessionDeletedEvent | IFlexRunStartedEvent | IFlexMessageChangedEvent | TFlexPartEvent | IFlexPermissionRequestedEvent | IFlexPermissionResolvedEvent | IFlexRunFinishedEvent | IFlexRunRetryingEvent | TFlexModelUsageEvent | IFlexPromptQueueEvent | IFlexSessionHistoryChangedEvent;
|
|
955
978
|
export type TFlexHarnessEventListener = (event: TFlexHarnessEvent) => void;
|
|
956
979
|
export {};
|
package/dist_ts/interfaces.js
CHANGED
|
@@ -27,4 +27,4 @@ export const FLEX_REVERSION_MAX_AFFECTED_WORKSPACES = 64;
|
|
|
27
27
|
export const FLEX_REVERSION_WORKSPACE_ID_MAX_BYTES = 512;
|
|
28
28
|
export const FLEX_REVERSION_WORKSPACE_LABEL_MAX_BYTES = 2048;
|
|
29
29
|
export const FLEX_REVERSION_REASON_CODE_MAX_BYTES = 128;
|
|
30
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2ludGVyZmFjZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBbWxCQSxNQUFNLENBQUMsTUFBTSxzQ0FBc0MsR0FBRyxDQUFVLENBQUM7QUFDakUsTUFBTSxDQUFDLE1BQU0sb0NBQW9DLEdBQUcsR0FBRyxDQUFDO0FBQ3hELE1BQU0sQ0FBQyxNQUFNLDBDQUEwQyxHQUFHLElBQUksQ0FBQztBQStCL0QsTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUMxRCxZQUFZLEVBQUUsQ0FBQyxHQUFHLElBQUk7SUFDdEIsa0JBQWtCLEVBQUUsR0FBRyxHQUFHLElBQUk7SUFDOUIsbUJBQW1CLEVBQUUsQ0FBQyxHQUFHLElBQUk7SUFDN0IsY0FBYyxFQUFFLEdBQUc7SUFDbkIsUUFBUSxFQUFFLEdBQUc7SUFDYixhQUFhLEVBQUUsSUFBSTtJQUNuQixnQkFBZ0IsRUFBRSxJQUFJLEdBQUcsSUFBSTtDQUM5QixDQUFDLENBQUM7QUErTEgsTUFBTSxDQUFDLE1BQU0sNkJBQTZCLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUN6RCxpQkFBaUIsRUFBRSxHQUFHO0lBQ3RCLFdBQVcsRUFBRSxHQUFHO0lBQ2hCLGlCQUFpQixFQUFFLElBQUk7SUFDdkIsMkJBQTJCLEVBQUUsSUFBSTtDQUNsQyxDQUFDLENBQUM7QUFFSCxNQUFNLENBQUMsTUFBTSw2QkFBNkIsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ3pELGlCQUFpQixFQUFFLElBQUk7SUFDdkIsV0FBVyxFQUFFLElBQUk7SUFDakIsaUJBQWlCLEVBQUUsTUFBTTtJQUN6QiwyQkFBMkIsRUFBRSxNQUFNO0NBQ3BDLENBQUMsQ0FBQztBQUVILE1BQU0sQ0FBQyxNQUFNLGtDQUFrQyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUM7QUFDN0QsTUFBTSxDQUFDLE1BQU0sc0NBQXNDLEdBQUcsRUFBRSxDQUFDO0FBQ3pELE1BQU0sQ0FBQyxNQUFNLHFDQUFxQyxHQUFHLEdBQUcsQ0FBQztBQUN6RCxNQUFNLENBQUMsTUFBTSx3Q0FBd0MsR0FBRyxJQUFJLENBQUM7QUFDN0QsTUFBTSxDQUFDLE1BQU0sb0NBQW9DLEdBQUcsR0FBRyxDQUFDIn0=
|
package/dist_ts/plugins.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import * as path from 'node:path';
|
|
|
5
5
|
export { AsyncLocalStorage, crypto, fs, path };
|
|
6
6
|
import { AgentEventStoreConflictError, AgentSession, buildModelMessages, ToolJobStoreConflictError, createAgentEvent, filterModelVisibleAgentEvents, getAgentGenerationTransactions, modelMessagesToAgentEvents, tool, validateAgentEventArchiveV2, validateAgentEventSnapshotV2, z } from '@modelprofile.com/flexharness-agent';
|
|
7
7
|
export { AgentEventStoreConflictError, AgentSession, buildModelMessages, ToolJobStoreConflictError, createAgentEvent, filterModelVisibleAgentEvents, getAgentGenerationTransactions, modelMessagesToAgentEvents, tool, validateAgentEventArchiveV2, validateAgentEventSnapshotV2, z, };
|
|
8
|
-
export type { IAgentEventArchiveV2, IAgentContextCompactionOptions, IAgentEventSnapshotV2, IAgentEventStoreV2, IAgentGenerateResult, IAgentGenerationHandle, IAgentGenerationLease, IAgentRetryEvent, IAgentRunResult, IAgentSession, IAgentSessionOptions, IAgentToolCallUpdateEvent, IAgentRuntimeEventPayload, IGenerationBegunEvent, IGenerationExecutionCompletedEvent, IGenerationExecutionStartedEvent, IGenerationOutcomeEvent, IToolExecutionContext, IToolExecutionIntentEvent, IToolJobSnapshot, IToolJobState, IToolJobStore, TAgentContextBuilder, TAgentContextCompactor, TAgentEvent, TAgentGenerationOutcome, TAgentRetryReason, TAgentToolCallFinishEvent, TAgentToolExecutionReconciliationOptions, } from '@modelprofile.com/flexharness-agent';
|
|
8
|
+
export type { IAgentEventArchiveV2, IAgentContextCompactionOptions, IAgentEventSnapshotV2, IAgentEventStoreV2, IAgentGenerateResult, IAgentGenerationHandle, IAgentGenerationLease, IAgentRetryEvent, IAgentRunResult, IAgentSession, IAgentSessionOptions, IAgentToolCallUpdateEvent, IAgentRuntimeEventPayload, IGenerationBegunEvent, IGenerationExecutionCompletedEvent, IGenerationExecutionStartedEvent, IGenerationOutcomeEvent, IToolExecutionContext, IToolExecutionIntentEvent, IToolJobSnapshot, IToolJobState, IToolJobStore, TAgentContextBuilder, TAgentContextCompactor, TAgentEvent, TAgentGenerationOutcome, TAgentModelCallUsage, TAgentModelCallUsageEvent, TAgentRetryReason, TAgentToolCallFinishEvent, TAgentToolExecutionReconciliationOptions, } from '@modelprofile.com/flexharness-agent';
|
|
9
9
|
import { isModelLimitError, isModelLimitInfo } from '@modelprofile.com/flexharness-models';
|
|
10
10
|
export { isModelLimitError, isModelLimitInfo };
|
|
11
11
|
export type { IModelLimitInfo } from '@modelprofile.com/flexharness-models';
|
package/dist_ts/plugins.js
CHANGED
|
@@ -9,4 +9,4 @@ import { AgentEventStoreConflictError, AgentSession, buildModelMessages, ToolJob
|
|
|
9
9
|
export { AgentEventStoreConflictError, AgentSession, buildModelMessages, ToolJobStoreConflictError, createAgentEvent, filterModelVisibleAgentEvents, getAgentGenerationTransactions, modelMessagesToAgentEvents, tool, validateAgentEventArchiveV2, validateAgentEventSnapshotV2, z, };
|
|
10
10
|
import { isModelLimitError, isModelLimitInfo } from '@modelprofile.com/flexharness-models';
|
|
11
11
|
export { isModelLimitError, isModelLimitInfo };
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3JELE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkMsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFFbEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7QUFFL0Msb0JBQW9CO0FBQ3BCLE9BQU8sRUFDTCw0QkFBNEIsRUFDNUIsWUFBWSxFQUNaLGtCQUFrQixFQUNsQix5QkFBeUIsRUFDekIsZ0JBQWdCLEVBQ2hCLDZCQUE2QixFQUM3Qiw4QkFBOEIsRUFDOUIsMEJBQTBCLEVBQzFCLElBQUksRUFDSiwyQkFBMkIsRUFDM0IsNEJBQTRCLEVBQzVCLENBQUMsR0FDRixNQUFNLHFDQUFxQyxDQUFDO0FBRTdDLE9BQU8sRUFDTCw0QkFBNEIsRUFDNUIsWUFBWSxFQUNaLGtCQUFrQixFQUNsQix5QkFBeUIsRUFDekIsZ0JBQWdCLEVBQ2hCLDZCQUE2QixFQUM3Qiw4QkFBOEIsRUFDOUIsMEJBQTBCLEVBQzFCLElBQUksRUFDSiwyQkFBMkIsRUFDM0IsNEJBQTRCLEVBQzVCLENBQUMsR0FDRixDQUFDO0FBbUNGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBRTNGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDIn0=
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import { generateText } from 'ai';
|
|
2
|
-
export { generateText };
|
|
1
|
+
import { generateText, wrapLanguageModel } from 'ai';
|
|
2
|
+
export { generateText, wrapLanguageModel };
|
|
3
3
|
export type { ModelMessage } from 'ai';
|
|
4
4
|
export type { TSmartAiLanguageModel } from '@modelprofile.com/flexharness-models';
|
|
5
|
+
import { AgentModelCallUsageRecorder } from '@modelprofile.com/flexharness-agent';
|
|
6
|
+
export { AgentModelCallUsageRecorder };
|
|
7
|
+
export type { TAgentModelCallUsageReporter } from '@modelprofile.com/flexharness-agent';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import { generateText } from 'ai';
|
|
2
|
-
export { generateText };
|
|
3
|
-
|
|
1
|
+
import { generateText, wrapLanguageModel } from 'ai';
|
|
2
|
+
export { generateText, wrapLanguageModel };
|
|
3
|
+
import { AgentModelCallUsageRecorder } from '@modelprofile.com/flexharness-agent';
|
|
4
|
+
export { AgentModelCallUsageRecorder };
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX2NvbXBhY3Rpb24vcGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sSUFBSSxDQUFDO0FBRXJELE9BQU8sRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQztBQUszQyxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUVsRixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQyJ9
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
export interface ICompactMessagesOptions {
|
|
3
3
|
abortSignal?: AbortSignal;
|
|
4
|
+
/**
|
|
5
|
+
* Receives the usage of every model call the compaction makes, once per call: `reported` with the
|
|
6
|
+
* provider's usage, or `unreported` for a call that failed or was aborted, retried attempts
|
|
7
|
+
* included. A context compactor passes its own options through, so the calls reach the session's
|
|
8
|
+
* `onUsage`. Must not throw.
|
|
9
|
+
*/
|
|
10
|
+
reportUsage?: plugins.TAgentModelCallUsageReporter;
|
|
4
11
|
}
|
|
5
12
|
/**
|
|
6
13
|
* Compacts a message history into a summary.
|
|
@@ -8,7 +15,7 @@ export interface ICompactMessagesOptions {
|
|
|
8
15
|
*
|
|
9
16
|
* @param model The same model used by runAgent, or a cheaper small model
|
|
10
17
|
* @param messages The full message history that overflowed
|
|
11
|
-
* @param options Invocation options, including cancellation
|
|
18
|
+
* @param options Invocation options, including cancellation and usage reporting
|
|
12
19
|
* @returns A minimal ModelMessage[] containing the summary as context
|
|
13
20
|
*/
|
|
14
21
|
export declare function compactMessages(model: plugins.TSmartAiLanguageModel, messages: plugins.ModelMessage[], options?: ICompactMessagesOptions): Promise<plugins.ModelMessage[]>;
|
|
@@ -26,24 +26,66 @@ When constructing the summary, try to stick to this template:
|
|
|
26
26
|
*
|
|
27
27
|
* @param model The same model used by runAgent, or a cheaper small model
|
|
28
28
|
* @param messages The full message history that overflowed
|
|
29
|
-
* @param options Invocation options, including cancellation
|
|
29
|
+
* @param options Invocation options, including cancellation and usage reporting
|
|
30
30
|
* @returns A minimal ModelMessage[] containing the summary as context
|
|
31
31
|
*/
|
|
32
32
|
export async function compactMessages(model, messages, options = {}) {
|
|
33
|
-
const
|
|
33
|
+
const prompt = [
|
|
34
|
+
...messages,
|
|
35
|
+
{ role: 'user', content: COMPACTION_PROMPT },
|
|
36
|
+
];
|
|
37
|
+
const reportUsage = options.reportUsage;
|
|
38
|
+
if (!reportUsage) {
|
|
39
|
+
const result = await plugins.generateText({
|
|
40
|
+
model,
|
|
41
|
+
abortSignal: options.abortSignal,
|
|
42
|
+
allowSystemInMessages: true,
|
|
43
|
+
messages: prompt,
|
|
44
|
+
});
|
|
45
|
+
return summaryMessages(result.text);
|
|
46
|
+
}
|
|
47
|
+
const modelCalls = new plugins.AgentModelCallUsageRecorder(model, reportUsage);
|
|
48
|
+
// Each attempt, retries included, is one model call: it starts in the middleware, which also
|
|
49
|
+
// settles an attempt that throws; a call whose response arrives ends in onLanguageModelCallEnd.
|
|
50
|
+
const observedModel = plugins.wrapLanguageModel({
|
|
34
51
|
model,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
52
|
+
middleware: {
|
|
53
|
+
wrapGenerate: async ({ doGenerate, params }) => {
|
|
54
|
+
modelCalls.start();
|
|
55
|
+
try {
|
|
56
|
+
return await doGenerate();
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
modelCalls.settle(params.abortSignal?.aborted ? 'aborted' : 'failed');
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
},
|
|
41
64
|
});
|
|
65
|
+
try {
|
|
66
|
+
const result = await plugins.generateText({
|
|
67
|
+
model: observedModel,
|
|
68
|
+
abortSignal: options.abortSignal,
|
|
69
|
+
allowSystemInMessages: true,
|
|
70
|
+
messages: prompt,
|
|
71
|
+
onLanguageModelCallEnd: ({ modelId, usage }) => {
|
|
72
|
+
modelCalls.end(modelId, usage);
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
modelCalls.settle('missing');
|
|
76
|
+
return summaryMessages(result.text);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
modelCalls.settle(options.abortSignal?.aborted ? 'aborted' : 'failed');
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function summaryMessages(summary) {
|
|
42
84
|
return [
|
|
43
85
|
{
|
|
44
86
|
role: 'user',
|
|
45
|
-
content: `[Previous conversation summary]\n\n${
|
|
87
|
+
content: `[Previous conversation summary]\n\n${summary}\n\n[End of summary. Continue from here.]`,
|
|
46
88
|
},
|
|
47
89
|
];
|
|
48
90
|
}
|
|
49
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhZ2VudC5jb21wYWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfY29tcGFjdGlvbi9zbWFydGFnZW50LmNvbXBhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFFeEMsTUFBTSxpQkFBaUIsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7SUFvQnRCLENBQUM7QUFhTDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsZUFBZSxDQUNuQyxLQUFvQyxFQUNwQyxRQUFnQyxFQUNoQyxVQUFtQyxFQUFFO0lBRXJDLE1BQU0sTUFBTSxHQUEyQjtRQUNyQyxHQUFHLFFBQVE7UUFDWCxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLGlCQUFpQixFQUFFO0tBQzdDLENBQUM7SUFDRixNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDO0lBQ3hDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNqQixNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxZQUFZLENBQUM7WUFDeEMsS0FBSztZQUNMLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVztZQUNoQyxxQkFBcUIsRUFBRSxJQUFJO1lBQzNCLFFBQVEsRUFBRSxNQUFNO1NBQ2pCLENBQUMsQ0FBQztRQUNILE9BQU8sZUFBZSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBQ0QsTUFBTSxVQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsMkJBQTJCLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQy9FLDZGQUE2RjtJQUM3RixnR0FBZ0c7SUFDaEcsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixDQUFDO1FBQzlDLEtBQUs7UUFDTCxVQUFVLEVBQUU7WUFDVixZQUFZLEVBQUUsS0FBSyxFQUFFLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7Z0JBQzdDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDO29CQUNILE9BQU8sTUFBTSxVQUFVLEVBQUUsQ0FBQztnQkFDNUIsQ0FBQztnQkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO29CQUNmLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUM7b0JBQ3RFLE1BQU0sS0FBSyxDQUFDO2dCQUNkLENBQUM7WUFDSCxDQUFDO1NBQ0Y7S0FDRixDQUFDLENBQUM7SUFDSCxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxZQUFZLENBQUM7WUFDeEMsS0FBSyxFQUFFLGFBQWE7WUFDcEIsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXO1lBQ2hDLHFCQUFxQixFQUFFLElBQUk7WUFDM0IsUUFBUSxFQUFFLE1BQU07WUFDaEIsc0JBQXNCLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFO2dCQUM3QyxVQUFVLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNqQyxDQUFDO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsVUFBVSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM3QixPQUFPLGVBQWUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixVQUFVLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sS0FBSyxDQUFDO0lBQ2QsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLGVBQWUsQ0FBQyxPQUFlO0lBQ3RDLE9BQU87UUFDTDtZQUNFLElBQUksRUFBRSxNQUFNO1lBQ1osT0FBTyxFQUFFLHNDQUFzQyxPQUFPLDJDQUEyQztTQUNsRztLQUNGLENBQUM7QUFDSixDQUFDIn0=
|
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",
|
|
5
|
-
"version": "8.
|
|
5
|
+
"version": "8.4.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"description": "Managed agent sessions with tools, MCP, chat, OCR, documents and browser control through focused subpath imports.",
|
|
8
8
|
"main": "./dist_ts/index.js",
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@modelprofile.com/flexharness-agent": "8.
|
|
66
|
-
"@modelprofile.com/flexharness-models": "8.
|
|
65
|
+
"@modelprofile.com/flexharness-agent": "8.4.0",
|
|
66
|
+
"@modelprofile.com/flexharness-models": "8.4.0",
|
|
67
67
|
"@push.rocks/smartrequest": "^5.0.1",
|
|
68
68
|
"ai": "^7.0.79",
|
|
69
69
|
"zod": "^4.4.1"
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -99,6 +99,7 @@ import type {
|
|
|
99
99
|
IFlexUndoSessionResult,
|
|
100
100
|
IFlexUpdateSessionOptions,
|
|
101
101
|
IFlexUpdateProjectTaskInput,
|
|
102
|
+
IFlexUsage,
|
|
102
103
|
IJsonObject,
|
|
103
104
|
TFlexAgentToolCallUpdateEvent,
|
|
104
105
|
TFlexAgentToolCallFinishEvent,
|
|
@@ -337,6 +338,8 @@ interface IActiveRun {
|
|
|
337
338
|
callbackParts: TFlexMessagePart[];
|
|
338
339
|
partTextUtf8Bytes: Map<string, number>;
|
|
339
340
|
callbacksClosed: boolean;
|
|
341
|
+
/** The usage the provider reported for the run's model calls so far. */
|
|
342
|
+
usage: IFlexUsage;
|
|
340
343
|
reasoningPartIds: Map<string, string>;
|
|
341
344
|
toolPartIds: Map<string, string>;
|
|
342
345
|
trustedToolExecutionErrors: Map<string, Error>;
|
|
@@ -3396,6 +3399,13 @@ export class FlexHarness<TScope = unknown> {
|
|
|
3396
3399
|
callbackParts: [],
|
|
3397
3400
|
partTextUtf8Bytes: new Map(),
|
|
3398
3401
|
callbacksClosed: false,
|
|
3402
|
+
usage: {
|
|
3403
|
+
inputTokens: 0,
|
|
3404
|
+
outputTokens: 0,
|
|
3405
|
+
totalTokens: 0,
|
|
3406
|
+
cacheReadTokens: 0,
|
|
3407
|
+
cacheWriteTokens: 0,
|
|
3408
|
+
},
|
|
3399
3409
|
reasoningPartIds: new Map(),
|
|
3400
3410
|
toolPartIds: new Map(),
|
|
3401
3411
|
trustedToolExecutionErrors: new Map(),
|
|
@@ -3957,6 +3967,8 @@ export class FlexHarness<TScope = unknown> {
|
|
|
3957
3967
|
): Promise<IFlexPromptResult> {
|
|
3958
3968
|
let generated = false;
|
|
3959
3969
|
try {
|
|
3970
|
+
// The transactional generation settles only after its model calls are reported, so
|
|
3971
|
+
// `run.usage` is complete once it settles, also for a cancelled run.
|
|
3960
3972
|
const rawResult = await generation;
|
|
3961
3973
|
generated = true;
|
|
3962
3974
|
if (run.callbackError) throw run.callbackError;
|
|
@@ -5686,6 +5698,7 @@ export class FlexHarness<TScope = unknown> {
|
|
|
5686
5698
|
}
|
|
5687
5699
|
assistantMessage.usage = cloneSerializable(result.usage);
|
|
5688
5700
|
} else {
|
|
5701
|
+
assistantMessage.usage = cloneSerializable(run.usage);
|
|
5689
5702
|
const message = truncateUtf8(error?.message ?? externalErrorFallback.message, maxTransferMetadataBytes);
|
|
5690
5703
|
const limit = error instanceof FlexHarnessExternalError ? error.limit : undefined;
|
|
5691
5704
|
for (const failedMessage of [userMessage, assistantMessage]) {
|
|
@@ -5705,7 +5718,7 @@ export class FlexHarness<TScope = unknown> {
|
|
|
5705
5718
|
finishReason: result.finishReason,
|
|
5706
5719
|
steps: result.steps,
|
|
5707
5720
|
}
|
|
5708
|
-
: {}),
|
|
5721
|
+
: { usage: cloneSerializable(run.usage) }),
|
|
5709
5722
|
};
|
|
5710
5723
|
}
|
|
5711
5724
|
|
|
@@ -7051,6 +7064,50 @@ export class FlexHarness<TScope = unknown> {
|
|
|
7051
7064
|
});
|
|
7052
7065
|
}
|
|
7053
7066
|
|
|
7067
|
+
/**
|
|
7068
|
+
* Emits the usage of every model call and adds reported usage to its run. A run executes a
|
|
7069
|
+
* transactional generation, and `AgentSession.generate()` settles a transactional generation only
|
|
7070
|
+
* after it has reported each of its model calls, also when it is aborted. `executeRun()` awaits
|
|
7071
|
+
* that settlement before it builds the terminal, so the run is still active for each of its
|
|
7072
|
+
* events: they all reach `run.usage` and precede its `run.finished`. The events bypass the
|
|
7073
|
+
* callback limits and a failed callback: their number is bounded by the run's model calls, and
|
|
7074
|
+
* the usage of a run that exhausted its callback budget or failed in a callback must not be lost.
|
|
7075
|
+
*/
|
|
7076
|
+
private onModelCallUsage(
|
|
7077
|
+
state: IStorageState,
|
|
7078
|
+
stored: IStoredSessionState,
|
|
7079
|
+
event: plugins.TAgentModelCallUsageEvent,
|
|
7080
|
+
): void {
|
|
7081
|
+
const { source, generationId, ...call } = event;
|
|
7082
|
+
const sessionId = stored.session.sessionId;
|
|
7083
|
+
const activeRun = state.activeRuns.get(sessionId);
|
|
7084
|
+
const run = generationId !== undefined && activeRun?.runId === generationId ? activeRun : undefined;
|
|
7085
|
+
let scopeId = run?.scopeId;
|
|
7086
|
+
if (scopeId === undefined) {
|
|
7087
|
+
const ambientContext = this.compactorInvocationContext.getStore();
|
|
7088
|
+
const invocationContext = ambientContext
|
|
7089
|
+
? this.deferredCompactorContexts.get(ambientContext) ?? ambientContext
|
|
7090
|
+
: undefined;
|
|
7091
|
+
if (
|
|
7092
|
+
!invocationContext
|
|
7093
|
+
|| invocationContext.storageKey !== state.storageKey
|
|
7094
|
+
|| invocationContext.sessionId !== sessionId
|
|
7095
|
+
) {
|
|
7096
|
+
throw new Error('Model call usage is missing its exact FlexHarness invocation context.');
|
|
7097
|
+
}
|
|
7098
|
+
scopeId = invocationContext.scopeId;
|
|
7099
|
+
}
|
|
7100
|
+
if (run && call.status === 'reported') {
|
|
7101
|
+
for (const key of Object.keys(run.usage) as (keyof IFlexUsage)[]) run.usage[key] += call.usage[key];
|
|
7102
|
+
}
|
|
7103
|
+
this.emitEvent(scopeId, stored.session, {
|
|
7104
|
+
type: 'model.usage',
|
|
7105
|
+
...(generationId === undefined ? {} : { runId: generationId }),
|
|
7106
|
+
source,
|
|
7107
|
+
...call,
|
|
7108
|
+
});
|
|
7109
|
+
}
|
|
7110
|
+
|
|
7054
7111
|
private callbackRun(state: IStorageState, sessionId: string): IActiveRun | undefined {
|
|
7055
7112
|
const run = state.activeRuns.get(sessionId);
|
|
7056
7113
|
return !run || run.callbacksClosed || run.callbackError ? undefined : run;
|
|
@@ -8261,6 +8318,7 @@ export class FlexHarness<TScope = unknown> {
|
|
|
8261
8318
|
onToolCallUpdate: (event) => this.onToolUpdate(state, sessionId, event),
|
|
8262
8319
|
onToolCallFinish: (event) => this.onToolFinish(state, sessionId, event),
|
|
8263
8320
|
onRetry: (event) => this.onRetry(state, sessionId, event),
|
|
8321
|
+
onUsage: (event) => this.onModelCallUsage(state, stored, event),
|
|
8264
8322
|
};
|
|
8265
8323
|
stored.agentSession = await this.withCompactorContext(
|
|
8266
8324
|
compactorContext,
|
|
@@ -8516,7 +8574,11 @@ export class FlexHarness<TScope = unknown> {
|
|
|
8516
8574
|
const message = status === 'cancelled' ? repairCancellationMessage : externalErrorFallback.message;
|
|
8517
8575
|
userMessage.error = message;
|
|
8518
8576
|
assistantMessage.error = message;
|
|
8519
|
-
|
|
8577
|
+
if (stage?.usage) {
|
|
8578
|
+
assistantMessage.usage = cloneSerializable(stage.usage);
|
|
8579
|
+
} else {
|
|
8580
|
+
delete assistantMessage.usage;
|
|
8581
|
+
}
|
|
8520
8582
|
}
|
|
8521
8583
|
return {
|
|
8522
8584
|
runId,
|
|
@@ -8524,7 +8586,7 @@ export class FlexHarness<TScope = unknown> {
|
|
|
8524
8586
|
userMessage,
|
|
8525
8587
|
assistantMessage,
|
|
8526
8588
|
...(status === 'completed' && stage?.model ? { model: stage.model } : {}),
|
|
8527
|
-
...(
|
|
8589
|
+
...(stage?.usage ? { usage: stage.usage } : {}),
|
|
8528
8590
|
...(status === 'completed' && stage?.finishReason ? { finishReason: stage.finishReason } : {}),
|
|
8529
8591
|
...(status === 'completed' && stage?.steps !== undefined ? { steps: stage.steps } : {}),
|
|
8530
8592
|
};
|
package/ts/interfaces.ts
CHANGED
|
@@ -25,6 +25,12 @@ export type TFlexAgentToolCallFinishEvent = Parameters<
|
|
|
25
25
|
/** A usage or rate limit a model provider reported; `resetsAt` is in epoch milliseconds. */
|
|
26
26
|
export type TFlexModelLimit = plugins.IModelLimitInfo;
|
|
27
27
|
export type TFlexRetryReason = plugins.TAgentRetryReason;
|
|
28
|
+
/**
|
|
29
|
+
* The usage outcome of one model call: `reported` with the provider's `usage` and
|
|
30
|
+
* `responseModelId`, or `unreported` with a `reason` (`aborted`, `failed` or `missing`).
|
|
31
|
+
* Every call carries `provider` and `requestedModelId`; key usage caps on those two.
|
|
32
|
+
*/
|
|
33
|
+
export type TFlexModelCallUsage = plugins.TAgentModelCallUsage;
|
|
28
34
|
|
|
29
35
|
export interface IFlexTextPromptPart {
|
|
30
36
|
type: 'text';
|
|
@@ -126,6 +132,11 @@ export interface IFlexMessage {
|
|
|
126
132
|
completedAt?: string;
|
|
127
133
|
parts: TFlexMessagePart[];
|
|
128
134
|
model?: IFlexModelIdentity;
|
|
135
|
+
/**
|
|
136
|
+
* On a terminal assistant message: the usage the provider reported for the run's model calls.
|
|
137
|
+
* For a failed or cancelled run it is a lower bound when a `model.usage` event of the run was
|
|
138
|
+
* `unreported`.
|
|
139
|
+
*/
|
|
129
140
|
usage?: IFlexUsage;
|
|
130
141
|
error?: string;
|
|
131
142
|
/** The model limit that failed this run, next to its error. */
|
|
@@ -464,6 +475,7 @@ export interface IFlexTerminalProjection {
|
|
|
464
475
|
userMessage: IFlexMessage;
|
|
465
476
|
assistantMessage: IFlexMessage;
|
|
466
477
|
model?: IFlexModelIdentity;
|
|
478
|
+
/** The usage the provider reported for the run's model calls, whatever the status. */
|
|
467
479
|
usage?: IFlexUsage;
|
|
468
480
|
finishReason?: string;
|
|
469
481
|
steps?: number;
|
|
@@ -1244,6 +1256,18 @@ export interface IFlexRunRetryingEvent extends IFlexEventBase {
|
|
|
1244
1256
|
readonly reason: TFlexRetryReason;
|
|
1245
1257
|
}
|
|
1246
1258
|
|
|
1259
|
+
/**
|
|
1260
|
+
* The usage outcome of one model call of a session, emitted once per call whatever the run's
|
|
1261
|
+
* outcome. `source: 'generation'` is a model step of the run `runId`. `source: 'compaction'` is a
|
|
1262
|
+
* model call of a context compaction the context compactor reported; `runId` names the run whose
|
|
1263
|
+
* context overflow caused it and is absent for `compactSession()` and event retention.
|
|
1264
|
+
*/
|
|
1265
|
+
export type TFlexModelUsageEvent = IFlexEventBase & {
|
|
1266
|
+
readonly type: 'model.usage';
|
|
1267
|
+
readonly runId?: string;
|
|
1268
|
+
readonly source: 'generation' | 'compaction';
|
|
1269
|
+
} & Readonly<TFlexModelCallUsage>;
|
|
1270
|
+
|
|
1247
1271
|
export interface IFlexPromptQueueEvent extends IFlexEventBase {
|
|
1248
1272
|
readonly type: 'prompt.queued' | 'prompt.started' | 'prompt.running' | 'prompt.finished';
|
|
1249
1273
|
readonly queueId: string;
|
|
@@ -1276,6 +1300,7 @@ export type TFlexHarnessEvent =
|
|
|
1276
1300
|
| IFlexPermissionResolvedEvent
|
|
1277
1301
|
| IFlexRunFinishedEvent
|
|
1278
1302
|
| IFlexRunRetryingEvent
|
|
1303
|
+
| TFlexModelUsageEvent
|
|
1279
1304
|
| IFlexPromptQueueEvent
|
|
1280
1305
|
| IFlexSessionHistoryChangedEvent;
|
|
1281
1306
|
|
package/ts/plugins.ts
CHANGED
package/ts_compaction/plugins.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { generateText } from 'ai';
|
|
1
|
+
import { generateText, wrapLanguageModel } from 'ai';
|
|
2
2
|
|
|
3
|
-
export { generateText };
|
|
3
|
+
export { generateText, wrapLanguageModel };
|
|
4
4
|
|
|
5
5
|
export type { ModelMessage } from 'ai';
|
|
6
6
|
export type { TSmartAiLanguageModel } from '@modelprofile.com/flexharness-models';
|
|
7
|
+
|
|
8
|
+
import { AgentModelCallUsageRecorder } from '@modelprofile.com/flexharness-agent';
|
|
9
|
+
|
|
10
|
+
export { AgentModelCallUsageRecorder };
|
|
11
|
+
|
|
12
|
+
export type { TAgentModelCallUsageReporter } from '@modelprofile.com/flexharness-agent';
|
|
@@ -24,6 +24,13 @@ When constructing the summary, try to stick to this template:
|
|
|
24
24
|
|
|
25
25
|
export interface ICompactMessagesOptions {
|
|
26
26
|
abortSignal?: AbortSignal;
|
|
27
|
+
/**
|
|
28
|
+
* Receives the usage of every model call the compaction makes, once per call: `reported` with the
|
|
29
|
+
* provider's usage, or `unreported` for a call that failed or was aborted, retried attempts
|
|
30
|
+
* included. A context compactor passes its own options through, so the calls reach the session's
|
|
31
|
+
* `onUsage`. Must not throw.
|
|
32
|
+
*/
|
|
33
|
+
reportUsage?: plugins.TAgentModelCallUsageReporter;
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
/**
|
|
@@ -32,7 +39,7 @@ export interface ICompactMessagesOptions {
|
|
|
32
39
|
*
|
|
33
40
|
* @param model The same model used by runAgent, or a cheaper small model
|
|
34
41
|
* @param messages The full message history that overflowed
|
|
35
|
-
* @param options Invocation options, including cancellation
|
|
42
|
+
* @param options Invocation options, including cancellation and usage reporting
|
|
36
43
|
* @returns A minimal ModelMessage[] containing the summary as context
|
|
37
44
|
*/
|
|
38
45
|
export async function compactMessages(
|
|
@@ -40,20 +47,60 @@ export async function compactMessages(
|
|
|
40
47
|
messages: plugins.ModelMessage[],
|
|
41
48
|
options: ICompactMessagesOptions = {},
|
|
42
49
|
): Promise<plugins.ModelMessage[]> {
|
|
43
|
-
const
|
|
50
|
+
const prompt: plugins.ModelMessage[] = [
|
|
51
|
+
...messages,
|
|
52
|
+
{ role: 'user', content: COMPACTION_PROMPT },
|
|
53
|
+
];
|
|
54
|
+
const reportUsage = options.reportUsage;
|
|
55
|
+
if (!reportUsage) {
|
|
56
|
+
const result = await plugins.generateText({
|
|
57
|
+
model,
|
|
58
|
+
abortSignal: options.abortSignal,
|
|
59
|
+
allowSystemInMessages: true,
|
|
60
|
+
messages: prompt,
|
|
61
|
+
});
|
|
62
|
+
return summaryMessages(result.text);
|
|
63
|
+
}
|
|
64
|
+
const modelCalls = new plugins.AgentModelCallUsageRecorder(model, reportUsage);
|
|
65
|
+
// Each attempt, retries included, is one model call: it starts in the middleware, which also
|
|
66
|
+
// settles an attempt that throws; a call whose response arrives ends in onLanguageModelCallEnd.
|
|
67
|
+
const observedModel = plugins.wrapLanguageModel({
|
|
44
68
|
model,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
69
|
+
middleware: {
|
|
70
|
+
wrapGenerate: async ({ doGenerate, params }) => {
|
|
71
|
+
modelCalls.start();
|
|
72
|
+
try {
|
|
73
|
+
return await doGenerate();
|
|
74
|
+
} catch (error) {
|
|
75
|
+
modelCalls.settle(params.abortSignal?.aborted ? 'aborted' : 'failed');
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
},
|
|
51
80
|
});
|
|
81
|
+
try {
|
|
82
|
+
const result = await plugins.generateText({
|
|
83
|
+
model: observedModel,
|
|
84
|
+
abortSignal: options.abortSignal,
|
|
85
|
+
allowSystemInMessages: true,
|
|
86
|
+
messages: prompt,
|
|
87
|
+
onLanguageModelCallEnd: ({ modelId, usage }) => {
|
|
88
|
+
modelCalls.end(modelId, usage);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
modelCalls.settle('missing');
|
|
92
|
+
return summaryMessages(result.text);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
modelCalls.settle(options.abortSignal?.aborted ? 'aborted' : 'failed');
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
52
98
|
|
|
99
|
+
function summaryMessages(summary: string): plugins.ModelMessage[] {
|
|
53
100
|
return [
|
|
54
101
|
{
|
|
55
102
|
role: 'user',
|
|
56
|
-
content: `[Previous conversation summary]\n\n${
|
|
103
|
+
content: `[Previous conversation summary]\n\n${summary}\n\n[End of summary. Continue from here.]`,
|
|
57
104
|
},
|
|
58
105
|
];
|
|
59
106
|
}
|