@jay-framework/jay-stack-cli 0.21.0 → 0.22.1

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.
@@ -1,28 +1,26 @@
1
1
  # CLI Commands Reference
2
2
 
3
- ## jay-stack setup
3
+ ## jay-stack-cli setup
4
4
 
5
- Run plugin setup. Plugins can create configuration files, generate reference data, and validate their prerequisites.
5
+ Run plugin setup. Plugins create configuration files, prompt for credentials, and validate services.
6
6
 
7
7
  ```bash
8
- # Run setup for all installed plugins
9
- jay-stack setup
8
+ # Run setup for all installed plugins (interactive — may prompt for input)
9
+ jay-stack-cli setup
10
10
 
11
11
  # Run setup for a specific plugin
12
- jay-stack setup wix-stores
12
+ jay-stack-cli setup wix-stores
13
13
 
14
14
  # Re-run setup (e.g., after config change)
15
- jay-stack setup wix-data --force
16
- ```
17
-
18
- Plugins declare their setup handler in `plugin.yaml`. Setup does two things:
15
+ jay-stack-cli setup --force
19
16
 
20
- 1. **Config templates**: Creates `config/<plugin>.yaml` with placeholder credentials if missing
21
- 2. **Credential validation**: Attempts to initialize services, reports success or failure
17
+ # Non-interactive mode (creates config templates without prompting)
18
+ jay-stack-cli setup --no-interactive
19
+ ```
22
20
 
23
- Reference data (product catalogs, collection schemas) is generated by `jay-stack agent-kit`, not by setup.
21
+ Setup is **interactive by default** plugins may prompt for API keys and credentials. Use `--no-interactive` in CI/scripts.
24
22
 
25
- Run this after installing new plugins, before `jay-stack agent-kit`.
23
+ Run this after installing new plugins, before `jay-stack-cli agent-kit`.
26
24
 
27
25
  ## jay-stack agent-kit
28
26
 
@@ -51,23 +51,22 @@ src/pages/products/
51
51
 
52
52
  The static `ceramic-flower-vase/` route takes priority over `[slug]/` for that URL, but all other product URLs still use the dynamic route.
53
53
 
54
- ### Static Override Params (`jay-params`)
54
+ ### Static Override Params and Headless Component Props
55
55
 
56
- Static override routes often use the same contract as the dynamic route they override. Since the static route has no dynamic directory segment, the params must be declared explicitly using `<script type="application/jay-params">`:
56
+ Static override routes use the same headless component as the dynamic route they override. Since the static route has no dynamic directory segment, the params must be declared in the headless component's YAML body:
57
57
 
58
58
  ```html
59
59
  <!-- src/pages/products/ceramic-flower-vase/page.jay-html -->
60
60
  <html>
61
61
  <head>
62
- <script type="application/jay-params">
63
- slug: ceramic-flower-vase
64
- </script>
65
62
  <script
66
63
  type="application/jay-headless"
67
64
  plugin="wix-stores"
68
65
  contract="product-page"
69
66
  key="product"
70
- ></script>
67
+ >
68
+ slug: ceramic-flower-vase
69
+ </script>
71
70
  </head>
72
71
  <body>
73
72
  <h1>{product.productName}</h1>
@@ -75,7 +74,20 @@ Static override routes often use the same contract as the dynamic route they ove
75
74
  </html>
76
75
  ```
77
76
 
78
- The script body is YAML. The declared params are passed to the component as if extracted from a dynamic URL segment. Without this, the component would receive no param values.
77
+ The script body is YAML. Values are passed to the component as props alongside route params. This same mechanism is used for any per-component configuration:
78
+
79
+ ```html
80
+ <script
81
+ type="application/jay-headless"
82
+ plugin="@jay-framework/markdown"
83
+ contract="markdown-pages"
84
+ key="post"
85
+ >
86
+ contentDir: ./content
87
+ </script>
88
+ ```
89
+
90
+ > **Note:** `<script type="application/jay-params">` is deprecated. Move param values into the headless component's script tag body.
79
91
 
80
92
  ## Page Files
81
93
 
@@ -1,28 +1,34 @@
1
1
  # CLI Commands Reference
2
2
 
3
- ## jay-stack setup
3
+ ## jay-stack-cli setup
4
4
 
5
- Run plugin setup. Plugins can create configuration files, generate reference data, and validate their prerequisites.
5
+ Run plugin setup. Plugins can create configuration files, prompt for credentials, and validate their prerequisites.
6
6
 
7
7
  ```bash
8
- # Run setup for all installed plugins
9
- jay-stack setup
8
+ # Run setup for all installed plugins (interactive — may prompt for input)
9
+ jay-stack-cli setup
10
10
 
11
11
  # Run setup for a specific plugin
12
- jay-stack setup wix-stores
12
+ jay-stack-cli setup wix-stores
13
13
 
14
14
  # Re-run setup (e.g., after config change)
15
- jay-stack setup wix-data --force
15
+ jay-stack-cli setup wix-data --force
16
+
17
+ # Non-interactive mode (CI/scripts — creates config templates without prompting)
18
+ jay-stack-cli setup --no-interactive
16
19
  ```
17
20
 
18
- Plugins declare their setup handler in `plugin.yaml`. Setup does two things:
21
+ Setup is **interactive by default** plugins can prompt for API keys, credentials, and configuration choices. In non-interactive mode (`--no-interactive`), prompts are skipped and plugins create config templates with placeholders instead.
22
+
23
+ Plugins declare their setup handler in `plugin.yaml`. Setup does three things:
19
24
 
20
- 1. **Config templates**: Creates `config/<plugin>.yaml` with placeholder credentials if missing
21
- 2. **Credential validation**: Attempts to initialize services, reports success or failure
25
+ 1. **Config templates**: Creates `config/<plugin>.yaml` with credentials (interactive) or placeholders (non-interactive)
26
+ 2. **Credential prompts**: Asks for API keys and configuration when running interactively
27
+ 3. **Service validation**: Attempts to initialize services, reports success or failure
22
28
 
23
- Reference data (product catalogs, collection schemas) is generated by `jay-stack agent-kit`, not by setup.
29
+ Reference data (product catalogs, collection schemas) is generated by `jay-stack-cli agent-kit`, not by setup.
24
30
 
25
- Run this after installing new plugins, before `jay-stack agent-kit`.
31
+ Run this after installing new plugins, before `jay-stack-cli agent-kit`.
26
32
 
27
33
  ## jay-stack agent-kit
28
34
 
@@ -51,23 +51,22 @@ src/pages/products/
51
51
 
52
52
  The static `ceramic-flower-vase/` route takes priority over `[slug]/` for that URL, but all other product URLs still use the dynamic route.
53
53
 
54
- ### Static Override Params (`jay-params`)
54
+ ### Static Override Params and Headless Component Props
55
55
 
56
- Static override routes often use the same contract as the dynamic route they override. Since the static route has no dynamic directory segment, the params must be declared explicitly using `<script type="application/jay-params">`:
56
+ Static override routes use the same headless component as the dynamic route they override. Since the static route has no dynamic directory segment, the params must be declared in the headless component's YAML body:
57
57
 
58
58
  ```html
59
59
  <!-- src/pages/products/ceramic-flower-vase/page.jay-html -->
60
60
  <html>
61
61
  <head>
62
- <script type="application/jay-params">
63
- slug: ceramic-flower-vase
64
- </script>
65
62
  <script
66
63
  type="application/jay-headless"
67
64
  plugin="wix-stores"
68
65
  contract="product-page"
69
66
  key="product"
70
- ></script>
67
+ >
68
+ slug: ceramic-flower-vase
69
+ </script>
71
70
  </head>
72
71
  <body>
73
72
  <h1>{product.productName}</h1>
@@ -75,7 +74,20 @@ Static override routes often use the same contract as the dynamic route they ove
75
74
  </html>
76
75
  ```
77
76
 
78
- The script body is YAML. The declared params are passed to the component as if extracted from a dynamic URL segment. Without this, the component would receive no param values.
77
+ The script body is YAML. Values are passed to the component as props alongside route params. This same mechanism is used for any per-component configuration:
78
+
79
+ ```html
80
+ <script
81
+ type="application/jay-headless"
82
+ plugin="@jay-framework/markdown"
83
+ contract="markdown-pages"
84
+ key="post"
85
+ >
86
+ contentDir: ./content
87
+ </script>
88
+ ```
89
+
90
+ > **Note:** `<script type="application/jay-params">` is deprecated. Move param values into the headless component's script tag body.
79
91
 
80
92
  ## Page Files
81
93
 
@@ -14,6 +14,56 @@ The devops role handles the production lifecycle: building artifacts, configurin
14
14
  4. **Invalidate** — rebuild specific pages when data changes
15
15
  5. **Admin** — run plugin CLI commands via `jay-stack run <plugin>/<command>` (media upload, data sync, cache purge)
16
16
 
17
+ ## Plugin Setup
18
+
19
+ Plugins may need credentials or configuration before they can run. The setup command handles this.
20
+
21
+ ```bash
22
+ # Default (non-interactive) — exits with structured output if input is needed
23
+ jay-stack-cli setup
24
+
25
+ # Interactive — prompts for credentials via terminal
26
+ jay-stack-cli setup --interactive
27
+
28
+ # With pre-provided answers (for automation)
29
+ jay-stack-cli setup --answers answers.yaml
30
+ ```
31
+
32
+ ### Automated setup (CI / agents)
33
+
34
+ When running `jay-stack-cli setup` without `--interactive`, plugins that need user input will exit with structured YAML output:
35
+
36
+ ```yaml
37
+ setup-needs-answer:
38
+ plugin: wix-server-client
39
+ key: api-key
40
+ type: input
41
+ message: 'Enter your API key'
42
+ ```
43
+
44
+ To provide the answer, create a YAML file and re-run:
45
+
46
+ ```yaml
47
+ # answers.yaml
48
+ api-key: 'IST.abc123...'
49
+ ```
50
+
51
+ ```bash
52
+ jay-stack-cli setup --answers answers.yaml
53
+ ```
54
+
55
+ Repeat until all plugins report `configured`. The flow is iterative — each run may reveal the next question.
56
+
57
+ ### Setup order
58
+
59
+ Run setup **before** agent-kit and build:
60
+
61
+ ```bash
62
+ jay-stack-cli setup # 1. Configure plugins
63
+ jay-stack-cli agent-kit # 2. Generate contracts and discovery data
64
+ jay-stack-cli build # 3. Production build
65
+ ```
66
+
17
67
  ## Guides
18
68
 
19
69
  | File | Topic |
@@ -13,8 +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. **Optionally add validators** — custom jay-html validation rules
16
- 6. **Optionally add setup/references handlers** — config templating, add-menu generation
17
- 7. **Set up `plugin.yaml`** — list contracts, actions, services, contexts, routes, validators, setup
16
+ 6. **Optionally add setup/agentkit handlers** — config templating, add-menu generation
17
+ 7. **Set up `plugin.yaml`** — list contracts, actions, services, contexts, routes, validators, setup, agentkit
18
18
  8. **Configure build** — dual entry points (server + client), vite.config.ts, package.json exports
19
19
  9. **Validate** with `jay-stack validate-plugin`
20
20
 
@@ -25,8 +25,8 @@ The plugin participates in four CLI commands, each running different hooks:
25
25
  | Command | When | What runs from your plugin |
26
26
  | --------------------------- | ------------------ | ---------------------------------------------------------------------------------- |
27
27
  | `jay-stack validate-plugin` | Plugin development | Checks plugin.yaml structure, contracts, exports, handler references |
28
- | `jay-stack setup <plugin>` | Project setup | `setup.handler` — creates config files, validates credentials |
29
- | `jay-stack agent-kit` | Before development | `setup.references` — generates add-menu items, reference data |
28
+ | `jay-stack setup <plugin>` | Project setup | `setup` — creates config files, validates credentials |
29
+ | `jay-stack agent-kit` | Before development | `agentkit` — generates add-menu items, reference data, skills, thumbnails |
30
30
  | `jay-stack validate` | During development | `validators[].handler` — runs your validation rules against project jay-html files |
31
31
 
32
32
  **`validate-plugin`** validates YOUR plugin's structure. Run it during plugin development.
@@ -66,12 +66,9 @@ validators:
66
66
  handler: validateMediaOptimization
67
67
  description: Ensures media URLs use resize parameters
68
68
 
69
- setup:
70
- handler: setup-handler
71
- references: references-handler
72
- configTemplate:
73
- - source: templates/config.yaml
74
- target: my-plugin.yaml
69
+ setup: setup-handler
70
+ agentkit: agentkit-handler
71
+ description: Configure My Plugin
75
72
  ```
76
73
 
77
74
  ### Contract Entry Fields
@@ -201,16 +198,16 @@ Commands are CLI operations run via `jay-stack run`. Use `makeCliCommand()` to c
201
198
 
202
199
  Validators run during `jay-stack validate` against every parsed jay-html file in the project. See [validation.md](validation.md) for implementation details.
203
200
 
204
- ### Setup Fields
201
+ ### Setup and agent-kit fields
205
202
 
206
- - `handler` — Export name (NPM) or relative path (local) for `jay-stack setup <plugin>`. Creates config files, validates credentials and services.
207
- - `references` — Export name (NPM) or relative path (local) for `jay-stack agent-kit`. Generates discovery data: add-menu items, reference files.
208
- - `description` — (optional) What this setup does
203
+ - `setup` — Export name (NPM) or relative path (local) for `jay-stack setup <plugin>`. Creates config files, validates credentials and services.
204
+ - `agentkit` — Export name (NPM) or relative path (local) for `jay-stack agent-kit`. Generates discovery data: add-menu catalogs, reference files, skills, thumbnails.
205
+ - `description` — (optional, top-level) Human-readable description of what setup validates
209
206
 
210
- **NPM plugins:** `handler` and `references` are export names from the package entry point.
207
+ **NPM plugins:** `setup` and `agentkit` are export names from the package entry point.
211
208
  **Local plugins:** relative paths to the handler modules.
212
209
 
213
- `jay-stack validate-plugin` checks that these handlers exist and are correctly exported.
210
+ `jay-stack validate-plugin` checks that declared handlers exist and are correctly exported.
214
211
 
215
212
  See [setup-guide.md](setup-guide.md) for implementation details.
216
213
 
@@ -1,36 +1,40 @@
1
- # Plugin Setup & References
1
+ # Plugin Setup & Agent-Kit
2
2
 
3
3
  Plugins can provide two hooks for project configuration and AI agent discovery:
4
4
 
5
- - **Setup handler** — runs during `jay-stack setup <plugin>`. Creates config files, validates credentials, copies AIditor assets.
6
- - **References handler** — runs during `jay-stack agent-kit`. Generates discovery data (add-menu items, reference files) using live services.
5
+ - **Setup handler** (`setup` in `plugin.yaml`) — runs during `jay-stack setup <plugin>`. Creates config files, validates credentials.
6
+ - **Agent-kit handler** (`agentkit` in `plugin.yaml`) — runs during `jay-stack agent-kit`. Generates discovery data (add-menu catalogs, reference files, skills, thumbnails) using live services when needed.
7
7
 
8
8
  ## When Each Runs
9
9
 
10
10
  ```
11
- jay-stack setup <plugin> → setup.handler()
12
- jay-stack agent-kit → setup.references() (after contract materialization)
11
+ jay-stack setup <plugin> → setup handler (config + credentials)
12
+ jay-stack agent-kit → agentkit handler (after contract materialization)
13
13
  ```
14
14
 
15
- Setup runs once when a project first installs the plugin. Agent-kit runs whenever the developer regenerates the agent kit — it can use live services to produce fresh data.
15
+ Setup runs when a project configures the plugin. Agent-kit runs whenever the developer regenerates the agent kit — it can use live services to produce fresh data.
16
16
 
17
17
  ## Declaring in plugin.yaml
18
18
 
19
19
  ```yaml
20
- setup:
21
- handler: setupMyPlugin # export name (NPM) or ./path (local)
22
- references: generateMyReferences # export name (NPM) or ./path (local)
23
- description: Install My Plugin config and AIditor catalog
20
+ name: my-plugin
21
+ setup: setupMyPlugin # export name (NPM) or ./path (local) — optional
22
+ agentkit: generateMyAgentKit # export name (NPM) or ./path (local) — optional
23
+ description: Validate credentials and install config # optional, top-level
24
24
  ```
