@enfocussw/switch-scripting-context 25.11.1-beta.4 → 25.11.1-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,66 @@ All notable changes to this package are documented here. Format follows
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [25.11.1-beta.6] - 2026-10-07
9
+
10
+ ### Added
11
+
12
+ - The Node.js version table now lists Switch 26.11, which runs scripts on Node.js 24.
13
+ - Every doc over 100 lines now opens with a Contents list of its section headings. An agent that
14
+ reads only the first part of a file can still see which sections exist further down.
15
+ - `--tools pi` configures the Pi coding agent. It is an alias for `codex`, because Pi reads the
16
+ same instructions file as Codex.
17
+ - `--tools continue` writes a Continue rule that is always in context, with the same rules and doc
18
+ list the other tools get.
19
+ - `--tools aider` adds the docs index to the read-only files Aider loads at startup. If your Aider
20
+ config already lists read-only files, `init` leaves it alone and prints the line to add.
21
+
22
+ ### Changed
23
+
24
+ - The docs now list only publicly released Switch versions. Version tables drop unreleased builds,
25
+ and examples that named one now use Switch 25.11 or 26.11.
26
+ - The Node.js version table and the rules for `SwitchVersion` moved out of the script project
27
+ structure doc into their own doc, with its own row in the routing table. Agents
28
+ asking which Node.js version a script runs on now read only that section.
29
+
30
+ ### Fixed
31
+
32
+ - The example of packing changing the Node.js version said a `SwitchVersion` of 21.0 runs on
33
+ Node.js 16. It runs on Node.js 14, as the version table already said.
34
+ - Agents often answered a short Switch question from the index page alone, without opening the doc
35
+ that holds the answer, and got it wrong. The generated instructions now tell agents to read the
36
+ matching doc before answering any Switch question, not only before writing code.
37
+ - The `Job` private data docs did not point to the string values of `EnfocusSwitchPrivateDataTag`,
38
+ so agents reported bare names such as `userEmail`. They now link to the enum reference.
39
+ - The property editor docs told readers to verify the `getLibraryForMultipleProperty` entry point
40
+ name "against source", which a consuming project does not have. The note now says the name is
41
+ unconfirmed.
42
+ - Re-running `init` stacked a second copy of the YAML frontmatter in the Cursor and Copilot
43
+ scoped-instructions files, one copy per run, which left the frontmatter invalid for both tools.
44
+ `init` now replaces its own frontmatter instead of prepending a new one, and leaves frontmatter
45
+ you have edited alone.
46
+ - An agent working in an already-scaffolded script folder skipped the Script vs App question. The
47
+ planning docs now say to ask it anyway, because a scaffolded manifest is always typed `Script`.
48
+ - The execution environment docs said top-level script variables survive between jobs and
49
+ suggested using them as a cache. The executor re-evaluates the script on every call, so they do
50
+ not. The docs now list what can leak (globals, `require()` caches, open handles) and say not to
51
+ rely on any of it.
52
+
53
+ ## [25.11.1-beta.5] - 2026-09-21
54
+
55
+ ### Fixed
56
+
57
+ - The property editor and declaration docs listed a `rational` (decimal) inline editor type,
58
+ which Node.js scripts do not allow. The docs no longer offer it and now say it is not allowed.
59
+ - `createJob()` was documented as valid only from `jobArrived` and `timerFired`. It also works from
60
+ `httpRequestTriggeredAsync`, the only webhook entry point that receives `flowElement`.
61
+ - Documented that `Type="password"` needs `Subtype=""`, not `"inline"`. The latter fails at script
62
+ load with an unsupported-editor error, even though it is the usual `Subtype` for a single inline
63
+ editor.
64
+ - Documented that `IncomingConnections="Yes"` with `RequireAtLeastOne="No"` makes the incoming
65
+ connection optional per flow element instance, letting one script support both a flow-starting
66
+ role and a mid-flow role.
67
+
8
68
  ## [25.11.1-beta.4] - 2026-09-20
9
69
 
