Commit Graph

15 Commits

Author SHA1 Message Date
marcus f27a5456f6 feat: v0.5.0 — welle B Teil 1 (registry tools: search, tags, pull)
Three new SYNO.Docker.Registry tools, reverse-engineered from a live
DSM API capture (n4s4 reference disagrees on param names and methods).

- search_registry (#5): SYNO.Docker.Registry/search v1 with JSON-encoded
  q, plus offset/limit/page_size. Renders stars, downloads, official
  flag, truncated description, and total match count. Read-only.
- list_image_tags: SYNO.Docker.Registry/tags v1 with JSON-encoded repo
  (not name — DSM live capture diverges from n4s4). Response shape is
  unusual: tag list comes back as the envelope's data field directly.
  Output capped by limit (default 50); accepts both list and dict
  response shapes defensively. Read-only.
- pull_image (#3): SYNO.Docker.Registry/pull_start v1 with both
  repository and tag JSON-encoded. Async pull — no pull_status method
  confirmed on this DSM, so completion is detected by polling
  SYNO.Docker.Image/list (2–10 s backoff, 240 s budget under the
  Claude Desktop ~4 min tool-call ceiling). Timeout returns a
  non-fatal "still running" hint. Short-circuits when the image is
  already present locally. Confirmation gate required.

Tool count: 31 → 34. CLAUDE.md confirmation list updated. New DSM
quirks documented for pull_start (no pull_status) and tags (repo
param name, top-level data array).

Closes #3
Closes #5

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 13:25:59 +02:00
marcus 24b97338ba fix: v0.4.1 — remove pause_container / unpause_container (DSM unsupported)
Live test on this DSM firmware: SYNO.Docker.Container has no pause/
unpause method ("Method does not exist"). The Container Manager GUI
action menu only exposes Start / Stop / Force-Stop / Restart / Reset —
pause/resume simply isn't a feature here.

The two tools were briefly shipped in 0.4.0 (implemented by symmetry
with the verified stop call) and have now been removed rather than
left as a broken surface. The remaining lifecycle tools
(start_container, stop_container, restart_container) are unaffected.

Tool count: 33 → 31. Closes #7 (won't fix — DSM limitation).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 12:52:52 +02:00
marcus 12d532da7b feat: v0.4.0 — welle A (8 new tools: container lifecycle, inspect_image, system_overview)
Closes #1, #4, #6, #7.

Container lifecycle (#1, #7):
- start_container, stop_container, restart_container, pause_container,
  unpause_container — all via SYNO.Docker.Container with JSON-encoded
  name parameter, routed through _resolve_container_name for hash-
  prefix resolution. stop is live-verified; the other four are
  implemented by symmetry on the same API surface.

inspect_image (#4):
- Returns full image detail (layers, env, ports, entrypoint/cmd,
  labels) via SYNO.Docker.Image/get. Accepts name:tag, registry-
  prefixed names, and bare hashes. Defensive response parsing
  handles both wrapped (details.*) and flat envelopes.

system_overview (#6):
- Aggregates CPU %, RAM, network and block I/O across all running
  containers plus running/stopped counts. No new DSM endpoint —
  composed from list + stats, reusing the container_stats CPU
  formula. Per-source errors are non-fatal.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 12:40:11 +02:00
marcus 3f73ed0aef feat: v0.3.2 — delete_project tool
Closes the project lifecycle (create → start/stop/redeploy → delete).
The tool calls SYNO.Docker.Project/delete with the UUID JSON-encoded
as the `id` parameter (per DSM convention) and removes only the
Container Manager registration — the project folder and compose
file remain on the NAS. This mirrors DSM's own "Delete project"
behaviour, not a bug; the success message states the folder was
preserved so the user is not surprised.

Safety:
- Project-name validation runs before any I/O.
- A `_find_project` pre-flight returns "not found" with a clear
  message rather than letting DSM reject an unknown UUID.
- No automatic stop. If the project is RUNNING and DSM rejects
  the delete, the response tells the user to `stop_project` first
  rather than silently halting containers under the guise of a
  "delete" call.
- Requires confirmed=True; preview shows name, UUID, status, full
  path, and share path so the user can verify before deleting.

Tests cover preview-only, not-found, invalid-name, happy path
(verifies the UUID is JSON-encoded in the delete call), and the
running-project rejection path that surfaces the stop_project hint.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 11:29:09 +02:00
marcus 801dbe15dc feat: v0.3.1 — create_project tool
Adds `create_project` for registering a new Container Manager project
from a compose YAML string. Three-step flow that mirrors the DSM
"Create Project" wizard:

  1. SYNO.FileStation.CreateFolder with force_parent=true (idempotent
     — does not fail if the folder already exists, and creates missing
     intermediate directories). Without this step, Docker.Project/create
     fails with DSM error 2100.
  2. SYNO.Docker.Project/create (form-encoded POST; JSON-encoded string
     parameters per DSM convention) returns the new project UUID.
  3. trigger_build_stream + _wait_for_project_running, reusing the
     existing image-pull / start / poll machinery (including the
     BUILD_FAILED early-exit from welle 2).

Safety:
- Project-name validation (Welle-1 regex) runs before any I/O.
- Compose content is YAML-parsed and must contain a top-level
  `services` key before any side effects.
- A pre-flight list_projects check rejects duplicate names with a
  clear message rather than leaving an orphaned folder on the NAS.
- share_path defaults to compose_base_path + project_name (e.g.
  /volume1/docker + myapp → /docker/myapp); a caller-supplied value
  overrides it.
- Requires confirmed=True; the preview shows the resolved share path
  and the service count parsed from the compose content.
- DSM error 2100 surfaces as "target folder issue" with the attempted
  path. A build_stream failure after a successful Project/create tells
  the user the project is registered-but-not-started and points at
  redeploy_project for recovery.

Tests cover preview-only, already-exists, happy path (with parameter
JSON-encoding assertions), explicit share_path, malformed YAML,
missing services key, invalid project name, error 2100, and
build_stream failure after registration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 11:13:18 +02:00
marcus 8878eda0b2 docs: CLAUDE.md — codify changelog-update rule
Add an explicit rule that every user-visible change updates
CHANGELOG.md in the same commit, under an `## [Unreleased]` heading
between releases. References the C-2 gap (0.2.7 and 0.2.8 shipped
without changelog entries) so the motivation is durable.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 09:11:40 +02:00
marcus 4b8b1a0a6e docs: CLAUDE.md — push-retry rule and version-consistency invariant
- Document that git push to gitea.gecheckt.de occasionally returns
  Unauthorized on the first attempt and must be retried once after a
  1 s wait before reporting an auth failure.
- Codify the version-consistency invariant: pyproject.toml, uv.lock,
  and the latest CHANGELOG heading must move together;
  src/mcp_synology_container/__init__.py reads __version__ from
  importlib.metadata and is never hand-edited.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 09:09:30 +02:00
marcus ae36a9fbac v0.2.3: scrub operator-specific details from CLAUDE.md
Remove hostnames, concrete container names, image tags, personal notes,
and the completed task backlog. Replace with generic DSM quirks reference,
implementation rules, and tool inventory — suitable for a public connector.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 07:26:56 +02:00
marcus 81d5acd83e Release 0.2.0: README, CHANGELOG, version bump
- README: complete 22-tool reference table across 6 categories;
  updated feature list to reflect all additions and bug fixes
- CHANGELOG: added with [0.2.0] and [0.1.0] entries
- pyproject.toml: 0.1.0 → 0.2.0
- CLAUDE.md: corrected tool count 17 → 22

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 07:11:08 +02:00
marcus c8cda5ef2b Fix container hash-prefix + status-aware redeploy
Bug 1: Container name hash-prefix (e.g. f93cb8b504f7_jenkins)
- _strip_hash_prefix(): strips 12-char hex prefix and leading slash
- _resolve_container_name(): looks up actual DSM name from container list
- Applied in list_containers (display), container_stats (matching),
  get_container_status/get_container_logs/exec_in_container (lookup)

Bug 2: redeploy_project DSM 2101/1202 on wrong project state
- Fetch project status before acting
- RUNNING     → stop then start
- STOPPED     → start directly (nothing to stop)
- BUILD_FAILED → suppress stop error, then start
- Other       → return error with workaround hint

36 tests all passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 21:43:02 +02:00
marcus 6fa35e1b48 Remove pull_image + list_registries; mark Gruppen 6+7 as entfällt
DSM methods for SYNO.Docker.Image/pull and SYNO.Docker.Registry/get
did not behave as expected in production testing against the NAS.
Tools deregistered, modules deleted, tests removed, CLAUDE.md updated.
Tool count: 19 → 17.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 20:03:17 +02:00
marcus 5fe8f5bc73 Add pull_image + list_registries; remove Gruppe 5 (no Volume API)
- pull_image: SYNO.Docker.Image/pull with repository+tag split via
  rpartition; polls image list every 3 s until image appears, 120 s timeout
- list_registries: SYNO.Docker.Registry/get; shows name, URL, active marker
- Gruppe 5 (Volumes) removed from roadmap — SYNO.Docker.Volume does not exist
- CLAUDE.md: tool count 17 → 19, Volumes section removed
- 28 tests all passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 19:28:45 +02:00
marcus a8da306ce5 Add container_stats tool (Gruppe 2); remove rename_container
container_stats(container_name) calls SYNO.Docker.Container/stats,
locates the entry by name (stripping the DSM-added leading slash),
and reports:
  - CPU %  (standard Docker formula: cpu_delta / system_delta * cpus * 100)
  - Memory used / limit  (human-readable)
  - Network I/O rx / tx  (summed across all interfaces)
  - Block I/O read / write  (from io_service_bytes_recursive)

Gracefully handles first-poll (precpu system_cpu_usage absent → 0%).
7 unit tests covering: found, CPU formula, memory format, slash-strip,
not-found, API error, no-precpu fallback.

rename_container removed: DSM Container Manager offers no rename API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 18:29:17 +02:00
marcus 0b48190f99 Anpassungen 2026-04-13 17:55:08 +02:00
marcus a0c1b6ed93 Initial implementation 2026-04-13 14:22:37 +02:00