25
25
 
26
- **NPM plugins:** both values are export names from the package entry point (`lib/index.ts`).
27
- **Local plugins:** relative paths to the handler modules.
26
+ **NPM plugins:** `setup` and `agentkit` are export names from the package entry point (`lib/index.ts`).
27
+ **Local plugins:** relative paths to handler modules (e.g. `agentkit: ./agentkit` — export `agentkit` or `default` from that module).
28
28
 
29
- `jay-stack validate-plugin` checks that these exist and are correctly exported.
29
+ `jay-stack validate-plugin` checks that declared handlers exist and are correctly exported.
30
30
 
31
31
  ## Writing a Setup Handler
32
32
 
33
- The setup handler creates config files and AIditor assets. It receives a `PluginSetupContext` and returns a `PluginSetupResult`.
33
+ The setup handler creates config files, validates services, and can prompt the user for credentials. It receives a `PluginSetupContext` and returns a `PluginSetupResult`.
34
+
35
+ **Do not** write add-menu catalogs in setup — use the agent-kit handler.
36
+
37
+ ### Basic setup (non-interactive)
34
38
 
35
39
  ```typescript
36
40
  import type { PluginSetupContext, PluginSetupResult } from '@jay-framework/stack-server-runtime';
@@ -43,13 +47,12 @@ export async function setupMyPlugin(ctx: PluginSetupContext): Promise<PluginSetu
43
47
  }
44
48
 
45
49
  const configCreated: string[] = [];
50
+ const configPath = path.join(ctx.configDir, '.my-plugin.yaml');
46
51
 
47
- // Write AIditor add-menu catalog
48
- const addMenuPath = path.join(ctx.projectRoot, 'agent-kit/aiditor/add-menu/my-plugin.yaml');
49
- if (!fs.existsSync(addMenuPath) || ctx.force) {
50
- fs.mkdirSync(path.dirname(addMenuPath), { recursive: true });
51
- fs.writeFileSync(addMenuPath, templateContent, 'utf-8');
52
- configCreated.push('agent-kit/aiditor/add-menu/my-plugin.yaml');
52
+ if (!fs.existsSync(configPath) || ctx.force) {
53
+ fs.mkdirSync(ctx.configDir, { recursive: true });
54
+ fs.writeFileSync(configPath, '# My Plugin config\napiKey: "<your-api-key>"\n', 'utf-8');
55
+ configCreated.push('config/.my-plugin.yaml');
53
56
  }
54
57
 
55
58
  return {
@@ -57,22 +60,130 @@ export async function setupMyPlugin(ctx: PluginSetupContext): Promise<PluginSetu
57
60
  configCreated,
58
61
  message:
59
62
  configCreated.length > 0
60
- ? 'My Plugin catalog installed.'
61
- : 'My Plugin catalog already present (use --force to rewrite).',
63
+ ? 'My Plugin config installed.'
64
+ : 'My Plugin config already present (use --force to rewrite).',
65
+ };
66
+ }
67
+ ```
68
+
69
+ ### Interactive setup (with prompts)
70
+
71
+ When the setup handler needs user input (API keys, credentials, configuration choices), use `ctx.prompt`:
72
+
73
+ ```typescript
74
+ export async function setupMyPlugin(ctx: PluginSetupContext): Promise<PluginSetupResult> {
75
+ const configPath = path.join(ctx.configDir, '.my-plugin.yaml');
76
+
77
+ // Already configured — skip unless --force
78
+ if (fs.existsSync(configPath) && !ctx.force) {
79
+ return { status: 'configured', message: 'Already configured' };
80
+ }
81
+
82
+ // In non-interactive mode, create a template and ask the user to fill it in later
83
+ if (!ctx.interactive) {
84
+ fs.mkdirSync(ctx.configDir, { recursive: true });
85
+ fs.writeFileSync(configPath, 'apiKey: "<your-api-key>"\n', 'utf-8');
86
+ return {
87
+ status: 'needs-config',
88
+ configCreated: ['config/.my-plugin.yaml'],
89
+ message: 'Run `jay-stack-cli setup` interactively to enter your API key',
90
+ };
91
+ }
92
+
93
+ // Interactive mode — prompt the user
94
+ const apiKey = await ctx.prompt.input({
95
+ message: 'Enter your API key (create one at https://example.com/api-keys):',
96
+ validate: (v) => (v.trim() ? true : 'API key is required'),
97
+ });
98
+
99
+ const region = await ctx.prompt.select({
100
+ message: 'Select your region:',
101
+ choices: [
102
+ { name: 'US East', value: 'us-east' },
103
+ { name: 'EU West', value: 'eu-west' },
104
+ ],
105
+ });
106
+
107
+ fs.mkdirSync(ctx.configDir, { recursive: true });
108
+ fs.writeFileSync(configPath, `apiKey: "${apiKey.trim()}"\nregion: ${region}\n`, 'utf-8');
109
+
110
+ return {
111
+ status: 'configured',
112
+ configCreated: ['config/.my-plugin.yaml'],
113
+ message: 'Credentials configured successfully',
62
114
  };
63
115
  }
64
116
  ```