10
70
  ### Added
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  AI coding assistant context for [Enfocus Switch](https://www.enfocus.com/en/switch) scripting projects (Node.js/TypeScript).
4
4
 
5
- Installs curated API reference docs and generates config files for 8 AI coding agents (Claude Code, GitHub Copilot, Cursor, Codex CLI/OpenCode, Gemini CLI, Windsurf, Zed, and Cline) so AI assistants understand the Switch scripting API out of the box.
5
+ Installs curated API reference docs and generates config files for 10 AI coding agents (Claude Code, GitHub Copilot, Cursor, Codex CLI/OpenCode/Pi, Gemini CLI, Windsurf, Zed, Cline, Continue, and Aider) so AI assistants understand the Switch scripting API out of the box.
6
6
 
7
- See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.1-beta.4/CHANGELOG.md) (also included in this package) for what's changed between versions.
7
+ See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.1-beta.6/CHANGELOG.md) (also included in this package) for what's changed between versions.
8
8
 
9
9
  ## Usage
10
10
 
@@ -62,13 +62,20 @@ stay on the old name.
62
62
  | GitHub Copilot | `.github/copilot-instructions.md` | `#file:` reference to hub |
63
63
  | GitHub Copilot (scoped) | `.github/instructions/switch-scripting.instructions.md` | `applyTo: "**/*.ts"`; auto-attaches to every TypeScript file edit |
64
64
  | Cursor | `.cursor/rules/switch-scripting.mdc` | Inline key rules + full API file path list |
65
- | Codex CLI / OpenCode | `AGENTS.md` | Inline key rules + full API file path list |
65
+ | Codex CLI / OpenCode / Pi | `AGENTS.md` | Inline key rules + full API file path list |
66
66
  | Gemini CLI | `GEMINI.md` | `@docs-for-agents/switch-scripting.md` import |
67
67
  | Windsurf | `.windsurfrules` | Inline key rules + full API file path list |
68
68
  | Zed | `.rules` | Inline key rules + full API file path list |
69
69
  | Cline | `.clinerules` | Inline key rules + full API file path list |
70
+ | Continue | `.continue/rules/switch-scripting.md` | `alwaysApply: true`; inline key rules + full API file path list |
71
+ | Aider | `.aider.conf.yml` | `read:` entry that loads the hub file read-only at startup |
70
72
 
71
- All files use `<!-- switch-scripting-context begin -->` / `<!-- switch-scripting-context end -->` markers. Re-running `init` replaces only the Switch section in existing files. Project-specific rules outside the markers are untouched.
73
+ All files use `<!-- switch-scripting-context begin -->` / `<!-- switch-scripting-context end -->` markers, or `# switch-scripting-context begin` / `# switch-scripting-context end` in `.aider.conf.yml`. Re-running `init` replaces only the Switch section in existing files. Project-specific rules outside the markers are untouched.
74
+
75
+ Two limits apply to Aider:
76
+
77
+ - Start Aider from the project root. Aider resolves the `read:` path against the folder it starts in, so from a subfolder it skips the file and prints an error.
78
+ - If your `.aider.conf.yml` already has a `read:` key, `init` leaves the file alone and prints the path to add to your list. A second `read:` key would replace your list, not extend it.
72
79
 
73
80
  ## Using this with your coding agent
74
81
 
@@ -89,7 +96,7 @@ A few things this gets you without asking for them by name:
89
96
  properties (app path/licence) are off-limits and left to SwitchScripter's GUI instead.
90
97
 
91
98
  Re-run `init` after upgrading this package so the copied docs and generated config files catch up.
92
- See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.1-beta.4/CHANGELOG.md) for what changed.
99
+ See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-context@25.11.1-beta.6/CHANGELOG.md) for what changed.
93
100
 
94
101
  ## Options
95
102
 
