@modelprofile.com/flexharness 8.4.0 → 8.5.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_document/index.d.ts +9 -0
- package/dist_ts_document/index.js +58 -20
- package/dist_ts_document/plugins.d.ts +4 -2
- package/dist_ts_document/plugins.js +4 -3
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_document/index.ts +64 -20
- package/ts_document/plugins.ts +4 -2
- package/ts_document/readme.md +24 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@modelprofile.com/flexharness',
|
|
6
|
-
version: '8.
|
|
6
|
+
version: '8.5.0',
|
|
7
7
|
description: 'The FlexHarness toolbox source repository and shared dependency catalog.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSwrQkFBK0I7SUFDckMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDBFQUEwRTtDQUN4RixDQUFBIn0=
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
1
2
|
import type { ModelMessage } from 'ai';
|
|
2
3
|
import type { TSmartAiLanguageModel, TSmartAiProviderOptions } from '@modelprofile.com/flexharness-models';
|
|
3
4
|
/** Options every document request accepts in addition to its model and messages. */
|
|
@@ -15,6 +16,14 @@ export interface IDocumentRequestOptions {
|
|
|
15
16
|
* exceeded the limit are not rendered.
|
|
16
17
|
*/
|
|
17
18
|
maxPages?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Called once for every model call of the request, as soon as its usage is known, whatever the
|
|
21
|
+
* request's outcome: `reported` with the provider's usage, or `unreported` with the reason when
|
|
22
|
+
* the call failed, was aborted or its response carried no usage. A retried attempt is a call of
|
|
23
|
+
* its own. Nothing is reported for a request that ends before its model is called. When a request
|
|
24
|
+
* returns, its reported calls sum to its `usage`. Must not throw.
|
|
25
|
+
*/
|
|
26
|
+
onUsage?: plugins.TAgentModelCallUsageReporter;
|
|
18
27
|
}
|
|
19
28
|
export interface IDocumentOptions extends IDocumentRequestOptions {
|
|
20
29
|
model: TSmartAiLanguageModel;
|
|
@@ -48,6 +48,7 @@ export async function extractTextFromPdfWithUsage(pdfDocument, options) {
|
|
|
48
48
|
providerOptions: options.providerOptions,
|
|
49
49
|
abortSignal: options.abortSignal,
|
|
50
50
|
maxPages: options.maxPages,
|
|
51
|
+
onUsage: options.onUsage,
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
export async function analyzeDocuments(options) {
|
|
@@ -79,26 +80,63 @@ export async function analyzeDocumentsWithUsage(options) {
|
|
|
79
80
|
}
|
|
80
81
|
// Filter out empty buffers
|
|
81
82
|
const validPages = imagePages.filter(page => page && page.length > 0);
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
83
|
+
const onUsage = options.onUsage;
|
|
84
|
+
const modelCalls = onUsage ? new plugins.AgentModelCallUsageRecorder(options.model, onUsage) : null;
|
|
85
|
+
// Each attempt, retries included, is one model call: it starts in the middleware, which also
|
|
86
|
+
// settles an attempt that throws; a call whose response arrives ends in onLanguageModelCallEnd.
|
|
87
|
+
const model = modelCalls
|
|
88
|
+
? plugins.wrapLanguageModel({
|
|
89
|
+
model: options.model,
|
|
90
|
+
middleware: {
|
|
91
|
+
wrapGenerate: async ({ doGenerate, params }) => {
|
|
92
|
+
modelCalls.start();
|
|
93
|
+
try {
|
|
94
|
+
return await doGenerate();
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
modelCalls.settle(params.abortSignal?.aborted ? 'aborted' : 'failed');
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
97
101
|
},
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
})
|
|
103
|
+
: options.model;
|
|
104
|
+
const messages = [
|
|
105
|
+
...(options.messageHistory ?? []),
|
|
106
|
+
{
|
|
107
|
+
role: 'user',
|
|
108
|
+
content: [
|
|
109
|
+
{ type: 'text', text: options.userMessage },
|
|
110
|
+
...validPages.map(page => ({
|
|
111
|
+
type: 'file',
|
|
112
|
+
data: page,
|
|
113
|
+
mediaType: 'image/png',
|
|
114
|
+
})),
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
let result;
|
|
119
|
+
try {
|
|
120
|
+
result = await plugins.generateText({
|
|
121
|
+
model,
|
|
122
|
+
instructions: options.systemMessage,
|
|
123
|
+
messages,
|
|
124
|
+
providerOptions: options.providerOptions,
|
|
125
|
+
abortSignal,
|
|
126
|
+
...(modelCalls
|
|
127
|
+
? {
|
|
128
|
+
onLanguageModelCallEnd: ({ modelId, usage: callUsage }) => {
|
|
129
|
+
modelCalls.end(modelId, callUsage);
|
|
130
|
+
},
|
|
131
|
+
}
|
|
132
|
+
: {}),
|
|
133
|
+
});
|
|
134
|
+
modelCalls?.settle('missing');
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
modelCalls?.settle(abortSignal?.aborted ? 'aborted' : 'failed');
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
102
140
|
const usage = result.totalUsage;
|
|
103
141
|
const inputTokens = usage.inputTokens ?? 0;
|
|
104
142
|
const outputTokens = usage.outputTokens ?? 0;
|
|
@@ -132,4 +170,4 @@ export async function stopSmartpdf() {
|
|
|
132
170
|
}
|
|
133
171
|
await instance.stop();
|
|
134
172
|
}
|
|
135
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
173
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19kb2N1bWVudC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQU14QywrR0FBK0c7QUFDL0csSUFBSSxhQUFhLEdBQThCLElBQUksQ0FBQztBQUVwRCxTQUFTLGNBQWM7SUFDckIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ25CLE1BQU0sUUFBUSxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNqRCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3BELGFBQWEsR0FBRyxLQUFLLENBQUM7UUFDdEIsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUU7WUFDZixJQUFJLGFBQWEsS0FBSyxLQUFLLEVBQUUsQ0FBQztnQkFDNUIsYUFBYSxHQUFHLElBQUksQ0FBQztZQUN2QixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBQ0QsT0FBTyxhQUFhLENBQUM7QUFDdkIsQ0FBQztBQWlFRCxvR0FBb0c7QUFDcEcsTUFBTSxPQUFPLHNCQUF1QixTQUFRLEtBQUs7SUFDL0MsMEdBQTBHO0lBQzFGLGFBQWEsQ0FBUztJQUN0QixRQUFRLENBQVM7SUFFakMsWUFBWSxPQUF1QztRQUNqRCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsYUFBYSxLQUFLLENBQUM7WUFDekMsQ0FBQyxDQUFDLG9CQUFvQixPQUFPLENBQUMsYUFBYSxRQUFRO1lBQ25ELENBQUMsQ0FBQyxPQUFPLENBQUMsb0JBQW9CO2dCQUM1QixDQUFDLENBQUMsc0JBQXNCLE9BQU8sQ0FBQyxhQUFhLFFBQVE7Z0JBQ3JELENBQUMsQ0FBQywrQkFBK0IsT0FBTyxDQUFDLGFBQWEsUUFBUSxDQUFD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
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import { generateText } from 'ai';
|
|
1
|
+
import { generateText, wrapLanguageModel } from 'ai';
|
|
2
2
|
import * as smartpdf from '@push.rocks/smartpdf';
|
|
3
|
-
|
|
3
|
+
import { AgentModelCallUsageRecorder } from '@modelprofile.com/flexharness-agent';
|
|
4
|
+
export { generateText, wrapLanguageModel, smartpdf, AgentModelCallUsageRecorder };
|
|
5
|
+
export type { TAgentModelCallUsageReporter } from '@modelprofile.com/flexharness-agent';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { generateText } from 'ai';
|
|
1
|
+
import { generateText, wrapLanguageModel } from 'ai';
|
|
2
2
|
import * as smartpdf from '@push.rocks/smartpdf';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { AgentModelCallUsageRecorder } from '@modelprofile.com/flexharness-agent';
|
|
4
|
+
export { generateText, wrapLanguageModel, smartpdf, AgentModelCallUsageRecorder };
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX2RvY3VtZW50L3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxpQkFBaUIsRUFBRSxNQUFNLElBQUksQ0FBQztBQUNyRCxPQUFPLEtBQUssUUFBUSxNQUFNLHNCQUFzQixDQUFDO0FBQ2pELE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ2xGLE9BQU8sRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsUUFBUSxFQUFFLDJCQUEyQixFQUFFLENBQUMifQ==
|
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.5.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.5.0",
|
|
66
|
+
"@modelprofile.com/flexharness-models": "8.5.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
package/ts_document/index.ts
CHANGED
|
@@ -36,6 +36,14 @@ export interface IDocumentRequestOptions {
|
|
|
36
36
|
* exceeded the limit are not rendered.
|
|
37
37
|
*/
|
|
38
38
|
maxPages?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Called once for every model call of the request, as soon as its usage is known, whatever the
|
|
41
|
+
* request's outcome: `reported` with the provider's usage, or `unreported` with the reason when
|
|
42
|
+
* the call failed, was aborted or its response carried no usage. A retried attempt is a call of
|
|
43
|
+
* its own. Nothing is reported for a request that ends before its model is called. When a request
|
|
44
|
+
* returns, its reported calls sum to its `usage`. Must not throw.
|
|
45
|
+
*/
|
|
46
|
+
onUsage?: plugins.TAgentModelCallUsageReporter;
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
export interface IDocumentOptions extends IDocumentRequestOptions {
|
|
@@ -120,6 +128,7 @@ export async function extractTextFromPdfWithUsage(
|
|
|
120
128
|
providerOptions: options.providerOptions,
|
|
121
129
|
abortSignal: options.abortSignal,
|
|
122
130
|
maxPages: options.maxPages,
|
|
131
|
+
onUsage: options.onUsage,
|
|
123
132
|
});
|
|
124
133
|
}
|
|
125
134
|
|
|
@@ -156,26 +165,61 @@ export async function analyzeDocumentsWithUsage(options: IDocumentOptions): Prom
|
|
|
156
165
|
// Filter out empty buffers
|
|
157
166
|
const validPages = imagePages.filter(page => page && page.length > 0);
|
|
158
167
|
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
{
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
168
|
+
const onUsage = options.onUsage;
|
|
169
|
+
const modelCalls = onUsage ? new plugins.AgentModelCallUsageRecorder(options.model, onUsage) : null;
|
|
170
|
+
// Each attempt, retries included, is one model call: it starts in the middleware, which also
|
|
171
|
+
// settles an attempt that throws; a call whose response arrives ends in onLanguageModelCallEnd.
|
|
172
|
+
const model = modelCalls
|
|
173
|
+
? plugins.wrapLanguageModel({
|
|
174
|
+
model: options.model,
|
|
175
|
+
middleware: {
|
|
176
|
+
wrapGenerate: async ({ doGenerate, params }) => {
|
|
177
|
+
modelCalls.start();
|
|
178
|
+
try {
|
|
179
|
+
return await doGenerate();
|
|
180
|
+
} catch (error) {
|
|
181
|
+
modelCalls.settle(params.abortSignal?.aborted ? 'aborted' : 'failed');
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
})
|
|
187
|
+
: options.model;
|
|
188
|
+
const messages: ModelMessage[] = [
|
|
189
|
+
...(options.messageHistory ?? []),
|
|
190
|
+
{
|
|
191
|
+
role: 'user',
|
|
192
|
+
content: [
|
|
193
|
+
{ type: 'text', text: options.userMessage },
|
|
194
|
+
...validPages.map(page => ({
|
|
195
|
+
type: 'file' as const,
|
|
196
|
+
data: page,
|
|
197
|
+
mediaType: 'image/png' as const,
|
|
198
|
+
})),
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
let result: Awaited<ReturnType<typeof plugins.generateText>>;
|
|
203
|
+
try {
|
|
204
|
+
result = await plugins.generateText({
|
|
205
|
+
model,
|
|
206
|
+
instructions: options.systemMessage,
|
|
207
|
+
messages,
|
|
208
|
+
providerOptions: options.providerOptions,
|
|
209
|
+
abortSignal,
|
|
210
|
+
...(modelCalls
|
|
211
|
+
? {
|
|
212
|
+
onLanguageModelCallEnd: ({ modelId, usage: callUsage }) => {
|
|
213
|
+
modelCalls.end(modelId, callUsage);
|
|
214
|
+
},
|
|
215
|
+
}
|
|
216
|
+
: {}),
|
|
217
|
+
});
|
|
218
|
+
modelCalls?.settle('missing');
|
|
219
|
+
} catch (error) {
|
|
220
|
+
modelCalls?.settle(abortSignal?.aborted ? 'aborted' : 'failed');
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
179
223
|
const usage = result.totalUsage;
|
|
180
224
|
const inputTokens = usage.inputTokens ?? 0;
|
|
181
225
|
const outputTokens = usage.outputTokens ?? 0;
|
package/ts_document/plugins.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import { generateText } from 'ai';
|
|
1
|
+
import { generateText, wrapLanguageModel } from 'ai';
|
|
2
2
|
import * as smartpdf from '@push.rocks/smartpdf';
|
|
3
|
-
|
|
3
|
+
import { AgentModelCallUsageRecorder } from '@modelprofile.com/flexharness-agent';
|
|
4
|
+
export { generateText, wrapLanguageModel, smartpdf, AgentModelCallUsageRecorder };
|
|
5
|
+
export type { TAgentModelCallUsageReporter } from '@modelprofile.com/flexharness-agent';
|
package/ts_document/readme.md
CHANGED
|
@@ -23,11 +23,12 @@ Supply a model from your selected FlexHarness provider. `extractTextFromPdf` rep
|
|
|
23
23
|
|
|
24
24
|
`analyzeDocuments({ model, userMessage, pdfDocuments, systemMessage?, messageHistory? })` supports general analysis across multiple PDFs. This component owns a shared SmartPDF instance; call `stopSmartpdf()` when all document work has finished. Image-only OCR is available independently in `flexharness/ocr`.
|
|
25
25
|
|
|
26
|
-
Both functions accept
|
|
26
|
+
Both functions accept four request options:
|
|
27
27
|
|
|
28
28
|
- `providerOptions` is passed to the model call unchanged, for example `{ openai: { store: false } }` so the provider does not keep the request as application state.
|
|
29
29
|
- `abortSignal` is checked before each document is rendered and before the model call, and is passed to the model call. SmartPDF cannot stop a document it is already rendering, so that render finishes first.
|
|
30
30
|
- `maxPages` is the most rendered pages one request may send to the model. A request with more pages rejects with `DocumentPageLimitError` (`renderedPages`, `maxPages`) before the model is called, and documents after the one that exceeded the limit are not rendered.
|
|
31
|
+
- `onUsage` receives the usage of each model call of the request, also of a request that fails or is aborted; see [Usage of a request that fails or is aborted](#usage-of-a-request-that-fails-or-is-aborted).
|
|
31
32
|
|
|
32
33
|
`extractTextFromPdfWithUsage` and `analyzeDocumentsWithUsage` take the same arguments and return `{ text, usage, pageCount }`. `usage` has the shape of an agent run's usage (`inputTokens`, `outputTokens`, `totalTokens`, `cacheReadTokens`, `cacheWriteTokens`), summed over the request's model steps, with usage the provider leaves out counted as zero; `pageCount` is the number of rendered pages sent to the model.
|
|
33
34
|
|
|
@@ -49,6 +50,28 @@ try {
|
|
|
49
50
|
}
|
|
50
51
|
```
|
|
51
52
|
|
|
53
|
+
### Usage of a request that fails or is aborted
|
|
54
|
+
|
|
55
|
+
A request that throws returns no `usage`. `onUsage` reports each model call of a request once, as soon as its usage is known, whatever the outcome, with the events of `AgentModelCallUsageRecorder` (the type is `TFlexModelCallUsage` from `@modelprofile.com/flexharness`):
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import type { TFlexModelCallUsage } from '@modelprofile.com/flexharness';
|
|
59
|
+
|
|
60
|
+
const calls: TFlexModelCallUsage[] = [];
|
|
61
|
+
try {
|
|
62
|
+
await extractTextFromPdfWithUsage(pdfBytes, { model, abortSignal, onUsage: (call) => calls.push(call) });
|
|
63
|
+
} finally {
|
|
64
|
+
const reported = calls.filter((call) => call.status === 'reported');
|
|
65
|
+
const complete = reported.length === calls.length; // an unreported call used an unknown number of tokens
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- `status: 'reported'`: the provider reported the call's `usage`; `requestedModelId` is the model's id and `responseModelId` the id the response named.
|
|
70
|
+
- `status: 'unreported'`: the call `failed`, was `aborted`, or its response carried no usage (`missing`). The provider may still have consumed tokens for it.
|
|
71
|
+
- Every attempt is a call of its own: a call retried after a failure reports the failed attempt and the retry.
|
|
72
|
+
- A request that ends before its model is called (an abort during rendering, `DocumentPageLimitError`) reports nothing.
|
|
73
|
+
- When a request returns, its reported calls sum to its `usage`; count one or the other. `onUsage` must not throw.
|
|
74
|
+
|
|
52
75
|
## Issue Reporting and Security
|
|
53
76
|
|
|
54
77
|
Report issues and security concerns through [community.foss.global](https://community.foss.global).
|