65
117
 
118
+ ### Setup modes
119
+
120
+ Setup runs in three modes:
121
+
122
+ | Mode | Command | `ctx.interactive` | `ctx.prompt` behavior |
123
+ | ----------------------------- | ----------------------------------------- | ----------------- | ----------------------------------------------------- |
124
+ | **Default** (agents, CI) | `jay-stack-cli setup` | `false` | Throws `SetupNeedsAnswerError` with structured output |
125
+ | **Interactive** (humans) | `jay-stack-cli setup --interactive` | `true` | Prompts via terminal |
126
+ | **Answers file** (automation) | `jay-stack-cli setup --answers file.yaml` | `false` | Reads from file, throws if missing |
127
+
128
+ In default mode, when a prompt has no answer, the CLI exits with structured YAML telling the caller what's needed. Agents can then provide the answer via `--answers` and re-run.
129
+
130
+ ### Idempotency requirement
131
+
132
+ Setup handlers **must be idempotent** — re-running with the same answers must produce the same result without side effects. This is critical because:
133
+
134
+ - Agents re-run setup iteratively as they provide answers one at a time
135
+ - Users re-run setup after fixing credentials
136
+ - CI pipelines may run setup on every deploy
137
+
138
+ **Rules:**
139
+
140
+ 1. Check if config already exists before creating it — skip if present (unless `ctx.force`)
141
+ 2. Check if credentials are already valid before prompting — skip if configured
142
+ 3. Never append to files — write the complete content each time
143
+ 4. Use `ctx.force` to allow explicit re-creation when the user asks for it
144
+
145
+ ```typescript
146
+ export async function setupMyPlugin(ctx: PluginSetupContext): Promise<PluginSetupResult> {
147
+ const configPath = path.join(ctx.configDir, '.my-plugin.yaml');
148
+
149
+ // Idempotent: skip if already configured (unless --force)
150
+ if (fs.existsSync(configPath) && !ctx.force) {
151
+ // Optionally validate the existing config
152
+ return { status: 'configured', message: 'Already configured' };
153
+ }
154
+
155
+ // Prompt only when needed
156
+ const apiKey = await ctx.prompt.input({
157
+ key: 'api-key',
158
+ message: 'Enter your API key:',
159
+ });
160
+
161
+ // Write complete config (not append)
162
+ fs.writeFileSync(configPath, `apiKey: "${apiKey}"\n`);
163
+ return { status: 'configured', configCreated: ['config/.my-plugin.yaml'] };
164
+ }
165
+ ```
166
+
66
167
  ### PluginSetupContext
67
168
 