@@ -97,8 +104,9 @@ See [CHANGELOG.md](https://cdn.jsdelivr.net/npm/@enfocussw/switch-scripting-cont
97
104
  npx switch-scripting-context init [options]
98
105
 
99
106
  --tools <list> Tools to configure. Default: all
100
- IDs: claude, copilot, cursor, codex, gemini, windsurf, zed, cline
101
- Aliases: opencode (→ codex), clawcode (→ claude)
107
+ IDs: claude, copilot, cursor, codex, gemini, windsurf, zed, cline,
108
+ continue, aider
109
+ Aliases: opencode, pi (→ codex), clawcode (→ claude)
102
110
  --docs-dir <dir> Destination folder for docs. Default: docs-for-agents
103
111
  --force Overwrite existing AI config files instead of merging
104
112
  --dry-run Print what would happen without writing any files
@@ -152,7 +160,7 @@ The `docs-for-agents/` folder contains:
152
160
 
153
161
  - `switch-scripting.md`: master index with execution environment rules and "load when" routing table
154
162
  <!-- docs-index:readme begin -->
155
- - `switch-project/project-planning.md`: Pre-scaffolding checklist: Script vs App, job-processing approach, one script folder or several, target OS, Switch version baseline, concurrency, native/binary npm dependencies, Appstore competition risk
163
+ - `switch-project/project-planning.md`: Planning checklist, run before scaffolding or on a project that is already scaffolded: Script vs App, job-processing approach, one script folder or several, target OS, Switch version baseline, concurrency, native/binary npm dependencies, Appstore competition risk
156
164
  - `switch-api/entry-points.md`: All entry point signatures, constraints, and when each is called
157
165
  - `switch-api/switch.md`: `Switch` (`s`): global data, webhooks, abort, server utilities
158
166
  - `switch-api/flow-element.md`: `FlowElement`: properties, connections, job creation, logging
@@ -161,7 +169,7 @@ The `docs-for-agents/` folder contains:
161
169
  - `switch-api/http.md`: `HttpRequest` / `HttpResponse` + webhook pattern
162
170
  - `switch-api/enums.md`: All enums with string values (`LogLevel`, `AccessLevel`, `DatasetModel`, `Scope`, `Priority`, `Connection.Level`, etc.)
163
171
  - `switch-api/document-classes.md`: `PdfDocument`, `PdfPage`, `ImageDocument`, `XmlDocument`, `XmpDocument`: read-only file introspection
164
- - `switch-project/script-structure.md`: What files a script folder contains, laying out several script folders side by side, `manifest.xml` format, how `SwitchVersion` selects the Node.js version and which tools overwrite it, Script vs App
172
+ - `switch-project/script-structure.md`: What files a script folder contains, laying out several script folders side by side, `manifest.xml` format, Script vs App, packing an app with SwitchScripter
165
173
  - `switch-project/tooling.md`: SwitchScriptTool commands and install paths, folder vs `.sscript` trade-offs, deployment
166
174
  - `switch-project/debugging.md`: Enabling debug mode in Switch Designer, debuggable entry points, VS Code attach
167
175
  - `switch-project/vscode.md`: Type declarations, tsconfig for TypeScript 6, ESLint rules
@@ -177,4 +185,5 @@ The `docs-for-agents/` folder contains:
177
185
  - `switch-appstore/app-manual.md`: Writing guidance for the separate app manual document uploaded during Appstore review (`documentation-app_name.docx` template)
178
186
  - `switch-appstore/app-store-submission.md`: Writing guidance for the Create Appstore App / Create Appstore App Version web forms: Short Description, What's new, Eula, icon specs, and which fields reuse content already written elsewhere
179
187
  - `switch-api/api-versions.md`: Which Switch release added each scripting API class, method, and enum value; API availability follows the running Switch, not `manifest.xml`
188
+ - `switch-project/node-versions.md`: How `SwitchVersion` in `manifest.xml` selects the Node.js version, the version table per Switch release, which tools overwrite `SwitchVersion`, values missing from the table, other effects of `SwitchVersion`
180
189
  <!-- docs-index:readme end -->
package/dist/init.d.ts CHANGED
@@ -1,6 +1,17 @@
1
+ export interface Markers {
2
+ begin: string;
3
+ end: string;
4
+ }
1
5
  export interface ToolFile {
2
6
  targetPath: (root: string, docsDir: string) => string;
3
7
  generate: (docsDir: string) => string;
8
+ /** Comment syntax around the generated section. Default: HTML comments, for Markdown files. */
9
+ markers?: Markers;
10
+ /**
11
+ * Checks an existing file that has no Switch section yet. Returns why appending one would break
12
+ * the file, or null when appending is safe. init then skips the file and prints the reason.
13
+ */
14
+ appendConflict?: (existing: string, docsDir: string) => string | null;
4
15
  }
5
16
  export interface ToolDefinition {
6
17
  id: string;
@@ -29,8 +40,15 @@ export declare function generateGeminiMd(docsDir: string): string;
29
40
  export declare function generateWindsurfRules(docsDir: string): string;
30
41
  export declare function generateZedRules(docsDir: string): string;
31
42
  export declare function generateClineRules(docsDir: string): string;
43
+ export declare function generateContinueRule(docsDir: string): string;
44
+ export declare function generateAiderConf(docsDir: string): string;
45
+ /**
46
+ * A second top-level read key would not merge with the user's own: Aider keeps only the last
47
+ * one, so appending ours would silently drop every file the user already loads.
48
+ */
49
+ export declare function aiderReadConflict(existing: string, docsDir: string): string | null;
32
50
  export declare function buildIdMap(registry: ToolDefinition[]): Map<string, string>;
33
- export declare function findMarkerRange(content: string): [number, number] | null;
51
+ export declare function findMarkerRange(content: string, markers?: Markers): [number, number] | null;
34
52
  /** The running package's own version, so a git-clone install stamps what actually ran. */
35
53
  export declare function packageVersion(root?: string): string;
36
54
  /** The comment init writes as the first line of the copied hub file. */
package/dist/init.js CHANGED
@@ -40,6 +40,9 @@ exports.generateGeminiMd = generateGeminiMd;
40
40
  exports.generateWindsurfRules = generateWindsurfRules;
41
41
  exports.generateZedRules = generateZedRules;
42
42
  exports.generateClineRules = generateClineRules;
43
+ exports.generateContinueRule = generateContinueRule;
44
+ exports.generateAiderConf = generateAiderConf;
45
+ exports.aiderReadConflict = aiderReadConflict;
43
46
  exports.buildIdMap = buildIdMap;
44
47
  exports.findMarkerRange = findMarkerRange;
45
48
  exports.packageVersion = packageVersion;
@@ -52,6 +55,12 @@ const readline = __importStar(require("readline"));
52
55
  // ─── Markers ─────────────────────────────────────────────────────────────────
53
56
  const MARKER_BEGIN = '<!-- switch-scripting-context begin -->';
54
57
  const MARKER_END = '<!-- switch-scripting-context end -->';
58
+ const HTML_MARKERS = { begin: MARKER_BEGIN, end: MARKER_END };
59
+ // YAML has no HTML comments, so a YAML config file marks its section with # comments instead.
60
+ const YAML_MARKERS = {
61
+ begin: '# switch-scripting-context begin',
62
+ end: '# switch-scripting-context end',
63
+ };
55
64
  // ─── Shared content (single source of truth for all generated tool files) ────
56
65
  /** Package root, whether running from src/ (ts-node) or dist/. */
57
66
  function packageRoot() {
@@ -84,6 +93,7 @@ function apiFiles(root) {
84
93
  }
85
94
  const INLINE_CORE_RULES = `## Core rules
86
95
 
96
+ - Read the matching file from the API reference list below before answering any question about Switch scripting, not only before writing code, including short and yes/no questions. These rules only summarise; Switch often differs from what general Node.js knowledge suggests.
87
97
  - Entry point functions are top-level async functions — do NOT use \`export\`, arrow functions, or class methods; declare them with the literal \`function\` keyword.
88
98
  - Switch finds entry points with a regex, not a parser. Never write a string literal whose content ends with a backslash, a regex literal, or division outside the plain \`word / word\` shape — each silently deletes a span of real code and the entry points inside it, with no error. Read \`entry-points.md\` § Entry-point scanner constraints before editing \`main.ts\`/\`main.js\`.
89
99
  - Every \`jobArrived\` must end with exactly one \`job.sendTo*()\` or \`job.fail()\`.
@@ -95,11 +105,12 @@ const INLINE_CORE_RULES = `## Core rules
95
105
  // ─── Content generators ──────────────────────────────────────────────────────
96
106
  // Claude Code and Gemini CLI resolve @file imports themselves, so their generated
97
107
  // block is just a pointer to switch-scripting.md; the routing table and key rules
98
- // living there are the actual instructions. Codex, Windsurf, Zed, and Cline don't
99
- // reliably follow that import syntax, so their generators (generateInlineBlock)
108
+ // living there are the actual instructions. Codex, Windsurf, Zed, Cline, and Continue
109
+ // don't reliably follow that import syntax, so their generators (generateInlineBlock)
100
110
  // paste INLINE_CORE_RULES and the routing table directly into the generated file
101
- // instead. Don't collapse these into one shared generator; the split is deliberate,
102
- // not duplication.
111
+ // instead. Aider has no instructions file at all; its config loads the hub as a
112
+ // read-only file. Don't collapse these into one shared generator; the split is
113
+ // deliberate, not duplication.
103
114
  function generateClaudeMd(docsDir) {
104
115
  return `${MARKER_BEGIN}
105
116
  ## Switch Scripting (Enfocus Switch)
@@ -112,7 +123,7 @@ function generateCopilotInstructions(docsDir) {
112
123
  ## Switch Scripting (Enfocus Switch)
113
124
 
114
125
  This project uses Enfocus Switch scripting (Node.js/TypeScript).
115
- Consult the Switch scripting reference before writing or modifying code.
126
+ Consult the Switch scripting reference before answering questions about Switch scripting or writing or modifying code.
116
127
 
117
128
  #file:../${docsDir}/switch-scripting.md
118
129
  ${MARKER_END}`;
@@ -200,6 +211,38 @@ function generateClineRules(docsDir) {
200
211
  ${generateInlineBlock(docsDir)}
201
212
  ${MARKER_END}`;
202
213
  }
214
+ // Continue reads every Markdown file in .continue/rules/. alwaysApply keeps the rules in context
215
+ // for questions too, not only when a matching file is open.
216
+ function generateContinueRule(docsDir) {
217
+ return `---
218
+ name: Switch scripting
219
+ description: Enfocus Switch scripting rules and API reference for Node.js/TypeScript scripts
220
+ alwaysApply: true
221
+ ---
222
+
223
+ ${MARKER_BEGIN}
224
+ ## Switch Scripting (Enfocus Switch)
225
+
226
+ ${generateInlineBlock(docsDir)}
227
+ ${MARKER_END}`;
228
+ }
229
+ // Aider resolves a relative read path against the folder it was started from, not the git root,
230
+ // so this entry only works when Aider starts at the project root.
231
+ function generateAiderConf(docsDir) {
232
+ return `${YAML_MARKERS.begin}
233
+ read:
234
+ - ${docsDir}/switch-scripting.md
235
+ ${YAML_MARKERS.end}`;
236
+ }
237
+ /**
238
+ * A second top-level read key would not merge with the user's own: Aider keeps only the last
239
+ * one, so appending ours would silently drop every file the user already loads.
240
+ */
241
+ function aiderReadConflict(existing, docsDir) {
242
+ if (!/^read\s*:/m.test(existing))
243
+ return null;
244
+ return `it already has a read: key. Add ${docsDir}/switch-scripting.md to that list yourself.`;
245
+ }
203
246
  // ─── Tool registry ───────────────────────────────────────────────────────────
204
247
  const TOOL_REGISTRY = [
205
248
  {
@@ -240,8 +283,8 @@ const TOOL_REGISTRY = [
240
283
  },
241
284
  {
242
285
  id: 'codex',
243
- label: 'Codex CLI / OpenCode',
244
- altIds: ['opencode'],
286
+ label: 'Codex CLI / OpenCode / Pi',
287
+ altIds: ['opencode', 'pi'],
245
288
  files: [
246
289
  {
247
290
  targetPath: (root) => path.join(root, 'AGENTS.md'),
@@ -289,6 +332,28 @@ const TOOL_REGISTRY = [
289
332
  },
290
333
  ],
291
334
  },
335
+ {
336
+ id: 'continue',
337
+ label: 'Continue',
338
+ files: [
339
+ {
340
+ targetPath: (root) => path.join(root, '.continue', 'rules', 'switch-scripting.md'),
341
+ generate: generateContinueRule,
342
+ },
343
+ ],
344
+ },
345
+ {
346
+ id: 'aider',
347
+ label: 'Aider',
348
+ files: [
349
+ {
350
+ targetPath: (root) => path.join(root, '.aider.conf.yml'),
351
+ generate: generateAiderConf,
352
+ markers: YAML_MARKERS,
353
+ appendConflict: aiderReadConflict,
354
+ },
355
+ ],
356
+ },
292
357
  ];
293
358
  // ─── ID map ──────────────────────────────────────────────────────────────────
294
359
  function buildIdMap(registry) {
@@ -301,16 +366,18 @@ function buildIdMap(registry) {
301
366
  return map;
302
367
  }
303
368
  // ─── Merge logic ─────────────────────────────────────────────────────────────
304
- function findMarkerRange(content) {
305
- const begin = content.indexOf(MARKER_BEGIN);
306
- const end = content.indexOf(MARKER_END);
369
+ function findMarkerRange(content, markers = HTML_MARKERS) {
370
+ const begin = content.indexOf(markers.begin);
371
+ const end = content.indexOf(markers.end);
307
372
  if (begin === -1 || end === -1)
308
373
  return null;
309
374
  if (begin >= end)
310
375
  return null;
311
- return [begin, end + MARKER_END.length];
376
+ return [begin, end + markers.end.length];
312
377
  }
313
- function resolveFileAction(targetPath, block, force) {
378
+ function resolveFileAction(targetPath, file, docsDir, force) {
379
+ const block = file.generate(docsDir);
380
+ const markers = file.markers ?? HTML_MARKERS;
314
381
  if (!fs.existsSync(targetPath)) {
315
382
  return { path: targetPath, action: 'create', content: block };
316
383
  }
@@ -318,16 +385,40 @@ function resolveFileAction(targetPath, block, force) {
318
385
  return { path: targetPath, action: 'overwrite', content: block };
319
386
  }
320
387
  const existing = fs.readFileSync(targetPath, 'utf8');
321
- const range = findMarkerRange(existing);
388
+ const range = findMarkerRange(existing, markers);
322
389
  if (range) {
323
- const updated = existing.slice(0, range[0]) + block + existing.slice(range[1]);
390
+ // The Cursor .mdc and Copilot scoped-instructions blocks carry frontmatter above the marker,
391
+ // and only the marker range is replaced. Writing the block whole would stack a second copy of
392
+ // that frontmatter on every re-run, so drop one of the two copies.
393
+ const frontmatter = block.slice(0, block.indexOf(markers.begin)).trim();
394
+ let before = existing.slice(0, range[0]);
395
+ let incoming = block;
396
+ if (frontmatter) {
397
+ if (before.replace(/\r\n/g, '\n').trim() === frontmatter) {
398
+ before = ''; // our own frontmatter from an earlier run; the block's copy replaces it
399
+ }
400
+ else {
401
+ // User-written or user-edited frontmatter, or init appended below the user's own content.
402
+ // Leave what is there and write only the marker section.
403
+ incoming = block.slice(block.indexOf(markers.begin));
404
+ }
405
+ }
406
+ const updated = before + incoming + existing.slice(range[1]);
324
407
  return { path: targetPath, action: 'merge-replace', content: updated };
325
408
  }
409
+ const reason = file.appendConflict?.(existing, docsDir);
410
+ if (reason) {
411
+ return { path: targetPath, action: 'skip', content: existing, reason };
412
+ }
326
413
  const separator = existing.endsWith('\n') ? '\n' : '\n\n';
327
414
  return { path: targetPath, action: 'merge-append', content: existing + separator + block + '\n' };
328
415
  }
329
416
  function applyFileAction(action, dryRun) {
330
417
  const rel = path.relative(process.cwd(), action.path);
418
+ if (action.action === 'skip') {
419
+ console.log(` ${rel} → skipped: ${action.reason}`);
420
+ return;
421
+ }
331
422
  const label = action.action === 'create' ? 'created'
332
423
  : action.action === 'overwrite' ? 'overwritten'
333
424
  : action.action === 'merge-replace' ? 'updated (replaced Switch section)'
@@ -458,7 +549,7 @@ function aiConfigFiles(targetRoot, docsDir, tools) {
458
549
  /** The frontmatter a generator writes above the marker, trimmed; empty if it writes none. */
459
550
  function generatedFrontmatter(file, docsDir) {
460
551
  const generated = file.generate(docsDir);
461
- return generated.slice(0, generated.indexOf(MARKER_BEGIN)).trim();
552
+ return generated.slice(0, generated.indexOf((file.markers ?? HTML_MARKERS).begin)).trim();
462
553
  }
463
554
  /** Deletes now-empty folders from dir upwards, stopping at targetRoot. */
464
555
  function removeEmptyDirs(dir, targetRoot) {
@@ -473,13 +564,13 @@ function removeAiConfig(filePath, file, docsDir, targetRoot, dryRun) {
473
564
  const raw = fs.readFileSync(filePath, 'utf8');
474
565
  const eol = raw.includes('\r\n') ? '\r\n' : '\n';
475
566
  const content = raw.replace(/\r\n/g, '\n');
476
- const range = findMarkerRange(content);
567
+ const range = findMarkerRange(content, file.markers);
477
568
  if (!range)
478
569
  return; // nothing from us in this file
479
570
  const rel = path.relative(process.cwd(), filePath);
480
571
  let before = content.slice(0, range[0]).trim();
481
572
  const after = content.slice(range[1]).trim();
482
- // Copilot scoped instructions and Cursor .mdc put frontmatter above the marker. Only an exact
573
+ // Copilot scoped instructions, Cursor .mdc, and Continue rules put frontmatter above the marker. Only an exact
483
574
  // copy of what the generator writes counts as ours; edited or user-written frontmatter stays.
484
575
  const ours = generatedFrontmatter(file, docsDir);
485
576
  if (ours && before === ours) {
@@ -598,16 +689,13 @@ function init(options) {
598
689
  if (!options.tools.includes(toolDef.id))
599
690
  continue;
600
691
  for (const f of toolDef.files) {
601
- toolActions.push({
602
- targetPath: f.targetPath(targetRoot, options.docsDir),
603
- block: f.generate(options.docsDir),
604
- });
692
+ toolActions.push({ targetPath: f.targetPath(targetRoot, options.docsDir), file: f });
605
693
  }
606
694
  }
607
695
  if (toolActions.length > 0) {
608
696
  console.log('\nGenerating AI config files...');
609
- for (const { targetPath, block } of toolActions) {
610
- const action = resolveFileAction(targetPath, block, options.force);
697
+ for (const { targetPath, file } of toolActions) {
698
+ const action = resolveFileAction(targetPath, file, options.docsDir, options.force);
611
699
  applyFileAction(action, options.dryRun);
612
700
  }
613
701
  }
@@ -705,8 +793,9 @@ Commands:
705
793
 
706
794
  Options (init):
707
795
  --tools <list> Comma-separated tools to configure
708
- IDs: claude, copilot, cursor, codex, gemini, windsurf, zed, cline
709
- Aliases: opencode (→ codex), clawcode (→ claude)
796
+ IDs: claude, copilot, cursor, codex, gemini, windsurf, zed, cline,
797
+ continue, aider
798
+ Aliases: opencode, pi (→ codex), clawcode (→ claude)
710
799
  Default: all tools
711
800
  --docs-dir <dir> Destination folder for docs in target project (default: docs-for-agents)
712
801
  --force Overwrite existing AI config files rather than merging
@@ -9,18 +9,30 @@ triggers:
9
9
 
10
10
  # API availability by Switch version
11
11
 
12
+ <!-- docs-index:contents begin -->
13
+ ## Contents
14
+
15
+ - The running Switch decides which methods exist
16
+ - Checking at runtime
17
+ - Release names
18
+ - Source and limits of this list
19
+ - Baseline (every Switch version with Node.js scripting)
20
+ - Added per release
21
+ - Declaration changes to existing methods
22
+ <!-- docs-index:contents end -->
23
+
12
24
  ## The running Switch decides which methods exist
13
25
 
14
26
  Each Switch installation ships one copy of the scripting module, and every bundled Node.js version
15
27
  uses that same copy. So which API methods a script can call depends on the Switch Server the script
16
28
  runs on, not on anything in the script package. A script whose `manifest.xml` says `20.1` runs on
17
- Node.js 12 in Switch 26.07, and it still gets the full 26.07 API.
29
+ Node.js 12 in Switch 26.11, and it still gets the full 26.11 API.
18
30
 
19
31
  The two versions are independent:
20
32
 
21
33
  | Depends on | Decided by |
22
34
  |---|---|
23
- | Node.js version (language features, Node built-ins) | `SwitchVersion` in `manifest.xml`, looked up by the running Switch. See [script-structure.md § Node.js version per Switch version](../switch-project/script-structure.md#nodejs-version-per-switch-version) |
35
+ | Node.js version (language features, Node built-ins) | `SwitchVersion` in `manifest.xml`, looked up by the running Switch. See [node-versions.md](../switch-project/node-versions.md) |
24
36
  | Scripting API (classes, methods, enum values below) | The version of the Switch Server the script runs on |
25
37
 
26
38
  When code must run on an older Switch, check every API call against the tables below for the
@@ -54,10 +66,8 @@ if (typeof job.getVariableAsString === 'function') {
54
66
  | `23.1` | Switch 2023 Fall |
55
67
  | `24.0` | Switch 2024 Spring |
56
68
  | `24.1` | Switch 2024 Fall |
57
- | `25.07` | Switch 25.07 |
58
69
  | `25.11` | Switch 25.11 |
59
- | `26.03` | Switch 26.03 |
60
- | `26.07` | Switch 26.07 |
70
+ | `26.11` | Switch 26.11 |
61
71
 
62
72
  ## Source and limits of this list
63
73
 
@@ -72,9 +82,10 @@ nothing.
72
82
  that runs Node.js scripts.
73
83
  - Tag 1.1.0 (May 2021) is Switch 2021 Spring. The later tags carry the release number (21.1.x,
74
84
  22.0.x, 22.1.x, 24.0.x, 24.1.x).
75
- - The declarations end at v24.1.1-final (Switch 2024 Fall). SwitchScriptTool 26.07 still scaffolds
76
- that version. A check of the Switch 26.07 scripting module found no public class, method, or enum
77
- value that v24.1.1 lacks. So nothing was added in 23.1, 25.07, 25.11, 26.03, or 26.07.
85
+ - The declarations end at v24.1.1-final (Switch 2024 Fall). SwitchScriptTool 26.11 still scaffolds
86
+ that version. A check of the scripting module in a pre-release Switch build found no public class,
87
+ method, or enum value that v24.1.1 lacks, and 26.11 adds no scripting API. So nothing was added in
88
+ 23.1, 25.11, or 26.11.
78
89
  - Entry points aren't part of the type declarations, so this list doesn't record when each entry
79
90
  point appeared. The webhook entry points (`httpRequestTriggeredSync`/`Async`) need
80
91
  `s.httpRequestSubscribe()`, so they can't be used before Switch 21.1 either.
@@ -100,7 +111,7 @@ nothing.
100
111
  | 23.1 | Nothing |
101
112
  | 24.0 | `flowElement.getScriptDataPath()`, `flowElement.createPathWithName()`; `job.getVariableAsString()`, `job.getxmlData()`, `job.getxmpData()`, `job.getJdfData()`, `job.getJSONData()`; `s.getPreferenceSetting()`, `s.getServerVersion()`; `NoYesListPropertyStringValue` |
102
113
  | 24.1 | `connection.getType()`, `connection.getFileCount()`, `flowElement.getFileCount()` |
103
- | 25.07, 25.11, 26.03, 26.07 | Nothing |
114
+ | 25.11, 26.11 | Nothing |
104
115
 
105
116
  ## Declaration changes to existing methods
106
117
 
@@ -13,6 +13,17 @@ Read-only document introspection utilities. All methods may throw — wrap in `t
13
13
 
14
14
  Each class needs a minimum Switch version: `PdfDocument` and `PdfPage` 21.0+, `ImageDocument` 21.1+, `XmlDocument` 22.0+, `XmpDocument` and `doc.getXMP()` 22.1+.
15
15
 
16
+ <!-- docs-index:contents begin -->
17
+ ## Contents
18
+
19
+ - PdfDocument
20
+ - Static page dimension methods
21
+ - PdfPage
22
+ - ImageDocument
23
+ - XmlDocument
24
+ - XmpDocument
25
+ <!-- docs-index:contents end -->
26
+
16
27
  ## PdfDocument
17
28
 
18
29
  Open a PDF to inspect metadata and page geometry.
@@ -11,6 +11,18 @@ triggers:
11
11
 
12
12
  Entry points are top-level `async` functions with specific names. They are **not exported**. Switch calls them automatically based on flow events.
13
13
 
14
+ <!-- docs-index:contents begin -->
15
+ ## Contents
16
+
17
+ - Entry-point scanner constraints
18
+ - Flow lifecycle
19
+ - Timer
20
+ - Job processing
21
+ - Webhooks
22
+ - Script expression
23
+ - Property UI callbacks
24
+ <!-- docs-index:contents end -->
25
+
14
26
  ## Entry-point scanner constraints
15
27
 
16
28
  Switch discovers a script's entry points by regex, not by parsing. Before matching
@@ -11,6 +11,23 @@ triggers:
11
11
 
12
12
  All enums are available globally in `main.ts`. They are also accessible via `EnfocusSwitch.*` when used outside `main.ts` (e.g. in imported modules). Enums and values without a Switch version below exist in every Switch version with Node.js scripting; see [api-versions.md](api-versions.md).
13
13
 
14
+ <!-- docs-index:contents begin -->
15
+ ## Contents
16
+
17
+ - LogLevel
18
+ - AccessLevel
19
+ - DatasetModel
20
+ - Scope
21
+ - Priority
22
+ - Connection.Level
23
+ - HttpRequest.Method
24
+ - PropertyType
25
+ - NoYesListPropertyStringValue
26
+ - EnfocusSwitchPrivateDataTag
27
+ - ImageDocument.ColorMode
28
+ - ImageDocument.ColorSpace
29
+ <!-- docs-index:contents end -->
30
+
14
31
  ## LogLevel
15
32
 
16
33
  Used with `job.log()` and `flowElement.log()`.