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.

ソース情報

リポジトリ
Datus-ai/Datus-Plugins
ソースの最終更新活動
2026年8月11日 14:00
検出された SKILL.md の言語
英語
スター
0
フォーク
1

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
2 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
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.
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る