@jay-framework/jay-stack-cli 0.22.2 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,114 @@
1
+ # AIditor Add-Menu Items
2
+
3
+ Plugins contribute items to the AIditor's Add Menu via YAML catalog files generated by the agent-kit handler.
4
+
5
+ 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.
6
+
7
+ ## Required and recommended fields
8
+
9
+ ```yaml
10
+ items:
11
+ - id: my-plugin:feature-name # required — unique, stable
12
+ title: Feature Name # required — shown in the add menu
13
+ category: My Plugin # required — top-level nav label
14
+ prompt: | # required — injected verbatim into agent task
15
+ Use headless component @my-org/my-plugin / contract feature-name.
16
+ Read agent-kit/designer/feature-name.md for usage guide.
17
+ pluginName: my-plugin # required — plugin attribution
18
+ packageName: '@my-org/my-plugin' # required — visibility filter
19
+ subCategory: Components # optional — second nav level
20
+ ```
21
+
22
+ `pluginName` and `packageName` must always be set and must match the plugin's `plugin.yaml` name and npm package name respectively. AIditor uses them to filter items — only items whose `packageName` or `pluginName` matches an installed plugin are visible.
23
+
24
+ ## Interaction mode
25
+
26
+ Every item should declare how the user attaches it:
27
+
28
+ ```yaml
29
+ interaction:
30
+ mode: reference # default — attach as context or @mention
31
+ ```
32
+
33
+ ```yaml
34
+ interaction:
35
+ mode: stage-place # click/drag onto live preview
36
+ stagePromptTemplate: | # placed at the marker location
37
+ Add a product card at this location using wix-stores/product-widget.
38
+ ```
39
+
40
+ Use `reference` for data sources (contracts, categories). Use `stage-place` for visual elements the user places on the page (components, design tokens, effects).
41
+
42
+ ## Browse size
43
+
44
+ Controls card size in the browse grid:
45
+
46
+ ```yaml
47
+ browse:
48
+ size: small # 4 per row — color swatches, small tokens
49
+ size: medium # 2 per row — default
50
+ size: large # 1 per row — full-width previews
51
+ ```
52
+
53
+ ## Presentation (preview)
54
+
55
+ Optional visual preview in the browse grid:
56
+
57
+ ```yaml
58
+ # Static image
59
+ presentation:
60
+ type: image
61
+ src: thumbnails/my-plugin/feature.png
62
+
63
+ # HTML fragment — must use @scope for CSS isolation
64
+ presentation:
65
+ type: html-fragment
66
+ html: |
67
+ <div>
68
+ <style>@scope { .demo { color: blue; } }</style>
69
+ <div class="demo">Preview content</div>
70
+ </div>
71
+ ```
72
+
73
+ Html-fragment rules:
74
+
75
+ - Single root `<div>`
76
+ - `<style>` with `@scope { }` (even if CSS is inline-only)
77
+ - No `<script>`, no `on*` handlers
78
+ - Keep under 8 KB
79
+
80
+ ## TypeScript type
81
+
82
+ Import `AddMenuItem` from `@jay-framework/plugin-validator` for type-safe item construction:
83
+
84
+ ```typescript
85
+ import type { AddMenuItem } from '@jay-framework/plugin-validator';
86
+
87
+ const items: AddMenuItem[] = [
88
+ {
89
+ id: 'my-plugin:feature',
90
+ title: 'Feature',
91
+ category: 'My Plugin',
92
+ pluginName: 'my-plugin',
93
+ packageName: '@my-org/my-plugin',
94
+ interaction: { mode: 'stage-place', stagePromptTemplate: 'Add feature here.' },
95
+ prompt: 'Use headless @my-org/my-plugin / contract feature.',
96
+ },
97
+ ];
98
+ ```
99
+
100
+ ## YAML serialization
101
+
102
+ When writing YAML with `js-yaml`, use `noRefs: true` to prevent anchor/alias syntax (`&ref_0` / `*ref_0`) which the AIditor does not support:
103
+
104
+ ```typescript
105
+ fs.writeFileSync(outputPath, yaml.dump({ items }, { lineWidth: 120, noRefs: true }), 'utf-8');
106
+ ```
107
+
108
+ ## Project settings (separate surface)
109
+
110
+ Add Menu and **Project settings** are both materialized by the `agentkit` handler but use different paths and schemas. For a settings tab in AIditor, follow [aiditor-settings-guide.md](aiditor-settings-guide.md) — do not fold settings discovery into add-menu YAML.
111
+
112
+ ## Full reference
113
+
114
+ See `agent-kit/plugin/aiditor-add-menu.md` (installed by `jay-stack setup aiditor`) for the full Add Menu contributor guide including validation rules, browse packing, and surface-specific behavior.
@@ -0,0 +1,296 @@
1
+ # AIditor Project Settings — Plugin Contributor Guide
2
+
3
+ **Audience:** Plugin authors and AI agents adding a **Project settings** tab to a Jay Stack plugin.
4
+
5
+ **Related guides:** [setup-guide.md](setup-guide.md) (agent-kit handler), [plugin-routes.md](plugin-routes.md) (`devOnly` routes), [add-menu-guide.md](add-menu-guide.md) (Add Menu — orthogonal surface). After `jay-stack setup aiditor`, see also `agent-kit/plugin/aiditor-add-menu.md` for AIditor runtime behavior (iframe, postMessage).
6
+
7
+ ---
8
+
9
+ ## What is Project settings?
10
+
11
+ AIditor **Project settings** shows one tab per **installed** plugin that has a materialized discovery file under `agent-kit/aiditor/settings/`. Each tab embeds the plugin's settings **route** in an iframe (`?_jay_embed=true`).
12
+
13
+ This is separate from:
14
+
15
+ | Surface | Purpose | Plugin output |
16
+ | -------------------- | ------------------------------------------------ | ---------------------------------------------------- |
17
+ | **Add Menu** | Attach agent context to a change request | `agent-kit/aiditor/add-menu/*.yaml` |
18
+ | **Project settings** | Configure the project; run backend ops from a UI | `agent-kit/aiditor/settings/*.yaml` + dev-only route |
19
+ | **Headless on page** | Site runtime | contracts + components |
20
+
21
+ ---
22
+
23
+ ## Contributor checklist
24
+
25
+ Follow these steps in order. Skipping a step is the most common reason a tab never appears.
26
+
27
+ 1. **Ship template in the npm package** at `agent-kit/aiditor/settings.template.yaml` (exact path — validated by `jay-stack validate-plugin`).
28
+ 2. **List `agent-kit/` in `package.json` `files`** so the template is included in the published npm tarball and available under `node_modules` after install.
29
+ 3. **Declare `agentkit` in `plugin.yaml`** and materialize the template in the agent-kit handler to `agent-kit/aiditor/settings/<plugin-name>.yaml` in the **project** root (not inside the package).
30
+ 4. **Declare a matching route** in `plugin.yaml` `routes[]` with **`devOnly: true`** (settings UIs are dev-server tooling).
31
+ 5. **Implement the settings page** — `lib/pages/settings/page.jay-html` + page component; use plugin **actions** or **jay-commands** for mutations (never arbitrary shell).
32
+ 6. **Run `jay-stack agent-kit`** in the consuming project and confirm the YAML file exists.
33
+ 7. **Run `jay-stack validate-plugin`** — fix errors; heed warnings for missing `devOnly` or route mismatch.
34
+
35
+ ---
36
+
37
+ ## Package layout
38
+
39
+ ```
40
+ my-plugin/
41
+ ├── agent-kit/
42
+ │ └── aiditor/
43
+ │ └── settings.template.yaml # shipped in package — source for copy/generate
44
+ ├── lib/
45
+ │ ├── aiditor/
46
+ │ │ └── write-settings-contribution.ts # materialization helper
47
+ │ ├── pages/
48
+ │ │ └── settings/
49
+ │ │ ├── page.jay-html
50
+ │ │ └── page.ts
51
+ │ └── agentkit.ts # calls materialize + other agent-kit work
52
+ ├── plugin.yaml
53
+ └── package.json # "files": [..., "agent-kit"]
54
+ ```
55
+
56
+ **Materialized output (project only, gitignored or committed per team policy):**
57
+
58
+ ```
59
+ <project-root>/agent-kit/aiditor/settings/my-plugin.yaml
60
+ ```
61
+
62
+ Use `<plugin>.generated.yaml` only for fixture/dogfood plugins that intentionally differ from the shipped template name.
63
+
64
+ ---
65
+
66
+ ## Settings template schema
67
+
68
+ ```yaml
69
+ # agent-kit/aiditor/settings.template.yaml
70
+ label: Media Manager # required — tab title in Project settings (text only in v1)
71
+ route: /my-plugin/settings # required — must match plugin.yaml routes[].path
72
+ pluginName: my-plugin # optional — defaults from output filename (my-plugin.yaml)
73
+ requires: # optional — tab blocked until dependency setup succeeds
74
+ - plugin: wix-server-client
75
+ status: configured # only "configured" is valid in v1
76
+ ```
77
+
78
+ Validate locally with types from `@jay-framework/plugin-validator`:
79
+
80
+ ```typescript
81
+ import { validateAiditorSettingsFile } from '@jay-framework/plugin-validator';
82
+ ```
83
+
84
+ ---
85
+
86
+ ## plugin.yaml route
87
+
88
+ Settings pages are **[dev-only plugin routes](plugin-routes.md#dev-only-routes)**. They are served on the dev server, hidden from page-navigation pickers that filter `devOnly`, and loaded by AIditor via explicit route URL.
89
+
90
+ ```yaml
91
+ name: my-plugin
92
+ agentkit: generateMyAgentKit
93
+
94
+ routes:
95
+ - path: /my-plugin/settings
96
+ jayHtml: ./lib/pages/settings/page.jay-html
97
+ component: myPluginSettingsPage
98
+ description: Project settings — configure my-plugin for this project
99
+ devOnly: true
100
+ ```
101
+
102
+ See [plugin-routes.md](plugin-routes.md) for route authoring, project override precedence, and standalone URL behavior.
103
+
104
+ ---
105
+
106
+ ## Materialize in the agent-kit handler
107
+
108
+ **Do not** write settings YAML in the `setup` handler. Settings discovery is regenerated on **`jay-stack agent-kit`**, same as Add Menu catalogs.
109
+
110
+ ```typescript
111
+ import type {
112
+ PluginAgentKitContext,
113
+ PluginAgentKitResult,
114
+ } from '@jay-framework/stack-server-runtime';
115
+ import { materializeMyPluginAiditorSettings } from './aiditor/write-settings-contribution.js';
116
+
117
+ export async function generateMyAgentKit(
118
+ ctx: PluginAgentKitContext,
119
+ ): Promise<PluginAgentKitResult> {
120
+ const created: string[] = [];
121
+
122
+ const settingsPath = materializeMyPluginAiditorSettings(ctx.projectRoot, ctx.force);
123
+ if (settingsPath) created.push(settingsPath);
124
+
125
+ // ... add-menu, references, etc.
126
+
127
+ return {
128
+ agentKitCreated: created,
129
+ message: created.length ? `Wrote ${created.join(', ')}` : 'Up to date',
130
+ };
131
+ }
132
+ ```
133
+
134
+ ### Static copy vs generated YAML
135
+
136
+ | Case | Pattern |
137
+ | --------------------------------- | ------------------------------------------------------------------------------------------------------ |
138
+ | Fixed label + route | Copy `settings.template.yaml` → `settings/<plugin>.yaml` |
139
+ | Label/route depends on live data | Build YAML object in handler; write with `yaml.stringify` |
140
+ | Add Menu rebuild from settings UI | Write `add-menu/<plugin>.generated.yaml` only — never overwrite hand-authored `add-menu/<plugin>.yaml` |
141
+
142
+ ---
143
+
144
+ ## Resolving the packaged template path (required)
145
+
146
+ Agent-kit handlers run from **bundled** `dist/index.js` in published packages. A fixed `path.join(__dirname, '..')` hop count **breaks** when the module lives under `dist/` vs `lib/` (Vitest) vs nested bundles.
147
+
148
+ **Use a walk-up resolver** until `agent-kit/aiditor/settings.template.yaml` exists under a parent directory:
149
+
150
+ ```typescript
151
+ import * as fs from 'node:fs';
152
+ import * as path from 'node:path';
153
+ import { fileURLToPath } from 'node:url';
154
+
155
+ export const AIDITOR_SETTINGS_OUTPUT_REL = 'agent-kit/aiditor/settings/my-plugin.yaml';
156
+ const SETTINGS_TEMPLATE_REL = 'agent-kit/aiditor/settings.template.yaml';
157
+
158
+ /**
159
+ * Resolve a file shipped inside the plugin package (agent-kit templates, etc.).
160
+ * Works from dist/index.js (production) and lib/aiditor/*.ts (Vitest).
161
+ */
162
+ export function resolvePackagedAgentKitPath(
163
+ relativePath: string,
164
+ moduleUrl: string = import.meta.url,
165
+ ): string | null {
166
+ let directory = path.dirname(fileURLToPath(moduleUrl));
167
+ for (let depth = 0; depth < 4; depth++) {
168
+ const candidate = path.join(directory, relativePath);
169
+ if (fs.existsSync(candidate)) {
170
+ return candidate;
171
+ }
172
+ const parent = path.dirname(directory);
173
+ if (parent === directory) break;
174
+ directory = parent;
175
+ }
176
+ return null;
177
+ }
178
+
179
+ export function writeAiditorSettingsContribution(
180
+ projectRoot: string,
181
+ templatePath: string,
182
+ force = false,
183
+ ): string | null {
184
+ const outputPath = path.join(projectRoot, AIDITOR_SETTINGS_OUTPUT_REL);
185
+ if (fs.existsSync(outputPath) && !force) {
186
+ return null;
187
+ }
188
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
189
+ fs.copyFileSync(templatePath, outputPath);
190
+ return AIDITOR_SETTINGS_OUTPUT_REL;
191
+ }
192
+
193
+ export function materializeMyPluginAiditorSettings(
194
+ projectRoot: string,
195
+ force = false,
196
+ ): string | null {
197
+ const templatePath = resolvePackagedAgentKitPath(SETTINGS_TEMPLATE_REL);
198
+ if (!templatePath) {
199
+ return null;
200
+ }
201
+ return writeAiditorSettingsContribution(projectRoot, templatePath, force);
202
+ }
203
+ ```
204
+
205
+ ### Common mistakes
206
+
207
+ | Mistake | Symptom |
208
+ | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
209
+ | `path.join(dirname(import.meta.url), '..', '..')` from bundled code | Walks to `node_modules/@jay-framework/` — template not found, **no settings YAML** |
210
+ | **No client bundle** (`index.client.ts` + `vite build` without `--ssr`) | Settings iframe SSR works; Vite errors on hydrate — `Failed to resolve import .../dist/index.client.js` |
211
+ | Writing YAML inside the package instead of `ctx.projectRoot` | Tab missing in consumer project |
212
+ | Route in template ≠ `plugin.yaml` `routes[].path` | `validate-plugin` warning `settings-route-missing`; iframe 404 |
213
+ | Missing `devOnly: true` | `settings-route-dev-only` warning; route may appear in page pickers |
214
+ | Template present but no `agentkit` handler | `settings-missing-agentkit-handler` warning |
215
+ | `agent-kit/` not in `package.json` `files` | Template missing after `yarn add` |
216
+
217
+ **Reference implementations:**
218
+
219
+ - `@jay-framework/design-system-validator` — `lib/aiditor/write-settings-contribution.ts` (walk-up resolver)
220
+ - `@jay-framework/wix-media` — same pattern (prefer walk-up over single `..` from `dist/`)
221
+
222
+ ---
223
+
224
+ ## Settings page responsibilities
225
+
226
+ The embedded settings route should:
227
+
228
+ 1. **About / onboarding** — what the plugin does, which `config/` files matter, links to agent-kit docs.
229
+ 2. **Run backend work** via plugin **actions** (`makeJayAction`) or **`jay-stack run <plugin>/<command>`** — not `child_process` shell.
230
+ 3. **Write project-owned generated files only** — e.g. `agent-kit/aiditor/add-menu/<plugin>.generated.yaml`, reference data under `agent-kit/references/`.
231
+ 4. **Never collect API keys or OAuth secrets** in settings forms — credentials belong in `setup` → `config/`.
232
+
233
+ ### Notify AIditor when Add Menu catalog changes
234
+
235
+ After regenerating add-menu YAML from settings:
236
+
237
+ ```typescript
238
+ window.parent.postMessage({ type: 'aiditor:addMenuCatalogChanged' }, window.location.origin);
239
+ ```
240
+
241
+ ### Optional — submit an agent task (explicit user click only)
242
+
243
+ ```typescript
244
+ window.parent.postMessage(
245
+ {
246
+ type: 'aiditor:submitAgentTask',
247
+ prompt: '…',
248
+ context: { pageRoute: '/', renderedUrl: window.location.origin },
249
+ },
250
+ window.location.origin,
251
+ );
252
+ ```
253
+
254
+ Full iframe and discovery behavior: `agent-kit/plugin/aiditor-add-menu.md` (installed by `jay-stack setup aiditor`).
255
+
256
+ ---
257
+
258
+ ## Validation (`jay-stack validate-plugin`)
259
+
260
+ When `agent-kit/aiditor/settings.template.yaml` exists, the validator:
261
+
262
+ - Parses schema (`label`, `route`, optional `requires`, `pluginName`)
263
+ - Warns if `route` is not in `plugin.yaml` `routes[]`
264
+ - Warns if matching route lacks `devOnly: true`
265
+ - Warns if template exists but `agentkit` is not declared
266
+
267
+ Fix all **errors** before publish; treat **warnings** as required for AIditor-facing plugins.
268
+
269
+ ---
270
+
271
+ ## Verification
272
+
273
+ In a project that depends on your plugin:
274
+
275
+ ```bash
276
+ jay-stack agent-kit
277
+ ls agent-kit/aiditor/settings/my-plugin.yaml # must exist
278
+ jay-stack validate-plugin /path/to/my-plugin # or from package root
279
+ ```
280
+
281
+ In AIditor: open **Project settings** — tab label matches `label`; iframe loads `route` with `?_jay_embed=true`. If `requires` is set, tab stays blocked until dependency `setup` reports `configured`.
282
+
283
+ **Dogfood fixture:** `jay-stack setup aiditor` on a starter project with the plugin-settings-fixture local plugin (see aiditor package examples).
284
+
285
+ ---
286
+
287
+ ## AI agent quick reference
288
+
289
+ When asked to "add Project settings for plugin X":
290
+
291
+ 1. Read this file and `plugin-routes.md` (`devOnly`).
292
+ 2. Add `agent-kit/aiditor/settings.template.yaml` + ensure `package.json` ships `agent-kit/`.
293
+ 3. Add `lib/aiditor/write-settings-contribution.ts` with **`resolvePackagedAgentKitPath`** — do not hard-code `..` depth.
294
+ 4. Wire materialization into existing `agentkit` handler; return path in `agentKitCreated`.
295
+ 5. Add `routes[]` entry with `devOnly: true` and implement settings page.
296
+ 6. Do **not** duplicate Add Menu schema here — use [add-menu-guide.md](add-menu-guide.md) for catalog items.
@@ -135,3 +135,5 @@ The parent constructs the frozen page URL:
135
135
  route + '?_jay_freeze=' + id // full page
136
136
  route + '?_jay_freeze=' + id + '&format=fragment' // shadow DOM fragment
137
137
  ```
138
+
139
+ See also **Dev-only routes** in `plugin-routes.md` — settings pages loaded in AIditor Project settings use `_jay_embed` but are not blocked from direct URL access.
@@ -45,6 +45,8 @@ A plugin route is a **headless component + jay-html template + route path**. It
45
45
  </html>
46
46
  ```
47
47
 
48
+ **Jay-html expression rules** — plugin route templates use the same binding syntax as project pages. `if` and `{…}` resolve **tag names only**; no `.length`, method calls, or bracket indexing. For empty lists, expose `hasItems: boolean` or `itemCount: number` in ViewState / the inline `application/jay-data` block. See [jay-html-template-syntax.md](../designer/jay-html-template-syntax.md#expression-limits-important).
49
+
48
50
  ### 2. Create the page component
49
51
 
50
52
  ```typescript
@@ -144,3 +146,50 @@ Each plugin should choose a recognizable route prefix to avoid collisions:
144
146
  - `/cms/...` — content management
145
147
 
146
148
  There is no enforced convention — just pick a prefix that's unique and descriptive.
149
+
150
+ ## Dev-only routes
151
+
152
+ Some plugin pages are **dev-server tooling** — internal dashboards, QA fixtures, builder settings UIs. Mark them with `devOnly: true` so consumers of `listRoutes()` can distinguish them from public site pages. Production builds do not yet exclude `devOnly` routes — that is planned for a future framework release.
153
+
154
+ ```yaml
155
+ routes:
156
+ - path: /my-plugin/admin
157
+ jayHtml: ./lib/pages/admin/page.jay-html
158
+ component: adminPage
159
+ devOnly: true
160
+ description: Dev-server admin UI
161
+ ```
162
+
163
+ ### What `devOnly` does (framework)
164
+
165
+ | Concern | Behavior |
166
+ | ------------------------------ | -------------------------------------------------------------------- |
167
+ | Dev server HTTP | **Served normally** — direct URL works |
168
+ | `listRoutes()` / `RouteInfo` | Includes route with `devOnly: true` |
169
+ | Page navigation UIs | **Consumer choice** — tools may filter `devOnly` routes from pickers |
170
+ | Routes loaded by explicit path | **Unaffected** — embed/host tools pass a known route URL |
171
+ | Production build | **Deferred** — future task excludes dev-only routes |
172
+
173
+ ### Standalone access
174
+
175
+ Dev-only pages remain reachable at their URL on the dev server (new browser tab, bookmark). **This is intentional** — useful for debugging and optional standalone experiences.
176
+
177
+ Plugin authors decide how to handle visitors who open the URL outside an embedding host:
178
+
179
+ - **Redirect / gate** — explain the page is meant for a design tool
180
+ - **Standalone mode** — offer the same UI with appropriate copy
181
+ - **Hybrid** — embed in tool + "open in new tab" for power users
182
+
183
+ Example: detect iframe context (`?_jay_embed=true` or `window.parent !== window`) and adjust messaging.
184
+
185
+ ### AIditor Project settings routes
186
+
187
+ Settings tabs embed a plugin route by URL. The usual pattern:
188
+
189
+ 1. Ship `agent-kit/aiditor/settings.template.yaml` with `route` matching `routes[].path`
190
+ 2. Materialize to `agent-kit/aiditor/settings/<plugin>.yaml` in the **project** via the `agentkit` handler
191
+ 3. Set **`devOnly: true`** on that route entry
192
+
193
+ AIditor filters `devOnly` routes from the **Pages** dropdown but loads the settings iframe by explicit path — HTTP must remain available on the dev server.
194
+
195
+ Full contributor steps: [aiditor-settings-guide.md](aiditor-settings-guide.md). Runtime iframe protocol: `agent-kit/plugin/aiditor-add-menu.md` (after `jay-stack setup aiditor`).
@@ -254,27 +254,15 @@ export async function generateMyAgentKit(
254
254
  | Generate data from live services (product catalogs, CMS schemas) | `agentkit` | Needs services initialized; refreshed on each agent-kit run |
255
255
  | Validate credentials / API keys | `setup` | Part of initial project configuration |
256
256
  | Write AIditor add-menu from project-specific data (DESIGN.md tokens) | `agentkit` | Data comes from project files at agent-kit time |
257
+ | Materialize AIditor Project settings tab discovery | `agentkit` | Copy/generate `agent-kit/aiditor/settings/<plugin>.yaml` |
257
258
 
258
259
  ## AIditor Add-Menu Items
259
260
 
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.
261
+ See [add-menu-guide.md](add-menu-guide.md) for the complete add-menu item schema, interaction modes, browse sizes, presentation formats, and TypeScript types.
261
262
 
262
- Each item:
263
+ ## AIditor Project Settings
263
264
 
264
- ```yaml
265
- items:
266
- - id: my-plugin:feature-name # unique ID
267
- title: Feature Name # shown in the add menu
268
- category: My Plugin # grouping
269
- subCategory: Components # sub-grouping
270
- pluginName: my-plugin # optional: plugin attribution
271
- packageName: '@my-org/my-plugin' # optional: npm package name
272
- prompt: | # instructions for the AI agent
273
- Use headless component @my-org/my-plugin / contract feature-name.
274
- Read agent-kit/designer/feature-name.md for usage guide.
275
- ```
276
-
277
- See `agent-kit/plugin/aiditor-add-menu.md` (installed by `jay-stack setup aiditor`) for the full contributor guide.
265
+ See [aiditor-settings-guide.md](aiditor-settings-guide.md) for the full checklist: `settings.template.yaml` in the package, walk-up path resolution from bundled `dist/`, `devOnly` route in `plugin.yaml`, and settings page responsibilities (actions, postMessage, no secrets in forms).
278
266
 
279
267
  ## Exporting Handlers
280
268
 
package/dist/index.d.ts CHANGED
@@ -1,14 +1,10 @@
1
1
  import { LogLevel } from '@jay-framework/logger';
2
- import { PublishMessage, PublishResponse, SaveImageMessage, SaveImageResponse, HasImageMessage, HasImageResponse, GetProjectInfoMessage, GetProjectInfoResponse, ExportMessage, ExportResponse, ImportMessage, ImportResponse, ProjectPage, Plugin } from '@jay-framework/editor-protocol';
3
2
  export { MaterializeContractsOptions, MaterializeResult, PluginContractEntry, PluginsIndex, PluginsIndexEntry, listContracts, materializeContracts } from '@jay-framework/stack-server-runtime';
4
3
 
5
4
  interface StartDevServerOptions {
6
5
  projectPath?: string;
7
- /** Enable test endpoints (/_jay/health, /_jay/shutdown) */
8
6
  testMode?: boolean;
9
- /** Auto-shutdown after N seconds */
10
7
  timeout?: number;
11
- /** Log level for output */
12
8
  logLevel?: LogLevel;
13
9
  }
14
10
  declare function startDevServer(options?: StartDevServerOptions): Promise<void>;
@@ -21,92 +17,9 @@ interface JayConfig {
21
17
  publicFolder?: string;
22
18
  configBase?: string;
23
19
  };
24
- editorServer?: {
25
- portRange?: [number, number];
26
- editorId?: string;
27
- };
28
20
  }
29
21
  declare function loadConfig(): JayConfig;
30
22
  declare function getConfigWithDefaults(config: JayConfig): Required<JayConfig>;
31
23
  declare function updateConfig(updates: Partial<JayConfig>): void;
32
24
 
33
- declare function createEditorHandlers(config: Required<JayConfig>, tsConfigPath: string, projectRoot: string): {
34
- onPublish: (params: PublishMessage) => Promise<PublishResponse>;
35
- onSaveImage: (params: SaveImageMessage) => Promise<SaveImageResponse>;
36
- onHasImage: (params: HasImageMessage) => Promise<HasImageResponse>;
37
- onGetProjectInfo: (params: GetProjectInfoMessage) => Promise<GetProjectInfoResponse>;
38
- onExport: <TVendorDoc>(params: ExportMessage<TVendorDoc>) => Promise<ExportResponse>;
39
- onImport: <TVendorDoc_1>(params: ImportMessage<TVendorDoc_1>) => Promise<ImportResponse<TVendorDoc_1>>;
40
- };
41
-
42
- /**
43
- * Vendor Interface
44
- *
45
- * Each vendor (e.g., Figma, Sketch, Adobe XD) implements this interface
46
- * to provide conversion from their native format to Jay HTML format.
47
- */
48
-
49
- /**
50
- * Result of vendor conversion containing body HTML, fonts, and contract data
51
- */
52
- interface VendorConversionResult {
53
- /**
54
- * The body HTML content (without <html>, <head>, or <body> tags)
55
- */
56
- bodyHtml: string;
57
- /**
58
- * Set of font family names used in the document
59
- */
60
- fontFamilies: Set<string>;
61
- /**
62
- * Optional contract data for the page
63
- * If provided, will be used to generate the jay-data script tag
64
- */
65
- contractData?: {
66
- /**
67
- * Contract name
68
- */
69
- name: string;
70
- /**
71
- * Contract tags in YAML format
72
- */
73
- tagsYaml: string;
74
- };
75
- }
76
- interface Vendor<TVendorDoc = any> {
77
- /**
78
- * The unique identifier for this vendor (e.g., 'figma', 'sketch', 'xd')
79
- */
80
- vendorId: string;
81
- /**
82
- * Convert vendor document to body HTML with metadata
83
- *
84
- * @param vendorDoc - The vendor's native document format (e.g., Figma SectionNode)
85
- * @param pageUrl - The page URL/route (e.g., '/home', '/products')
86
- * @returns Conversion result with body HTML, fonts, and contract data
87
- */
88
- convertToBodyHtml(vendorDoc: TVendorDoc, pageUrl: string, projectPage: ProjectPage, plugins: Plugin[]): Promise<VendorConversionResult>;
89
- }
90
-
91
- /**
92
- * Get a vendor by ID
93
- *
94
- * @param vendorId - The vendor ID
95
- * @returns The vendor or undefined if not found
96
- */
97
- declare function getVendor(vendorId: string): Vendor | undefined;
98
- /**
99
- * Check if a vendor exists
100
- *
101
- * @param vendorId - The vendor ID
102
- * @returns True if vendor exists
103
- */
104
- declare function hasVendor(vendorId: string): boolean;
105
- /**
106
- * Get all registered vendor IDs
107
- *
108
- * @returns Array of vendor IDs
109
- */
110
- declare function getRegisteredVendors(): string[];
111
-
112
- export { type JayConfig, type StartDevServerOptions, type Vendor, createEditorHandlers, getConfigWithDefaults, getRegisteredVendors, getVendor, hasVendor, loadConfig, startDevServer, updateConfig };
25
+ export { type JayConfig, type StartDevServerOptions, getConfigWithDefaults, loadConfig, startDevServer, updateConfig };