@mastra/code-sdk 1.2.0-alpha.8 → 1.2.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/CHANGELOG.md +237 -0
- package/README.md +22 -0
- package/dist/agents/model.d.ts.map +1 -1
- package/dist/agents/model.js +5 -2
- package/dist/agents/model.js.map +1 -1
- package/dist/agents/modes/build.d.ts.map +1 -1
- package/dist/agents/modes/build.js +6 -1
- package/dist/agents/modes/build.js.map +1 -1
- package/dist/agents/modes/explore.d.ts.map +1 -1
- package/dist/agents/modes/explore.js +4 -1
- package/dist/agents/modes/explore.js.map +1 -1
- package/dist/agents/modes/plan.d.ts.map +1 -1
- package/dist/agents/modes/plan.js +8 -3
- package/dist/agents/modes/plan.js.map +1 -1
- package/dist/agents/prompts/index.d.ts.map +1 -1
- package/dist/agents/prompts/index.js +4 -1
- package/dist/agents/prompts/index.js.map +1 -1
- package/dist/agents/prompts/plan.d.ts +1 -1
- package/dist/agents/prompts/plan.d.ts.map +1 -1
- package/dist/agents/prompts/plan.js +2 -2
- package/dist/agents/prompts/plan.js.map +1 -1
- package/dist/agents/prompts/tool-guidance.d.ts +2 -0
- package/dist/agents/prompts/tool-guidance.d.ts.map +1 -1
- package/dist/agents/prompts/tool-guidance.js +3 -2
- package/dist/agents/prompts/tool-guidance.js.map +1 -1
- package/dist/agents/tool-availability.d.ts.map +1 -1
- package/dist/agents/tool-availability.js +15 -6
- package/dist/agents/tool-availability.js.map +1 -1
- package/dist/agents/tools.d.ts +16 -0
- package/dist/agents/tools.d.ts.map +1 -1
- package/dist/agents/tools.js +16 -3
- package/dist/agents/tools.js.map +1 -1
- package/dist/agents/workflow-builder-agent.d.ts +2 -0
- package/dist/agents/workflow-builder-agent.d.ts.map +1 -0
- package/dist/agents/workflow-builder-agent.js +80 -0
- package/dist/agents/workflow-builder-agent.js.map +1 -0
- package/dist/headless/cli.d.ts.map +1 -1
- package/dist/headless/cli.js +3 -0
- package/dist/headless/cli.js.map +1 -1
- package/dist/hooks/manager.d.ts +9 -2
- package/dist/hooks/manager.d.ts.map +1 -1
- package/dist/hooks/manager.js +19 -3
- package/dist/hooks/manager.js.map +1 -1
- package/dist/hooks/types.d.ts +20 -0
- package/dist/hooks/types.d.ts.map +1 -1
- package/dist/hooks/types.js.map +1 -1
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +204 -69
- package/dist/index.js.map +1 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +6 -1
- package/dist/permissions.js.map +1 -1
- package/dist/plugin.d.ts +64 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +3 -1
- package/dist/plugin.js.map +1 -1
- package/dist/plugins/loader.d.ts +7 -3
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +53 -1
- package/dist/plugins/loader.js.map +1 -1
- package/dist/plugins/manager.d.ts +36 -2
- package/dist/plugins/manager.d.ts.map +1 -1
- package/dist/plugins/manager.js +74 -2
- package/dist/plugins/manager.js.map +1 -1
- package/dist/plugins/signal-lane.d.ts +58 -0
- package/dist/plugins/signal-lane.d.ts.map +1 -0
- package/dist/plugins/signal-lane.js +166 -0
- package/dist/plugins/signal-lane.js.map +1 -0
- package/dist/plugins/types.d.ts +36 -0
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/tools/workflows/create-workflow.d.ts +7 -0
- package/dist/tools/workflows/create-workflow.d.ts.map +1 -0
- package/dist/tools/workflows/create-workflow.js +81 -0
- package/dist/tools/workflows/create-workflow.js.map +1 -0
- package/dist/tools/workflows/delete-workflow.d.ts +7 -0
- package/dist/tools/workflows/delete-workflow.d.ts.map +1 -0
- package/dist/tools/workflows/delete-workflow.js +21 -0
- package/dist/tools/workflows/delete-workflow.js.map +1 -0
- package/dist/tools/workflows/ephemeral-memory.d.ts +7 -0
- package/dist/tools/workflows/ephemeral-memory.d.ts.map +1 -0
- package/dist/tools/workflows/ephemeral-memory.js +45 -0
- package/dist/tools/workflows/ephemeral-memory.js.map +1 -0
- package/dist/tools/workflows/extract-json-schema.d.ts +12 -0
- package/dist/tools/workflows/extract-json-schema.d.ts.map +1 -0
- package/dist/tools/workflows/extract-json-schema.js +22 -0
- package/dist/tools/workflows/extract-json-schema.js.map +1 -0
- package/dist/tools/workflows/get-workflow.d.ts +11 -0
- package/dist/tools/workflows/get-workflow.d.ts.map +1 -0
- package/dist/tools/workflows/get-workflow.js +34 -0
- package/dist/tools/workflows/get-workflow.js.map +1 -0
- package/dist/tools/workflows/list-available-agents.d.ts +8 -0
- package/dist/tools/workflows/list-available-agents.d.ts.map +1 -0
- package/dist/tools/workflows/list-available-agents.js +32 -0
- package/dist/tools/workflows/list-available-agents.js.map +1 -0
- package/dist/tools/workflows/list-available-tools.d.ts +9 -0
- package/dist/tools/workflows/list-available-tools.d.ts.map +1 -0
- package/dist/tools/workflows/list-available-tools.js +40 -0
- package/dist/tools/workflows/list-available-tools.js.map +1 -0
- package/dist/tools/workflows/list-available-workflows.d.ts +9 -0
- package/dist/tools/workflows/list-available-workflows.d.ts.map +1 -0
- package/dist/tools/workflows/list-available-workflows.js +32 -0
- package/dist/tools/workflows/list-available-workflows.js.map +1 -0
- package/dist/tools/workflows/list-workflows.d.ts +9 -0
- package/dist/tools/workflows/list-workflows.d.ts.map +1 -0
- package/dist/tools/workflows/list-workflows.js +33 -0
- package/dist/tools/workflows/list-workflows.js.map +1 -0
- package/dist/tools/workflows/run-workflow.d.ts +9 -0
- package/dist/tools/workflows/run-workflow.d.ts.map +1 -0
- package/dist/tools/workflows/run-workflow.js +52 -0
- package/dist/tools/workflows/run-workflow.js.map +1 -0
- package/dist/tools/workflows/save-workflow.d.ts +369 -0
- package/dist/tools/workflows/save-workflow.d.ts.map +1 -0
- package/dist/tools/workflows/save-workflow.js +28 -0
- package/dist/tools/workflows/save-workflow.js.map +1 -0
- package/dist/tools/workflows/tool-ids.d.ts +15 -0
- package/dist/tools/workflows/tool-ids.d.ts.map +1 -0
- package/dist/tools/workflows/tool-ids.js +19 -0
- package/dist/tools/workflows/tool-ids.js.map +1 -0
- package/dist/utils/plans.d.ts +9 -6
- package/dist/utils/plans.d.ts.map +1 -1
- package/dist/utils/plans.js +11 -11
- package/dist/utils/plans.js.map +1 -1
- package/dist/workflows/register-primitives.d.ts +52 -0
- package/dist/workflows/register-primitives.d.ts.map +1 -0
- package/dist/workflows/register-primitives.js +39 -0
- package/dist/workflows/register-primitives.js.map +1 -0
- package/dist/workflows/service.d.ts +64 -0
- package/dist/workflows/service.d.ts.map +1 -0
- package/dist/workflows/service.js +53 -0
- package/dist/workflows/service.js.map +1 -0
- package/package.json +15 -15
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Agent } from '@mastra/core/agent';
|
|
2
|
+
import type { Mastra } from '@mastra/core/mastra';
|
|
3
|
+
import type { InputProcessorOrWorkflow, OutputProcessorOrWorkflow } from '@mastra/core/processors';
|
|
4
|
+
import type { SignalProvider } from '@mastra/core/signals';
|
|
5
|
+
import type { PluginContribution } from './types.js';
|
|
6
|
+
export type PluginSignalLaneOptions = {
|
|
7
|
+
/**
|
|
8
|
+
* Ids of providers Mastra Code wires itself (through the Agent constructor).
|
|
9
|
+
* The lane refuses to start a provider that collides with one of them:
|
|
10
|
+
* two live instances of the same provider silently clobber each other's
|
|
11
|
+
* polling, and the built-ins are invisible to the lane's own registry.
|
|
12
|
+
*/
|
|
13
|
+
reservedProviderIds?: string[];
|
|
14
|
+
onError?: (message: string, error: unknown) => void;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Owns the lifecycle of signal providers contributed by plugins.
|
|
18
|
+
*
|
|
19
|
+
* Providers are long-lived; processors are per-request. The Agent constructor
|
|
20
|
+
* conflates the two — it harvests a provider's processors into a closure that
|
|
21
|
+
* can never be undone — so plugin providers are deliberately kept out of the
|
|
22
|
+
* `signals` array and driven from here instead, through the same public methods
|
|
23
|
+
* the constructor uses. That is what makes a provider removable when its plugin
|
|
24
|
+
* is disabled, updated or uninstalled.
|
|
25
|
+
*/
|
|
26
|
+
export declare class PluginSignalLane {
|
|
27
|
+
#private;
|
|
28
|
+
constructor(options?: PluginSignalLaneOptions);
|
|
29
|
+
getInputProcessors(): readonly InputProcessorOrWorkflow[];
|
|
30
|
+
getOutputProcessors(): readonly OutputProcessorOrWorkflow[];
|
|
31
|
+
/**
|
|
32
|
+
* Reconciles the live providers against a freshly loaded plugin list.
|
|
33
|
+
*
|
|
34
|
+
* A plugin whose stamp is unchanged keeps the provider instance it already
|
|
35
|
+
* has, and the freshly resolved one is dropped without ever being registered,
|
|
36
|
+
* connected or polled — reload re-runs every plugin's resolver, so unchanged
|
|
37
|
+
* plugins hand over new instances on every call.
|
|
38
|
+
*
|
|
39
|
+
* Providers of plugins that went inactive, failed to load or were uninstalled
|
|
40
|
+
* are absent from the contributions and get stopped here.
|
|
41
|
+
*/
|
|
42
|
+
sync(contributions: PluginContribution<SignalProvider<string>>[]): void;
|
|
43
|
+
/**
|
|
44
|
+
* Called once Mastra exists. Providers resolved before then are registered and
|
|
45
|
+
* started here — without a Mastra instance a provider has no storage, and
|
|
46
|
+
* nothing else will ever hand it one: the Agent propagates Mastra only to the
|
|
47
|
+
* providers in its own `signals` array, which these deliberately are not in.
|
|
48
|
+
*/
|
|
49
|
+
setMastra(mastra: Mastra, agent: Agent): void;
|
|
50
|
+
/**
|
|
51
|
+
* Retires every live provider and empties both processor lanes. The inverse of
|
|
52
|
+
* `sync()`, for a caller that is done with this lane — an embedder sharing one
|
|
53
|
+
* `PluginManager` across controllers would otherwise leave a controller's
|
|
54
|
+
* providers polling after it is gone.
|
|
55
|
+
*/
|
|
56
|
+
stopAll(): void;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=signal-lane.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-lane.d.ts","sourceRoot":"","sources":["../../src/plugins/signal-lane.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACnG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AASrD,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrD,CAAC;AAEF;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;;gBAYf,OAAO,GAAE,uBAA4B;IASjD,kBAAkB,IAAI,SAAS,wBAAwB,EAAE;IAIzD,mBAAmB,IAAI,SAAS,yBAAyB,EAAE;IAI3D;;;;;;;;;;OAUG;IACH,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,IAAI;IA+BvE;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAO7C;;;;;OAKG;IACH,OAAO,IAAI,IAAI;CAyGhB"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
//#region src/plugins/signal-lane.ts
|
|
2
|
+
/**
|
|
3
|
+
* Owns the lifecycle of signal providers contributed by plugins.
|
|
4
|
+
*
|
|
5
|
+
* Providers are long-lived; processors are per-request. The Agent constructor
|
|
6
|
+
* conflates the two — it harvests a provider's processors into a closure that
|
|
7
|
+
* can never be undone — so plugin providers are deliberately kept out of the
|
|
8
|
+
* `signals` array and driven from here instead, through the same public methods
|
|
9
|
+
* the constructor uses. That is what makes a provider removable when its plugin
|
|
10
|
+
* is disabled, updated or uninstalled.
|
|
11
|
+
*/
|
|
12
|
+
var PluginSignalLane = class {
|
|
13
|
+
#live = /* @__PURE__ */ new Map();
|
|
14
|
+
#reservedProviderIds;
|
|
15
|
+
#onError;
|
|
16
|
+
#agent;
|
|
17
|
+
#mastra;
|
|
18
|
+
#inputProcessors = [];
|
|
19
|
+
#outputProcessors = [];
|
|
20
|
+
constructor(options = {}) {
|
|
21
|
+
this.#reservedProviderIds = new Set(options.reservedProviderIds ?? []);
|
|
22
|
+
this.#onError = options.onError ?? ((message, error) => {
|
|
23
|
+
console.warn(message, error);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
getInputProcessors() {
|
|
27
|
+
return this.#inputProcessors;
|
|
28
|
+
}
|
|
29
|
+
getOutputProcessors() {
|
|
30
|
+
return this.#outputProcessors;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Reconciles the live providers against a freshly loaded plugin list.
|
|
34
|
+
*
|
|
35
|
+
* A plugin whose stamp is unchanged keeps the provider instance it already
|
|
36
|
+
* has, and the freshly resolved one is dropped without ever being registered,
|
|
37
|
+
* connected or polled — reload re-runs every plugin's resolver, so unchanged
|
|
38
|
+
* plugins hand over new instances on every call.
|
|
39
|
+
*
|
|
40
|
+
* Providers of plugins that went inactive, failed to load or were uninstalled
|
|
41
|
+
* are absent from the contributions and get stopped here.
|
|
42
|
+
*/
|
|
43
|
+
sync(contributions) {
|
|
44
|
+
const seen = /* @__PURE__ */ new Set();
|
|
45
|
+
for (const { pluginId, versionStamp, value: provider } of contributions) {
|
|
46
|
+
const key = `${pluginId}::${provider.id}`;
|
|
47
|
+
seen.add(key);
|
|
48
|
+
const live = this.#live.get(key);
|
|
49
|
+
if (live && live.versionStamp === versionStamp) continue;
|
|
50
|
+
if (live) this.#retire(key, live);
|
|
51
|
+
if (this.#isProviderIdTaken(provider.id)) {
|
|
52
|
+
this.#onError(`Plugin "${pluginId}" signal provider "${provider.id}" is already running; refusing to start a second instance.`, void 0);
|
|
53
|
+
seen.delete(key);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
this.#live.set(key, {
|
|
57
|
+
pluginId,
|
|
58
|
+
provider,
|
|
59
|
+
versionStamp,
|
|
60
|
+
started: false
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
for (const [key, live] of this.#live) if (!seen.has(key)) this.#retire(key, live);
|
|
64
|
+
this.#startPending();
|
|
65
|
+
this.#rebuildProcessors();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Called once Mastra exists. Providers resolved before then are registered and
|
|
69
|
+
* started here — without a Mastra instance a provider has no storage, and
|
|
70
|
+
* nothing else will ever hand it one: the Agent propagates Mastra only to the
|
|
71
|
+
* providers in its own `signals` array, which these deliberately are not in.
|
|
72
|
+
*/
|
|
73
|
+
setMastra(mastra, agent) {
|
|
74
|
+
this.#mastra = mastra;
|
|
75
|
+
this.#agent = agent;
|
|
76
|
+
this.#startPending();
|
|
77
|
+
this.#rebuildProcessors();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Retires every live provider and empties both processor lanes. The inverse of
|
|
81
|
+
* `sync()`, for a caller that is done with this lane — an embedder sharing one
|
|
82
|
+
* `PluginManager` across controllers would otherwise leave a controller's
|
|
83
|
+
* providers polling after it is gone.
|
|
84
|
+
*/
|
|
85
|
+
stopAll() {
|
|
86
|
+
for (const [key, live] of this.#live) this.#retire(key, live);
|
|
87
|
+
this.#rebuildProcessors();
|
|
88
|
+
}
|
|
89
|
+
#startPending() {
|
|
90
|
+
const mastra = this.#mastra;
|
|
91
|
+
const agent = this.#agent;
|
|
92
|
+
if (!mastra || !agent) return;
|
|
93
|
+
for (const [key, live] of this.#live) {
|
|
94
|
+
if (live.started) continue;
|
|
95
|
+
try {
|
|
96
|
+
live.provider.__registerMastra(mastra);
|
|
97
|
+
live.provider.connect(agent);
|
|
98
|
+
live.provider.startPolling();
|
|
99
|
+
live.started = true;
|
|
100
|
+
this.#runStart(key, live);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
this.#failProvider(key, live, error);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async #runStart(key, live) {
|
|
107
|
+
try {
|
|
108
|
+
await live.provider.start?.();
|
|
109
|
+
if (this.#live.get(key) !== live) this.#stopProvider(live);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (this.#live.get(key) !== live) {
|
|
112
|
+
this.#stopProvider(live);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
this.#failProvider(key, live, error);
|
|
116
|
+
this.#rebuildProcessors();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Isolated: one failing provider does not take down its plugin's tools,
|
|
121
|
+
* commands, skills or sibling providers. A plugin author who wants a provider
|
|
122
|
+
* treated as required throws from the `signalProviders` resolver instead,
|
|
123
|
+
* which fails the whole plugin record.
|
|
124
|
+
*/
|
|
125
|
+
#failProvider(key, live, error) {
|
|
126
|
+
this.#onError(`Plugin "${live.pluginId}" signal provider "${live.provider.id}" failed to start:`, error);
|
|
127
|
+
this.#retire(key, live);
|
|
128
|
+
}
|
|
129
|
+
#retire(key, live) {
|
|
130
|
+
this.#stopProvider(live);
|
|
131
|
+
this.#live.delete(key);
|
|
132
|
+
}
|
|
133
|
+
#stopProvider(live) {
|
|
134
|
+
try {
|
|
135
|
+
live.provider.stop();
|
|
136
|
+
} catch (error) {
|
|
137
|
+
this.#onError(`Plugin "${live.pluginId}" signal provider "${live.provider.id}" failed to stop:`, error);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
#isProviderIdTaken(providerId) {
|
|
141
|
+
if (this.#reservedProviderIds.has(providerId)) return true;
|
|
142
|
+
for (const live of this.#live.values()) if (live.provider.id === providerId) return true;
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
#rebuildProcessors() {
|
|
146
|
+
const input = [];
|
|
147
|
+
const output = [];
|
|
148
|
+
for (const live of this.#live.values()) {
|
|
149
|
+
if (!live.started) continue;
|
|
150
|
+
try {
|
|
151
|
+
const providerInput = live.provider.getInputProcessors?.() ?? [];
|
|
152
|
+
const providerOutput = live.provider.getOutputProcessors?.() ?? [];
|
|
153
|
+
input.push(...providerInput);
|
|
154
|
+
output.push(...providerOutput);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
this.#onError(`Plugin "${live.pluginId}" signal provider "${live.provider.id}" failed to provide processors:`, error);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
this.#inputProcessors = input;
|
|
160
|
+
this.#outputProcessors = output;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
//#endregion
|
|
164
|
+
export { PluginSignalLane };
|
|
165
|
+
|
|
166
|
+
//# sourceMappingURL=signal-lane.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-lane.js","names":["#live","#reservedProviderIds","#onError","#inputProcessors","#outputProcessors","#retire","#isProviderIdTaken","#startPending","#rebuildProcessors","#mastra","#agent","#runStart","#failProvider","#stopProvider"],"sources":["../../src/plugins/signal-lane.ts"],"sourcesContent":["import type { Agent } from '@mastra/core/agent';\nimport type { Mastra } from '@mastra/core/mastra';\nimport type { InputProcessorOrWorkflow, OutputProcessorOrWorkflow } from '@mastra/core/processors';\nimport type { SignalProvider } from '@mastra/core/signals';\n\nimport type { PluginContribution } from './types.js';\n\ntype LiveProvider = {\n pluginId: string;\n provider: SignalProvider<string>;\n versionStamp: string;\n started: boolean;\n};\n\nexport type PluginSignalLaneOptions = {\n /**\n * Ids of providers Mastra Code wires itself (through the Agent constructor).\n * The lane refuses to start a provider that collides with one of them:\n * two live instances of the same provider silently clobber each other's\n * polling, and the built-ins are invisible to the lane's own registry.\n */\n reservedProviderIds?: string[];\n onError?: (message: string, error: unknown) => void;\n};\n\n/**\n * Owns the lifecycle of signal providers contributed by plugins.\n *\n * Providers are long-lived; processors are per-request. The Agent constructor\n * conflates the two — it harvests a provider's processors into a closure that\n * can never be undone — so plugin providers are deliberately kept out of the\n * `signals` array and driven from here instead, through the same public methods\n * the constructor uses. That is what makes a provider removable when its plugin\n * is disabled, updated or uninstalled.\n */\nexport class PluginSignalLane {\n readonly #live = new Map<string, LiveProvider>();\n readonly #reservedProviderIds: Set<string>;\n readonly #onError: (message: string, error: unknown) => void;\n #agent: Agent | undefined;\n #mastra: Mastra | undefined;\n // Replaced wholesale, never mutated: a request that already resolved its\n // processors keeps the array it read, so a reload mid-request cannot change\n // the pipeline underneath it.\n #inputProcessors: InputProcessorOrWorkflow[] = [];\n #outputProcessors: OutputProcessorOrWorkflow[] = [];\n\n constructor(options: PluginSignalLaneOptions = {}) {\n this.#reservedProviderIds = new Set(options.reservedProviderIds ?? []);\n this.#onError =\n options.onError ??\n ((message, error) => {\n console.warn(message, error);\n });\n }\n\n getInputProcessors(): readonly InputProcessorOrWorkflow[] {\n return this.#inputProcessors;\n }\n\n getOutputProcessors(): readonly OutputProcessorOrWorkflow[] {\n return this.#outputProcessors;\n }\n\n /**\n * Reconciles the live providers against a freshly loaded plugin list.\n *\n * A plugin whose stamp is unchanged keeps the provider instance it already\n * has, and the freshly resolved one is dropped without ever being registered,\n * connected or polled — reload re-runs every plugin's resolver, so unchanged\n * plugins hand over new instances on every call.\n *\n * Providers of plugins that went inactive, failed to load or were uninstalled\n * are absent from the contributions and get stopped here.\n */\n sync(contributions: PluginContribution<SignalProvider<string>>[]): void {\n const seen = new Set<string>();\n\n for (const { pluginId, versionStamp, value: provider } of contributions) {\n const key = `${pluginId}::${provider.id}`;\n seen.add(key);\n\n const live = this.#live.get(key);\n if (live && live.versionStamp === versionStamp) continue;\n if (live) this.#retire(key, live);\n\n if (this.#isProviderIdTaken(provider.id)) {\n this.#onError(\n `Plugin \"${pluginId}\" signal provider \"${provider.id}\" is already running; refusing to start a second instance.`,\n undefined,\n );\n seen.delete(key);\n continue;\n }\n\n this.#live.set(key, { pluginId, provider, versionStamp, started: false });\n }\n\n for (const [key, live] of this.#live) {\n if (!seen.has(key)) this.#retire(key, live);\n }\n\n this.#startPending();\n this.#rebuildProcessors();\n }\n\n /**\n * Called once Mastra exists. Providers resolved before then are registered and\n * started here — without a Mastra instance a provider has no storage, and\n * nothing else will ever hand it one: the Agent propagates Mastra only to the\n * providers in its own `signals` array, which these deliberately are not in.\n */\n setMastra(mastra: Mastra, agent: Agent): void {\n this.#mastra = mastra;\n this.#agent = agent;\n this.#startPending();\n this.#rebuildProcessors();\n }\n\n /**\n * Retires every live provider and empties both processor lanes. The inverse of\n * `sync()`, for a caller that is done with this lane — an embedder sharing one\n * `PluginManager` across controllers would otherwise leave a controller's\n * providers polling after it is gone.\n */\n stopAll(): void {\n for (const [key, live] of this.#live) this.#retire(key, live);\n this.#rebuildProcessors();\n }\n\n #startPending(): void {\n const mastra = this.#mastra;\n const agent = this.#agent;\n if (!mastra || !agent) return;\n\n for (const [key, live] of this.#live) {\n if (live.started) continue;\n try {\n live.provider.__registerMastra(mastra);\n live.provider.connect(agent);\n live.provider.startPolling();\n live.started = true;\n // `start()` is the provider's own warm-up and may do network work, so it\n // is not awaited — this runs on the boot path and on every plugin\n // reload, and a slow provider must not hold either up. The Agent\n // constructor treats it the same way (agent.ts: `void provider.start?.()`).\n void this.#runStart(key, live);\n } catch (error) {\n this.#failProvider(key, live, error);\n }\n }\n }\n\n async #runStart(key: string, live: LiveProvider): Promise<void> {\n try {\n await live.provider.start?.();\n // Retired or replaced while warming up: whatever `start()` just armed was\n // armed after this provider was stopped, so it is stopped again. Without\n // this a provider replaced mid-warm-up keeps working against the thread\n // its successor is now watching.\n if (this.#live.get(key) !== live) this.#stopProvider(live);\n } catch (error) {\n if (this.#live.get(key) !== live) {\n this.#stopProvider(live);\n return;\n }\n this.#failProvider(key, live, error);\n this.#rebuildProcessors();\n }\n }\n\n /**\n * Isolated: one failing provider does not take down its plugin's tools,\n * commands, skills or sibling providers. A plugin author who wants a provider\n * treated as required throws from the `signalProviders` resolver instead,\n * which fails the whole plugin record.\n */\n #failProvider(key: string, live: LiveProvider, error: unknown): void {\n this.#onError(`Plugin \"${live.pluginId}\" signal provider \"${live.provider.id}\" failed to start:`, error);\n this.#retire(key, live);\n }\n\n #retire(key: string, live: LiveProvider): void {\n this.#stopProvider(live);\n this.#live.delete(key);\n }\n\n #stopProvider(live: LiveProvider): void {\n try {\n live.provider.stop();\n } catch (error) {\n this.#onError(`Plugin \"${live.pluginId}\" signal provider \"${live.provider.id}\" failed to stop:`, error);\n }\n }\n\n #isProviderIdTaken(providerId: string): boolean {\n if (this.#reservedProviderIds.has(providerId)) return true;\n for (const live of this.#live.values()) {\n if (live.provider.id === providerId) return true;\n }\n return false;\n }\n\n #rebuildProcessors(): void {\n const input: InputProcessorOrWorkflow[] = [];\n const output: OutputProcessorOrWorkflow[] = [];\n for (const live of this.#live.values()) {\n // Only started providers contribute: one that has not been handed Mastra\n // yet has no storage, so running its processors would fail on the first\n // request rather than wait for the lifecycle to complete.\n if (!live.started) continue;\n // Guarded like every other provider call: a throwing getter drops that\n // provider's processors from this rebuild instead of unwinding the whole\n // lane mid-sync. Both getters are read before either lane is touched so a\n // provider never contributes input processors without its output ones.\n try {\n const providerInput = live.provider.getInputProcessors?.() ?? [];\n const providerOutput = live.provider.getOutputProcessors?.() ?? [];\n input.push(...providerInput);\n output.push(...providerOutput);\n } catch (error) {\n this.#onError(\n `Plugin \"${live.pluginId}\" signal provider \"${live.provider.id}\" failed to provide processors:`,\n error,\n );\n }\n }\n this.#inputProcessors = input;\n this.#outputProcessors = output;\n }\n}\n"],"mappings":"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"}
|
package/dist/plugins/types.d.ts
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
|
+
import type { InputProcessor, OutputProcessor } from '@mastra/core/processors';
|
|
2
|
+
import type { SignalProvider } from '@mastra/core/signals';
|
|
1
3
|
import type { MastraCodePluginConfigSchema, MastraCodePluginConfigValue, MastraCodePluginTools, MastraCodeToolRenderConfig } from '../plugin.js';
|
|
4
|
+
/** Processors a plugin contributed, normalized into the lane they belong to. */
|
|
5
|
+
export type LoadedPluginProcessors = {
|
|
6
|
+
input: InputProcessor[];
|
|
7
|
+
output: OutputProcessor[];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* A single contribution, carrying the id of the plugin that owns it. Ownership
|
|
11
|
+
* has to survive collection: the signal lane keys live providers by
|
|
12
|
+
* `(pluginId, providerId)`, and a processor's state id is derived from the
|
|
13
|
+
* plugin id so it stays stable when the plugin is reloaded.
|
|
14
|
+
*/
|
|
15
|
+
export type PluginContribution<TValue> = {
|
|
16
|
+
pluginId: string;
|
|
17
|
+
/** The owning plugin's {@link LoadedPlugin.versionStamp} at collection time. */
|
|
18
|
+
versionStamp: string;
|
|
19
|
+
value: TValue;
|
|
20
|
+
};
|
|
21
|
+
export type PluginProcessorEntries = {
|
|
22
|
+
input: PluginContribution<InputProcessor>[];
|
|
23
|
+
output: PluginContribution<OutputProcessor>[];
|
|
24
|
+
};
|
|
2
25
|
export type PluginScope = 'global' | 'project';
|
|
3
26
|
export type PluginSource = 'local' | 'github';
|
|
4
27
|
export type PluginStatus = 'active' | 'inactive' | 'blocked' | 'load failed' | 'conflicted';
|
|
@@ -30,11 +53,24 @@ export type LoadedPlugin = ScopedInstalledPluginRecord & {
|
|
|
30
53
|
tools: MastraCodePluginTools;
|
|
31
54
|
renderConfigs?: Record<string, MastraCodeToolRenderConfig>;
|
|
32
55
|
toolNames: string[];
|
|
56
|
+
processors?: LoadedPluginProcessors;
|
|
57
|
+
signalProviders?: SignalProvider<string>[];
|
|
33
58
|
skillPaths?: string[];
|
|
34
59
|
commandPaths?: string[];
|
|
35
60
|
configSchema?: MastraCodePluginConfigSchema;
|
|
36
61
|
configValues?: Record<string, MastraCodePluginConfigValue>;
|
|
37
62
|
conflicts?: string[];
|
|
63
|
+
/**
|
|
64
|
+
* Changes when this plugin's contributions should be rebuilt: source content
|
|
65
|
+
* (git HEAD for GitHub checkouts, entry file version for local plugins) plus
|
|
66
|
+
* the registry record's config values and enabled flag. Reload fires on
|
|
67
|
+
* non-content events too — a config edit hands the plugin different values
|
|
68
|
+
* while every file is untouched — so both halves matter.
|
|
69
|
+
*
|
|
70
|
+
* Consumers that own long-lived instances (the signal-provider lane) compare
|
|
71
|
+
* this to decide between keeping what they have and cycling it.
|
|
72
|
+
*/
|
|
73
|
+
versionStamp?: string;
|
|
38
74
|
};
|
|
39
75
|
export type PluginScopePaths = {
|
|
40
76
|
scope: PluginScope;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC/C,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC9C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,YAAY,CAAC;AAE5F,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;CACtD,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC/C,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,qBAAqB,GAAG;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,2BAA2B,GAAG;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,qBAAqB,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IAC3D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,4BAA4B,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const createWorkflowTool: import("@mastra/core/tools").Tool<{
|
|
2
|
+
request: string;
|
|
3
|
+
}, {
|
|
4
|
+
summary: string;
|
|
5
|
+
workflowId?: string | undefined;
|
|
6
|
+
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "create-workflow", unknown>;
|
|
7
|
+
//# sourceMappingURL=create-workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-workflow.d.ts","sourceRoot":"","sources":["../../../src/tools/workflows/create-workflow.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,kBAAkB;;;;;8HAsG7B,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createTool } from "@mastra/core/tools";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/tools/workflows/create-workflow.ts
|
|
4
|
+
/**
|
|
5
|
+
* Coerce an unknown thrown value into a readable string. Sub-agent tool errors
|
|
6
|
+
* come through the stream in various shapes (Error, plain object, string) —
|
|
7
|
+
* normalise so the parent tool's error message is always useful.
|
|
8
|
+
*/
|
|
9
|
+
function stringifyError(err) {
|
|
10
|
+
if (err instanceof Error) return err.message;
|
|
11
|
+
if (typeof err === "string") return err;
|
|
12
|
+
try {
|
|
13
|
+
return JSON.stringify(err) ?? String(err);
|
|
14
|
+
} catch {
|
|
15
|
+
return String(err);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const createWorkflowTool = createTool({
|
|
19
|
+
id: "create-workflow",
|
|
20
|
+
description: "Build and save a Dynamic Workflow on behalf of the user. Pass the user request verbatim — a focused sub-agent handles discovery, construction, and persistence, then returns a summary. Use this whenever the user asks to \"build a workflow\", \"compose a workflow\", or similar. Do NOT try to construct workflows inline yourself.",
|
|
21
|
+
inputSchema: z.object({ request: z.string().describe("The user request, verbatim — do not paraphrase or summarise.") }),
|
|
22
|
+
outputSchema: z.object({
|
|
23
|
+
summary: z.string().describe("Natural-language summary of what the sub-agent built. Relay this to the user."),
|
|
24
|
+
workflowId: z.string().optional().describe("The id of the saved workflow, if save-workflow returned ok.")
|
|
25
|
+
}),
|
|
26
|
+
execute: async ({ request }, { mastra, requestContext }) => {
|
|
27
|
+
if (!mastra) throw new Error("create-workflow requires a Mastra context.");
|
|
28
|
+
const builder = mastra.getAgent("workflow-builder");
|
|
29
|
+
if (!builder) throw new Error("The \"workflow-builder\" sub-agent is not registered on this Mastra instance. Cannot build workflows.");
|
|
30
|
+
const stream = await builder.stream(request, { requestContext });
|
|
31
|
+
let workflowId;
|
|
32
|
+
let saveAttempted = false;
|
|
33
|
+
let saveSucceeded = false;
|
|
34
|
+
const toolErrors = [];
|
|
35
|
+
const reader = stream.fullStream.getReader();
|
|
36
|
+
let streamCompleted = false;
|
|
37
|
+
try {
|
|
38
|
+
while (true) {
|
|
39
|
+
const { value, done } = await reader.read();
|
|
40
|
+
if (done) {
|
|
41
|
+
streamCompleted = true;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
if (value?.type === "tool-call" && value.payload?.toolName === "save-workflow") saveAttempted = true;
|
|
45
|
+
if (value?.type === "tool-result" && value.payload?.toolName === "save-workflow") {
|
|
46
|
+
const result = value.payload.result;
|
|
47
|
+
if (result && result.ok === true && typeof result.id === "string") {
|
|
48
|
+
workflowId = result.id;
|
|
49
|
+
saveSucceeded = true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (value?.type === "tool-error" && typeof value.payload?.toolName === "string") toolErrors.push({
|
|
53
|
+
toolName: value.payload.toolName,
|
|
54
|
+
error: stringifyError(value.payload.error)
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
} finally {
|
|
58
|
+
if (!streamCompleted) await reader.cancel().catch(() => void 0);
|
|
59
|
+
reader.releaseLock();
|
|
60
|
+
}
|
|
61
|
+
const summary = await stream.text;
|
|
62
|
+
const saveErrors = toolErrors.filter((e) => e.toolName === "save-workflow");
|
|
63
|
+
if (saveErrors.length > 0 && !saveSucceeded) throw new Error(`create-workflow failed: save-workflow threw ${saveErrors.length} error(s):\n- ${saveErrors.map((e) => e.error).join("\n- ")}\n\nSub-agent summary (unreliable, save did not succeed):\n${summary}`);
|
|
64
|
+
if (!saveAttempted) {
|
|
65
|
+
const otherErrors = toolErrors.length ? `\n\nOther sub-agent tool errors:\n- ${toolErrors.map((e) => `${e.toolName}: ${e.error}`).join("\n- ")}` : "";
|
|
66
|
+
throw new Error(`create-workflow failed: the workflow-builder sub-agent never called save-workflow. No workflow was persisted.${otherErrors}\n\nSub-agent summary:\n${summary}`);
|
|
67
|
+
}
|
|
68
|
+
if (!saveSucceeded) {
|
|
69
|
+
const otherErrors = toolErrors.length ? `\n\nSub-agent tool errors:\n- ${toolErrors.map((e) => `${e.toolName}: ${e.error}`).join("\n- ")}` : "";
|
|
70
|
+
throw new Error(`create-workflow failed: save-workflow was called but did not return { ok: true }.${otherErrors}\n\nSub-agent summary:\n${summary}`);
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
summary,
|
|
74
|
+
workflowId
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
//#endregion
|
|
79
|
+
export { createWorkflowTool };
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=create-workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-workflow.js","names":[],"sources":["../../../src/tools/workflows/create-workflow.ts"],"sourcesContent":["/**\n * Parent-mode tool: delegate workflow construction to the workflow-builder\n * sub-agent. The parent code-agent calls this with the user's request verbatim;\n * the sub-agent runs its own discovery → compose → save loop and returns a\n * one-paragraph summary the parent relays to the user.\n *\n * The split exists so the parent code-agent's system prompt stays focused on\n * coding and isn't polluted with the long workflow-authoring contract.\n */\nimport type { Mastra } from '@mastra/core/mastra';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\n/**\n * Coerce an unknown thrown value into a readable string. Sub-agent tool errors\n * come through the stream in various shapes (Error, plain object, string) —\n * normalise so the parent tool's error message is always useful.\n */\nfunction stringifyError(err: unknown): string {\n if (err instanceof Error) return err.message;\n if (typeof err === 'string') return err;\n try {\n return JSON.stringify(err) ?? String(err);\n } catch {\n return String(err);\n }\n}\n\nexport const createWorkflowTool = createTool({\n id: 'create-workflow',\n description:\n 'Build and save a Dynamic Workflow on behalf of the user. Pass the user request verbatim — a focused sub-agent handles discovery, construction, and persistence, then returns a summary. Use this whenever the user asks to \"build a workflow\", \"compose a workflow\", or similar. Do NOT try to construct workflows inline yourself.',\n inputSchema: z.object({\n request: z.string().describe('The user request, verbatim — do not paraphrase or summarise.'),\n }),\n outputSchema: z.object({\n summary: z.string().describe('Natural-language summary of what the sub-agent built. Relay this to the user.'),\n workflowId: z.string().optional().describe('The id of the saved workflow, if save-workflow returned ok.'),\n }),\n execute: async ({ request }, { mastra, requestContext }) => {\n if (!mastra) throw new Error('create-workflow requires a Mastra context.');\n const builder = (mastra as Mastra).getAgent('workflow-builder' as never);\n if (!builder) {\n throw new Error(\n 'The \"workflow-builder\" sub-agent is not registered on this Mastra instance. Cannot build workflows.',\n );\n }\n\n // Propagate the parent code-agent's requestContext so the sub-agent's\n // dynamic model resolver (getDynamicModel) sees controller.session.modelId.\n // Without this the sub-agent throws \"No model selected\" even when the user\n // has /models configured for the main code-agent.\n const stream = await builder.stream(request, { requestContext });\n\n // Sub-agent runs its own tool loop. We MUST verify save-workflow actually\n // ran and returned ok — otherwise the sub-agent's natural-language \"summary\"\n // is worthless (it will happily claim success without ever calling the tool,\n // or claim success after save-workflow threw). Surface every error the\n // sub-agent's tools produce so the caller sees them instead of a fake ok.\n let workflowId: string | undefined;\n let saveAttempted = false;\n let saveSucceeded = false;\n const toolErrors: Array<{ toolName: string; error: string }> = [];\n\n const reader = stream.fullStream.getReader();\n let streamCompleted = false;\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n streamCompleted = true;\n break;\n }\n if (value?.type === 'tool-call' && value.payload?.toolName === 'save-workflow') {\n saveAttempted = true;\n }\n if (value?.type === 'tool-result' && value.payload?.toolName === 'save-workflow') {\n const result = value.payload.result as { id?: string; ok?: boolean } | undefined;\n if (result && result.ok === true && typeof result.id === 'string') {\n workflowId = result.id;\n saveSucceeded = true;\n }\n }\n if (value?.type === 'tool-error' && typeof value.payload?.toolName === 'string') {\n toolErrors.push({ toolName: value.payload.toolName, error: stringifyError(value.payload.error) });\n }\n }\n } finally {\n if (!streamCompleted) {\n await reader.cancel().catch(() => undefined);\n }\n reader.releaseLock();\n }\n\n const summary = await stream.text;\n\n // If save-workflow errored, surface that error explicitly — do NOT return\n // the sub-agent's summary as if things were fine.\n const saveErrors = toolErrors.filter(e => e.toolName === 'save-workflow');\n if (saveErrors.length > 0 && !saveSucceeded) {\n throw new Error(\n `create-workflow failed: save-workflow threw ${saveErrors.length} error(s):\\n- ${saveErrors\n .map(e => e.error)\n .join('\\n- ')}\\n\\nSub-agent summary (unreliable, save did not succeed):\\n${summary}`,\n );\n }\n\n // If save-workflow was never called, the sub-agent gave up (or hallucinated\n // success). Fail loudly so the caller doesn't think a workflow exists.\n if (!saveAttempted) {\n const otherErrors = toolErrors.length\n ? `\\n\\nOther sub-agent tool errors:\\n- ${toolErrors.map(e => `${e.toolName}: ${e.error}`).join('\\n- ')}`\n : '';\n throw new Error(\n `create-workflow failed: the workflow-builder sub-agent never called save-workflow. No workflow was persisted.${otherErrors}\\n\\nSub-agent summary:\\n${summary}`,\n );\n }\n\n // Save was attempted but never returned ok (no tool-result with { ok: true, id }).\n if (!saveSucceeded) {\n const otherErrors = toolErrors.length\n ? `\\n\\nSub-agent tool errors:\\n- ${toolErrors.map(e => `${e.toolName}: ${e.error}`).join('\\n- ')}`\n : '';\n throw new Error(\n `create-workflow failed: save-workflow was called but did not return { ok: true }.${otherErrors}\\n\\nSub-agent summary:\\n${summary}`,\n );\n }\n\n return { summary, workflowId };\n },\n});\n"],"mappings":";;;;;;;;AAkBA,SAAS,eAAe,KAAsB;CAC5C,IAAI,eAAe,OAAO,OAAO,IAAI;CACrC,IAAI,OAAO,QAAQ,UAAU,OAAO;CACpC,IAAI;EACF,OAAO,KAAK,UAAU,GAAG,KAAK,OAAO,GAAG;CAC1C,QAAQ;EACN,OAAO,OAAO,GAAG;CACnB;AACF;AAEA,MAAa,qBAAqB,WAAW;CAC3C,IAAI;CACJ,aACE;CACF,aAAa,EAAE,OAAO,EACpB,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,8DAA8D,EAC7F,CAAC;CACD,cAAc,EAAE,OAAO;EACrB,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,+EAA+E;EAC5G,YAAY,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,6DAA6D;CAC1G,CAAC;CACD,SAAS,OAAO,EAAE,WAAW,EAAE,QAAQ,qBAAqB;EAC1D,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,4CAA4C;EACzE,MAAM,UAAW,OAAkB,SAAS,kBAA2B;EACvE,IAAI,CAAC,SACH,MAAM,IAAI,MACR,uGACF;EAOF,MAAM,SAAS,MAAM,QAAQ,OAAO,SAAS,EAAE,eAAe,CAAC;EAO/D,IAAI;EACJ,IAAI,gBAAgB;EACpB,IAAI,gBAAgB;EACpB,MAAM,aAAyD,CAAC;EAEhE,MAAM,SAAS,OAAO,WAAW,UAAU;EAC3C,IAAI,kBAAkB;EACtB,IAAI;GACF,OAAO,MAAM;IACX,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO,KAAK;IAC1C,IAAI,MAAM;KACR,kBAAkB;KAClB;IACF;IACA,IAAI,OAAO,SAAS,eAAe,MAAM,SAAS,aAAa,iBAC7D,gBAAgB;IAElB,IAAI,OAAO,SAAS,iBAAiB,MAAM,SAAS,aAAa,iBAAiB;KAChF,MAAM,SAAS,MAAM,QAAQ;KAC7B,IAAI,UAAU,OAAO,OAAO,QAAQ,OAAO,OAAO,OAAO,UAAU;MACjE,aAAa,OAAO;MACpB,gBAAgB;KAClB;IACF;IACA,IAAI,OAAO,SAAS,gBAAgB,OAAO,MAAM,SAAS,aAAa,UACrE,WAAW,KAAK;KAAE,UAAU,MAAM,QAAQ;KAAU,OAAO,eAAe,MAAM,QAAQ,KAAK;IAAE,CAAC;GAEpG;EACF,UAAU;GACR,IAAI,CAAC,iBACH,MAAM,OAAO,OAAO,CAAC,CAAC,YAAY,KAAA,CAAS;GAE7C,OAAO,YAAY;EACrB;EAEA,MAAM,UAAU,MAAM,OAAO;EAI7B,MAAM,aAAa,WAAW,QAAO,MAAK,EAAE,aAAa,eAAe;EACxE,IAAI,WAAW,SAAS,KAAK,CAAC,eAC5B,MAAM,IAAI,MACR,+CAA+C,WAAW,OAAO,gBAAgB,WAC9E,KAAI,MAAK,EAAE,KAAK,CAAC,CACjB,KAAK,MAAM,EAAE,6DAA6D,SAC/E;EAKF,IAAI,CAAC,eAAe;GAClB,MAAM,cAAc,WAAW,SAC3B,uCAAuC,WAAW,KAAI,MAAK,GAAG,EAAE,SAAS,IAAI,EAAE,OAAO,CAAC,CAAC,KAAK,MAAM,MACnG;GACJ,MAAM,IAAI,MACR,gHAAgH,YAAY,0BAA0B,SACxJ;EACF;EAGA,IAAI,CAAC,eAAe;GAClB,MAAM,cAAc,WAAW,SAC3B,iCAAiC,WAAW,KAAI,MAAK,GAAG,EAAE,SAAS,IAAI,EAAE,OAAO,CAAC,CAAC,KAAK,MAAM,MAC7F;GACJ,MAAM,IAAI,MACR,oFAAoF,YAAY,0BAA0B,SAC5H;EACF;EAEA,OAAO;GAAE;GAAS;EAAW;CAC/B;AACF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const deleteWorkflowTool: import("@mastra/core/tools").Tool<{
|
|
2
|
+
id: string;
|
|
3
|
+
}, {
|
|
4
|
+
ok: true;
|
|
5
|
+
id: string;
|
|
6
|
+
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "delete-workflow", unknown>;
|
|
7
|
+
//# sourceMappingURL=delete-workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-workflow.d.ts","sourceRoot":"","sources":["../../../src/tools/workflows/delete-workflow.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,kBAAkB;;;;;8HAe7B,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { deleteWorkflow } from "../../workflows/service.js";
|
|
2
|
+
import { createTool } from "@mastra/core/tools";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
//#region src/tools/workflows/delete-workflow.ts
|
|
5
|
+
const deleteWorkflowTool = createTool({
|
|
6
|
+
id: "delete-workflow",
|
|
7
|
+
description: "Remove a saved workflow from storage and unregister the live in-process Workflow instance. Idempotent. Subsequent save-workflow calls with the same id re-register cleanly.",
|
|
8
|
+
inputSchema: z.object({ id: z.string().describe("The workflow id to delete.") }),
|
|
9
|
+
outputSchema: z.object({
|
|
10
|
+
ok: z.literal(true),
|
|
11
|
+
id: z.string()
|
|
12
|
+
}),
|
|
13
|
+
execute: async ({ id }, { mastra }) => {
|
|
14
|
+
if (!mastra) throw new Error("delete-workflow requires a Mastra context.");
|
|
15
|
+
return deleteWorkflow(mastra, id);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
//#endregion
|
|
19
|
+
export { deleteWorkflowTool };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=delete-workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-workflow.js","names":[],"sources":["../../../src/tools/workflows/delete-workflow.ts"],"sourcesContent":["/**\n * Parent-mode tool: delete a saved workflow from storage and unregister the\n * live in-process Workflow instance so a subsequent save-workflow with the\n * same id re-registers cleanly.\n */\nimport type { Mastra } from '@mastra/core/mastra';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\nimport { deleteWorkflow } from '../../workflows/service.js';\n\nexport const deleteWorkflowTool = createTool({\n id: 'delete-workflow',\n description:\n 'Remove a saved workflow from storage and unregister the live in-process Workflow instance. Idempotent. Subsequent save-workflow calls with the same id re-register cleanly.',\n inputSchema: z.object({\n id: z.string().describe('The workflow id to delete.'),\n }),\n outputSchema: z.object({\n ok: z.literal(true),\n id: z.string(),\n }),\n execute: async ({ id }, { mastra }) => {\n if (!mastra) throw new Error('delete-workflow requires a Mastra context.');\n return deleteWorkflow(mastra as Mastra, id);\n },\n});\n"],"mappings":";;;;AAUA,MAAa,qBAAqB,WAAW;CAC3C,IAAI;CACJ,aACE;CACF,aAAa,EAAE,OAAO,EACpB,IAAI,EAAE,OAAO,CAAC,CAAC,SAAS,4BAA4B,EACtD,CAAC;CACD,cAAc,EAAE,OAAO;EACrB,IAAI,EAAE,QAAQ,IAAI;EAClB,IAAI,EAAE,OAAO;CACf,CAAC;CACD,SAAS,OAAO,EAAE,MAAM,EAAE,aAAa;EACrC,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,4CAA4C;EACzE,OAAO,eAAe,QAAkB,EAAE;CAC5C;AACF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RequestContext } from '@mastra/core/request-context';
|
|
2
|
+
interface EphemeralMemoryOptions {
|
|
3
|
+
threadId?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function withEphemeralMemory<T>(requestContext: RequestContext | undefined, fn: (requestContext: RequestContext | undefined) => Promise<T>, options?: EphemeralMemoryOptions): Promise<T>;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=ephemeral-memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ephemeral-memory.d.ts","sourceRoot":"","sources":["../../../src/tools/workflows/ephemeral-memory.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAgD,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE5G,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1C,EAAE,EAAE,CAAC,cAAc,EAAE,cAAc,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,EAC9D,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
import { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY, RequestContext } from "@mastra/core/request-context";
|
|
3
|
+
//#region src/tools/workflows/ephemeral-memory.ts
|
|
4
|
+
/**
|
|
5
|
+
* Sub-invocations launched from a parent chat turn (workflow agent steps,
|
|
6
|
+
* sub-agent tool calls) must run under a fresh isolated Mastra memory scope
|
|
7
|
+
* so they don't:
|
|
8
|
+
*
|
|
9
|
+
* - write their prompts/responses into the parent chat thread's history, or
|
|
10
|
+
* - contend with the parent turn's memory-dependent processors
|
|
11
|
+
* (observational-memory, task-state, working-memory-state).
|
|
12
|
+
*
|
|
13
|
+
* `withEphemeralMemory` copies the caller's request context into a child,
|
|
14
|
+
* replaces its MastraMemory with a fresh thread id and inherited resource id,
|
|
15
|
+
* then passes that isolated child to `fn`. The parent context is never mutated,
|
|
16
|
+
* so concurrent sub-invocations cannot overwrite or restore each other's
|
|
17
|
+
* memory values. Isolation writes the ephemeral ids instead of scrubbing them:
|
|
18
|
+
* inner agent invocations resolve their thread/resource via those reserved
|
|
19
|
+
* keys, and leaving them unset causes downstream storage saves to throw
|
|
20
|
+
* "Thread ID is required".
|
|
21
|
+
*
|
|
22
|
+
* Callers can override the ephemeral thread id (e.g. for tests) via
|
|
23
|
+
* `options.threadId`.
|
|
24
|
+
*/
|
|
25
|
+
async function withEphemeralMemory(requestContext, fn, options = {}) {
|
|
26
|
+
if (!requestContext) return fn(void 0);
|
|
27
|
+
const childRequestContext = new RequestContext(requestContext.entries());
|
|
28
|
+
const mastraMemory = requestContext.get("MastraMemory");
|
|
29
|
+
const resourceId = requestContext.get(MASTRA_RESOURCE_ID_KEY);
|
|
30
|
+
const ephemeralThreadId = options.threadId ?? randomUUID();
|
|
31
|
+
const parentResourceId = mastraMemory?.resourceId ?? resourceId ?? "";
|
|
32
|
+
childRequestContext.set("MastraMemory", {
|
|
33
|
+
thread: { id: ephemeralThreadId },
|
|
34
|
+
resourceId: parentResourceId,
|
|
35
|
+
memoryConfig: void 0
|
|
36
|
+
});
|
|
37
|
+
childRequestContext.set(MASTRA_THREAD_ID_KEY, ephemeralThreadId);
|
|
38
|
+
if (parentResourceId) childRequestContext.set(MASTRA_RESOURCE_ID_KEY, parentResourceId);
|
|
39
|
+
else childRequestContext.delete(MASTRA_RESOURCE_ID_KEY);
|
|
40
|
+
return fn(childRequestContext);
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { withEphemeralMemory };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=ephemeral-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ephemeral-memory.js","names":[],"sources":["../../../src/tools/workflows/ephemeral-memory.ts"],"sourcesContent":["/**\n * Sub-invocations launched from a parent chat turn (workflow agent steps,\n * sub-agent tool calls) must run under a fresh isolated Mastra memory scope\n * so they don't:\n *\n * - write their prompts/responses into the parent chat thread's history, or\n * - contend with the parent turn's memory-dependent processors\n * (observational-memory, task-state, working-memory-state).\n *\n * `withEphemeralMemory` copies the caller's request context into a child,\n * replaces its MastraMemory with a fresh thread id and inherited resource id,\n * then passes that isolated child to `fn`. The parent context is never mutated,\n * so concurrent sub-invocations cannot overwrite or restore each other's\n * memory values. Isolation writes the ephemeral ids instead of scrubbing them:\n * inner agent invocations resolve their thread/resource via those reserved\n * keys, and leaving them unset causes downstream storage saves to throw\n * \"Thread ID is required\".\n *\n * Callers can override the ephemeral thread id (e.g. for tests) via\n * `options.threadId`.\n */\nimport { randomUUID } from 'node:crypto';\nimport { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY, RequestContext } from '@mastra/core/request-context';\n\ninterface EphemeralMemoryOptions {\n threadId?: string;\n}\n\nexport async function withEphemeralMemory<T>(\n requestContext: RequestContext | undefined,\n fn: (requestContext: RequestContext | undefined) => Promise<T>,\n options: EphemeralMemoryOptions = {},\n): Promise<T> {\n if (!requestContext) return fn(undefined);\n\n const childRequestContext = new RequestContext(requestContext.entries());\n const mastraMemory = requestContext.get('MastraMemory') as\n | { thread?: { id?: string }; resourceId?: string; memoryConfig?: unknown }\n | undefined;\n const resourceId = requestContext.get(MASTRA_RESOURCE_ID_KEY) as string | undefined;\n const ephemeralThreadId = options.threadId ?? randomUUID();\n const parentResourceId = mastraMemory?.resourceId ?? resourceId ?? '';\n\n childRequestContext.set('MastraMemory', {\n thread: { id: ephemeralThreadId },\n resourceId: parentResourceId,\n memoryConfig: undefined,\n });\n // Stamp the reserved thread/resource-key context values with the same\n // ephemeral ids. Inner agent invocations (workflow agent steps, sub-agent\n // tool calls) read these keys to resolve their runtime thread; leaving\n // MASTRA_THREAD_ID_KEY unset causes prepare-memory-step to build a\n // MessageList without a threadId, which storage rejects downstream.\n childRequestContext.set(MASTRA_THREAD_ID_KEY, ephemeralThreadId);\n if (parentResourceId) {\n childRequestContext.set(MASTRA_RESOURCE_ID_KEY, parentResourceId);\n } else {\n childRequestContext.delete(MASTRA_RESOURCE_ID_KEY);\n }\n\n return fn(childRequestContext);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA4BA,eAAsB,oBACpB,gBACA,IACA,UAAkC,CAAC,GACvB;CACZ,IAAI,CAAC,gBAAgB,OAAO,GAAG,KAAA,CAAS;CAExC,MAAM,sBAAsB,IAAI,eAAe,eAAe,QAAQ,CAAC;CACvE,MAAM,eAAe,eAAe,IAAI,cAAc;CAGtD,MAAM,aAAa,eAAe,IAAI,sBAAsB;CAC5D,MAAM,oBAAoB,QAAQ,YAAY,WAAW;CACzD,MAAM,mBAAmB,cAAc,cAAc,cAAc;CAEnE,oBAAoB,IAAI,gBAAgB;EACtC,QAAQ,EAAE,IAAI,kBAAkB;EAChC,YAAY;EACZ,cAAc,KAAA;CAChB,CAAC;CAMD,oBAAoB,IAAI,sBAAsB,iBAAiB;CAC/D,IAAI,kBACF,oBAAoB,IAAI,wBAAwB,gBAAgB;MAEhE,oBAAoB,OAAO,sBAAsB;CAGnD,OAAO,GAAG,mBAAmB;AAC/B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a JSON Schema from a Mastra tool's schema field. Tools created via
|
|
3
|
+
* `createTool({...})` wrap their Zod schemas with `toStandardSchema`, exposing
|
|
4
|
+
* `['~standard'].jsonSchema` as a `{ input(opts), output(opts) }` converter
|
|
5
|
+
* (see packages/schema-compat/src/standard-schema/adapters/zod-v3.ts:110-119).
|
|
6
|
+
* `direction` selects which side — pass 'input' for inputSchema, 'output' for
|
|
7
|
+
* outputSchema. Returns undefined if the schema is missing or not
|
|
8
|
+
* standard-schema-compliant — the workflow-builder agent then knows the tool's
|
|
9
|
+
* shape is opaque and must reshape via mapping.
|
|
10
|
+
*/
|
|
11
|
+
export declare function extractJsonSchema(maybeSchema: unknown, direction: 'input' | 'output'): unknown | undefined;
|
|
12
|
+
//# sourceMappingURL=extract-json-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-json-schema.d.ts","sourceRoot":"","sources":["../../../src/tools/workflows/extract-json-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAc1G"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/tools/workflows/extract-json-schema.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extract a JSON Schema from a Mastra tool's schema field. Tools created via
|
|
4
|
+
* `createTool({...})` wrap their Zod schemas with `toStandardSchema`, exposing
|
|
5
|
+
* `['~standard'].jsonSchema` as a `{ input(opts), output(opts) }` converter
|
|
6
|
+
* (see packages/schema-compat/src/standard-schema/adapters/zod-v3.ts:110-119).
|
|
7
|
+
* `direction` selects which side — pass 'input' for inputSchema, 'output' for
|
|
8
|
+
* outputSchema. Returns undefined if the schema is missing or not
|
|
9
|
+
* standard-schema-compliant — the workflow-builder agent then knows the tool's
|
|
10
|
+
* shape is opaque and must reshape via mapping.
|
|
11
|
+
*/
|
|
12
|
+
function extractJsonSchema(maybeSchema, direction) {
|
|
13
|
+
try {
|
|
14
|
+
return (maybeSchema?.["~standard"]?.jsonSchema)?.[direction]?.({ target: "draft-2020-12" });
|
|
15
|
+
} catch {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { extractJsonSchema };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=extract-json-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-json-schema.js","names":["s"],"sources":["../../../src/tools/workflows/extract-json-schema.ts"],"sourcesContent":["/**\n * Extract a JSON Schema from a Mastra tool's schema field. Tools created via\n * `createTool({...})` wrap their Zod schemas with `toStandardSchema`, exposing\n * `['~standard'].jsonSchema` as a `{ input(opts), output(opts) }` converter\n * (see packages/schema-compat/src/standard-schema/adapters/zod-v3.ts:110-119).\n * `direction` selects which side — pass 'input' for inputSchema, 'output' for\n * outputSchema. Returns undefined if the schema is missing or not\n * standard-schema-compliant — the workflow-builder agent then knows the tool's\n * shape is opaque and must reshape via mapping.\n */\nexport function extractJsonSchema(maybeSchema: unknown, direction: 'input' | 'output'): unknown | undefined {\n try {\n const s = maybeSchema as\n | {\n ['~standard']?: {\n jsonSchema?: { input?: (opts: unknown) => unknown; output?: (opts: unknown) => unknown };\n };\n }\n | undefined;\n const converter = s?.['~standard']?.jsonSchema;\n return converter?.[direction]?.({ target: 'draft-2020-12' });\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,kBAAkB,aAAsB,WAAoD;CAC1G,IAAI;EASF,QADkBA,cAAI,YAAY,EAAE,WAAA,GACjB,UAAU,GAAG,EAAE,QAAQ,gBAAgB,CAAC;CAC7D,QAAQ;EACN;CACF;AACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const getWorkflowTool: import("@mastra/core/tools").Tool<{
|
|
2
|
+
id: string;
|
|
3
|
+
}, {
|
|
4
|
+
id: string;
|
|
5
|
+
status: "active" | "archived";
|
|
6
|
+
description?: string | undefined;
|
|
7
|
+
inputSchema?: any;
|
|
8
|
+
outputSchema?: any;
|
|
9
|
+
graph?: any[] | undefined;
|
|
10
|
+
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "get-workflow", unknown>;
|
|
11
|
+
//# sourceMappingURL=get-workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-workflow.d.ts","sourceRoot":"","sources":["../../../src/tools/workflows/get-workflow.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,eAAe;;;;;;;;;2HA2B1B,CAAC"}
|