68
- | Field | Type | Description |
69
- | ------------- | --------- | ----------------------------------------------------------------- |
70
- | `pluginName` | `string` | Plugin name from plugin.yaml |
71
- | `projectRoot` | `string` | Absolute project root path |
72
- | `configDir` | `string` | Config directory (from `.jay` configBase, defaults to `./config`) |
73
- | `services` | `Map` | Registered services (may be empty if init failed) |
74
- | `initError` | `Error?` | Present if plugin init failed — check this before using services |
75
- | `force` | `boolean` | Whether `--force` flag was passed |
169
+ | Field | Type | Description |
170
+ | ------------- | ------------------- | ----------------------------------------------------------------- |
171
+ | `pluginName` | `string` | Plugin name from plugin.yaml |
172
+ | `projectRoot` | `string` | Absolute project root path |
173
+ | `configDir` | `string` | Config directory (from `.jay` configBase, defaults to `./config`) |
174
+ | `services` | `Map` | Registered services (may be empty if init failed) |
175
+ | `initError` | `Error?` | Present if plugin init failed — check this before using services |
176
+ | `force` | `boolean` | Whether `--force` flag was passed |
177
+ | `interactive` | `boolean` | Whether running in interactive mode (can prompt user) |
178
+ | `prompt` | `PluginSetupPrompt` | Prompt functions for user input (see below) |
179
+
180
+ ### PluginSetupPrompt
181
+
182
+ | Method | Signature | Description |
183
+ | --------- | -------------------------------------------------- | ---------------------------------------------------------- |
184
+ | `input` | `(opts: { message, validate? }) → Promise<string>` | Text input. Non-interactive: returns `""` |
185
+ | `confirm` | `(opts: { message, default? }) → Promise<boolean>` | Yes/no. Non-interactive: returns `default` or `false` |
186
+ | `select` | `(opts: { message, choices }) → Promise<string>` | Single choice. Non-interactive: returns first choice value |
76
187
 
77
188
  ### PluginSetupResult
78
189
 
@@ -82,42 +193,42 @@ export async function setupMyPlugin(ctx: PluginSetupContext): Promise<PluginSetu
82
193
  | `configCreated` | `string[]?` | Config files created (relative to project root) |
83
194
  | `message` | `string?` | Human-readable status message |
84
195
 
85
- ## Writing a References Handler
196
+ ## Writing an Agent-Kit Handler
86
197
 
87
- The references handler generates discovery data at agent-kit time. It can use live services (database queries, API calls) to produce dynamic content.
198
+ The agent-kit handler generates discovery data at agent-kit time: add-menu catalogs, `agent-kit/references/<plugin>/` files, skills, thumbnails. It can use live services (database queries, API calls) to produce dynamic content.
88
199
 
89
200
  ```typescript
90
201
  import type {
91
- PluginReferencesContext,
92
- PluginReferencesResult,
202
+ PluginAgentKitContext,
203
+ PluginAgentKitResult,
93
204
  } from '@jay-framework/stack-server-runtime';
94
205
  import fs from 'node:fs';
95
206
  import path from 'node:path';
207
+ import yaml from 'yaml';
96
208
 
97
- export async function generateMyReferences(
98
- ctx: PluginReferencesContext,
99
- ): Promise<PluginReferencesResult> {
209
+ export async function generateMyAgentKit(
210
+ ctx: PluginAgentKitContext,
211
+ ): Promise<PluginAgentKitResult> {
100
212
  if (ctx.initError) {
101
- return { referencesCreated: [], message: `Skipped: ${ctx.initError.message}` };
213
+ return { agentKitCreated: [], message: `Skipped: ${ctx.initError.message}` };
102
214
  }
103
215
 
104
- // Example: generate add-menu items from live data
105
216
  const outputPath = path.join(ctx.projectRoot, 'agent-kit/aiditor/add-menu/my-plugin.yaml');
106
217
  fs.mkdirSync(path.dirname(outputPath), { recursive: true });
107
218
 
108
219
  const items = [
109
220
  { id: 'my-plugin:feature-1', title: 'Feature 1', category: 'My Plugin', prompt: '...' },
110
221
  ];
111
- fs.writeFileSync(outputPath, yaml.dump({ items }), 'utf-8');
222
+ fs.writeFileSync(outputPath, yaml.stringify({ items }), 'utf-8');
112
223
 
113
224
  return {
114
- referencesCreated: ['agent-kit/aiditor/add-menu/my-plugin.yaml'],
225
+ agentKitCreated: ['agent-kit/aiditor/add-menu/my-plugin.yaml'],
115
226
  message: `Generated ${items.length} add-menu items`,
116
227
  };
117
228
  }
118
229
  ```
