@mastra/code-sdk 1.2.0-alpha.10 → 1.2.0-alpha.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/CHANGELOG.md +54 -0
- package/dist/agents/model.d.ts.map +1 -1
- package/dist/agents/model.js +4 -1
- package/dist/agents/model.js.map +1 -1
- package/dist/agents/modes/plan.js +2 -2
- 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 +9 -4
- package/dist/agents/tool-availability.js.map +1 -1
- package/dist/agents/tools.js +1 -1
- 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/index.d.ts +68 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +173 -61
- package/dist/index.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/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/package.json +11 -11
|
@@ -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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"}
|
package/dist/utils/plans.d.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
/** Global plans directory for approved-plan archives. */
|
|
2
2
|
export declare function getPlansDir(): string;
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
export interface LocalPlansOptions {
|
|
4
|
+
factoryProjectId?: string | null;
|
|
5
|
+
}
|
|
5
6
|
/** Workspace-relative directory the agent writes plan files into. */
|
|
6
|
-
export declare function getLocalPlansRelativeDir(): string;
|
|
7
|
+
export declare function getLocalPlansRelativeDir(options?: LocalPlansOptions): string;
|
|
8
|
+
/** Local (project-scoped) plans directory where the agent writes named plan files. */
|
|
9
|
+
export declare function getLocalPlansDir(projectPath: string, options?: LocalPlansOptions): string;
|
|
7
10
|
/** Derive a plan filename from a title (e.g. `add-dark-mode.md`). */
|
|
8
11
|
export declare function getPlanFilename(title: string): string;
|
|
9
12
|
/**
|
|
10
13
|
* Suggested workspace-relative path for a new plan file, shown in plan-mode prompts.
|
|
11
14
|
* Without a title we fall back to a generic name the agent can rename later.
|
|
12
15
|
*/
|
|
13
|
-
export declare function getSuggestedPlanRelativePath(title?: string): string;
|
|
16
|
+
export declare function getSuggestedPlanRelativePath(title?: string, options?: LocalPlansOptions): string;
|
|
14
17
|
/**
|
|
15
18
|
* Resolve a plan path submitted by the agent (absolute or project-relative) to an
|
|
16
19
|
* absolute path. Returns `undefined` when no usable path was provided.
|
|
@@ -18,11 +21,11 @@ export declare function getSuggestedPlanRelativePath(title?: string): string;
|
|
|
18
21
|
export declare function resolvePlanPath(projectPath: string, submittedPath: string): string | undefined;
|
|
19
22
|
/**
|
|
20
23
|
* Whether `targetPath` (absolute or project-relative) is a valid plan file: a `.md`
|
|
21
|
-
* file located directly inside the project's
|
|
24
|
+
* file located directly inside the project's configured plan directory. Used by the
|
|
22
25
|
* plan-mode write guard so the agent can write any named plan file there, but nothing
|
|
23
26
|
* outside that directory.
|
|
24
27
|
*/
|
|
25
|
-
export declare function isPlanFilePath(projectPath: string, targetPath: string): boolean;
|
|
28
|
+
export declare function isPlanFilePath(projectPath: string, targetPath: string, options?: LocalPlansOptions): boolean;
|
|
26
29
|
export declare function savePlanToDisk(opts: {
|
|
27
30
|
title: string;
|
|
28
31
|
plan: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../../src/utils/plans.ts"],"names":[],"mappings":"AAKA,yDAAyD;AACzD,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,
|
|
1
|
+
{"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../../src/utils/plans.ts"],"names":[],"mappings":"AAKA,yDAAyD;AACzD,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,qEAAqE;AACrE,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAEhF;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAE7F;AAUD,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAGpG;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG9F;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAUhH;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBhB;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAsBxG;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAc9B"}
|
package/dist/utils/plans.js
CHANGED
|
@@ -7,13 +7,13 @@ import fs from "fs/promises";
|
|
|
7
7
|
function getPlansDir() {
|
|
8
8
|
return process.env.MASTRA_PLANS_DIR ?? path.join(getAppDataDir(), "plans");
|
|
9
9
|
}
|
|
10
|
-
/** Local (project-scoped) plans directory where the agent writes named plan files. */
|
|
11
|
-
function getLocalPlansDir(projectPath) {
|
|
12
|
-
return path.join(projectPath, DEFAULT_CONFIG_DIR, "plans");
|
|
13
|
-
}
|
|
14
10
|
/** Workspace-relative directory the agent writes plan files into. */
|
|
15
|
-
function getLocalPlansRelativeDir() {
|
|
16
|
-
return path.join(DEFAULT_CONFIG_DIR, "plans");
|
|
11
|
+
function getLocalPlansRelativeDir(options = {}) {
|
|
12
|
+
return options.factoryProjectId ? path.join(".artifacts", "plans") : path.join(DEFAULT_CONFIG_DIR, "plans");
|
|
13
|
+
}
|
|
14
|
+
/** Local (project-scoped) plans directory where the agent writes named plan files. */
|
|
15
|
+
function getLocalPlansDir(projectPath, options = {}) {
|
|
16
|
+
return path.join(projectPath, getLocalPlansRelativeDir(options));
|
|
17
17
|
}
|
|
18
18
|
function slugify(str) {
|
|
19
19
|
return str.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "untitled";
|
|
@@ -26,9 +26,9 @@ function getPlanFilename(title) {
|
|
|
26
26
|
* Suggested workspace-relative path for a new plan file, shown in plan-mode prompts.
|
|
27
27
|
* Without a title we fall back to a generic name the agent can rename later.
|
|
28
28
|
*/
|
|
29
|
-
function getSuggestedPlanRelativePath(title) {
|
|
29
|
+
function getSuggestedPlanRelativePath(title, options = {}) {
|
|
30
30
|
const filename = title ? getPlanFilename(title) : "plan.md";
|
|
31
|
-
return path.join(getLocalPlansRelativeDir(), filename);
|
|
31
|
+
return path.join(getLocalPlansRelativeDir(options), filename);
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Resolve a plan path submitted by the agent (absolute or project-relative) to an
|
|
@@ -40,15 +40,15 @@ function resolvePlanPath(projectPath, submittedPath) {
|
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Whether `targetPath` (absolute or project-relative) is a valid plan file: a `.md`
|
|
43
|
-
* file located directly inside the project's
|
|
43
|
+
* file located directly inside the project's configured plan directory. Used by the
|
|
44
44
|
* plan-mode write guard so the agent can write any named plan file there, but nothing
|
|
45
45
|
* outside that directory.
|
|
46
46
|
*/
|
|
47
|
-
function isPlanFilePath(projectPath, targetPath) {
|
|
47
|
+
function isPlanFilePath(projectPath, targetPath, options = {}) {
|
|
48
48
|
const abs = resolvePlanPath(projectPath, targetPath);
|
|
49
49
|
if (!abs) return false;
|
|
50
50
|
if (path.extname(abs).toLowerCase() !== ".md") return false;
|
|
51
|
-
const plansDir = path.resolve(getLocalPlansDir(projectPath));
|
|
51
|
+
const plansDir = path.resolve(getLocalPlansDir(projectPath, options));
|
|
52
52
|
const rel = path.relative(plansDir, abs);
|
|
53
53
|
if (rel === "" || rel.startsWith("..") || path.isAbsolute(rel)) return false;
|
|
54
54
|
return !rel.includes(path.sep);
|
package/dist/utils/plans.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plans.js","names":[],"sources":["../../src/utils/plans.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { getAppDataDir } from './project.js';\n\n/** Global plans directory for approved-plan archives. */\nexport function getPlansDir(): string {\n return process.env.MASTRA_PLANS_DIR ?? path.join(getAppDataDir(), 'plans');\n}\n\n/**
|
|
1
|
+
{"version":3,"file":"plans.js","names":[],"sources":["../../src/utils/plans.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { getAppDataDir } from './project.js';\n\n/** Global plans directory for approved-plan archives. */\nexport function getPlansDir(): string {\n return process.env.MASTRA_PLANS_DIR ?? path.join(getAppDataDir(), 'plans');\n}\n\nexport interface LocalPlansOptions {\n factoryProjectId?: string | null;\n}\n\n/** Workspace-relative directory the agent writes plan files into. */\nexport function getLocalPlansRelativeDir(options: LocalPlansOptions = {}): string {\n return options.factoryProjectId ? path.join('.artifacts', 'plans') : path.join(DEFAULT_CONFIG_DIR, 'plans');\n}\n\n/** Local (project-scoped) plans directory where the agent writes named plan files. */\nexport function getLocalPlansDir(projectPath: string, options: LocalPlansOptions = {}): string {\n return path.join(projectPath, getLocalPlansRelativeDir(options));\n}\n\nfunction slugify(str: string): string {\n const slug = str\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n return slug || 'untitled';\n}\n\n/** Derive a plan filename from a title (e.g. `add-dark-mode.md`). */\nexport function getPlanFilename(title: string): string {\n return `${slugify(title)}.md`;\n}\n\n/**\n * Suggested workspace-relative path for a new plan file, shown in plan-mode prompts.\n * Without a title we fall back to a generic name the agent can rename later.\n */\nexport function getSuggestedPlanRelativePath(title?: string, options: LocalPlansOptions = {}): string {\n const filename = title ? getPlanFilename(title) : 'plan.md';\n return path.join(getLocalPlansRelativeDir(options), filename);\n}\n\n/**\n * Resolve a plan path submitted by the agent (absolute or project-relative) to an\n * absolute path. Returns `undefined` when no usable path was provided.\n */\nexport function resolvePlanPath(projectPath: string, submittedPath: string): string | undefined {\n if (!submittedPath) return undefined;\n return path.isAbsolute(submittedPath) ? submittedPath : path.resolve(projectPath, submittedPath);\n}\n\n/**\n * Whether `targetPath` (absolute or project-relative) is a valid plan file: a `.md`\n * file located directly inside the project's configured plan directory. Used by the\n * plan-mode write guard so the agent can write any named plan file there, but nothing\n * outside that directory.\n */\nexport function isPlanFilePath(projectPath: string, targetPath: string, options: LocalPlansOptions = {}): boolean {\n const abs = resolvePlanPath(projectPath, targetPath);\n if (!abs) return false;\n if (path.extname(abs).toLowerCase() !== '.md') return false;\n\n const plansDir = path.resolve(getLocalPlansDir(projectPath, options));\n const rel = path.relative(plansDir, abs);\n // Must be directly inside the plans dir (no nested subdirectories, no escaping it).\n if (rel === '' || rel.startsWith('..') || path.isAbsolute(rel)) return false;\n return !rel.includes(path.sep);\n}\n\nexport async function savePlanToDisk(opts: {\n title: string;\n plan: string;\n resourceId: string;\n plansDir?: string;\n}): Promise<void> {\n const { title, plan, resourceId } = opts;\n const plansDir = opts.plansDir ?? getPlansDir();\n const baseDir = path.resolve(plansDir);\n const dir = path.resolve(baseDir, resourceId);\n const rel = path.relative(baseDir, dir);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n throw new Error(`Invalid resourceId: ${resourceId}`);\n }\n\n await fs.mkdir(dir, { recursive: true });\n\n const now = new Date();\n const timestamp = now.toISOString().replace(/:/g, '-');\n const slug = slugify(title);\n const filename = `${timestamp}-${slug}.md`;\n\n const content = `# ${title}\\n\\nApproved: ${now.toISOString()}\\n\\n${plan}\\n`;\n\n await fs.writeFile(path.join(dir, filename), content, 'utf-8');\n}\n\n/**\n * Read a plan markdown file by absolute path.\n *\n * The leading `# <title>` heading (if present) is parsed as the title and the remaining\n * content is returned as the plan body. Returns `undefined` when the file does not exist.\n */\nexport async function readPlanFile(absPath: string): Promise<{ title: string; plan: string } | undefined> {\n let raw: string;\n try {\n raw = await fs.readFile(absPath, 'utf-8');\n } catch {\n return undefined;\n }\n\n const lines = raw.split(/\\r?\\n/);\n const headingIndex = lines.findIndex(line => line.trim().length > 0);\n const heading = headingIndex >= 0 ? lines[headingIndex] : undefined;\n if (heading?.startsWith('# ')) {\n const title = heading.slice(2).trim();\n const plan = lines\n .slice(headingIndex + 1)\n .join('\\n')\n .replace(/^\\n+/, '')\n .trimEnd();\n return { title, plan };\n }\n\n return { title: '', plan: raw.trimEnd() };\n}\n\n/**\n * Approve the plan file at `planPath`: write a timestamped copy to the global plans\n * archive so approved plans are findable later. The local named plan file is left in\n * place so the user can review every plan made over time.\n *\n * Returns the local plan filename (e.g. `add-dark-mode.md`), or `undefined` when there\n * was no plan file to approve.\n */\nexport async function approvePlanFile(opts: {\n planPath: string;\n title: string;\n resourceId: string;\n plansDir?: string;\n}): Promise<string | undefined> {\n const { planPath, title, resourceId, plansDir } = opts;\n\n const current = await readPlanFile(planPath);\n if (!current) {\n return undefined;\n }\n\n const resolvedTitle = title || current.title || 'Implementation Plan';\n\n // Global archive (timestamped, never overwritten) so approved plans are findable later.\n await savePlanToDisk({ title: resolvedTitle, plan: current.plan, resourceId, plansDir });\n\n return path.basename(planPath);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/code-sdk",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.14",
|
|
4
4
|
"description": "Mastra Code SDK: the agent core behind Mastra Code (everything except the TUI) — build your own UIs and surfaces on top of it",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -56,19 +56,19 @@
|
|
|
56
56
|
"vscode-languageserver-protocol": "^3.17.5",
|
|
57
57
|
"yaml": "^2.7.1",
|
|
58
58
|
"zod": "^4.3.6",
|
|
59
|
-
"@mastra/core": "1.58.0-alpha.9",
|
|
60
59
|
"@mastra/agent-browser": "0.5.1-alpha.0",
|
|
61
|
-
"@mastra/
|
|
60
|
+
"@mastra/core": "1.58.0-alpha.12",
|
|
62
61
|
"@mastra/fastembed": "1.2.0",
|
|
63
|
-
"@mastra/
|
|
62
|
+
"@mastra/duckdb": "1.6.1-alpha.0",
|
|
63
|
+
"@mastra/github-signals": "0.2.5-alpha.1",
|
|
64
64
|
"@mastra/libsql": "1.20.0-alpha.2",
|
|
65
|
-
"@mastra/mcp": "1.16.0-alpha.
|
|
66
|
-
"@mastra/observability": "1.16.6-alpha.
|
|
67
|
-
"@mastra/memory": "1.26.1-alpha.
|
|
65
|
+
"@mastra/mcp": "1.16.0-alpha.2",
|
|
66
|
+
"@mastra/observability": "1.16.6-alpha.3",
|
|
67
|
+
"@mastra/memory": "1.26.1-alpha.6",
|
|
68
68
|
"@mastra/pg": "1.20.0-alpha.3",
|
|
69
69
|
"@mastra/tavily": "1.1.1",
|
|
70
|
-
"@mastra/
|
|
71
|
-
"@mastra/
|
|
70
|
+
"@mastra/stagehand": "0.3.2-alpha.1",
|
|
71
|
+
"@mastra/schema-compat": "1.3.6-alpha.3"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@libsql/client": "^0.17.4",
|
|
@@ -79,9 +79,9 @@
|
|
|
79
79
|
"typescript": "^6.0.3",
|
|
80
80
|
"typescript-eslint": "^8.57.0",
|
|
81
81
|
"vitest": "4.1.10",
|
|
82
|
-
"@internal/
|
|
82
|
+
"@internal/types-builder": "0.0.96",
|
|
83
83
|
"@internal/workspace-test-utils": "0.0.65",
|
|
84
|
-
"@internal/
|
|
84
|
+
"@internal/lint": "0.0.121"
|
|
85
85
|
},
|
|
86
86
|
"engines": {
|
|
87
87
|
"node": ">=22.19.0"
|