@modelprofile.com/flexharness 10.19.0 → 10.20.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_typedrequest/catalog.d.ts +3 -1
- package/dist_ts_typedrequest/catalog.js +13 -6
- package/dist_ts_typedrequest/interfaces.d.ts +17 -1
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_typedrequest/catalog.ts +12 -5
- package/ts_typedrequest/interfaces.ts +21 -1
- package/ts_typedrequest/readme.md +4 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@modelprofile.com/flexharness',
|
|
6
|
-
version: '10.
|
|
6
|
+
version: '10.20.0',
|
|
7
7
|
description: 'The FlexHarness toolbox source repository and shared dependency catalog.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSwrQkFBK0I7SUFDckMsT0FBTyxFQUFFLFNBQVM7SUFDbEIsV0FBVyxFQUFFLDBFQUEwRTtDQUN4RixDQUFBIn0=
|
|
@@ -23,6 +23,8 @@ export declare class FlexTypedRequestError extends Error {
|
|
|
23
23
|
* The tool catalog of a typedrequest surface: every included method becomes a catalog method of
|
|
24
24
|
* its path, declared as its contract writes it and validated against its schema, and runs through
|
|
25
25
|
* `router.routeAndAddResponse()` in process, its request the model's parameters with the omitted
|
|
26
|
-
* properties `request` fills. A refusal rejects
|
|
26
|
+
* properties `request` fills and its result what `response` makes of the answer. A refusal rejects
|
|
27
|
+
* with `FlexTypedRequestError`. A method `readOnly` marks is declared read-only and not gated by
|
|
28
|
+
* `onCall`.
|
|
27
29
|
*/
|
|
28
30
|
export declare function catalogFromTypedRequests<TScope = unknown>(surface: IFlexTypedRequestSurface, options: IFlexTypedRequestCatalogOptions<TScope>): IFlexToolCatalog<TScope>;
|
|
@@ -25,7 +25,9 @@ export class FlexTypedRequestError extends Error {
|
|
|
25
25
|
* The tool catalog of a typedrequest surface: every included method becomes a catalog method of
|
|
26
26
|
* its path, declared as its contract writes it and validated against its schema, and runs through
|
|
27
27
|
* `router.routeAndAddResponse()` in process, its request the model's parameters with the omitted
|
|
28
|
-
* properties `request` fills. A refusal rejects
|
|
28
|
+
* properties `request` fills and its result what `response` makes of the answer. A refusal rejects
|
|
29
|
+
* with `FlexTypedRequestError`. A method `readOnly` marks is declared read-only and not gated by
|
|
30
|
+
* `onCall`.
|
|
29
31
|
*/
|
|
30
32
|
export function catalogFromTypedRequests(surface, options) {
|
|
31
33
|
if (typeof options?.router?.routeAndAddResponse !== 'function') {
|
|
@@ -41,6 +43,7 @@ export function catalogFromTypedRequests(surface, options) {
|
|
|
41
43
|
throw new plugins.FlexHarnessValidationError(`The surface leaves ${surface.omit.join(', ')} out of every request; the options' request() must fill them.`);
|
|
42
44
|
}
|
|
43
45
|
const include = options.include ?? ((method) => !method.deprecated);
|
|
46
|
+
const readOnly = options.readOnly ?? (() => false);
|
|
44
47
|
const { router } = options;
|
|
45
48
|
const call = async (method, params, context) => {
|
|
46
49
|
const filled = options.request ? await options.request(method, context) : {};
|
|
@@ -55,7 +58,9 @@ export function catalogFromTypedRequests(surface, options) {
|
|
|
55
58
|
throw new FlexTypedRequestError(method.method, 'The router answered nothing.');
|
|
56
59
|
if (answer.error)
|
|
57
60
|
throw new FlexTypedRequestError(method.method, answer.error.text, answer.error.data);
|
|
58
|
-
return
|
|
61
|
+
return options.response
|
|
62
|
+
? await options.response(method, answer.response, context)
|
|
63
|
+
: answer.response;
|
|
59
64
|
};
|
|
60
65
|
return {
|
|
61
66
|
methods: surface.methods.filter((method) => include(method)).map((method) => ({
|
|
@@ -67,13 +72,15 @@ export function catalogFromTypedRequests(surface, options) {
|
|
|
67
72
|
outputSchema: method.outputSchema,
|
|
68
73
|
declaration: method.declaration,
|
|
69
74
|
run: (params, context) => call(method, params, context),
|
|
70
|
-
...(
|
|
71
|
-
? {
|
|
72
|
-
:
|
|
75
|
+
...(readOnly(method)
|
|
76
|
+
? { readOnly: true }
|
|
77
|
+
: options.onCall
|
|
78
|
+
? { onCall: (params, context) => options.onCall(method, params, context) }
|
|
79
|
+
: {}),
|
|
73
80
|
})),
|
|
74
81
|
types: surface.types,
|
|
75
82
|
...(options.vocabulary ? { vocabulary: options.vocabulary } : {}),
|
|
76
83
|
...(options.onProposals ? { onProposals: options.onProposals } : {}),
|
|
77
84
|
};
|
|
78
85
|
}
|
|
79
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
86
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2F0YWxvZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3R5cGVkcmVxdWVzdC9jYXRhbG9nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBUXhDOzs7R0FHRztBQUNILE1BQU0sT0FBTyxxQkFBc0IsU0FBUSxLQUFLO0lBRzVCO0lBRUE7SUFFQTtJQU5sQjtJQUNFLHNDQUFzQztJQUN0QixNQUFjO0lBQzlCLGtFQUFrRTtJQUNsRCxJQUFZO0lBQzVCLHdCQUF3QjtJQUNSLElBQWM7UUFFOUIsS0FBSyxDQUFDLEdBQUcsTUFBTSxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztRQU54QixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBRWQsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUVaLFNBQUksR0FBSixJQUFJLENBQVU7UUFHOUIsSUFBSSxDQUFDLElBQUksR0FBRyx1QkFBdUIsQ0FBQztJQUN0QyxDQUFDO0NBQ0Y7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLHdCQUF3QixDQUN0QyxPQUFpQyxFQUNqQyxPQUFnRDtJQUVoRCxJQUFJLE9BQU8sT0FBTyxFQUFFLE1BQU0sRUFBRSxtQkFBbUIsS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUMvRCxNQUFNLElBQUksT0FBTyxDQUFDLDBCQUEwQixDQUFDLHFFQUFxRSxDQUFDLENBQUM7SUFDdEgsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDO0lBQ3RDLE1BQU0sS0FBSyxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUN0RSxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxD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QUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBOEIsRUFBRSxDQUFDLENBQUM7WUFDeEcsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJO1lBQ25CLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztZQUN2QixHQUFHLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDbEUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3RFLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVztZQUMvQixZQUFZLEVBQUUsTUFBTSxDQUFDLFlBQVk7WUFDakMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO1lBQy9CLEdBQUcsRUFBRSxDQUFDLE1BQStCLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUM7WUFDaEYsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7Z0JBQ2xCLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Z0JBQ3BCLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTTtvQkFDZCxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxNQUErQixFQUFFLE9BQXVDLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFPLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsRUFBRTtvQkFDcEksQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUNWLENBQUMsQ0FBQztRQUNILEtBQUssRUFBRSxPQUFPLENBQUMsS0FBSztRQUNwQixHQUFHLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDakUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQ3JFLENBQUM7QUFDSixDQUFDIn0=
|
|
@@ -96,11 +96,27 @@ export interface IFlexTypedRequestCatalogOptions<TScope = unknown> {
|
|
|
96
96
|
localData?(method: IFlexTypedRequestMethod, context: IFlexCatalogRunContext<TScope>): Record<string, unknown> | PromiseLike<Record<string, unknown>>;
|
|
97
97
|
/** The methods the model may use. Default: every method that is not deprecated. */
|
|
98
98
|
include?(method: IFlexTypedRequestMethod): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* The methods that only read: a call has no effect but its result. Such a method is declared
|
|
101
|
+
* `readOnly` and `onCall` does not decide its calls, so they run concurrently with other reads, may
|
|
102
|
+
* start while the model still streams its response, and a turn answers identical ones once; see
|
|
103
|
+
* `IFlexCatalogMethod.readOnly`. Default: none.
|
|
104
|
+
*/
|
|
105
|
+
readOnly?(method: IFlexTypedRequestMethod): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* What the model sees of a method's answered response, such as the response without a
|
|
108
|
+
* credential's secret. Default: the response. A refusal does not reach it, and the method's
|
|
109
|
+
* declaration still shows the contract's response.
|
|
110
|
+
*/
|
|
111
|
+
response?(method: IFlexTypedRequestMethod, response: Record<string, unknown>, context: IFlexCatalogRunContext<TScope>): unknown;
|
|
99
112
|
/** Other names of methods, by typed method: `{ getVoucher: ['Beleg abrufen'] }`. */
|
|
100
113
|
aliases?: Readonly<Record<string, readonly string[]>>;
|
|
101
114
|
/** The words the API's users say for its own words; see `IFlexToolCatalog.vocabulary`. */
|
|
102
115
|
vocabulary?: IFlexToolCatalog['vocabulary'];
|
|
103
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* Decides each validated call of a method `readOnly` does not mark before it runs; see
|
|
118
|
+
* `IFlexCatalogMethod.onCall`.
|
|
119
|
+
*/
|
|
104
120
|
onCall?(method: IFlexTypedRequestMethod, params: Record<string, unknown>, context: IFlexCatalogRunContext<TScope>): TFlexCatalogCallDecision | PromiseLike<TFlexCatalogCallDecision>;
|
|
105
121
|
/** Receives the calls `onCall` proposed; see `IFlexToolCatalog.onProposals`. */
|
|
106
122
|
onProposals?: IFlexToolCatalog<TScope>['onProposals'];
|
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": "10.
|
|
5
|
+
"version": "10.20.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",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
89
|
"@cfworker/json-schema": "^4.1.1",
|
|
90
|
-
"@modelprofile.com/flexharness-agent": "10.
|
|
91
|
-
"@modelprofile.com/flexharness-models": "10.
|
|
90
|
+
"@modelprofile.com/flexharness-agent": "10.20.0",
|
|
91
|
+
"@modelprofile.com/flexharness-models": "10.20.0",
|
|
92
92
|
"@push.rocks/smartrequest": "^5.5.1",
|
|
93
93
|
"ai": "^7.0.111",
|
|
94
94
|
"zod": "^4.6.5"
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -28,7 +28,9 @@ export class FlexTypedRequestError extends Error {
|
|
|
28
28
|
* The tool catalog of a typedrequest surface: every included method becomes a catalog method of
|
|
29
29
|
* its path, declared as its contract writes it and validated against its schema, and runs through
|
|
30
30
|
* `router.routeAndAddResponse()` in process, its request the model's parameters with the omitted
|
|
31
|
-
* properties `request` fills. A refusal rejects
|
|
31
|
+
* properties `request` fills and its result what `response` makes of the answer. A refusal rejects
|
|
32
|
+
* with `FlexTypedRequestError`. A method `readOnly` marks is declared read-only and not gated by
|
|
33
|
+
* `onCall`.
|
|
32
34
|
*/
|
|
33
35
|
export function catalogFromTypedRequests<TScope = unknown>(
|
|
34
36
|
surface: IFlexTypedRequestSurface,
|
|
@@ -49,6 +51,7 @@ export function catalogFromTypedRequests<TScope = unknown>(
|
|
|
49
51
|
);
|
|
50
52
|
}
|
|
51
53
|
const include = options.include ?? ((method: IFlexTypedRequestMethod) => !method.deprecated);
|
|
54
|
+
const readOnly = options.readOnly ?? (() => false);
|
|
52
55
|
const { router } = options;
|
|
53
56
|
const call = async (
|
|
54
57
|
method: IFlexTypedRequestMethod,
|
|
@@ -68,7 +71,9 @@ export function catalogFromTypedRequests<TScope = unknown>(
|
|
|
68
71
|
);
|
|
69
72
|
if (!answer) throw new FlexTypedRequestError(method.method, 'The router answered nothing.');
|
|
70
73
|
if (answer.error) throw new FlexTypedRequestError(method.method, answer.error.text, answer.error.data);
|
|
71
|
-
return
|
|
74
|
+
return options.response
|
|
75
|
+
? await options.response(method, answer.response as Record<string, unknown>, context)
|
|
76
|
+
: answer.response;
|
|
72
77
|
};
|
|
73
78
|
return {
|
|
74
79
|
methods: surface.methods.filter((method) => include(method)).map((method): IFlexCatalogMethod<TScope> => ({
|
|
@@ -80,9 +85,11 @@ export function catalogFromTypedRequests<TScope = unknown>(
|
|
|
80
85
|
outputSchema: method.outputSchema,
|
|
81
86
|
declaration: method.declaration,
|
|
82
87
|
run: (params: Record<string, unknown>, context) => call(method, params, context),
|
|
83
|
-
...(
|
|
84
|
-
? {
|
|
85
|
-
:
|
|
88
|
+
...(readOnly(method)
|
|
89
|
+
? { readOnly: true }
|
|
90
|
+
: options.onCall
|
|
91
|
+
? { onCall: (params: Record<string, unknown>, context: IFlexCatalogRunContext<TScope>) => options.onCall!(method, params, context) }
|
|
92
|
+
: {}),
|
|
86
93
|
})),
|
|
87
94
|
types: surface.types,
|
|
88
95
|
...(options.vocabulary ? { vocabulary: options.vocabulary } : {}),
|
|
@@ -109,11 +109,31 @@ export interface IFlexTypedRequestCatalogOptions<TScope = unknown> {
|
|
|
109
109
|
): Record<string, unknown> | PromiseLike<Record<string, unknown>>;
|
|
110
110
|
/** The methods the model may use. Default: every method that is not deprecated. */
|
|
111
111
|
include?(method: IFlexTypedRequestMethod): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* The methods that only read: a call has no effect but its result. Such a method is declared
|
|
114
|
+
* `readOnly` and `onCall` does not decide its calls, so they run concurrently with other reads, may
|
|
115
|
+
* start while the model still streams its response, and a turn answers identical ones once; see
|
|
116
|
+
* `IFlexCatalogMethod.readOnly`. Default: none.
|
|
117
|
+
*/
|
|
118
|
+
readOnly?(method: IFlexTypedRequestMethod): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* What the model sees of a method's answered response, such as the response without a
|
|
121
|
+
* credential's secret. Default: the response. A refusal does not reach it, and the method's
|
|
122
|
+
* declaration still shows the contract's response.
|
|
123
|
+
*/
|
|
124
|
+
response?(
|
|
125
|
+
method: IFlexTypedRequestMethod,
|
|
126
|
+
response: Record<string, unknown>,
|
|
127
|
+
context: IFlexCatalogRunContext<TScope>,
|
|
128
|
+
): unknown;
|
|
112
129
|
/** Other names of methods, by typed method: `{ getVoucher: ['Beleg abrufen'] }`. */
|
|
113
130
|
aliases?: Readonly<Record<string, readonly string[]>>;
|
|
114
131
|
/** The words the API's users say for its own words; see `IFlexToolCatalog.vocabulary`. */
|
|
115
132
|
vocabulary?: IFlexToolCatalog['vocabulary'];
|
|
116
|
-
/**
|
|
133
|
+
/**
|
|
134
|
+
* Decides each validated call of a method `readOnly` does not mark before it runs; see
|
|
135
|
+
* `IFlexCatalogMethod.onCall`.
|
|
136
|
+
*/
|
|
117
137
|
onCall?(
|
|
118
138
|
method: IFlexTypedRequestMethod,
|
|
119
139
|
params: Record<string, unknown>,
|
|
@@ -19,7 +19,8 @@ const surface = await describeTypedRequests({
|
|
|
19
19
|
const catalog = catalogFromTypedRequests<IAppScope>(surface, {
|
|
20
20
|
router: server.typedrouter,
|
|
21
21
|
request: (method, context) => ({ identity: identityOf(context.provider.scope) }),
|
|
22
|
-
|
|
22
|
+
readOnly: (method) => method.method.startsWith('get') || method.method.startsWith('list'),
|
|
23
|
+
onCall: () => 'propose',
|
|
23
24
|
});
|
|
24
25
|
```
|
|
25
26
|
|
|
@@ -38,6 +39,8 @@ The surface is plain JSON, so a build step can write it next to the server and t
|
|
|
38
39
|
- `router` answers the calls: anything with `routeAndAddResponse()`, such as a `TypedRouter` of `@api.global/typedrequest`. A call is routed as a typed request with the model's parameters and what `request` returns for the omitted properties, `localData` as the trusted route data a transport would hand the handlers, and the run's abort signal.
|
|
39
40
|
- A refusal rejects with `FlexTypedRequestError`: the typed method, the error's `text` and `data`, as a client of the API would receive them. A handler's own failure arrives as the router's internal error. A host's `externalErrorProjector` decides what of it the model sees.
|
|
40
41
|
- `include` picks the methods the model may use, by default every method that is not deprecated; `aliases` gives methods other names by typed method; `vocabulary`, `onCall` and `onProposals` are the catalog's own (`onCall` receives the typed method first).
|
|
42
|
+
- `readOnly` marks the methods that only read. A marked method is declared `readOnly` and `onCall` does not decide its calls, so they run concurrently with other reads, may start while the model still streams, and a turn answers identical ones once; every other method's calls, gated by `onCall` or not, run in the order the model made them. Mark nothing that asks for permission.
|
|
43
|
+
- `response` decides what the model sees of an answered response, such as the response without a credential's secret; by default the response itself. A refusal does not reach it, and the method's declaration still shows the contract's response.
|
|
41
44
|
- A surface that omits properties needs `request`; an alias for a method the surface lacks is refused.
|
|
42
45
|
|
|
43
46
|
## Issue Reporting and Security
|