119
230
 
120
- ### PluginReferencesContext
231
+ ### PluginAgentKitContext
121
232
 
122
233
  | Field | Type | Description |
123
234
  | --------------- | --------- | --------------------------------------------------------------- |
@@ -128,25 +239,25 @@ export async function generateMyReferences(
128
239
  | `initError` | `Error?` | Present if plugin init failed |
129
240
  | `force` | `boolean` | Whether `--force` flag was passed |
130
241
 
131
- ### PluginReferencesResult
242
+ ### PluginAgentKitResult
132
243
 
133
- | Field | Type | Description |
134
- | ------------------- | ---------- | ---------------------------------------- |
135
- | `referencesCreated` | `string[]` | Files created (relative to project root) |
136
- | `message` | `string?` | Human-readable status message |
244
+ | Field | Type | Description |
245
+ | ----------------- | ---------- | ---------------------------------------- |
246
+ | `agentKitCreated` | `string[]` | Files created (relative to project root) |
247
+ | `message` | `string?` | Human-readable status message |
137
248
 
138
- ## Setup vs References — When to Use Which
249
+ ## Setup vs Agent-Kit — When to Use Which
139
250
 
140
- | Use case | Handler | Why |
141
- | -------------------------------------------------------------------- | ------------------ | --------------------------------------------------------------- |
142
- | Copy static template files (add-menu catalog, skill guides) | `setup.handler` | Templates don't change copy once |
143
- | Generate data from live services (product catalogs, CMS schemas) | `setup.references` | Needs services initialized; regenerated on each `agent-kit` run |
144
- | Validate credentials / API keys | `setup.handler` | Part of initial project configuration |
145
- | Write AIditor add-menu from project-specific data (DESIGN.md tokens) | `setup.references` | Data comes from project files, not static templates |
251
+ | Use case | Hook | Why |
252
+ | -------------------------------------------------------------------- | ---------- | ----------------------------------------------------------- |
253
+ | Copy static add-menu template, skills, thumbnails | `agentkit` | Discovery dataregenerated on `jay-stack agent-kit` |
254
+ | Generate data from live services (product catalogs, CMS schemas) | `agentkit` | Needs services initialized; refreshed on each agent-kit run |
255
+ | Validate credentials / API keys | `setup` | Part of initial project configuration |
256
+ | Write AIditor add-menu from project-specific data (DESIGN.md tokens) | `agentkit` | Data comes from project files at agent-kit time |
146
257
 
147
258
  ## AIditor Add-Menu Items
148
259
 
149
- Both handlers can write to `agent-kit/aiditor/add-menu/<plugin-name>.yaml`. The AIditor discovers and loads all YAML files in this directory.
260
+ The agent-kit handler writes to `agent-kit/aiditor/add-menu/<plugin-name>.yaml`. The AIditor discovers and loads all YAML files in this directory.
150
261
 
151
262
  Each item:
152
263
 
@@ -163,15 +274,17 @@ items:
163
274
  Read agent-kit/designer/feature-name.md for usage guide.
164
275
  ```
165
276
 
277
+ See `agent-kit/plugin/aiditor-add-menu.md` (installed by `jay-stack setup aiditor`) for the full contributor guide.
278
+
166
279
  ## Exporting Handlers
167
280
 
168
- For NPM plugins, export the handlers from the package entry point:
281
+ For NPM plugins, export handlers from the package entry point:
169
282
 
170
283
  ```typescript
171
284
  // lib/index.ts
172
285
  export { setupMyPlugin } from './setup.js';
173
- export { generateMyReferences } from './references.js';
286
+ export { generateMyAgentKit } from './agentkit.js';
174
287
  // ... other exports (components, actions, services)
175
288
  ```
176
289
 
177
- For local plugins, use relative paths in plugin.yaml instead of export names.
290
+ For local plugins, use relative paths in `plugin.yaml` and export `agentkit` or `default` from the handler module.