@jay-framework/jay-stack-cli 0.16.2 → 0.16.4
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/agent-kit-template/developer/page-components.md +10 -0
- package/agent-kit-template/plugin/INSTRUCTIONS.md +2 -1
- package/agent-kit-template/plugin/component-structure.md +8 -5
- package/agent-kit-template/plugin/contracts-guide.md +9 -1
- package/agent-kit-template/plugin/plugin-structure.md +164 -4
- package/dist/index.js +107 -15
- package/package.json +10 -10
|
@@ -125,6 +125,16 @@ src/pages/products/[slug]/
|
|
|
125
125
|
|
|
126
126
|
The jay-html template uses unprefixed bindings for page data and key-prefixed bindings for plugin data.
|
|
127
127
|
|
|
128
|
+
## Note on `.withClientDefaults()`
|
|
129
|
+
|
|
130
|
+
`withClientDefaults` is only needed when a headless component is used **inside a `forEach`** and new items can be added on the client (e.g., "Add Item" button). It provides initial ViewState for instances that don't exist during SSR.
|
|
131
|
+
|
|
132
|
+
You do NOT need it for:
|
|
133
|
+
|
|
134
|
+
- Components outside forEach — `withFastRender` provides SSR initial state
|
|
135
|
+
- Components inside a conditional (`if=`) — server data is computed for all discovered instances regardless of the condition's SSR value
|
|
136
|
+
- Static forEach where all items come from the server
|
|
137
|
+
|
|
128
138
|
## Builder API Reference
|
|
129
139
|
|
|
130
140
|
See the plugin [component-structure.md](../plugin/component-structure.md) for the full builder API: `.withProps()`, `.withServices()`, `.withContexts()`, phase rendering, and render results.
|
|
@@ -13,7 +13,8 @@ A plugin provides headless components (data + interactions, no UI) that project
|
|
|
13
13
|
3. **Define actions** with `.jay-action` metadata
|
|
14
14
|
4. **Optionally add routes** — pages for admin tools and dashboards
|
|
15
15
|
5. **Set up `plugin.yaml`** — list contracts, actions, services, contexts, routes
|
|
16
|
-
6. **
|
|
16
|
+
6. **Configure build** — dual entry points (server + client), vite.config.ts, package.json exports
|
|
17
|
+
7. **Validate** with `jay-stack validate-plugin`
|
|
17
18
|
|
|
18
19
|
## Guides
|
|
19
20
|
|
|
@@ -96,17 +96,20 @@ Runs on each request. Receives props (including `query` for query parameters) an
|
|
|
96
96
|
})
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
### `.withClientDefaults(fn)` —
|
|
99
|
+
### `.withClientDefaults(fn)` — Defaults for dynamically created forEach items
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
Required only when the component is used inside a `forEach` where new items can be added on the client. When a user adds a new item to a forEach array, the new instance has no server data — `withClientDefaults` provides the initial ViewState.
|
|
102
102
|
|
|
103
103
|
```typescript
|
|
104
|
-
.withClientDefaults(() => ({
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
.withClientDefaults((props) => ({
|
|
105
|
+
viewState: { label: `Item ${props.itemId}`, value: 0 },
|
|
106
|
+
carryForward: {},
|
|
107
107
|
}))
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
**When to use:** Component inside `forEach` + items can be added client-side.
|
|
111
|
+
**When NOT to use:** Components outside forEach, or forEach with server-only items. Use `withFastRender` instead for SSR initial state.
|
|
112
|
+
|
|
110
113
|
### `.withInteractive(ComponentConstructor)` — Client-side logic
|
|
111
114
|
|
|
112
115
|
The interactive phase runs in the browser. Use hooks here (see component-state.md):
|
|
@@ -83,7 +83,15 @@ Linked (reference another contract file):
|
|
|
83
83
|
```yaml
|
|
84
84
|
- tag: author
|
|
85
85
|
type: sub-contract
|
|
86
|
-
link: ./author.jay-contract
|
|
86
|
+
link: ./author.jay-contract # relative path (same package)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
For dynamic/materialized contracts linking to static contracts in a plugin package, use the package path:
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
- tag: gallery
|
|
93
|
+
type: sub-contract
|
|
94
|
+
link: '@my-org/my-plugin/media-gallery' # package path (cross-directory)
|
|
87
95
|
```
|
|
88
96
|
|
|
89
97
|
### `sub-contract` with `repeated: true` — Arrays
|
|
@@ -19,6 +19,16 @@ contracts:
|
|
|
19
19
|
component: productSearch
|
|
20
20
|
description: Product listing with filters and pagination
|
|
21
21
|
|
|
22
|
+
dynamic_contracts:
|
|
23
|
+
# Single contract: prefix used as the contract name directly
|
|
24
|
+
- prefix: product-page
|
|
25
|
+
component: productPage
|
|
26
|
+
generator: productPageContractGenerator
|
|
27
|
+
# Multiple contracts: prefix/name format (e.g., list/recipes, list/articles)
|
|
28
|
+
- prefix: list
|
|
29
|
+
component: dynamicList
|
|
30
|
+
generator: listContractGenerator
|
|
31
|
+
|
|
22
32
|
actions:
|
|
23
33
|
- name: searchProducts
|
|
24
34
|
action: search-products.jay-action
|
|
@@ -56,6 +66,49 @@ setup:
|
|
|
56
66
|
- `component` — Export name of the component (e.g., `productPage`)
|
|
57
67
|
- `description` — What this component does and when to use it
|
|
58
68
|
|
|
69
|
+
### Dynamic Contract Entry Fields
|
|
70
|
+
|
|
71
|
+
Dynamic contracts are generated at setup time from site-specific data (e.g., CMS collection schemas, extended product fields).
|
|
72
|
+
|
|
73
|
+
- `prefix` — Identifier for this dynamic contract group. Used as the contract name for single contracts, or as `prefix/name` for multiple.
|
|
74
|
+
- `component` — Export name of the headless component that serves these contracts
|
|
75
|
+
- `generator` — Export name of the generator function that produces contract YAML
|
|
76
|
+
|
|
77
|
+
**Single contract** — generator returns one `{ yaml }` without a name:
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
dynamic_contracts:
|
|
81
|
+
- prefix: product-page
|
|
82
|
+
component: productPage
|
|
83
|
+
generator: productPageContractGenerator
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Referenced as `contract="product-page"` in jay-html.
|
|
87
|
+
|
|
88
|
+
**Multiple contracts** — generator yields `{ name, yaml }` for each:
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
dynamic_contracts:
|
|
92
|
+
- prefix: list
|
|
93
|
+
component: dynamicList
|
|
94
|
+
generator: listContractGenerator
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Referenced as `contract="list/recipes"`, `contract="list/articles"` etc.
|
|
98
|
+
|
|
99
|
+
Contracts are materialized by `jay-stack agent-kit` or `jay-stack setup` and stored in `agent-kit/materialized-contracts/`.
|
|
100
|
+
|
|
101
|
+
**Linking to static contracts from generated YAML** — materialized contracts live in a different directory than the plugin source. Use the plugin's package path (not relative paths) for `link:` references to static contracts:
|
|
102
|
+
|
|
103
|
+
```yaml
|
|
104
|
+
# In the generated contract YAML:
|
|
105
|
+
tags:
|
|
106
|
+
- tag: gallery
|
|
107
|
+
type: sub-contract
|
|
108
|
+
link: '@my-org/my-plugin/media-gallery' # package path — works from any directory
|
|
109
|
+
# NOT: link: ./media-gallery # relative path — breaks in materialized location
|
|
110
|
+
```
|
|
111
|
+
|
|
59
112
|
### Action Entry Fields
|
|
60
113
|
|
|
61
114
|
- `name` — Action name (used with `jay-stack action <plugin>/<action>`)
|
|
@@ -161,22 +214,101 @@ my-project/
|
|
|
161
214
|
|
|
162
215
|
See `examples/jay-stack/fake-shop` for a working example.
|
|
163
216
|
|
|
217
|
+
## Dual Entry Points
|
|
218
|
+
|
|
219
|
+
Jay plugins are fullstack — they run on both server and client. The build produces two bundles:
|
|
220
|
+
|
|
221
|
+
- **Server** (`dist/index.js`) — actions, services, SSR rendering, `init()`. Built with `vite build --ssr`.
|
|
222
|
+
- **Client** (`dist/index.client.js`) — components for hydration, context tokens, `init()`. Built with `vite build`.
|
|
223
|
+
|
|
224
|
+
Create two entry files:
|
|
225
|
+
|
|
226
|
+
| File | Exports |
|
|
227
|
+
| --------------------- | ---------------------------------------------------------- |
|
|
228
|
+
| `lib/index.ts` | Actions, services, components (SSR), init, service markers |
|
|
229
|
+
| `lib/index.client.ts` | Components (hydration), context markers, init |
|
|
230
|
+
|
|
231
|
+
Actions and service providers are server-only. Components appear in **both** entries.
|
|
232
|
+
|
|
233
|
+
## Build Scripts
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"scripts": {
|
|
238
|
+
"build": "npm run clean && npm run definitions && npm run build:client && npm run build:server && npm run build:copy-assets && npm run build:types && npm run validate",
|
|
239
|
+
"definitions": "jay-cli definitions lib",
|
|
240
|
+
"build:client": "vite build",
|
|
241
|
+
"build:server": "vite build --ssr",
|
|
242
|
+
"build:copy-assets": "cp lib/*.jay-contract* dist/",
|
|
243
|
+
"build:types": "tsup lib/index.ts lib/index.client.ts --dts-only --format esm",
|
|
244
|
+
"validate": "jay-stack-cli validate-plugin",
|
|
245
|
+
"clean": "rimraf dist"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The `vite.config.ts` uses `isSsrBuild` to switch entry points:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { resolve } from 'path';
|
|
254
|
+
import { defineConfig } from 'vite';
|
|
255
|
+
import { jayStackCompiler } from '@jay-framework/compiler-jay-stack';
|
|
256
|
+
|
|
257
|
+
const jayOptions = { tsConfigFilePath: resolve(__dirname, 'tsconfig.json'), outputDir: 'build' };
|
|
258
|
+
|
|
259
|
+
export default defineConfig(({ isSsrBuild }) => ({
|
|
260
|
+
plugins: [...jayStackCompiler(jayOptions)],
|
|
261
|
+
build: {
|
|
262
|
+
minify: false,
|
|
263
|
+
ssr: isSsrBuild,
|
|
264
|
+
emptyOutDir: false,
|
|
265
|
+
lib: {
|
|
266
|
+
entry: isSsrBuild
|
|
267
|
+
? { index: resolve(__dirname, 'lib/index.ts') }
|
|
268
|
+
: { 'index.client': resolve(__dirname, 'lib/index.client.ts') },
|
|
269
|
+
formats: ['es'],
|
|
270
|
+
},
|
|
271
|
+
rollupOptions: {
|
|
272
|
+
external: [
|
|
273
|
+
'@jay-framework/component',
|
|
274
|
+
'@jay-framework/fullstack-component',
|
|
275
|
+
'@jay-framework/stack-client-runtime',
|
|
276
|
+
'@jay-framework/stack-server-runtime',
|
|
277
|
+
'@jay-framework/reactive',
|
|
278
|
+
'@jay-framework/runtime',
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
}));
|
|
283
|
+
```
|
|
284
|
+
|
|
164
285
|
## package.json Exports
|
|
165
286
|
|
|
166
|
-
For NPM packages, declare exports
|
|
287
|
+
For NPM packages, declare exports for both server and client entry points:
|
|
167
288
|
|
|
168
289
|
```json
|
|
169
290
|
{
|
|
170
291
|
"name": "@my-org/my-plugin",
|
|
171
292
|
"type": "module",
|
|
293
|
+
"main": "dist/index.js",
|
|
172
294
|
"exports": {
|
|
173
|
-
".":
|
|
174
|
-
|
|
295
|
+
".": {
|
|
296
|
+
"types": "./dist/index.d.ts",
|
|
297
|
+
"default": "./dist/index.js"
|
|
298
|
+
},
|
|
299
|
+
"./client": {
|
|
300
|
+
"types": "./dist/index.client.d.ts",
|
|
301
|
+
"default": "./dist/index.client.js"
|
|
302
|
+
},
|
|
303
|
+
"./plugin.yaml": "./plugin.yaml",
|
|
304
|
+
"./my-contract.jay-contract": "./dist/my-contract.jay-contract"
|
|
175
305
|
},
|
|
176
|
-
"files": ["dist", "plugin.yaml"
|
|
306
|
+
"files": ["dist", "plugin.yaml"]
|
|
177
307
|
}
|
|
178
308
|
```
|
|
179
309
|
|
|
310
|
+
The `./client` export is required — the framework uses it for browser-side hydration code. The `.` export handles server-side rendering and action execution.
|
|
311
|
+
|
|
180
312
|
## Plugin-Contributed Agent-Kit Guides
|
|
181
313
|
|
|
182
314
|
A plugin can include guides that are merged into the project's agent-kit during `jay-stack agent-kit`. Create an `agent-kit/` folder with subfolders for each role:
|
|
@@ -192,6 +324,34 @@ my-plugin/
|
|
|
192
324
|
└── my-plugin-extending.md # How to extend the plugin
|
|
193
325
|
```
|
|
194
326
|
|
|
327
|
+
For NPM packages, include `agent-kit` in the `files` array:
|
|
328
|
+
|
|
329
|
+
```json
|
|
330
|
+
{
|
|
331
|
+
"files": ["dist", "plugin.yaml", "agent-kit"]
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
No `plugin.yaml` declaration needed — the CLI discovers guides by scanning the `agent-kit/` directory. Files are copied as-is into the project's `agent-kit/{role}/`.
|
|
336
|
+
|
|
337
|
+
**File format convention:** The first line after the `#` heading is used as the description in the INSTRUCTIONS.md index table. Write it as a short sentence explaining when to use this guide:
|
|
338
|
+
|
|
339
|
+
```markdown
|
|
340
|
+
# Scroll Carousel
|
|
341
|
+
|
|
342
|
+
Horizontal slider with prev/next buttons and edge detection. Headless component — requires import.
|
|
343
|
+
|
|
344
|
+
## Import
|
|
345
|
+
|
|
346
|
+
...
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
The INSTRUCTIONS.md table will show:
|
|
350
|
+
|
|
351
|
+
```
|
|
352
|
+
| scroll-carousel.md | my-plugin | Horizontal slider with prev/next buttons and edge detection. Headless component — requires import. |
|
|
353
|
+
```
|
|
354
|
+
|
|
195
355
|
## Reference Declarations
|
|
196
356
|
|
|
197
357
|
Plugins can declare reference data generated by `jay-stack agent-kit`:
|
package/dist/index.js
CHANGED
|
@@ -8,15 +8,19 @@ import path from "path";
|
|
|
8
8
|
import fs, { promises } from "fs";
|
|
9
9
|
import YAML from "yaml";
|
|
10
10
|
import { getLogger, createDevLogger, setDevLogger } from "@jay-framework/logger";
|
|
11
|
-
import { parseJayFile, JAY_IMPORT_RESOLVER, generateElementDefinitionFile, ContractTagType, parseContract, generateElementFile, htmlElementTagNameMap } from "@jay-framework/compiler-jay-html";
|
|
11
|
+
import { parseJayFile, JAY_IMPORT_RESOLVER, generateElementDefinitionFile, ContractTagType, parseContract, generateElementFile, generateServerElementFile, htmlElementTagNameMap } from "@jay-framework/compiler-jay-html";
|
|
12
12
|
import { JAY_CONTRACT_EXTENSION, JAY_EXTENSION, resolvePluginManifest, LOCAL_PLUGIN_PATH, JayAtomicType, JayEnumType, loadPluginManifest, RuntimeMode, GenerateTarget } from "@jay-framework/compiler-shared";
|
|
13
|
-
import { listContracts, materializeContracts } from "@jay-framework/stack-server-runtime";
|
|
13
|
+
import { scanPlugins as scanPlugins$1, listContracts, materializeContracts } from "@jay-framework/stack-server-runtime";
|
|
14
14
|
import { listContracts as listContracts2, materializeContracts as materializeContracts2 } from "@jay-framework/stack-server-runtime";
|
|
15
15
|
import { Command } from "commander";
|
|
16
16
|
import chalk from "chalk";
|
|
17
17
|
import { createRequire } from "module";
|
|
18
18
|
import { glob } from "glob";
|
|
19
19
|
import { parse } from "node-html-parser";
|
|
20
|
+
import path$1 from "node:path";
|
|
21
|
+
import fs$1 from "node:fs/promises";
|
|
22
|
+
import fsSync from "node:fs";
|
|
23
|
+
import { fileURLToPath } from "node:url";
|
|
20
24
|
const DEFAULT_CONFIG = {
|
|
21
25
|
devServer: {
|
|
22
26
|
portRange: [3e3, 3100],
|
|
@@ -3452,6 +3456,14 @@ async function validatePackageJson(context, result) {
|
|
|
3452
3456
|
suggestion: 'Add "." export for the main module entry'
|
|
3453
3457
|
});
|
|
3454
3458
|
}
|
|
3459
|
+
if (!packageJson.exports["./client"]) {
|
|
3460
|
+
result.warnings.push({
|
|
3461
|
+
type: "export-mismatch",
|
|
3462
|
+
message: 'package.json exports missing "./client" entry point',
|
|
3463
|
+
location: packageJsonPath,
|
|
3464
|
+
suggestion: 'Add "./client": "./dist/index.client.js" to exports. The client bundle provides components for hydration and client-side contexts. Build with: vite build (client) + vite build --ssr (server)'
|
|
3465
|
+
});
|
|
3466
|
+
}
|
|
3455
3467
|
if (context.manifest.contracts) {
|
|
3456
3468
|
for (const contract of context.manifest.contracts) {
|
|
3457
3469
|
const contractExport = "./" + contract.contract;
|
|
@@ -4159,6 +4171,16 @@ async function validateJayFiles(options = {}) {
|
|
|
4159
4171
|
} else if (options.verbose) {
|
|
4160
4172
|
getLogger().info(chalk.green(`✓ ${relativePath}`));
|
|
4161
4173
|
}
|
|
4174
|
+
const serverElementFile = generateServerElementFile(parsedFile.val);
|
|
4175
|
+
if (serverElementFile.validations.length > 0) {
|
|
4176
|
+
for (const validation of serverElementFile.validations) {
|
|
4177
|
+
errors.push({
|
|
4178
|
+
file: relativePath,
|
|
4179
|
+
message: `[SSR] ${validation}`,
|
|
4180
|
+
stage: "generate"
|
|
4181
|
+
});
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
4162
4184
|
} catch (error) {
|
|
4163
4185
|
errors.push({
|
|
4164
4186
|
file: relativePath,
|
|
@@ -4622,32 +4644,101 @@ program.command("validate-plugin [path]").description("Validate a Jay Stack plug
|
|
|
4622
4644
|
});
|
|
4623
4645
|
const ALL_ROLES = ["designer", "developer", "plugin"];
|
|
4624
4646
|
async function ensureAgentKitDocs(projectRoot, _force, mode) {
|
|
4625
|
-
const
|
|
4626
|
-
const
|
|
4627
|
-
const
|
|
4628
|
-
const agentKitDir = path2.join(projectRoot, "agent-kit");
|
|
4629
|
-
const thisDir = path2.dirname(fileURLToPath(import.meta.url));
|
|
4630
|
-
const templateDir = path2.resolve(thisDir, "..", "agent-kit-template");
|
|
4647
|
+
const agentKitDir = path$1.join(projectRoot, "agent-kit");
|
|
4648
|
+
const thisDir = path$1.dirname(fileURLToPath(import.meta.url));
|
|
4649
|
+
const templateDir = path$1.resolve(thisDir, "..", "agent-kit-template");
|
|
4631
4650
|
const roles = mode && ALL_ROLES.includes(mode) ? [mode] : ALL_ROLES;
|
|
4632
4651
|
for (const role of roles) {
|
|
4633
|
-
const roleTemplateDir =
|
|
4634
|
-
const roleOutputDir =
|
|
4652
|
+
const roleTemplateDir = path$1.join(templateDir, role);
|
|
4653
|
+
const roleOutputDir = path$1.join(agentKitDir, role);
|
|
4635
4654
|
let files;
|
|
4636
4655
|
try {
|
|
4637
|
-
files = (await
|
|
4656
|
+
files = (await fs$1.readdir(roleTemplateDir)).filter((f) => f.endsWith(".md"));
|
|
4638
4657
|
} catch {
|
|
4639
4658
|
continue;
|
|
4640
4659
|
}
|
|
4641
|
-
await
|
|
4660
|
+
await fs$1.mkdir(roleOutputDir, { recursive: true });
|
|
4642
4661
|
for (const filename of files) {
|
|
4643
|
-
await
|
|
4644
|
-
|
|
4645
|
-
|
|
4662
|
+
await fs$1.copyFile(
|
|
4663
|
+
path$1.join(roleTemplateDir, filename),
|
|
4664
|
+
path$1.join(roleOutputDir, filename)
|
|
4646
4665
|
);
|
|
4647
4666
|
getLogger().info(chalk.gray(` Created agent-kit/${role}/${filename}`));
|
|
4648
4667
|
}
|
|
4649
4668
|
}
|
|
4650
4669
|
}
|
|
4670
|
+
async function mergePluginAgentKitGuides(projectRoot, mode) {
|
|
4671
|
+
const plugins = await scanPlugins$1({ projectRoot });
|
|
4672
|
+
const agentKitDir = path$1.join(projectRoot, "agent-kit");
|
|
4673
|
+
const roles = mode && ALL_ROLES.includes(mode) ? [mode] : ALL_ROLES;
|
|
4674
|
+
const copiedPerRole = /* @__PURE__ */ new Map();
|
|
4675
|
+
for (const [, plugin] of plugins) {
|
|
4676
|
+
const pluginAgentKitDir = path$1.join(plugin.pluginPath, "agent-kit");
|
|
4677
|
+
if (!fsSync.existsSync(pluginAgentKitDir))
|
|
4678
|
+
continue;
|
|
4679
|
+
for (const role of roles) {
|
|
4680
|
+
const roleSourceDir = path$1.join(pluginAgentKitDir, role);
|
|
4681
|
+
let files;
|
|
4682
|
+
try {
|
|
4683
|
+
files = (await fs$1.readdir(roleSourceDir)).filter(
|
|
4684
|
+
(f) => f.endsWith(".md") && f !== "INSTRUCTIONS.md"
|
|
4685
|
+
);
|
|
4686
|
+
} catch {
|
|
4687
|
+
continue;
|
|
4688
|
+
}
|
|
4689
|
+
if (files.length === 0)
|
|
4690
|
+
continue;
|
|
4691
|
+
const roleOutputDir = path$1.join(agentKitDir, role);
|
|
4692
|
+
await fs$1.mkdir(roleOutputDir, { recursive: true });
|
|
4693
|
+
for (const filename of files) {
|
|
4694
|
+
const sourcePath = path$1.join(roleSourceDir, filename);
|
|
4695
|
+
await fs$1.copyFile(sourcePath, path$1.join(roleOutputDir, filename));
|
|
4696
|
+
let description = "";
|
|
4697
|
+
try {
|
|
4698
|
+
const content = await fs$1.readFile(sourcePath, "utf-8");
|
|
4699
|
+
const lines = content.split("\n");
|
|
4700
|
+
let pastHeading = false;
|
|
4701
|
+
for (const line of lines) {
|
|
4702
|
+
if (line.startsWith("# ")) {
|
|
4703
|
+
pastHeading = true;
|
|
4704
|
+
continue;
|
|
4705
|
+
}
|
|
4706
|
+
if (pastHeading && line.trim()) {
|
|
4707
|
+
description = line.trim();
|
|
4708
|
+
break;
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
} catch {
|
|
4712
|
+
}
|
|
4713
|
+
if (!copiedPerRole.has(role))
|
|
4714
|
+
copiedPerRole.set(role, []);
|
|
4715
|
+
copiedPerRole.get(role).push({ filename, pluginName: plugin.name, description });
|
|
4716
|
+
getLogger().info(
|
|
4717
|
+
chalk.gray(
|
|
4718
|
+
` Copied agent-kit/${role}/${filename} from plugin "${plugin.name}"`
|
|
4719
|
+
)
|
|
4720
|
+
);
|
|
4721
|
+
}
|
|
4722
|
+
}
|
|
4723
|
+
}
|
|
4724
|
+
for (const [role, entries] of copiedPerRole) {
|
|
4725
|
+
const instructionsPath = path$1.join(agentKitDir, role, "INSTRUCTIONS.md");
|
|
4726
|
+
if (!fsSync.existsSync(instructionsPath))
|
|
4727
|
+
continue;
|
|
4728
|
+
const lines = [
|
|
4729
|
+
"",
|
|
4730
|
+
"## Plugin-Contributed Guides",
|
|
4731
|
+
"",
|
|
4732
|
+
"| File | Plugin | Description |",
|
|
4733
|
+
"| --- | --- | --- |"
|
|
4734
|
+
];
|
|
4735
|
+
for (const { filename, pluginName, description } of entries) {
|
|
4736
|
+
lines.push(`| [${filename}](${filename}) | ${pluginName} | ${description} |`);
|
|
4737
|
+
}
|
|
4738
|
+
lines.push("");
|
|
4739
|
+
await fs$1.appendFile(instructionsPath, lines.join("\n"));
|
|
4740
|
+
}
|
|
4741
|
+
}
|
|
4651
4742
|
async function generatePluginReferences(projectRoot, options, initErrors, viteServer) {
|
|
4652
4743
|
const { discoverPluginsWithReferences, executePluginReferences } = await import("@jay-framework/stack-server-runtime");
|
|
4653
4744
|
const plugins = await discoverPluginsWithReferences({
|
|
@@ -4782,6 +4873,7 @@ program.command("agent-kit").description(
|
|
|
4782
4873
|
try {
|
|
4783
4874
|
if (!options.list) {
|
|
4784
4875
|
await ensureAgentKitDocs(projectRoot, options.force, options.mode);
|
|
4876
|
+
await mergePluginAgentKitGuides(projectRoot, options.mode);
|
|
4785
4877
|
if (options.references !== false) {
|
|
4786
4878
|
await generatePluginReferences(projectRoot, options, initErrors, viteServer);
|
|
4787
4879
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/jay-stack-cli",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.4",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
"test:watch": "vitest"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@jay-framework/compiler-jay-html": "^0.16.
|
|
28
|
-
"@jay-framework/compiler-shared": "^0.16.
|
|
29
|
-
"@jay-framework/dev-server": "^0.16.
|
|
30
|
-
"@jay-framework/editor-server": "^0.16.
|
|
31
|
-
"@jay-framework/fullstack-component": "^0.16.
|
|
32
|
-
"@jay-framework/logger": "^0.16.
|
|
33
|
-
"@jay-framework/plugin-validator": "^0.16.
|
|
34
|
-
"@jay-framework/stack-server-runtime": "^0.16.
|
|
27
|
+
"@jay-framework/compiler-jay-html": "^0.16.4",
|
|
28
|
+
"@jay-framework/compiler-shared": "^0.16.4",
|
|
29
|
+
"@jay-framework/dev-server": "^0.16.4",
|
|
30
|
+
"@jay-framework/editor-server": "^0.16.4",
|
|
31
|
+
"@jay-framework/fullstack-component": "^0.16.4",
|
|
32
|
+
"@jay-framework/logger": "^0.16.4",
|
|
33
|
+
"@jay-framework/plugin-validator": "^0.16.4",
|
|
34
|
+
"@jay-framework/stack-server-runtime": "^0.16.4",
|
|
35
35
|
"chalk": "^4.1.2",
|
|
36
36
|
"commander": "^14.0.0",
|
|
37
37
|
"express": "^5.0.1",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"yaml": "^2.3.4"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@jay-framework/dev-environment": "^0.16.
|
|
45
|
+
"@jay-framework/dev-environment": "^0.16.4",
|
|
46
46
|
"@types/express": "^5.0.2",
|
|
47
47
|
"@types/node": "^22.15.21",
|
|
48
48
|
"nodemon": "^3.0.3",
|