@modelprofile.com/flexharness 8.2.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.
@@ -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 result = await plugins.generateText({
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
- abortSignal: options.abortSignal,
46
- allowSystemInMessages: true,
47
- messages: [
48
- ...messages,
49
- { role: 'user', content: COMPACTION_PROMPT },
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${result.text}\n\n[End of summary. Continue from here.]`,
103
+ content: `[Previous conversation summary]\n\n${summary}\n\n[End of summary. Continue from here.]`,
57
104
  },
58
105
  ];
59
106
  }