@intelligo-dev/mastra 1.0.0-beta.1 → 1.0.0-beta.14
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/NOTICE +6 -0
- package/README.md +68 -0
- package/dist/index.d.ts +12 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -26
- package/dist/index.js.map +1 -1
- package/package.json +33 -10
- package/src/index.ts +202 -0
package/NOTICE
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
Intelligo
|
|
2
|
+
Copyright 2026 Turtuvshin Byambaa and the Intelligo contributors
|
|
3
|
+
|
|
4
|
+
This product is licensed under the Apache License, Version 2.0 (see
|
|
5
|
+
LICENSE). The Intelligo name and logo are trademarks; see TRADEMARK.md
|
|
6
|
+
in the source repository, https://github.com/intelligo-dev/intelligo.
|
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @intelligo-dev/mastra
|
|
2
|
+
|
|
3
|
+
An optional bridge from a native Mastra agent to the execution boundary.
|
|
4
|
+
|
|
5
|
+
Part of [Intelligo](https://intelligo.dev), an application framework and
|
|
6
|
+
operational platform for vertical AI SaaS products. Every `@intelligo-dev/*`
|
|
7
|
+
package is released at one version and shares one database schema;
|
|
8
|
+
`pnpm dlx @intelligo-dev/cli@beta create my-app` installs the set an
|
|
9
|
+
application needs. Documentation:
|
|
10
|
+
[intelligo.dev/docs/packages/mastra](https://intelligo.dev/docs/packages/mastra).
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @intelligo-dev/mastra@beta
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`@mastra/core` 1.x is an optional peer dependency and **nothing here imports
|
|
19
|
+
it** — the agent is typed structurally, so the bridge stays removable and the
|
|
20
|
+
agent stays native. What this package adds is the recording.
|
|
21
|
+
|
|
22
|
+
## Use
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { runWithExecution } from "@intelligo-dev/mastra";
|
|
26
|
+
import { executions } from "@/lib/intelligo";
|
|
27
|
+
|
|
28
|
+
const result = await runWithExecution(
|
|
29
|
+
{ executions, workspaceId, userId, capability: "support.reply" },
|
|
30
|
+
() => supportAgent.generate(messages) // native Mastra, untouched
|
|
31
|
+
);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`runWithExecution` opens an execution, runs the agent and settles what it
|
|
35
|
+
cost, reading usage and the model from whatever shape the provider reported.
|
|
36
|
+
`executions` is the instance the composition root builds with
|
|
37
|
+
`createExecutions` from
|
|
38
|
+
[`@intelligo-dev/executions`](https://www.npmjs.com/package/@intelligo-dev/executions);
|
|
39
|
+
naming the `model` sizes the credit hold admission takes.
|
|
40
|
+
|
|
41
|
+
When entitlement refuses, it throws an `ExecutionRefusedError` carrying the
|
|
42
|
+
`executionId` and the port's `reasonCode`, so a refusal cannot be mistaken for
|
|
43
|
+
an empty result. An error from the run itself is recorded, the hold is
|
|
44
|
+
released, and the error is rethrown unchanged — the caller still sees Mastra's
|
|
45
|
+
own.
|
|
46
|
+
|
|
47
|
+
## Streaming
|
|
48
|
+
|
|
49
|
+
A stream's usage is known only once it ends, so `streamWithExecution` returns
|
|
50
|
+
the native stream at once, with the two ways a stream finishes:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { streamWithExecution } from "@intelligo-dev/mastra";
|
|
54
|
+
|
|
55
|
+
const { stream, settle, abort } = await streamWithExecution(
|
|
56
|
+
{ executions, workspaceId, userId, capability: "support.reply" },
|
|
57
|
+
() => supportAgent.stream(messages)
|
|
58
|
+
);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`settle(result?)` records usage when the stream finishes; `abort(error?)` is
|
|
62
|
+
for a client disconnect or a timeout. Both are idempotent through the
|
|
63
|
+
execution, so a route can wire every one of its finish, error and abort hooks
|
|
64
|
+
without racing itself.
|
|
65
|
+
|
|
66
|
+
## Licence
|
|
67
|
+
|
|
68
|
+
Apache-2.0
|
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* the
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* IntelligoAgent, no re-declared tool or workflow type, no normalized
|
|
7
|
-
* result. Mastra's own types flow through untouched, and removing this
|
|
8
|
-
* package costs you the accounting, not the AI (ADR-0003).
|
|
9
|
-
*
|
|
10
|
-
* What it does is one repetitive, easy-to-get-wrong thing: open an
|
|
11
|
-
* execution, run the agent, settle usage from whatever shape the
|
|
12
|
-
* provider reported, and make sure a thrown error still releases the
|
|
13
|
-
* hold. Written by hand at every call site, the failure mode is a
|
|
14
|
-
* missing `run.fail()` in a catch block and a credit hold that only
|
|
15
|
-
* expires ten minutes later.
|
|
16
|
-
*
|
|
17
|
-
* `@mastra/core` is an OPTIONAL PEER DEPENDENCY. Nothing here imports
|
|
18
|
-
* it — the agent arrives as an argument, described by the narrowest
|
|
19
|
-
* structural type that makes the call work. That keeps the package
|
|
20
|
-
* installable without Mastra, usable with any Mastra version whose
|
|
21
|
-
* agents expose `generate`/`stream`, and equally usable with an AI SDK
|
|
22
|
-
* or Eve call that happens to fit the same shape.
|
|
2
|
+
* Runs a native agent call inside an execution: opens it, settles usage from
|
|
3
|
+
* whatever shape the provider reported, and releases the credit hold when the
|
|
4
|
+
* run throws. Mastra's types pass through untouched; `@mastra/core` is an
|
|
5
|
+
* optional peer and is never imported — the agent is typed structurally.
|
|
23
6
|
*/
|
|
24
7
|
import type { Executions } from "@intelligo-dev/executions";
|
|
25
8
|
/**
|
|
@@ -69,7 +52,7 @@ export type RunWithExecutionOptions = {
|
|
|
69
52
|
executions: Executions;
|
|
70
53
|
workspaceId: string;
|
|
71
54
|
userId?: string | null;
|
|
72
|
-
/** Product-defined verb, e.g. "
|
|
55
|
+
/** Product-defined verb, e.g. "support.reply". */
|
|
73
56
|
capability: string;
|
|
74
57
|
/** Model the run intends to use — sizes the credit hold. */
|
|
75
58
|
model?: string;
|
|
@@ -78,16 +61,20 @@ export type RunWithExecutionOptions = {
|
|
|
78
61
|
};
|
|
79
62
|
export declare class ExecutionRefusedError extends Error {
|
|
80
63
|
readonly executionId: string;
|
|
64
|
+
/** The entitlement port's stable refusal code, when it gave one. */
|
|
65
|
+
readonly reasonCode?: string | undefined;
|
|
81
66
|
readonly code = "EXECUTION_REFUSED";
|
|
82
|
-
constructor(message: string, executionId: string
|
|
67
|
+
constructor(message: string, executionId: string,
|
|
68
|
+
/** The entitlement port's stable refusal code, when it gave one. */
|
|
69
|
+
reasonCode?: string | undefined);
|
|
83
70
|
}
|
|
84
71
|
/**
|
|
85
72
|
* Run a native call inside an execution.
|
|
86
73
|
*
|
|
87
74
|
* ```ts
|
|
88
75
|
* const result = await runWithExecution(
|
|
89
|
-
* { executions, workspaceId, userId, capability: "
|
|
90
|
-
* () =>
|
|
76
|
+
* { executions, workspaceId, userId, capability: "support.reply" },
|
|
77
|
+
* () => supportAgent.generate(messages) // native Mastra, untouched
|
|
91
78
|
* );
|
|
92
79
|
* ```
|
|
93
80
|
*
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS;;;;EASzD;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CACvB,MAAM,EAAE,YAAY,GAAG,SAAS,GAC/B,MAAM,GAAG,SAAS,CAKpB;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,CAAC;AAEF,qBAAa,qBAAsB,SAAQ,KAAK;IAI5C,QAAQ,CAAC,WAAW,EAAE,MAAM;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM;IAL9B,QAAQ,CAAC,IAAI,uBAAuB;gBAElC,OAAO,EAAE,MAAM,EACN,WAAW,EAAE,MAAM;IAC5B,oEAAoE;IAC3D,UAAU,CAAC,EAAE,MAAM,YAAA;CAK/B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAC3D,OAAO,EAAE,uBAAuB,EAChC,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACpB,OAAO,CAAC,CAAC,CAAC,CAiCZ;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,SAAS,YAAY,EAC9D,OAAO,EAAE,uBAAuB,EAChC,KAAK,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACtB,OAAO,CAAC;IACT,MAAM,EAAE,CAAC,CAAC;IACV,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CAuCD"}
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* the
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* IntelligoAgent, no re-declared tool or workflow type, no normalized
|
|
7
|
-
* result. Mastra's own types flow through untouched, and removing this
|
|
8
|
-
* package costs you the accounting, not the AI (ADR-0003).
|
|
9
|
-
*
|
|
10
|
-
* What it does is one repetitive, easy-to-get-wrong thing: open an
|
|
11
|
-
* execution, run the agent, settle usage from whatever shape the
|
|
12
|
-
* provider reported, and make sure a thrown error still releases the
|
|
13
|
-
* hold. Written by hand at every call site, the failure mode is a
|
|
14
|
-
* missing `run.fail()` in a catch block and a credit hold that only
|
|
15
|
-
* expires ten minutes later.
|
|
16
|
-
*
|
|
17
|
-
* `@mastra/core` is an OPTIONAL PEER DEPENDENCY. Nothing here imports
|
|
18
|
-
* it — the agent arrives as an argument, described by the narrowest
|
|
19
|
-
* structural type that makes the call work. That keeps the package
|
|
20
|
-
* installable without Mastra, usable with any Mastra version whose
|
|
21
|
-
* agents expose `generate`/`stream`, and equally usable with an AI SDK
|
|
22
|
-
* or Eve call that happens to fit the same shape.
|
|
2
|
+
* Runs a native agent call inside an execution: opens it, settles usage from
|
|
3
|
+
* whatever shape the provider reported, and releases the credit hold when the
|
|
4
|
+
* run throws. Mastra's types pass through untouched; `@mastra/core` is an
|
|
5
|
+
* optional peer and is never imported — the agent is typed structurally.
|
|
23
6
|
*/
|
|
24
7
|
/**
|
|
25
8
|
* Normalize the usage shapes providers actually emit.
|
|
@@ -50,9 +33,12 @@ export function readModel(result) {
|
|
|
50
33
|
return undefined;
|
|
51
34
|
}
|
|
52
35
|
export class ExecutionRefusedError extends Error {
|
|
53
|
-
constructor(message, executionId
|
|
36
|
+
constructor(message, executionId,
|
|
37
|
+
/** The entitlement port's stable refusal code, when it gave one. */
|
|
38
|
+
reasonCode) {
|
|
54
39
|
super(message);
|
|
55
40
|
this.executionId = executionId;
|
|
41
|
+
this.reasonCode = reasonCode;
|
|
56
42
|
this.code = "EXECUTION_REFUSED";
|
|
57
43
|
this.name = "ExecutionRefusedError";
|
|
58
44
|
}
|
|
@@ -62,8 +48,8 @@ export class ExecutionRefusedError extends Error {
|
|
|
62
48
|
*
|
|
63
49
|
* ```ts
|
|
64
50
|
* const result = await runWithExecution(
|
|
65
|
-
* { executions, workspaceId, userId, capability: "
|
|
66
|
-
* () =>
|
|
51
|
+
* { executions, workspaceId, userId, capability: "support.reply" },
|
|
52
|
+
* () => supportAgent.generate(messages) // native Mastra, untouched
|
|
67
53
|
* );
|
|
68
54
|
* ```
|
|
69
55
|
*
|
|
@@ -82,7 +68,7 @@ export async function runWithExecution(options, run) {
|
|
|
82
68
|
metadata: options.metadata,
|
|
83
69
|
});
|
|
84
70
|
if (!execution.allowed) {
|
|
85
|
-
throw new ExecutionRefusedError(execution.reason ?? "Execution refused", execution.id);
|
|
71
|
+
throw new ExecutionRefusedError(execution.reason ?? "Execution refused", execution.id, execution.code);
|
|
86
72
|
}
|
|
87
73
|
let result;
|
|
88
74
|
try {
|
|
@@ -118,7 +104,7 @@ export async function streamWithExecution(options, start) {
|
|
|
118
104
|
metadata: options.metadata,
|
|
119
105
|
});
|
|
120
106
|
if (!execution.allowed) {
|
|
121
|
-
throw new ExecutionRefusedError(execution.reason ?? "Execution refused", execution.id);
|
|
107
|
+
throw new ExecutionRefusedError(execution.reason ?? "Execution refused", execution.id, execution.code);
|
|
122
108
|
}
|
|
123
109
|
let stream;
|
|
124
110
|
try {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intelligo-dev/mastra",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.14",
|
|
4
|
+
"description": "An optional bridge from a native Mastra agent to the execution boundary.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"intelligo",
|
|
7
|
+
"ai-saas",
|
|
8
|
+
"saas",
|
|
9
|
+
"typescript",
|
|
10
|
+
"mastra",
|
|
11
|
+
"agents",
|
|
12
|
+
"execution-boundary"
|
|
13
|
+
],
|
|
4
14
|
"license": "Apache-2.0",
|
|
15
|
+
"author": "Turtuvshin Byambaa <toroo.byamba@gmail.com>",
|
|
5
16
|
"repository": {
|
|
6
17
|
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/intelligo-
|
|
18
|
+
"url": "git+https://github.com/intelligo-dev/intelligo.git",
|
|
8
19
|
"directory": "packages/mastra"
|
|
9
20
|
},
|
|
10
|
-
"homepage": "https://
|
|
21
|
+
"homepage": "https://intelligo.dev/docs/packages/mastra",
|
|
11
22
|
"bugs": {
|
|
12
|
-
"url": "https://github.com/intelligo-
|
|
23
|
+
"url": "https://github.com/intelligo-dev/intelligo/issues"
|
|
13
24
|
},
|
|
14
25
|
"type": "module",
|
|
15
26
|
"exports": {
|
|
@@ -19,10 +30,10 @@
|
|
|
19
30
|
}
|
|
20
31
|
},
|
|
21
32
|
"dependencies": {
|
|
22
|
-
"@intelligo-dev/executions": "1.0.0-beta.
|
|
33
|
+
"@intelligo-dev/executions": "1.0.0-beta.14"
|
|
23
34
|
},
|
|
24
35
|
"peerDependencies": {
|
|
25
|
-
"@mastra/core": ">=1.0.0"
|
|
36
|
+
"@mastra/core": ">=1.0.0 <2.0.0"
|
|
26
37
|
},
|
|
27
38
|
"peerDependenciesMeta": {
|
|
28
39
|
"@mastra/core": {
|
|
@@ -30,18 +41,30 @@
|
|
|
30
41
|
}
|
|
31
42
|
},
|
|
32
43
|
"devDependencies": {
|
|
33
|
-
"@types/node": "^
|
|
34
|
-
"typescript": "^5.
|
|
44
|
+
"@types/node": "^26.6.1",
|
|
45
|
+
"typescript": "^5.9.3"
|
|
35
46
|
},
|
|
36
47
|
"files": [
|
|
37
|
-
"dist"
|
|
48
|
+
"dist",
|
|
49
|
+
"src",
|
|
50
|
+
"!src/**/*.test.ts",
|
|
51
|
+
"!src/**/*.test.tsx",
|
|
52
|
+
"!src/**/__tests__/**",
|
|
53
|
+
"LICENSE",
|
|
54
|
+
"NOTICE",
|
|
55
|
+
"README.md",
|
|
56
|
+
"!dist/**/*.tsbuildinfo"
|
|
38
57
|
],
|
|
39
58
|
"publishConfig": {
|
|
40
59
|
"access": "public"
|
|
41
60
|
},
|
|
61
|
+
"engines": {
|
|
62
|
+
"node": ">=22.14"
|
|
63
|
+
},
|
|
64
|
+
"sideEffects": false,
|
|
42
65
|
"scripts": {
|
|
43
66
|
"type-check": "tsc --noEmit",
|
|
44
67
|
"lint": "eslint .",
|
|
45
|
-
"build": "tsc -p tsconfig.build.json"
|
|
68
|
+
"build": "tsc -p tsconfig.build.json && node ../../scripts/fix-esm-extensions.mjs dist"
|
|
46
69
|
}
|
|
47
70
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs a native agent call inside an execution: opens it, settles usage from
|
|
3
|
+
* whatever shape the provider reported, and releases the credit hold when the
|
|
4
|
+
* run throws. Mastra's types pass through untouched; `@mastra/core` is an
|
|
5
|
+
* optional peer and is never imported — the agent is typed structurally.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Executions } from "@intelligo-dev/executions";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The slice of a Mastra result the boundary reads. Deliberately
|
|
12
|
+
* permissive: providers disagree about which usage fields they set,
|
|
13
|
+
* and about whether they nest usage under `usage` at all.
|
|
14
|
+
*/
|
|
15
|
+
export type NativeUsage = {
|
|
16
|
+
inputTokens?: number;
|
|
17
|
+
outputTokens?: number;
|
|
18
|
+
totalTokens?: number;
|
|
19
|
+
/** Older/other providers' spellings. */
|
|
20
|
+
promptTokens?: number;
|
|
21
|
+
completionTokens?: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type NativeResult = {
|
|
25
|
+
usage?: NativeUsage;
|
|
26
|
+
/**
|
|
27
|
+
* Usage across every step of a multi-step run. Mastra sets both, and
|
|
28
|
+
* `usage` holds only the LAST step — so a tool loop that made five
|
|
29
|
+
* model calls reports the fifth. Anything that reads `usage` alone
|
|
30
|
+
* under-bills every agentic run it settles.
|
|
31
|
+
*/
|
|
32
|
+
totalUsage?: NativeUsage;
|
|
33
|
+
model?: string | { modelId?: string };
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Normalize the usage shapes providers actually emit.
|
|
39
|
+
*
|
|
40
|
+
* Prefers `totalUsage` — the whole run — and falls back to `usage` for
|
|
41
|
+
* results that report one call and nothing else. Returns zeros when
|
|
42
|
+
* nothing was reported; the caller decides whether an unreported turn
|
|
43
|
+
* is free or charged a floor, because that is billing policy, not a
|
|
44
|
+
* property of the run.
|
|
45
|
+
*/
|
|
46
|
+
export function readUsage(result: NativeResult | undefined) {
|
|
47
|
+
const usage = result?.totalUsage ?? result?.usage ?? {};
|
|
48
|
+
const inputTokens = usage.inputTokens ?? usage.promptTokens ?? 0;
|
|
49
|
+
const outputTokens = usage.outputTokens ?? usage.completionTokens ?? 0;
|
|
50
|
+
return {
|
|
51
|
+
inputTokens,
|
|
52
|
+
outputTokens,
|
|
53
|
+
totalTokens: usage.totalTokens ?? inputTokens + outputTokens,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Providers report the model as a string or as an object with modelId. */
|
|
58
|
+
export function readModel(
|
|
59
|
+
result: NativeResult | undefined
|
|
60
|
+
): string | undefined {
|
|
61
|
+
const model = result?.model;
|
|
62
|
+
if (typeof model === "string") return model;
|
|
63
|
+
if (model && typeof model === "object") return model.modelId;
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type RunWithExecutionOptions = {
|
|
68
|
+
executions: Executions;
|
|
69
|
+
workspaceId: string;
|
|
70
|
+
userId?: string | null;
|
|
71
|
+
/** Product-defined verb, e.g. "support.reply". */
|
|
72
|
+
capability: string;
|
|
73
|
+
/** Model the run intends to use — sizes the credit hold. */
|
|
74
|
+
model?: string;
|
|
75
|
+
requestId?: string;
|
|
76
|
+
metadata?: Record<string, unknown>;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export class ExecutionRefusedError extends Error {
|
|
80
|
+
readonly code = "EXECUTION_REFUSED";
|
|
81
|
+
constructor(
|
|
82
|
+
message: string,
|
|
83
|
+
readonly executionId: string,
|
|
84
|
+
/** The entitlement port's stable refusal code, when it gave one. */
|
|
85
|
+
readonly reasonCode?: string
|
|
86
|
+
) {
|
|
87
|
+
super(message);
|
|
88
|
+
this.name = "ExecutionRefusedError";
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Run a native call inside an execution.
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* const result = await runWithExecution(
|
|
97
|
+
* { executions, workspaceId, userId, capability: "support.reply" },
|
|
98
|
+
* () => supportAgent.generate(messages) // native Mastra, untouched
|
|
99
|
+
* );
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* Throws {@link ExecutionRefusedError} when entitlement refuses, so a
|
|
103
|
+
* refusal is impossible to mistake for a successful empty result. Any
|
|
104
|
+
* error from the run itself is recorded and rethrown unchanged — the
|
|
105
|
+
* caller still sees Mastra's own error.
|
|
106
|
+
*/
|
|
107
|
+
export async function runWithExecution<T extends NativeResult>(
|
|
108
|
+
options: RunWithExecutionOptions,
|
|
109
|
+
run: () => Promise<T>
|
|
110
|
+
): Promise<T> {
|
|
111
|
+
const execution = await options.executions.begin({
|
|
112
|
+
workspaceId: options.workspaceId,
|
|
113
|
+
userId: options.userId,
|
|
114
|
+
capability: options.capability,
|
|
115
|
+
requestId: options.requestId,
|
|
116
|
+
model: options.model,
|
|
117
|
+
metadata: options.metadata,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (!execution.allowed) {
|
|
121
|
+
throw new ExecutionRefusedError(
|
|
122
|
+
execution.reason ?? "Execution refused",
|
|
123
|
+
execution.id,
|
|
124
|
+
execution.code
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let result: T;
|
|
129
|
+
try {
|
|
130
|
+
result = await run();
|
|
131
|
+
} catch (error) {
|
|
132
|
+
await execution.fail({ error });
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
await execution.complete({
|
|
137
|
+
usage: readUsage(result),
|
|
138
|
+
model: readModel(result) ?? options.model,
|
|
139
|
+
metadata: options.metadata,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Streaming variant. A stream's usage is only known once it finishes,
|
|
147
|
+
* so the caller gets the native stream immediately plus a `settle`
|
|
148
|
+
* callback to invoke when it ends — and an `abort` for the paths where
|
|
149
|
+
* it does not (client disconnect, timeout).
|
|
150
|
+
*
|
|
151
|
+
* Both are idempotent through the execution handle, so a route may
|
|
152
|
+
* wire all of onFinish/onError/onAbort without racing itself.
|
|
153
|
+
*/
|
|
154
|
+
export async function streamWithExecution<T extends NativeResult>(
|
|
155
|
+
options: RunWithExecutionOptions,
|
|
156
|
+
start: () => Promise<T>
|
|
157
|
+
): Promise<{
|
|
158
|
+
stream: T;
|
|
159
|
+
settle: (result?: NativeResult) => Promise<void>;
|
|
160
|
+
abort: (error?: unknown) => Promise<void>;
|
|
161
|
+
executionId: string;
|
|
162
|
+
requestId: string;
|
|
163
|
+
}> {
|
|
164
|
+
const execution = await options.executions.begin({
|
|
165
|
+
workspaceId: options.workspaceId,
|
|
166
|
+
userId: options.userId,
|
|
167
|
+
capability: options.capability,
|
|
168
|
+
requestId: options.requestId,
|
|
169
|
+
model: options.model,
|
|
170
|
+
metadata: options.metadata,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
if (!execution.allowed) {
|
|
174
|
+
throw new ExecutionRefusedError(
|
|
175
|
+
execution.reason ?? "Execution refused",
|
|
176
|
+
execution.id,
|
|
177
|
+
execution.code
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let stream: T;
|
|
182
|
+
try {
|
|
183
|
+
stream = await start();
|
|
184
|
+
} catch (error) {
|
|
185
|
+
await execution.fail({ error });
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
stream,
|
|
191
|
+
executionId: execution.id,
|
|
192
|
+
requestId: execution.requestId,
|
|
193
|
+
settle: (result) =>
|
|
194
|
+
execution.complete({
|
|
195
|
+
usage: readUsage(result ?? stream),
|
|
196
|
+
model: readModel(result ?? stream) ?? options.model,
|
|
197
|
+
metadata: options.metadata,
|
|
198
|
+
}),
|
|
199
|
+
abort: (error) =>
|
|
200
|
+
execution.fail({ error: error ?? new Error("Stream aborted") }),
|
|
201
|
+
};
|
|
202
|
+
}
|