@happyvertical/smrt-cli 0.40.61 → 0.40.63
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/AGENTS.md +14 -2
- package/README.md +27 -5
- package/dist/{commands-CB3xtl7p.js → commands-Bkdk2-S5.js} +5 -5
- package/dist/index.js +129 -11
- package/package.json +12 -12
package/AGENTS.md
CHANGED
|
@@ -15,10 +15,13 @@ smrt db:rollback # Rollback migrations
|
|
|
15
15
|
smrt docs:agents # Generate .agents/smrt-framework.md
|
|
16
16
|
smrt docs:claude # Deprecated alias writing .claude/smrt-framework.md
|
|
17
17
|
smrt dev:knowledge-* # Deterministic agent knowledge index/check/diff
|
|
18
|
+
smrt dev:knowledge-index --scope installed # Installed @happyvertical/* deps, versions, AGENTS.md hashes
|
|
18
19
|
smrt knowledge:review-context --scope package --package <name>
|
|
19
|
-
smrt knowledge:architecture-context --scope project|local|package|sdk
|
|
20
|
+
smrt knowledge:architecture-context --scope project|local|package|sdk|installed
|
|
20
21
|
smrt dev:knowledge-check --format markdown|json
|
|
21
|
-
smrt generate
|
|
22
|
+
smrt generate-mcp # Generate MCP server (aliases: generate-mcp-server, mcp)
|
|
23
|
+
smrt generate-types # Generate TypeScript declarations (alias: generate-declarations)
|
|
24
|
+
smrt generate-routes # Generate SvelteKit API routes (aliases: routes, generate:routes)
|
|
22
25
|
smrt config:export # Export agent config for SSG
|
|
23
26
|
smrt init # Init new project
|
|
24
27
|
smrt gnode # Scaffold gnode site
|
|
@@ -50,4 +53,13 @@ migrations are manifest-driven through registered objects and project manifests.
|
|
|
50
53
|
|
|
51
54
|
- **Test mode detection**: checks `NODE_ENV=test`, `VITEST=true`, `global.it`/`describe` — could conflict with other test runners
|
|
52
55
|
- **External package load failures silenced**: one package failing doesn't prevent others from loading
|
|
56
|
+
- **Generation command names are hyphenated**: `generate-mcp` and `generate-types` have
|
|
57
|
+
no colon alias. Only `generate-routes` and `generate-register` declare one, so
|
|
58
|
+
`smrt generate:mcp` is an unknown command (#2279).
|
|
59
|
+
- **Subcommand `--version` beats the global flag**: `parseCliArgs` in
|
|
60
|
+
`@happyvertical/utils` dispatches to the built-in `version` command for a
|
|
61
|
+
`--version` token anywhere in argv. `parseCliCommandArgs` rescopes that token to
|
|
62
|
+
the named subcommand (`smrt generate-mcp --version 0.1.0`) and only leaves it
|
|
63
|
+
global when it appears before or without a subcommand (#2279). `--help` is
|
|
64
|
+
deliberately untouched.
|
|
53
65
|
- **Schema history nuance**: `db:status` / `db:history` should distinguish active live drift from superseded failed generated schema repairs instead of treating all failed rows as current blockers
|
package/README.md
CHANGED
|
@@ -83,8 +83,30 @@ the tracker or writing to the database.
|
|
|
83
83
|
|
|
84
84
|
| Command | Description |
|
|
85
85
|
|---------|------------|
|
|
86
|
-
| `smrt generate
|
|
87
|
-
| `smrt generate
|
|
86
|
+
| `smrt generate-mcp` | Generate MCP server from registered objects (aliases: `generate-mcp-server`, `mcp`) |
|
|
87
|
+
| `smrt generate-types` | Generate TypeScript declarations from manifest (alias: `generate-declarations`) |
|
|
88
|
+
| `smrt generate-routes` | Generate SvelteKit API routes (aliases: `routes`, `generate:routes`) |
|
|
89
|
+
| `smrt generate-register` | Generate `.smrt/register.js` from discovered packages (aliases: `register`, `generate:register`) |
|
|
90
|
+
|
|
91
|
+
Generation commands are hyphenated. `generate-routes` and `generate-register`
|
|
92
|
+
also answer to a colon alias for backward compatibility; `generate-mcp` and
|
|
93
|
+
`generate-types` do not.
|
|
94
|
+
|
|
95
|
+
`smrt generate-mcp` writes `.smrt/mcp-server/index.js` by default and emits
|
|
96
|
+
JavaScript for a `.js` target, so `node .smrt/mcp-server/index.js` runs it
|
|
97
|
+
directly. Ask for a `.ts` target to keep the annotated TypeScript for `tsx` or
|
|
98
|
+
Node's type stripping:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
smrt generate-mcp --output-path .smrt/mcp-server/index.ts
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The generated server is always an ES module, so a `.cjs`/`.cts` output path is
|
|
105
|
+
rejected. It imports `@modelcontextprotocol/server`, `@happyvertical/smrt-core`,
|
|
106
|
+
and `@happyvertical/smrt-config` at runtime (plus `@happyvertical/smrt-jobs` for
|
|
107
|
+
task actions and `@happyvertical/smrt-tenancy` for tenant-scoped objects), so
|
|
108
|
+
those have to be resolvable from the project you run it in — under pnpm's strict
|
|
109
|
+
layout that means declaring them, not relying on the CLI's own dependencies.
|
|
88
110
|
|
|
89
111
|
### Documentation
|
|
90
112
|
|
|
@@ -95,8 +117,8 @@ the tracker or writing to the database.
|
|
|
95
117
|
| `smrt dev:knowledge-index --format markdown\|json` | Print the deterministic s-m-r-t + SDK knowledge index |
|
|
96
118
|
| `smrt dev:knowledge-check --format markdown\|json` | Check agent knowledge freshness |
|
|
97
119
|
| `smrt dev:knowledge-diff --format markdown\|json` | Show changed files and affected package experts |
|
|
98
|
-
| `smrt knowledge:review-context --scope project\|local\|package\|sdk --package <name> --format markdown\|json` | Build a model-ready domain review prompt bundle |
|
|
99
|
-
| `smrt knowledge:architecture-context --scope project\|local\|package\|sdk --package <name> --format markdown\|json` | Build a model-ready domain architecture prompt bundle |
|
|
120
|
+
| `smrt knowledge:review-context --scope project\|local\|package\|sdk\|installed --package <name> --format markdown\|json` | Build a model-ready domain review prompt bundle |
|
|
121
|
+
| `smrt knowledge:architecture-context --scope project\|local\|package\|sdk\|installed --package <name> --format markdown\|json` | Build a model-ready domain architecture prompt bundle |
|
|
100
122
|
|
|
101
123
|
### Configuration
|
|
102
124
|
|
|
@@ -162,7 +184,7 @@ Custom methods on s-m-r-t objects are auto-discovered from manifests. Method par
|
|
|
162
184
|
smrt introspect
|
|
163
185
|
|
|
164
186
|
# Generate an MCP server
|
|
165
|
-
smrt generate
|
|
187
|
+
smrt generate-mcp
|
|
166
188
|
|
|
167
189
|
# Scaffold a package playground definition
|
|
168
190
|
smrt playground init
|
|
@@ -3157,7 +3157,7 @@ var generateCommands = {
|
|
|
3157
3157
|
},
|
|
3158
3158
|
modular: {
|
|
3159
3159
|
type: "boolean",
|
|
3160
|
-
description: "Generate modular directory structure (tools/, handlers/, config
|
|
3160
|
+
description: "Generate modular directory structure (tools/, handlers/, config)",
|
|
3161
3161
|
default: false
|
|
3162
3162
|
},
|
|
3163
3163
|
debug: {
|
|
@@ -5758,7 +5758,7 @@ var devKnowledgeCommands = {
|
|
|
5758
5758
|
},
|
|
5759
5759
|
scope: {
|
|
5760
5760
|
type: "string",
|
|
5761
|
-
description: "Knowledge scope: project, local, package, or
|
|
5761
|
+
description: "Knowledge scope: project, local, package, sdk, or installed",
|
|
5762
5762
|
default: "project"
|
|
5763
5763
|
},
|
|
5764
5764
|
package: {
|
|
@@ -5807,7 +5807,7 @@ var devKnowledgeCommands = {
|
|
|
5807
5807
|
},
|
|
5808
5808
|
scope: {
|
|
5809
5809
|
type: "string",
|
|
5810
|
-
description: "Knowledge scope: project, local, package, or
|
|
5810
|
+
description: "Knowledge scope: project, local, package, sdk, or installed",
|
|
5811
5811
|
default: "project"
|
|
5812
5812
|
},
|
|
5813
5813
|
package: {
|
|
@@ -5852,7 +5852,7 @@ var devKnowledgeCommands = {
|
|
|
5852
5852
|
},
|
|
5853
5853
|
scope: {
|
|
5854
5854
|
type: "string",
|
|
5855
|
-
description: "Knowledge scope: project, local, package, or
|
|
5855
|
+
description: "Knowledge scope: project, local, package, sdk, or installed",
|
|
5856
5856
|
default: "project"
|
|
5857
5857
|
},
|
|
5858
5858
|
package: {
|
|
@@ -5935,7 +5935,7 @@ function contextOptions(defaultFormat) {
|
|
|
5935
5935
|
},
|
|
5936
5936
|
scope: {
|
|
5937
5937
|
type: "string",
|
|
5938
|
-
description: "Knowledge scope: project, local, package, or
|
|
5938
|
+
description: "Knowledge scope: project, local, package, sdk, or installed",
|
|
5939
5939
|
default: "project"
|
|
5940
5940
|
},
|
|
5941
5941
|
package: {
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
3
|
+
import { basename, dirname, join } from "node:path";
|
|
4
4
|
import { createInterface } from "node:readline";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { ObjectRegistry, getPackageFromQualifiedName } from "@happyvertical/smrt-core";
|
|
@@ -48,56 +48,56 @@ var _docsCommands = null;
|
|
|
48
48
|
var _playgroundCommands = null;
|
|
49
49
|
async function getGnodeCommands() {
|
|
50
50
|
if (!_gnodeCommands) {
|
|
51
|
-
const { gnodeCommands } = await import("./commands-
|
|
51
|
+
const { gnodeCommands } = await import("./commands-Bkdk2-S5.js");
|
|
52
52
|
_gnodeCommands = gnodeCommands;
|
|
53
53
|
}
|
|
54
54
|
return _gnodeCommands;
|
|
55
55
|
}
|
|
56
56
|
async function getGitCommands() {
|
|
57
57
|
if (!_gitCommands) {
|
|
58
|
-
const { gitCommands } = await import("./commands-
|
|
58
|
+
const { gitCommands } = await import("./commands-Bkdk2-S5.js");
|
|
59
59
|
_gitCommands = gitCommands;
|
|
60
60
|
}
|
|
61
61
|
return _gitCommands;
|
|
62
62
|
}
|
|
63
63
|
async function getGenerateCommands() {
|
|
64
64
|
if (!_generateCommands) {
|
|
65
|
-
const { generateCommands } = await import("./commands-
|
|
65
|
+
const { generateCommands } = await import("./commands-Bkdk2-S5.js");
|
|
66
66
|
_generateCommands = generateCommands;
|
|
67
67
|
}
|
|
68
68
|
return _generateCommands;
|
|
69
69
|
}
|
|
70
70
|
async function getInitCommands() {
|
|
71
71
|
if (!_initCommands) {
|
|
72
|
-
const { initCommands } = await import("./commands-
|
|
72
|
+
const { initCommands } = await import("./commands-Bkdk2-S5.js");
|
|
73
73
|
_initCommands = initCommands;
|
|
74
74
|
}
|
|
75
75
|
return _initCommands;
|
|
76
76
|
}
|
|
77
77
|
async function getUtilityCommands() {
|
|
78
78
|
if (!_utilityCommands) {
|
|
79
|
-
const { utilityCommands } = await import("./commands-
|
|
79
|
+
const { utilityCommands } = await import("./commands-Bkdk2-S5.js");
|
|
80
80
|
_utilityCommands = utilityCommands;
|
|
81
81
|
}
|
|
82
82
|
return _utilityCommands;
|
|
83
83
|
}
|
|
84
84
|
async function getDispatchCommands() {
|
|
85
85
|
if (!_dispatchCommands) {
|
|
86
|
-
const { dispatchCommands } = await import("./commands-
|
|
86
|
+
const { dispatchCommands } = await import("./commands-Bkdk2-S5.js");
|
|
87
87
|
_dispatchCommands = dispatchCommands;
|
|
88
88
|
}
|
|
89
89
|
return _dispatchCommands;
|
|
90
90
|
}
|
|
91
91
|
async function getDocsCommands() {
|
|
92
92
|
if (!_docsCommands) {
|
|
93
|
-
const { docsCommands } = await import("./commands-
|
|
93
|
+
const { docsCommands } = await import("./commands-Bkdk2-S5.js");
|
|
94
94
|
_docsCommands = docsCommands;
|
|
95
95
|
}
|
|
96
96
|
return _docsCommands;
|
|
97
97
|
}
|
|
98
98
|
async function getPlaygroundCommands() {
|
|
99
99
|
if (!_playgroundCommands) {
|
|
100
|
-
const { playgroundCommands } = await import("./commands-
|
|
100
|
+
const { playgroundCommands } = await import("./commands-Bkdk2-S5.js");
|
|
101
101
|
_playgroundCommands = playgroundCommands;
|
|
102
102
|
}
|
|
103
103
|
return _playgroundCommands;
|
|
@@ -122,11 +122,129 @@ function collectRepeatableOptionValues(argv, optionName) {
|
|
|
122
122
|
return values;
|
|
123
123
|
}
|
|
124
124
|
/**
|
|
125
|
+
* Option name a subcommand may declare that collides with a global CLI flag.
|
|
126
|
+
*
|
|
127
|
+
* `parseCliArgs` dispatches to the built-in `version` command whenever
|
|
128
|
+
* `--version` appears anywhere in argv, so `smrt generate-mcp --version 0.1.0`
|
|
129
|
+
* never reached the subcommand and exited without generating anything (#2279).
|
|
130
|
+
* Only `--version` is rescoped: `--help` after a subcommand still prints help,
|
|
131
|
+
* which is what someone typing it wants.
|
|
132
|
+
*/
|
|
133
|
+
var SCOPED_GLOBAL_FLAG = "version";
|
|
134
|
+
/**
|
|
135
|
+
* Private option name the scoped flag is parsed under. Renaming the token is
|
|
136
|
+
* what keeps `parseCliArgs` from intercepting it; the value is mapped back onto
|
|
137
|
+
* the declared name before any handler sees it.
|
|
138
|
+
*/
|
|
139
|
+
var SCOPED_GLOBAL_FLAG_ALIAS = "smrt-scoped-version";
|
|
140
|
+
/**
|
|
141
|
+
* Index of the first real argument, mirroring the node/script-path stripping
|
|
142
|
+
* `parseCliArgs` does. The CLI entry point passes `process.argv.slice(2)`, but
|
|
143
|
+
* the shared parser also accepts a full `process.argv`, and this wrapper must
|
|
144
|
+
* read the same tokens the parser will.
|
|
145
|
+
*/
|
|
146
|
+
function firstArgumentIndex(argv) {
|
|
147
|
+
let index = 0;
|
|
148
|
+
if (argv.length > index && basename(argv[index]) === "node") index += 1;
|
|
149
|
+
if (argv.length > index && argv[index].endsWith(".js")) index += 1;
|
|
150
|
+
return index;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Resolve the command a plain argv addresses, mirroring the multi-word command
|
|
154
|
+
* matching in `parseCliArgs` (up to three leading words, names or aliases).
|
|
155
|
+
*
|
|
156
|
+
* @returns The matched command, if any, and how many leading argv tokens it consumed
|
|
157
|
+
*/
|
|
158
|
+
function matchLeadingCommand(argv, commands, builtInCommands) {
|
|
159
|
+
for (let width = Math.min(3, argv.length); width > 0; width -= 1) {
|
|
160
|
+
const candidateName = argv.slice(0, width).join(" ");
|
|
161
|
+
const found = builtInCommands[candidateName] ?? commands.find((candidate) => candidate.name === candidateName || candidate.aliases?.includes(candidateName));
|
|
162
|
+
if (found) return {
|
|
163
|
+
command: found,
|
|
164
|
+
wordCount: width
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return { wordCount: 0 };
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Rewrite a subcommand-scoped `--version` token to a private alias so the
|
|
171
|
+
* shared parser routes it to the subcommand instead of the global version
|
|
172
|
+
* command. Tokens before the subcommand — and a bare `smrt --version` — are
|
|
173
|
+
* left alone, so the global flag still wins when it is used globally.
|
|
174
|
+
*
|
|
175
|
+
* @returns Rewritten argv and the matched command, or `null` when nothing applies
|
|
176
|
+
*/
|
|
177
|
+
function rescopeGlobalFlag(argv, commands, builtInCommands) {
|
|
178
|
+
const start = firstArgumentIndex(argv);
|
|
179
|
+
const leading = argv[start];
|
|
180
|
+
if (!leading || leading.startsWith("-")) return null;
|
|
181
|
+
const flag = `--${SCOPED_GLOBAL_FLAG}`;
|
|
182
|
+
const inlinePrefix = `${flag}=`;
|
|
183
|
+
const aliasFlag = `--${SCOPED_GLOBAL_FLAG_ALIAS}`;
|
|
184
|
+
const { command, wordCount } = matchLeadingCommand(argv.slice(start), commands, builtInCommands);
|
|
185
|
+
const firstOptionIndex = start + Math.max(wordCount, 1);
|
|
186
|
+
let rewritten = false;
|
|
187
|
+
const rescoped = [...argv];
|
|
188
|
+
for (let index = firstOptionIndex; index < rescoped.length; index += 1) {
|
|
189
|
+
const token = rescoped[index];
|
|
190
|
+
if (token === "--") break;
|
|
191
|
+
if (token === flag) {
|
|
192
|
+
rescoped[index] = aliasFlag;
|
|
193
|
+
rewritten = true;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (token.startsWith(inlinePrefix)) {
|
|
197
|
+
rescoped[index] = `${aliasFlag}=${token.slice(inlinePrefix.length)}`;
|
|
198
|
+
rewritten = true;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return rewritten ? {
|
|
202
|
+
argv: rescoped,
|
|
203
|
+
command
|
|
204
|
+
} : null;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Swap a matched command's declared `version` option for the private alias the
|
|
208
|
+
* rescoped token is parsed under, so its type, default, and short flag still
|
|
209
|
+
* apply. Commands that do not declare the option are returned untouched.
|
|
210
|
+
*/
|
|
211
|
+
function declareScopedGlobalFlag(command, commands, builtInCommands) {
|
|
212
|
+
const declaredOptions = command?.options;
|
|
213
|
+
const declared = declaredOptions?.[SCOPED_GLOBAL_FLAG];
|
|
214
|
+
if (!command || !declaredOptions || !declared) return {
|
|
215
|
+
commands,
|
|
216
|
+
builtInCommands
|
|
217
|
+
};
|
|
218
|
+
const { [SCOPED_GLOBAL_FLAG]: _replaced, ...otherOptions } = declaredOptions;
|
|
219
|
+
const rewrittenCommand = {
|
|
220
|
+
...command,
|
|
221
|
+
options: {
|
|
222
|
+
...otherOptions,
|
|
223
|
+
[SCOPED_GLOBAL_FLAG_ALIAS]: { ...declared }
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
return {
|
|
227
|
+
commands: commands.map((candidate) => candidate === command ? rewrittenCommand : candidate),
|
|
228
|
+
builtInCommands: Object.fromEntries(Object.entries(builtInCommands).map(([name, candidate]) => [name, candidate === command ? rewrittenCommand : candidate]))
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
125
232
|
* Parse one command while preserving every occurrence of options marked
|
|
126
|
-
* `multiple
|
|
233
|
+
* `multiple`, and while letting a subcommand's own options win over the
|
|
234
|
+
* global flags the shared parser intercepts. Everything else retains the
|
|
235
|
+
* shared SDK parser behavior.
|
|
127
236
|
*/
|
|
128
237
|
function parseCliCommandArgs(argv, commands, builtInCommands = {}) {
|
|
129
|
-
const
|
|
238
|
+
const rescoped = rescopeGlobalFlag(argv, commands, builtInCommands);
|
|
239
|
+
let parsed;
|
|
240
|
+
if (rescoped) {
|
|
241
|
+
const declared = declareScopedGlobalFlag(rescoped.command, commands, builtInCommands);
|
|
242
|
+
parsed = parseCliArgs(rescoped.argv, declared.commands, declared.builtInCommands);
|
|
243
|
+
if (SCOPED_GLOBAL_FLAG_ALIAS in parsed.options) {
|
|
244
|
+
parsed.options[SCOPED_GLOBAL_FLAG] = parsed.options[SCOPED_GLOBAL_FLAG_ALIAS];
|
|
245
|
+
delete parsed.options[SCOPED_GLOBAL_FLAG_ALIAS];
|
|
246
|
+
}
|
|
247
|
+
} else parsed = parseCliArgs(argv, commands, builtInCommands);
|
|
130
248
|
const command = parsed.command ? builtInCommands[parsed.command] ?? commands.find((candidate) => candidate.name === parsed.command || candidate.aliases?.includes(parsed.command)) : void 0;
|
|
131
249
|
if (!command?.options) return parsed;
|
|
132
250
|
for (const [name, option] of Object.entries(command.options)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-cli",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.63",
|
|
4
4
|
"description": "Developer CLI for SMRT framework - introspection, testing, and project management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -24,20 +24,20 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@happyvertical/ai": "^0.
|
|
28
|
-
"@happyvertical/files": "^0.
|
|
29
|
-
"@happyvertical/logger": "^0.
|
|
30
|
-
"@happyvertical/sql": "^0.
|
|
31
|
-
"@happyvertical/utils": "^0.
|
|
27
|
+
"@happyvertical/ai": "^0.86.1",
|
|
28
|
+
"@happyvertical/files": "^0.86.1",
|
|
29
|
+
"@happyvertical/logger": "^0.86.1",
|
|
30
|
+
"@happyvertical/sql": "^0.86.1",
|
|
31
|
+
"@happyvertical/utils": "^0.86.1",
|
|
32
32
|
"acorn": "^8.17.0",
|
|
33
33
|
"fast-glob": "3.3.3",
|
|
34
34
|
"tar": "^7.5.19",
|
|
35
|
-
"@happyvertical/smrt-agents": "0.40.
|
|
36
|
-
"@happyvertical/smrt-config": "0.40.
|
|
37
|
-
"@happyvertical/smrt-core": "0.40.
|
|
38
|
-
"@happyvertical/smrt-dev-mcp": "0.40.
|
|
39
|
-
"@happyvertical/smrt-
|
|
40
|
-
"@happyvertical/smrt-
|
|
35
|
+
"@happyvertical/smrt-agents": "0.40.63",
|
|
36
|
+
"@happyvertical/smrt-config": "0.40.63",
|
|
37
|
+
"@happyvertical/smrt-core": "0.40.63",
|
|
38
|
+
"@happyvertical/smrt-dev-mcp": "0.40.63",
|
|
39
|
+
"@happyvertical/smrt-types": "0.40.63",
|
|
40
|
+
"@happyvertical/smrt-playground": "0.40.63"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "24.13.2",
|