Files
jerapah-flow/AGENTS.md
T
nsrb 3f0774813d refactor(config): remove legacy config reference handling and streamline YAML management
- Deleted legacy config reference handling functions and related migration scripts to simplify the codebase.
- Updated documentation to reflect the removal of legacy YAML paths and configurations.
- Adjusted existing YAML management processes to ensure compatibility with the new mustache-style syntax.
- Removed tests related to legacy config references, focusing on current functionality and ensuring clarity in the testing suite.
2026-08-30 15:37:58 +07:00

157 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# JerapahFlow plugins
This file tells agents how to add a **user plugin**. Do not put personal or site-specific scripts in `packages/server/scripts/` (core, read-only). Do not put them in `examples/plugins/` (shipped examples only).
## Workflows (instance data)
Live workflows are **not** product source. They live under `packages/server/data/workflows/<owner>/` (gitignored; override with `JFLOW_WORKFLOWS_DIR`).
| Kind | In git? | Path |
|---|---|---|
| Live / personal YAML | No | `packages/server/data/workflows/<owner>/` |
| Example presets | Yes | `examples/workflows/*.yaml` (copy into editor only; runner does not load them) |
Do **not** add personal YAML under `packages/server/`, `examples/workflows/`, or `packages/server/data/workflows/`. Prefer owner `local`. Example presets must use **core** scripts only (no `plugin/…` that requires install).
## Where things live
| Kind | YAML `script` | Editable | Path |
|---|---|---|---|
| Core | `fetch-http.js` | No | `packages/server/scripts/` |
| User plugin | `plugin/<id>` | Yes | `plugins/<id>/` |
| Example source | install → `plugin/<id>` | After install | `examples/plugins/<id>/` |
Runtime load path is repo-root `plugins/` (`PLUGINS_DIR` in `packages/server/paths.js`). Override with `JFLOW_PLUGINS_DIR` only in tests.
Plugins are **outside** the pnpm workspace (`packages/*`). Do not add `plugins/*` to `pnpm-workspace.yaml`.
## When to create a plugin
Create a user plugin when the script is:
- Site-specific (LAN IPs, personal modems, private APIs)
- A fork of a core script the user wants to edit
- Anything that should stay in git but not ship as core
Use native `fetch` (not `$axios`) when the URL is RFC1918 / WG (`10.x`, `192.168.x`, …). `$axios` is screened and **blocks** those hosts.
## Create a new plugin
1. Pick an id: lowercase letters, numbers, hyphens; max 64 chars; `^[a-z0-9]+(?:-[a-z0-9]+)*$`.
2. Folder name **must equal** manifest `id`. Example: `plugins/joplin-api`.
3. Id **must not** collide with a core script basename (`fetch-http`, `ntfy`, …).
4. Create three files (see below). Prefer `main: "script.js"`.
5. Point workflows at `plugin/<id>`.
6. Restart the runner (`pnpm dev` / drain-restart under `pnpm dev:pm2`) so the plugin is picked up.
Copy the layout from `plugins/joplin-api`, `plugins/send-sms`, or `examples/plugins/get-current-time`.
### `plugins/<id>/jerapah-plugin.json`
```json
{
"id": "my-plugin",
"name": "My plugin",
"version": "0.1.0",
"jerapah": ">=0.1.0 <1.0.0",
"main": "script.js",
"description": "One-line description"
}
```
- `version` must be semver (`0.1.0`).
- `jerapah` must match the app (`0.1.0` in root `package.json`). Use `">=0.1.0 <1.0.0"` unless you know otherwise.
- `main` is a relative path; no `..`, not absolute.
### `plugins/<id>/package.json`
```json
{
"name": "jflow-plugin-my-plugin",
"version": "0.1.0",
"private": true,
"type": "module",
"description": "JerapahFlow plugin: …"
}
```
Add `dependencies` only if the script `require()`s extra npm packages. Then:
```bash
pnpm install --dir plugins/<id> --ignore-scripts --prefer-offline
```
`plugins/*/node_modules/` is gitignored. Host-allowlisted modules (`axios`, `jsonata`, …) come from the server; extra deps resolve from the plugin directory.
### `plugins/<id>/script.js`
Must `export default` a function. The sandbox rewrites ESM `import`/`export default` to CJS.
```js
function passContext(ctx) {
if (ctx?.context != null && typeof ctx.context === "object" && !Array.isArray(ctx.context)) {
return { ...ctx.context };
}
return {};
}
async function myPlugin(ctx) {
const output = { ok: true };
return { output, context: { ...passContext(ctx), ...output } };
}
myPlugin.meta = {
description: "What this step does",
previewConfigKey: "url",
tags: ["HTTP"],
config: {},
input: {},
output: { ok: { type: "boolean" } },
context: { ok: { type: "boolean" } },
example: { data: {}, config: {} },
};
export default myPlugin;
```
Return `{ output, context?, skipRemaining? }`. Do not return `ctx`. Mutations of `ctx.data` / `ctx.context` are discarded unless returned.
| Field | Meaning |
|---|---|
| `ctx.data` | Step input (trigger payload, previous `output`, or DAG `needs`) |
| `ctx.context` | Run clipboard (plain object) |
| `ctx.config` | YAML `config` (mustache refs like `{{ secrets.name }}` already resolved) |
| `output` | Next step’s `data` |
| `context` | Next clipboard. Omit to keep incoming |
`fn.meta` must be JSON-serializable (UI + dry-run). Include `config` / `input` / `output` field schemas and an `example`.
## Sandbox globals (do not import these)
Injected: `log` (pino), `console`, `fetch`, `require`, `$axios`, `$kv`, `$fingerprint`, `$secrets`, `$vars`, `$responses`, `$workflows`.
- Use `log.info({ … }, "my-plugin: …")` — `log` is not an import.
- `require("axios")` is the screened `$axios` (RFC1918 blocked). Prefer `fetch` for LAN.
- Plugin `require("some-npm-dep")` uses the plugin’s `node_modules`.
## Workflow YAML
```yaml
scripts:
- name: Notify to channel
script: plugin/my-plugin
config:
url: http://10.8.0.6:3030/notes
token: "{{ secrets.joplin_api_token }}"
```
Optional `name` is the display title in the editor and graph (falls back to the script filename). Canonical ref is `plugin/<id>` (`.js` suffix is optional).
## Do not
- Add user plugins under `packages/server/scripts/` or `examples/plugins/`.
- Use an id that matches a core script file (`ntfy`, `jsonata`, …).
- Mismatch folder name and `jerapah-plugin.json` `id` (plugin is disabled).
- Commit `plugins/.staging-*` or `plugins/*/node_modules/`.
- Put secrets in `script.js`; use YAML `{{ secrets.name }}` / `{{ vars.name }}` (quote if the value starts with `{`).