Skip to main content

datus-plugin-development

Wrap a user-provided SDK / REST API / documentation into an installable Datus plugin. Produces a design draft FIRST (config schema, CLI command list with doc citations + permission rules, bundled-skill plan), then STOPS for user confirmation before writing any code. Fully self-contained — the entire datus-plugin.yml manifest contract is inlined below.

Quellinformationen

Repository
Datus-ai/Datus-Plugins
Letzte Quellaktivität
11. August 2026 um 14:00
Erkannte Sprache von SKILL.md
Englisch
Sterne
0
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
2 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
datus-plugin-development
description
Wrap a user-provided SDK / REST API / documentation into an installable Datus plugin. Produces a design draft FIRST (config schema, CLI command list with doc citations + permission rules, bundled-skill plan), then STOPS for user confirmation before writing any code. Fully self-contained — the entire datus-plugin.yml manifest contract is inlined below.
# Datus Plugin Development Skill ## Goal Turn documentation the user hands you (an SDK reference, a REST/OpenAPI spec, a CLI man page, a README, a set of function signatures, …) into an installable **Datus plugin** — a Python package discovered through the `datus.plugins` entry-point group that adds a `datus <name>` command plus optional bundled skills, prompt awareness, bash permissions, and tool transformers. **The contract is declarative.** A plugin ships a single manifest file — `datus-plugin.yml` inside the importable package — that names its CLI entry function, its permissions, its skills directory, its system-prompt template, and its config schema. The only Python you write are plain functions. There is no plugin class, no base class, and no `datus` import anywhere. **This skill is design-first.** It NEVER writes plugin code on the first pass. It reads the provided documentation, produces a **design draft** the user can review, and then **stops and waits for explicit confirmation**. Only after the user approves (or amends) the draft does it implement the package. This skill is fully self-contained: the complete plugin contract is inlined in the **Contract Reference** appendix below. Do not depend on external docs or on reading Datus source code — everything needed to design and build a plugin is here. ## Non-negotiable ground rules Every design and every line of generated code must honor these (details in the appendix): - **A plugin never imports `datus.*`** and never depends on `datus` (or any shared SDK) in `pyproject.toml`. Datus is the config broker; the plugin only ships a manifest plus plain functions that Datus calls. - **One distribution ships exactly one plugin.** Each `pyproject.toml` declares a single `datus.plugins` entry point — never bundle several plugins into one distribution. Code shared across plugins goes into a separate **library** distribution (it registers no entry point) that the plugins depend on. - **The entry-point value is the package name** — `<name> = "datus_plugin_<name>"`, a pure name → package mapping. A legacy `pkg.module:Class` value is rejected by `datus plugin install` and `datus plugin pack`. - **`datus-plugin.yml` lives at the package root** (inside the importable package, next to `__init__.py`) and must ship in the wheel. Only `manifest_version: 1` is required; every other key is optional. - **The CLI entry is a function** — `main(argv: list[str], profile: dict) -> int | None`, named by the manifest's `cli` key. `argv` is everything after `datus <name>` with Datus' own `--profile` / `--config` already stripped; `profile` is the resolved, `${VAR}`-expanded `agent.plugins.<name>.<profile>` dict. Return an exit code; `None` means `0`; do not call `sys.exit()` on the success path. - **Reserved names.** The entry-point name may not be `upgrade`, `skill`, or `plugin`, and may not start with `-`. It doubles as both the `datus <name>` command and the `agent.plugins.<name>` config key, so pick one clean identifier. - **Never surface secrets.** Secret config fields are marked `x-secret: true` in the manifest's `config_schema`; Datus strips them (and every field NOT declared in the schema) before the system-prompt template renders, recursing into declared nested objects — so declare every non-secret field the template needs. Secrets in config are always `${ENV_VAR}` references, never literals. If the requested command name is reserved / collides / starts with `-`, flag it in the draft and propose an alternative. ## Input - `$ARGUMENTS` — path or URL to the source documentation, plus (ideally) the desired command name. If the docs location or the command name is missing, ask for it before drafting. - The user may instead paste the docs directly into the conversation. --- ## Phase A — DESIGN DRAFT (always first; then STOP) ### Step A1: Ingest the source documentation Read the user-provided docs. Extract: - **Capabilities** — the concrete operations the plugin could expose (API endpoints, SDK methods, CLI verbs). For each, note inputs, outputs, and whether it is read-only or state-changing. **Inventory them ALL first** — when the source exposes a large surface (an OpenAPI spec, dozens of resource groups), enumerate every group/endpoint before deciding anything; never silently skip parts of the API. - **Authentication & connection** — base URL / host, auth scheme (bearer token, API key, basic, OAuth), region, workspace/tenant, timeouts. These become profile fields in the `config_schema`. - **Dependencies** — which third-party libraries the wrapper needs (`requests`, `httpx`, the vendor SDK, `typer`, …). Never `datus`. **Relevance filter — Datus is a data-analysis / SQL / warehouse / ETL / metrics agent.** These plugins exist to serve that agent, not to mirror a vendor's whole API. After inventorying every capability, tier each by how well it serves data-analysis workflows and pick a **preliminary scope** that leads with the high-relevance operations. The discriminating axis is **analysis-relevant vs. management/config**, NOT read-vs-write: - Keep analysis-relevant **writes** — authoring metric/query SQL, triggering an ingestion/ETL run, managing a warehouse connection — gated as `ask`. Do not let a "read-only is safe" bias quietly shrink the scope; include the authoring/ETL writes the agent genuinely needs. - Drop analysis-irrelevant capabilities — feature-flag toggles, role/permission admin, project settings — even when they offer tidy CRUD. You never finalize the scope alone. The draft must present, side by side, the **selection rationale** for what you kept AND the **full list of excluded capabilities** with reasons, so the user makes the final call (Step A2 §5). If the docs are ambiguous or incomplete, collect the open questions — do not guess silently. ### Step A2: Produce the draft Render the draft in the conversation using this exact structure. Keep it concrete — every CLI command must trace back to a specific part of the source docs. ``` ## Datus Plugin Design Draft: <name> - CLI command / config key: `datus <name>` · `agent.plugins.<name>` - Purpose: <one line> - Source docs: <what was provided> - Scope: <K of N inventoried capabilities selected — rationale + exclusions in §5> - CLI routing style: <dict dispatch | argparse | REST wrapper | Typer> - Third-party dependencies: <libs, none = pure stdlib> (never datus) ### 1. Configuration parameters (config_schema) | Field | Type | Required | Secret (`x-secret`) | Default | Source doc ref | Notes | |-------|------|----------|---------------------|---------|----------------|-------| | api_base_url | string | yes | no | — | <spec §> | endpoint root | | token | string | yes | YES -> `${VAR}` | — | <auth §> | bearer token | | ... | | | | | | | - This table becomes the manifest's inline JSON Schema (`config_schema`). - Secret fields are configured as `${ENV_VAR}` references, expanded by Datus. - A `name` key is injected by Datus (= profile name); do not declare it. - Every NON-secret field the system-prompt template will reference MUST appear here — undeclared fields are stripped before rendering. - A group of related options (e.g. an `s3` credentials block) is declared as a nested `type: object` property with its own `properties`; use the dotted path as the table's field name (`s3.secret_access_key`) and mark the secret **leaves** `x-secret`, not the whole block, so the non-secret leaves stay editable in the `/plugins` TUI. ### 2. CLI command list For each subcommand: #### `datus <name> <subcommand> [args...]` - Function: <what it does, in one or two lines> - Analysis value: <the data-analysis / SQL / warehouse / ETL / metrics workflow this serves — if you cannot state one, it probably belongs in §5 exclusions> - Doc ref: <SDK method / endpoint / section it maps to> - Permission: - normal: allow | ask | deny — <pattern, e.g. `list-pets:*`> - auto: allow | ask | deny — <pattern> - rationale: <read-only => allow; state-changing => ask under normal> (Repeat per subcommand. Group read-only vs. state-changing so the permission posture is obvious.) This command list is written twice into the manifest: as `permissions` patterns (the posture) and as the `commands` catalogue (the descriptive tree that powers `!<plugin>` completion — see [Declaring the CLI command catalogue](#declaring-the-cli-command-catalogue)). Command groups become nested `subcommands`; note each command's key arguments so the catalogue can hint them. Permission patterns are namespace-relative — Datus prefixes `datus <name> ` automatically. Syntax: `cmd` exact, `cmd:*` prefix, `cmd:glob` prefix + first-arg glob, `:*` whole namespace. Only `normal` and `auto` profiles are accepted. ### 3. Bundled skills & prompt template - Main skill `<name>` — description + when the agent should invoke it. - Setup skill `<name>-setup` — the profile fields it collects from the user, and that it writes `${VAR}` references for secrets (never literals). - Each skill is ONE `SKILL.md` (no `references/`, no `assets/`): list the templates/scripts to inline in it, and split into another skill rather than another file when the content does not fit. - system_prompt template — the NON-SECRET fields to surface per environment (e.g. base URL, region, env name); all of them must be declared in §1. Plan the `{% else %}` installed-but-unconfigured branch pointing at `<name>-setup`. ### 4. Tool transformers (only if applicable) - If the plugin should rewrite/deny the agent's tool calls (e.g. SQL scoping), list the tool patterns and the transform/deny rule. Otherwise: "none". ### 5. Scope selection & excluded capabilities For any non-trivial API, the reader must be able to audit — and overturn — your scoping. Show both halves: - **Selection rationale** — why the §2 commands were kept: which data-analysis / SQL / warehouse / ETL / metrics workflows they serve. Tie back to the relevance filter (Step A1). - **Excluded / deferred capabilities** — EVERY capability inventoried in Step A1 but left out. Group by resource, one-line reason each (analysis-irrelevant / redundant / low priority / needs clarification). Never silently drop parts of a large API — the user decides the final scope from this list, and may pull any excluded item back in. | Capability / resource group | In scope? | Reason | |-----------------------------|-----------|--------| | metrics — read + warehouse-native SQL authoring | yes | core metric analysis | | ingestions — trigger / backfill | yes | ETL the agent drives (`ask`) | | experiments — read results / pulse | yes | analysis output | | feature gates / segments / holdouts | no — deferred | feature-flag mgmt, not data analysis | | roles / users / project settings | no — deferred | access & project admin, not analysis | | ... (list every remaining group) | | | End with an explicit prompt: "Confirm this scope, or tell me which excluded capabilities to include." ### 6. End-to-end testability - Deterministic user goal: <one bounded task the plugin must complete through `datus -p`>. - Environment fixtures: <minikube / MinIO / Flink Operator / other pinned services, or none>. - Independent oracle: <exact external state, schema, count, checksum, or resource fields to verify without calling the tested plugin>. - Generated artifacts: <workspace-relative output patterns to preserve>. - Support plugins and minimum permission prefixes: <only what the workflow needs>. - Efficiency signals: <expected command sequence plus tool-call / turn / token / unexpected-failure budgets>. - Feasibility: <runnable now | reference workflow pending fixture/oracle>, including prerequisites. This section becomes the input to `$build-datus-plugin-e2e` after implementation. The E2E oracle, not the LLM's narrative, owns the correctness verdict. ### 7. Open questions - <anything the docs did not resolve: auth details, pagination, rate limits, command-name conflicts, or scope calls you are unsure about …> ``` ### Step A3: STOP and wait for confirmation After presenting the draft: - Explicitly ask the user to **confirm, amend, or reject** the draft, to **confirm the scope or pull any excluded capability (§5) back in**, and to answer any open questions. - **Do not create any files, do not write any code, do not scaffold the package.** End the turn here. - Proceed to Phase B **only** after the user gives explicit approval. If the user requests changes, revise the draft and stop again. --- ## Phase B — IMPLEMENTATION (only after explicit confirmation) Use the recipes and semantics from the **Contract Reference** appendix. Implement in this order: 1. **Package layout** — `datus-plugin-<name>/` with `pyproject.toml` and a `datus_plugin_<name>/` package (`__init__.py`, `datus-plugin.yml`, `cli.py`, `prompts/`, `skills/`). See [Package layout & entry point](#package-layout--entry-point). 2. **Entry point** — register under `[project.entry-points."datus.plugins"]` as `<name> = "datus_plugin_<name>"` (the package name — no `:Class`). Dependencies list the plugin's own libs, **never `datus`**. 3. **The manifest** — write `datus_plugin_<name>/datus-plugin.yml` from the approved draft: `manifest_version: 1`, `description`, `cli`, `permissions` (§2 table), `system_prompt`, `skills`, `config_schema` (§1 table), and `commands` (the §2 command list as a nested catalogue — see [Declaring the CLI command catalogue](#declaring-the-cli-command-catalogue)). See [The manifest](#the-manifest). 4. **The CLI function** — `main(argv, profile)` using the routing style from the draft (see [CLI recipes](#cli-recipes)). Read endpoint/credentials from `profile`; map subcommands to operations; return conventional exit codes (`0` ok, `1` runtime, `2` usage, `3` config, `8` missing optional dep). 5. **The prompt template** — `prompts/system.md.j2` with a `{% if profiles %}` configured branch and an `{% else %}` branch pointing at `<name>-setup` ([System-prompt template](#system-prompt-template)). 6. **Bundled skills** — `skills/<name>/SKILL.md` and `skills/<name>-setup/SKILL.md`, each **one self-contained file**: no `references/` or `assets/` siblings, every template inlined as a fenced block (see [Bundling skills](#bundling-skills) and [Bundling a setup skill](#bundling-a-setup-skill)). 7. **Packaging** — ensure the manifest, template, and skill files ship in the wheel (Hatchling packages them by default; with setuptools add `[tool.setuptools.package-data]`). 8. **Tests** — call `main(argv, profile)` with a plain dict (no `agent.yml`, no Datus imports); validate the manifest with `yaml.safe_load` and render the template with plain Jinja2. See [Testing your plugin](#testing-your-plugin). 9. **E2E handoff** — after unit and manifest-contract tests pass, invoke `$build-datus-plugin-e2e` when end-to-end coverage is in scope. Implement the approved §6 deterministic goal through the repository's pytest harness; do not add a standalone test CLI and do not use LLM judgment as the oracle. ### Verify against the constraints checklist Before declaring done, confirm every item in [Constraints checklist](#constraints-checklist). ### End-to-end verification - **CLI dispatch**: `datus plugin install src:./datus-plugin-<name>` (or `pip install -e` into datus' environment) then `datus <name> ...`. If it falls through to the REPL, the entry point is missing or misnamed; if it prints "declares no CLI command", the manifest loaded but has no `cli` key.
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen